From f364060acfa20539b5c4ff7b89a89c3b2236efce Mon Sep 17 00:00:00 2001 From: Commander Tvis Date: Thu, 11 Jun 2020 12:16:22 +0700 Subject: [PATCH 001/199] Add project stub --- kmath-nd4j/build.gradle.kts | 3 +++ settings.gradle.kts | 1 + 2 files changed, 4 insertions(+) create mode 100644 kmath-nd4j/build.gradle.kts diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts new file mode 100644 index 000000000..5da7d66b7 --- /dev/null +++ b/kmath-nd4j/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("scientifik.jvm") +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 57173250b..afb5598b4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,6 +39,7 @@ include( ":kmath-commons", ":kmath-viktor", ":kmath-koma", + ":kmath-nd4j", ":kmath-prob", ":kmath-io", ":kmath-dimensions", From 3df9892de53c0aa719091ad3d0c4aa0405081655 Mon Sep 17 00:00:00 2001 From: Commander Tvis Date: Thu, 11 Jun 2020 14:10:39 +0700 Subject: [PATCH 002/199] Implement the ND4J module for scalars --- build.gradle.kts | 1 + kmath-nd4j/build.gradle.kts | 10 ++++++++-- .../INDArrayScalarsIterator.kt | 19 +++++++++++++++++++ .../scientifik.kmath.nd4j/ND4JStructure.kt | 14 ++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayScalarsIterator.kt create mode 100644 kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt diff --git a/build.gradle.kts b/build.gradle.kts index 6d102a77a..10e030520 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,6 +11,7 @@ allprojects { repositories { jcenter() maven("https://dl.bintray.com/kotlin/kotlinx") + mavenCentral() } group = "scientifik" diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 5da7d66b7..59354a8f9 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,3 +1,9 @@ -plugins { - id("scientifik.jvm") +plugins { id("scientifik.jvm") } + +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-platform:1.0.0-beta7") + testImplementation("org.slf4j:slf4j-simple:1.7.30") } diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayScalarsIterator.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayScalarsIterator.kt new file mode 100644 index 000000000..2c2dc970f --- /dev/null +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayScalarsIterator.kt @@ -0,0 +1,19 @@ +package scientifik.kmath.nd4j + +import org.nd4j.linalg.api.ndarray.INDArray +import org.nd4j.linalg.api.shape.Shape + +internal class INDArrayScalarsIterator(private val iterateOver: INDArray) : Iterator> { + private var i: Int = 0 + + override fun hasNext(): Boolean = i < iterateOver.length() + + override fun next(): Pair { + val idx = if (iterateOver.ordering() == 'c') + Shape.ind2subC(iterateOver, i++.toLong())!! + else + Shape.ind2sub(iterateOver, i++.toLong())!! + + return narrowToIntArray(idx) to iterateOver.getScalar(*idx) + } +} diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt new file mode 100644 index 000000000..eb9f9b80c --- /dev/null +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt @@ -0,0 +1,14 @@ +package scientifik.kmath.nd4j + +import org.nd4j.linalg.api.ndarray.INDArray +import scientifik.kmath.structures.NDStructure + +internal fun narrowToIntArray(la: LongArray): IntArray = IntArray(la.size) { la[it].toInt() } + +data class ND4JStructure(val ndArray: INDArray) : NDStructure { + override val shape: IntArray + get() = narrowToIntArray(ndArray.shape()) + + override fun get(index: IntArray): INDArray = ndArray.getScalar(*index) + override fun elements(): Sequence> = Sequence { INDArrayScalarsIterator(ndArray) } +} From 9a4dd315072e6cb27c430c799074b1dd36a06f94 Mon Sep 17 00:00:00 2001 From: Commander Tvis Date: Thu, 11 Jun 2020 14:17:46 +0700 Subject: [PATCH 003/199] Move narrowToIntArray to new file --- kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt | 3 +++ .../src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt new file mode 100644 index 000000000..5d341dd68 --- /dev/null +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt @@ -0,0 +1,3 @@ +package scientifik.kmath.nd4j + +internal fun narrowToIntArray(la: LongArray): IntArray = IntArray(la.size) { la[it].toInt() } \ No newline at end of file diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt index eb9f9b80c..1d0301ff9 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt @@ -3,8 +3,6 @@ package scientifik.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray import scientifik.kmath.structures.NDStructure -internal fun narrowToIntArray(la: LongArray): IntArray = IntArray(la.size) { la[it].toInt() } - data class ND4JStructure(val ndArray: INDArray) : NDStructure { override val shape: IntArray get() = narrowToIntArray(ndArray.shape()) From d0cc75098bdc523c1c5f945c5a83a460efa00af8 Mon Sep 17 00:00:00 2001 From: Commander Tvis Date: Thu, 11 Jun 2020 14:36:19 +0700 Subject: [PATCH 004/199] Rework with specialized NDStructure implementations --- .../kotlin/scientifik.kmath.nd4j/Arrays.kt | 3 +- .../INDArrayScalarsIterator.kt | 19 ---------- .../scientifik.kmath.nd4j/ND4JStructure.kt | 12 ------ .../scientifik.kmath.nd4j/NDArrayIterators.kt | 37 +++++++++++++++++++ .../ScalarsND4JStructure.kt | 34 +++++++++++++++++ 5 files changed, 73 insertions(+), 32 deletions(-) delete mode 100644 kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayScalarsIterator.kt delete mode 100644 kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt create mode 100644 kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/NDArrayIterators.kt create mode 100644 kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt index 5d341dd68..3d5062a4f 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt @@ -1,3 +1,4 @@ package scientifik.kmath.nd4j -internal fun narrowToIntArray(la: LongArray): IntArray = IntArray(la.size) { la[it].toInt() } \ No newline at end of file +internal fun widenToLongArray(ia: IntArray): LongArray = LongArray(ia.size) { ia[it].toLong() } +internal fun narrowToIntArray(la: LongArray): IntArray = IntArray(la.size) { la[it].toInt() } diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayScalarsIterator.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayScalarsIterator.kt deleted file mode 100644 index 2c2dc970f..000000000 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayScalarsIterator.kt +++ /dev/null @@ -1,19 +0,0 @@ -package scientifik.kmath.nd4j - -import org.nd4j.linalg.api.ndarray.INDArray -import org.nd4j.linalg.api.shape.Shape - -internal class INDArrayScalarsIterator(private val iterateOver: INDArray) : Iterator> { - private var i: Int = 0 - - override fun hasNext(): Boolean = i < iterateOver.length() - - override fun next(): Pair { - val idx = if (iterateOver.ordering() == 'c') - Shape.ind2subC(iterateOver, i++.toLong())!! - else - Shape.ind2sub(iterateOver, i++.toLong())!! - - return narrowToIntArray(idx) to iterateOver.getScalar(*idx) - } -} diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt deleted file mode 100644 index 1d0301ff9..000000000 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ND4JStructure.kt +++ /dev/null @@ -1,12 +0,0 @@ -package scientifik.kmath.nd4j - -import org.nd4j.linalg.api.ndarray.INDArray -import scientifik.kmath.structures.NDStructure - -data class ND4JStructure(val ndArray: INDArray) : NDStructure { - override val shape: IntArray - get() = narrowToIntArray(ndArray.shape()) - - override fun get(index: IntArray): INDArray = ndArray.getScalar(*index) - override fun elements(): Sequence> = Sequence { INDArrayScalarsIterator(ndArray) } -} diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/NDArrayIterators.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/NDArrayIterators.kt new file mode 100644 index 000000000..426b1ec2d --- /dev/null +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/NDArrayIterators.kt @@ -0,0 +1,37 @@ +package scientifik.kmath.nd4j + +import org.nd4j.linalg.api.ndarray.INDArray +import org.nd4j.linalg.api.shape.Shape + +internal sealed class INDArrayIteratorBase(protected val iterateOver: INDArray) : Iterator> { + private var i: Int = 0 + + override fun hasNext(): Boolean = i < iterateOver.length() + + abstract fun getSingle(indices: LongArray): T + + final override fun next(): Pair { + val la = if (iterateOver.ordering() == 'c') + Shape.ind2subC(iterateOver, i++.toLong())!! + else + Shape.ind2sub(iterateOver, i++.toLong())!! + + return narrowToIntArray(la) to getSingle(la) + } +} + +internal class INDArrayDoubleIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { + override fun getSingle(indices: LongArray): Double = iterateOver.getDouble(*indices) +} + +internal class INDArrayLongIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { + override fun getSingle(indices: LongArray) = iterateOver.getLong(*indices) +} + +internal class INDArrayIntIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { + override fun getSingle(indices: LongArray) = iterateOver.getInt(*narrowToIntArray(indices)) +} + +internal class INDArrayFloatIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { + override fun getSingle(indices: LongArray) = iterateOver.getFloat(*indices) +} diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt new file mode 100644 index 000000000..ef8c3ec2e --- /dev/null +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt @@ -0,0 +1,34 @@ +package scientifik.kmath.nd4j + +import org.nd4j.linalg.api.ndarray.INDArray +import scientifik.kmath.structures.NDStructure + +interface INDArrayStructureBase : NDStructure { + val ndArray: INDArray + + override val shape: IntArray + get() = narrowToIntArray(ndArray.shape()) + + fun elementsIterator(): Iterator> + override fun elements(): Sequence> = Sequence { elementsIterator() } +} + +data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructureBase { + override fun elementsIterator(): Iterator> = INDArrayIntIterator(ndArray) + override fun get(index: IntArray): Int = ndArray.getInt(*index) +} + +data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructureBase { + override fun elementsIterator(): Iterator> = INDArrayLongIterator(ndArray) + override fun get(index: IntArray): Long = ndArray.getLong(*widenToLongArray(index)) +} + +data class INDArrayDoubleStructure(override val ndArray: INDArray) : INDArrayStructureBase { + override fun elementsIterator(): Iterator> = INDArrayDoubleIterator(ndArray) + override fun get(index: IntArray): Double = ndArray.getDouble(*index) +} + +data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructureBase { + override fun elementsIterator(): Iterator> = INDArrayFloatIterator(ndArray) + override fun get(index: IntArray): Float = ndArray.getFloat(*index) +} From bac6451443f5cf9995453fc780cd2a8d037e60cd Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sat, 27 Jun 2020 21:17:40 +0700 Subject: [PATCH 005/199] Add tests --- .../kmath/nd4j/INDArrayStructureTest.kt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt diff --git a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt new file mode 100644 index 000000000..e851f2e80 --- /dev/null +++ b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt @@ -0,0 +1,38 @@ +package scientifik.kmath.nd4j + +import org.nd4j.linalg.factory.Nd4j +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class INDArrayStructureTest { + @Test + fun testElements() { + val nd = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! + val struct = INDArrayDoubleStructure(nd) + val res = struct.elements().map { it.second }.toList() + assertEquals(listOf(1.0, 2.0, 3.0), res) + } + + @Test + fun testShape() { + val nd = Nd4j.rand(10, 2, 3, 6)!! + val struct = INDArrayIntStructure(nd) + assertEquals(intArrayOf(10, 2, 3, 6).toList(), struct.shape.toList()) + } + + @Test + fun testEquals() { + val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! + val struct1 = INDArrayDoubleStructure(nd1) + val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! + val struct2 = INDArrayDoubleStructure(nd2) + assertEquals(struct1, struct2) + } + + @Test + fun testDimension() { + val nd = Nd4j.rand(8, 16, 3, 7, 1)!! + val struct = INDArrayIntStructure(nd) + assertEquals(5, struct.dimension) + } +} From b6bf741dbe72afdcbc311d6ac89ac8700ac81cb4 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sat, 27 Jun 2020 21:19:19 +0700 Subject: [PATCH 006/199] Replace lambdas with references --- .../main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt | 2 +- .../test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt index ef8c3ec2e..3ffcc110d 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt @@ -10,7 +10,7 @@ interface INDArrayStructureBase : NDStructure { get() = narrowToIntArray(ndArray.shape()) fun elementsIterator(): Iterator> - override fun elements(): Sequence> = Sequence { elementsIterator() } + override fun elements(): Sequence> = Sequence(::elementsIterator) } data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructureBase { diff --git a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt index e851f2e80..235b65556 100644 --- a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt @@ -9,7 +9,7 @@ internal class INDArrayStructureTest { fun testElements() { val nd = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! val struct = INDArrayDoubleStructure(nd) - val res = struct.elements().map { it.second }.toList() + val res = struct.elements().map(Pair::second).toList() assertEquals(listOf(1.0, 2.0, 3.0), res) } From e466f4bdf2448ed028c8895e5d6bb7b147fa0777 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sat, 27 Jun 2020 21:21:16 +0700 Subject: [PATCH 007/199] Add test for get --- .../kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt index 235b65556..239289262 100644 --- a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt @@ -3,6 +3,7 @@ package scientifik.kmath.nd4j import org.nd4j.linalg.factory.Nd4j import kotlin.test.Test import kotlin.test.assertEquals +import scientifik.kmath.structures.get internal class INDArrayStructureTest { @Test @@ -35,4 +36,11 @@ internal class INDArrayStructureTest { val struct = INDArrayIntStructure(nd) assertEquals(5, struct.dimension) } + + @Test + fun testGet() { + val nd = Nd4j.rand(10, 2, 3, 6)!! + val struct = INDArrayIntStructure(nd) + assertEquals(nd.getInt(0, 0, 0, 0), struct[0, 0, 0, 0]) + } } From fefa0db86ed15a7583f442aa1d2e958dcdfee5c3 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 28 Jun 2020 17:29:00 +0700 Subject: [PATCH 008/199] Rename files --- .../{NDArrayIterators.kt => INDArrayIterators.kt} | 0 .../{ScalarsND4JStructure.kt => INDArrayStructures.kt} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/{NDArrayIterators.kt => INDArrayIterators.kt} (100%) rename kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/{ScalarsND4JStructure.kt => INDArrayStructures.kt} (100%) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/NDArrayIterators.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt similarity index 100% rename from kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/NDArrayIterators.kt rename to kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt similarity index 100% rename from kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/ScalarsND4JStructure.kt rename to kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt From 5cc56b6ab01dff7c412e93a43feea400f70bbc96 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 28 Jun 2020 17:30:09 +0700 Subject: [PATCH 009/199] Remove Base suffix from class name --- .../kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt index 3ffcc110d..b444def3d 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt @@ -3,7 +3,7 @@ package scientifik.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray import scientifik.kmath.structures.NDStructure -interface INDArrayStructureBase : NDStructure { +interface INDArrayStructure : NDStructure { val ndArray: INDArray override val shape: IntArray @@ -13,22 +13,22 @@ interface INDArrayStructureBase : NDStructure { override fun elements(): Sequence> = Sequence(::elementsIterator) } -data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructureBase { +data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure { override fun elementsIterator(): Iterator> = INDArrayIntIterator(ndArray) override fun get(index: IntArray): Int = ndArray.getInt(*index) } -data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructureBase { +data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure { override fun elementsIterator(): Iterator> = INDArrayLongIterator(ndArray) override fun get(index: IntArray): Long = ndArray.getLong(*widenToLongArray(index)) } -data class INDArrayDoubleStructure(override val ndArray: INDArray) : INDArrayStructureBase { +data class INDArrayDoubleStructure(override val ndArray: INDArray) : INDArrayStructure { override fun elementsIterator(): Iterator> = INDArrayDoubleIterator(ndArray) override fun get(index: IntArray): Double = ndArray.getDouble(*index) } -data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructureBase { +data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure { override fun elementsIterator(): Iterator> = INDArrayFloatIterator(ndArray) override fun get(index: IntArray): Float = ndArray.getFloat(*index) } From f49c3e4f4d2158123640c442dd7ebe6447ec2474 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 28 Jun 2020 17:33:09 +0700 Subject: [PATCH 010/199] Add final modifier --- .../src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt index 426b1ec2d..f6efdc0ba 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt @@ -6,7 +6,7 @@ import org.nd4j.linalg.api.shape.Shape internal sealed class INDArrayIteratorBase(protected val iterateOver: INDArray) : Iterator> { private var i: Int = 0 - override fun hasNext(): Boolean = i < iterateOver.length() + final override fun hasNext(): Boolean = i < iterateOver.length() abstract fun getSingle(indices: LongArray): T From b41a9588bc6c98842126e89650d6a942f4369bdf Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 28 Jun 2020 18:21:27 +0700 Subject: [PATCH 011/199] Rename file --- .../main/kotlin/scientifik.kmath.nd4j/{Arrays.kt => arrays.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/{Arrays.kt => arrays.kt} (100%) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/arrays.kt similarity index 100% rename from kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/Arrays.kt rename to kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/arrays.kt From 05120929b0d18bb8a2bf7937a6f679e95ba5dc9b Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 28 Jun 2020 19:08:44 +0700 Subject: [PATCH 012/199] Encapsulate classOfT property of AsmBuilder --- .../kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt index e550bc563..5531fd5dc 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt @@ -16,13 +16,13 @@ import kotlin.reflect.KClass * ASM Builder is a structure that abstracts building a class designated to unwrap [MST] to plain Java expression. * This class uses [ClassLoader] for loading the generated class, then it is able to instantiate the new class. * - * @param T the type of AsmExpression to unwrap. - * @param algebra the algebra the applied AsmExpressions use. - * @param className the unique class name of new loaded class. - * @param invokeLabel0Visitor the function to apply to this object when generating invoke method, label 0. + * @property T the type of AsmExpression to unwrap. + * @property algebra the algebra the applied AsmExpressions use. + * @property className the unique class name of new loaded class. + * @property invokeLabel0Visitor the function to apply to this object when generating invoke method, label 0. */ internal class AsmBuilder internal constructor( - internal val classOfT: KClass<*>, + private val classOfT: KClass<*>, private val algebra: Algebra, private val className: String, private val invokeLabel0Visitor: AsmBuilder.() -> Unit From 3b18000f1edcd9d99e15037230885140b64b8001 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 29 Jun 2020 00:14:01 +0700 Subject: [PATCH 013/199] Make several NDStructures mutable --- .../scientifik.kmath.nd4j/INDArrayStructures.kt | 10 +++++++--- .../scientifik/kmath/nd4j/INDArrayStructureTest.kt | 14 +++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt index b444def3d..f39d84716 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt @@ -1,6 +1,7 @@ package scientifik.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray +import scientifik.kmath.structures.MutableNDStructure import scientifik.kmath.structures.NDStructure interface INDArrayStructure : NDStructure { @@ -13,9 +14,10 @@ interface INDArrayStructure : NDStructure { override fun elements(): Sequence> = Sequence(::elementsIterator) } -data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure { +data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { override fun elementsIterator(): Iterator> = INDArrayIntIterator(ndArray) override fun get(index: IntArray): Int = ndArray.getInt(*index) + override fun set(index: IntArray, value: Int): Unit = run { ndArray.putScalar(index, value) } } data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure { @@ -23,12 +25,14 @@ data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStruc override fun get(index: IntArray): Long = ndArray.getLong(*widenToLongArray(index)) } -data class INDArrayDoubleStructure(override val ndArray: INDArray) : INDArrayStructure { +data class INDArrayDoubleStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { override fun elementsIterator(): Iterator> = INDArrayDoubleIterator(ndArray) override fun get(index: IntArray): Double = ndArray.getDouble(*index) + override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) } } -data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure { +data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { override fun elementsIterator(): Iterator> = INDArrayFloatIterator(ndArray) override fun get(index: IntArray): Float = ndArray.getFloat(*index) + override fun set(index: IntArray, value: Float): Unit = run { ndArray.putScalar(index, value) } } diff --git a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt index 239289262..77565856a 100644 --- a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt @@ -1,9 +1,9 @@ package scientifik.kmath.nd4j import org.nd4j.linalg.factory.Nd4j +import scientifik.kmath.structures.get import kotlin.test.Test import kotlin.test.assertEquals -import scientifik.kmath.structures.get internal class INDArrayStructureTest { @Test @@ -17,7 +17,7 @@ internal class INDArrayStructureTest { @Test fun testShape() { val nd = Nd4j.rand(10, 2, 3, 6)!! - val struct = INDArrayIntStructure(nd) + val struct = INDArrayLongStructure(nd) assertEquals(intArrayOf(10, 2, 3, 6).toList(), struct.shape.toList()) } @@ -33,7 +33,7 @@ internal class INDArrayStructureTest { @Test fun testDimension() { val nd = Nd4j.rand(8, 16, 3, 7, 1)!! - val struct = INDArrayIntStructure(nd) + val struct = INDArrayFloatStructure(nd) assertEquals(5, struct.dimension) } @@ -43,4 +43,12 @@ internal class INDArrayStructureTest { val struct = INDArrayIntStructure(nd) assertEquals(nd.getInt(0, 0, 0, 0), struct[0, 0, 0, 0]) } + + @Test + fun testSet() { + val nd = Nd4j.rand(17, 12, 4, 8)!! + val struct = INDArrayIntStructure(nd) + struct[intArrayOf(1, 2, 3, 4)] = 777 + assertEquals(777, struct[1, 2, 3, 4]) + } } From eb9d40fd2aed7342a5584609fdfb83718093d400 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 29 Jun 2020 00:29:43 +0700 Subject: [PATCH 014/199] Convert INDArray NDStructures implementations to inline classes, add tests to verify equals and hashCode --- .../scientifik.kmath.nd4j/INDArrayStructures.kt | 13 +++++++++---- .../kmath/nd4j/INDArrayStructureTest.kt | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt index f39d84716..66aa00fac 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt @@ -14,25 +14,30 @@ interface INDArrayStructure : NDStructure { override fun elements(): Sequence> = Sequence(::elementsIterator) } -data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { +inline class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { override fun elementsIterator(): Iterator> = INDArrayIntIterator(ndArray) override fun get(index: IntArray): Int = ndArray.getInt(*index) override fun set(index: IntArray, value: Int): Unit = run { ndArray.putScalar(index, value) } + override fun toString(): String = "INDArrayIntStructure(ndArray=$ndArray)" } -data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure { +inline class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure { override fun elementsIterator(): Iterator> = INDArrayLongIterator(ndArray) override fun get(index: IntArray): Long = ndArray.getLong(*widenToLongArray(index)) + override fun toString(): String = "INDArrayLongStructure(ndArray=$ndArray)" + } -data class INDArrayDoubleStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { +inline class INDArrayDoubleStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { override fun elementsIterator(): Iterator> = INDArrayDoubleIterator(ndArray) override fun get(index: IntArray): Double = ndArray.getDouble(*index) override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) } + override fun toString(): String = "INDArrayDoubleStructure(ndArray=$ndArray)" } -data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { +inline class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { override fun elementsIterator(): Iterator> = INDArrayFloatIterator(ndArray) override fun get(index: IntArray): Float = ndArray.getFloat(*index) override fun set(index: IntArray, value: Float): Unit = run { ndArray.putScalar(index, value) } + override fun toString(): String = "INDArrayFloatStructure(ndArray=$ndArray)" } diff --git a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt index 77565856a..ad1cbb585 100644 --- a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt @@ -4,6 +4,7 @@ import org.nd4j.linalg.factory.Nd4j import scientifik.kmath.structures.get import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertNotEquals internal class INDArrayStructureTest { @Test @@ -25,9 +26,25 @@ internal class INDArrayStructureTest { fun testEquals() { val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! val struct1 = INDArrayDoubleStructure(nd1) + assertEquals(struct1, struct1) + assertNotEquals(struct1, null as INDArrayDoubleStructure?) val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! val struct2 = INDArrayDoubleStructure(nd2) assertEquals(struct1, struct2) + assertEquals(struct2, struct1) + val nd3 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! + val struct3 = INDArrayDoubleStructure(nd3) + assertEquals(struct2, struct3) + assertEquals(struct1, struct3) + } + + @Test + fun testHashCode() { + val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! + val struct1 = INDArrayDoubleStructure(nd1) + val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! + val struct2 = INDArrayDoubleStructure(nd2) + assertEquals(struct1.hashCode(), struct2.hashCode()) } @Test From 783087982fbe93f60a2c20e7a3d50627b69b8b58 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 29 Jun 2020 02:50:34 +0700 Subject: [PATCH 015/199] Rollback making Structures inline, implement Algebras for NDArrayStructure --- .../scientifik.kmath.nd4j/INDArrayAlgebra.kt | 89 +++++++++++++++++++ .../INDArrayIterators.kt | 7 +- .../INDArrayStructures.kt | 25 +++--- .../kmath/nd4j/INDArrayAlgebraTest.kt | 30 +++++++ .../kmath/nd4j/INDArrayStructureTest.kt | 14 +-- 5 files changed, 147 insertions(+), 18 deletions(-) create mode 100644 kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt create mode 100644 kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt new file mode 100644 index 000000000..760e3d03e --- /dev/null +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt @@ -0,0 +1,89 @@ +package scientifik.kmath.nd4j + +import org.nd4j.linalg.api.ndarray.INDArray +import org.nd4j.linalg.factory.Nd4j +import scientifik.kmath.operations.* +import scientifik.kmath.structures.MutableNDStructure +import scientifik.kmath.structures.NDField +import scientifik.kmath.structures.NDRing + +interface INDArrayRing : + NDRing where F : Ring, N : INDArrayStructure, N : MutableNDStructure { + fun INDArray.wrap(): N + + override val zero: N + get() = Nd4j.zeros(*shape).wrap() + + override val one: N + get() = Nd4j.ones(*shape).wrap() + + override fun produce(initializer: F.(IntArray) -> T): N { + val struct = Nd4j.create(*shape).wrap() + struct.elements().map(Pair::first).forEach { struct[it] = elementContext.initializer(it) } + return struct + } + + override fun map(arg: N, transform: F.(T) -> T): N { + val new = Nd4j.create(*shape) + Nd4j.copy(arg.ndArray, new) + val newStruct = new.wrap() + newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } + return newStruct + } + + override fun mapIndexed(arg: N, transform: F.(index: IntArray, T) -> T): N { + val new = Nd4j.create(*shape).wrap() + new.elements().forEach { (idx, _) -> new[idx] = elementContext.transform(idx, arg[idx]) } + return new + } + + override fun combine(a: N, b: N, transform: F.(T, T) -> T): N { + val new = Nd4j.create(*shape).wrap() + new.elements().forEach { (idx, _) -> new[idx] = elementContext.transform(a[idx], b[idx]) } + return new + } + + override fun add(a: N, b: N): N = a.ndArray.addi(b.ndArray).wrap() + override fun N.minus(b: N): N = ndArray.subi(b.ndArray).wrap() + override fun N.unaryMinus(): N = ndArray.negi().wrap() + override fun multiply(a: N, b: N): N = a.ndArray.muli(b.ndArray).wrap() + override fun multiply(a: N, k: Number): N = a.ndArray.muli(k).wrap() + override fun N.div(k: Number): N = ndArray.divi(k).wrap() + override fun N.minus(b: Number): N = ndArray.subi(b).wrap() + override fun N.plus(b: Number): N = ndArray.addi(b).wrap() + override fun N.times(k: Number): N = ndArray.muli(k).wrap() +} + +interface INDArrayField : NDField, + INDArrayRing where F : Field, N : INDArrayStructure, N : MutableNDStructure { + override fun divide(a: N, b: N): N = a.ndArray.divi(b.ndArray).wrap() +} + +class RealINDArrayField(override val shape: IntArray, override val elementContext: Field = RealField) : + INDArrayField, INDArrayRealStructure> { + override fun INDArray.wrap(): INDArrayRealStructure = asRealStructure() + override fun INDArrayRealStructure.div(arg: Double): INDArrayRealStructure = ndArray.divi(arg).wrap() + override fun INDArrayRealStructure.plus(arg: Double): INDArrayRealStructure = ndArray.addi(arg).wrap() + override fun INDArrayRealStructure.div(k: Number): INDArrayRealStructure = ndArray.divi(k).wrap() + override fun INDArrayRealStructure.minus(arg: Double): INDArrayRealStructure = ndArray.subi(arg).wrap() + override fun INDArrayRealStructure.times(arg: Double): INDArrayRealStructure = ndArray.muli(arg).wrap() +} + +class FloatINDArrayField(override val shape: IntArray, override val elementContext: Field = FloatField) : + INDArrayField, INDArrayFloatStructure> { + override fun INDArray.wrap(): INDArrayFloatStructure = asFloatStructure() + override fun INDArrayFloatStructure.div(arg: Float): INDArrayFloatStructure = ndArray.divi(arg).wrap() + override fun INDArrayFloatStructure.plus(arg: Float): INDArrayFloatStructure = ndArray.addi(arg).wrap() + override fun INDArrayFloatStructure.div(k: Number): INDArrayFloatStructure = ndArray.divi(k).wrap() + override fun INDArrayFloatStructure.minus(arg: Float): INDArrayFloatStructure = ndArray.subi(arg).wrap() + override fun INDArrayFloatStructure.times(arg: Float): INDArrayFloatStructure = ndArray.muli(arg).wrap() +} + +class IntINDArrayRing(override val shape: IntArray, override val elementContext: Ring = IntRing) : + INDArrayRing, INDArrayIntStructure> { + override fun INDArray.wrap(): INDArrayIntStructure = asIntStructure() + override fun INDArrayIntStructure.plus(arg: Int): INDArrayIntStructure = ndArray.addi(arg).wrap() + override fun INDArrayIntStructure.div(k: Number): INDArrayIntStructure = ndArray.divi(k).wrap() + override fun INDArrayIntStructure.minus(arg: Int): INDArrayIntStructure = ndArray.subi(arg).wrap() + override fun INDArrayIntStructure.times(arg: Int): INDArrayIntStructure = ndArray.muli(arg).wrap() +} diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt index f6efdc0ba..115c78cb9 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt @@ -20,14 +20,19 @@ internal sealed class INDArrayIteratorBase(protected val iterateOver: INDArra } } -internal class INDArrayDoubleIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { +internal class INDArrayRealIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray): Double = iterateOver.getDouble(*indices) } +internal fun INDArray.realIterator(): INDArrayRealIterator = INDArrayRealIterator(this) + internal class INDArrayLongIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getLong(*indices) } +// TODO +//internal fun INDArray.longI + internal class INDArrayIntIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getInt(*narrowToIntArray(indices)) } diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt index 66aa00fac..351110485 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt @@ -14,30 +14,35 @@ interface INDArrayStructure : NDStructure { override fun elements(): Sequence> = Sequence(::elementsIterator) } -inline class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { +data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { override fun elementsIterator(): Iterator> = INDArrayIntIterator(ndArray) override fun get(index: IntArray): Int = ndArray.getInt(*index) override fun set(index: IntArray, value: Int): Unit = run { ndArray.putScalar(index, value) } - override fun toString(): String = "INDArrayIntStructure(ndArray=$ndArray)" } -inline class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure { +fun INDArray.asIntStructure(): INDArrayIntStructure = INDArrayIntStructure(this) + +data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure { override fun elementsIterator(): Iterator> = INDArrayLongIterator(ndArray) override fun get(index: IntArray): Long = ndArray.getLong(*widenToLongArray(index)) - override fun toString(): String = "INDArrayLongStructure(ndArray=$ndArray)" - } -inline class INDArrayDoubleStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { - override fun elementsIterator(): Iterator> = INDArrayDoubleIterator(ndArray) +fun INDArray.asLongStructure(): INDArrayLongStructure = INDArrayLongStructure(this) + +data class INDArrayRealStructure(override val ndArray: INDArray) : INDArrayStructure, + MutableNDStructure { + override fun elementsIterator(): Iterator> = INDArrayRealIterator(ndArray) override fun get(index: IntArray): Double = ndArray.getDouble(*index) override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) } - override fun toString(): String = "INDArrayDoubleStructure(ndArray=$ndArray)" } -inline class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { +fun INDArray.asRealStructure(): INDArrayRealStructure = INDArrayRealStructure(this) + +data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure, + MutableNDStructure { override fun elementsIterator(): Iterator> = INDArrayFloatIterator(ndArray) override fun get(index: IntArray): Float = ndArray.getFloat(*index) override fun set(index: IntArray, value: Float): Unit = run { ndArray.putScalar(index, value) } - override fun toString(): String = "INDArrayFloatStructure(ndArray=$ndArray)" } + +fun INDArray.asFloatStructure(): INDArrayFloatStructure = INDArrayFloatStructure(this) diff --git a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt new file mode 100644 index 000000000..f971e7871 --- /dev/null +++ b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt @@ -0,0 +1,30 @@ +package scientifik.kmath.nd4j + +import org.nd4j.linalg.factory.Nd4j +import scientifik.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class INDArrayAlgebraTest { + @Test + fun testProduce() { + val res = (RealINDArrayField(intArrayOf(2, 2))) { produce { it.sum().toDouble() } } + val expected = Nd4j.create(2, 2)!!.asRealStructure() + expected[intArrayOf(0, 0)] = 0.0 + expected[intArrayOf(0, 1)] = 1.0 + expected[intArrayOf(1, 0)] = 1.0 + expected[intArrayOf(1, 1)] = 2.0 + assertEquals(expected, res) + } + + @Test + fun testMap() { + val res = (IntINDArrayRing(intArrayOf(2, 2))) { map(one) { it + it * 2 } } + val expected = Nd4j.create(2, 2)!!.asIntStructure() + expected[intArrayOf(0, 0)] = 3 + expected[intArrayOf(0, 1)] = 3 + expected[intArrayOf(1, 0)] = 3 + expected[intArrayOf(1, 1)] = 3 + assertEquals(expected, res) + } +} diff --git a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt index ad1cbb585..dfede6d32 100644 --- a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt @@ -10,7 +10,7 @@ internal class INDArrayStructureTest { @Test fun testElements() { val nd = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct = INDArrayDoubleStructure(nd) + val struct = INDArrayRealStructure(nd) val res = struct.elements().map(Pair::second).toList() assertEquals(listOf(1.0, 2.0, 3.0), res) } @@ -25,15 +25,15 @@ internal class INDArrayStructureTest { @Test fun testEquals() { val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct1 = INDArrayDoubleStructure(nd1) + val struct1 = INDArrayRealStructure(nd1) assertEquals(struct1, struct1) - assertNotEquals(struct1, null as INDArrayDoubleStructure?) + assertNotEquals(struct1, null as INDArrayRealStructure?) val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct2 = INDArrayDoubleStructure(nd2) + val struct2 = INDArrayRealStructure(nd2) assertEquals(struct1, struct2) assertEquals(struct2, struct1) val nd3 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct3 = INDArrayDoubleStructure(nd3) + val struct3 = INDArrayRealStructure(nd3) assertEquals(struct2, struct3) assertEquals(struct1, struct3) } @@ -41,9 +41,9 @@ internal class INDArrayStructureTest { @Test fun testHashCode() { val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct1 = INDArrayDoubleStructure(nd1) + val struct1 = INDArrayRealStructure(nd1) val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct2 = INDArrayDoubleStructure(nd2) + val struct2 = INDArrayRealStructure(nd2) assertEquals(struct1.hashCode(), struct2.hashCode()) } From d7949fdb01ac96a617bf7bf8e3c2579de481b946 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 29 Jun 2020 03:39:37 +0700 Subject: [PATCH 016/199] Remove duplicated code --- .../src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt index 760e3d03e..a4ecd09e5 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt @@ -64,7 +64,6 @@ class RealINDArrayField(override val shape: IntArray, override val elementContex override fun INDArray.wrap(): INDArrayRealStructure = asRealStructure() override fun INDArrayRealStructure.div(arg: Double): INDArrayRealStructure = ndArray.divi(arg).wrap() override fun INDArrayRealStructure.plus(arg: Double): INDArrayRealStructure = ndArray.addi(arg).wrap() - override fun INDArrayRealStructure.div(k: Number): INDArrayRealStructure = ndArray.divi(k).wrap() override fun INDArrayRealStructure.minus(arg: Double): INDArrayRealStructure = ndArray.subi(arg).wrap() override fun INDArrayRealStructure.times(arg: Double): INDArrayRealStructure = ndArray.muli(arg).wrap() } @@ -74,7 +73,6 @@ class FloatINDArrayField(override val shape: IntArray, override val elementConte override fun INDArray.wrap(): INDArrayFloatStructure = asFloatStructure() override fun INDArrayFloatStructure.div(arg: Float): INDArrayFloatStructure = ndArray.divi(arg).wrap() override fun INDArrayFloatStructure.plus(arg: Float): INDArrayFloatStructure = ndArray.addi(arg).wrap() - override fun INDArrayFloatStructure.div(k: Number): INDArrayFloatStructure = ndArray.divi(k).wrap() override fun INDArrayFloatStructure.minus(arg: Float): INDArrayFloatStructure = ndArray.subi(arg).wrap() override fun INDArrayFloatStructure.times(arg: Float): INDArrayFloatStructure = ndArray.muli(arg).wrap() } @@ -83,7 +81,6 @@ class IntINDArrayRing(override val shape: IntArray, override val elementContext: INDArrayRing, INDArrayIntStructure> { override fun INDArray.wrap(): INDArrayIntStructure = asIntStructure() override fun INDArrayIntStructure.plus(arg: Int): INDArrayIntStructure = ndArray.addi(arg).wrap() - override fun INDArrayIntStructure.div(k: Number): INDArrayIntStructure = ndArray.divi(k).wrap() override fun INDArrayIntStructure.minus(arg: Int): INDArrayIntStructure = ndArray.subi(arg).wrap() override fun INDArrayIntStructure.times(arg: Int): INDArrayIntStructure = ndArray.muli(arg).wrap() } From 8a8b314d0a60c027f6abcfcff8d0d924613cd0d1 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 29 Jun 2020 03:48:11 +0700 Subject: [PATCH 017/199] Optimize reverse division for FP INDArrayAlgebra --- .../scientifik.kmath.nd4j/INDArrayAlgebra.kt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt index a4ecd09e5..44d8f6611 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt @@ -7,8 +7,8 @@ import scientifik.kmath.structures.MutableNDStructure import scientifik.kmath.structures.NDField import scientifik.kmath.structures.NDRing -interface INDArrayRing : - NDRing where F : Ring, N : INDArrayStructure, N : MutableNDStructure { +interface INDArrayRing : + NDRing where R : Ring, N : INDArrayStructure, N : MutableNDStructure { fun INDArray.wrap(): N override val zero: N @@ -17,13 +17,13 @@ interface INDArrayRing : override val one: N get() = Nd4j.ones(*shape).wrap() - override fun produce(initializer: F.(IntArray) -> T): N { + override fun produce(initializer: R.(IntArray) -> T): N { val struct = Nd4j.create(*shape).wrap() struct.elements().map(Pair::first).forEach { struct[it] = elementContext.initializer(it) } return struct } - override fun map(arg: N, transform: F.(T) -> T): N { + override fun map(arg: N, transform: R.(T) -> T): N { val new = Nd4j.create(*shape) Nd4j.copy(arg.ndArray, new) val newStruct = new.wrap() @@ -31,13 +31,13 @@ interface INDArrayRing : return newStruct } - override fun mapIndexed(arg: N, transform: F.(index: IntArray, T) -> T): N { + override fun mapIndexed(arg: N, transform: R.(index: IntArray, T) -> T): N { val new = Nd4j.create(*shape).wrap() new.elements().forEach { (idx, _) -> new[idx] = elementContext.transform(idx, arg[idx]) } return new } - override fun combine(a: N, b: N, transform: F.(T, T) -> T): N { + override fun combine(a: N, b: N, transform: R.(T, T) -> T): N { val new = Nd4j.create(*shape).wrap() new.elements().forEach { (idx, _) -> new[idx] = elementContext.transform(a[idx], b[idx]) } return new @@ -66,6 +66,7 @@ class RealINDArrayField(override val shape: IntArray, override val elementContex override fun INDArrayRealStructure.plus(arg: Double): INDArrayRealStructure = ndArray.addi(arg).wrap() override fun INDArrayRealStructure.minus(arg: Double): INDArrayRealStructure = ndArray.subi(arg).wrap() override fun INDArrayRealStructure.times(arg: Double): INDArrayRealStructure = ndArray.muli(arg).wrap() + override fun Double.div(arg: INDArrayRealStructure): INDArrayRealStructure = arg.ndArray.rdivi(this).wrap() } class FloatINDArrayField(override val shape: IntArray, override val elementContext: Field = FloatField) : @@ -75,6 +76,7 @@ class FloatINDArrayField(override val shape: IntArray, override val elementConte override fun INDArrayFloatStructure.plus(arg: Float): INDArrayFloatStructure = ndArray.addi(arg).wrap() override fun INDArrayFloatStructure.minus(arg: Float): INDArrayFloatStructure = ndArray.subi(arg).wrap() override fun INDArrayFloatStructure.times(arg: Float): INDArrayFloatStructure = ndArray.muli(arg).wrap() + override fun Float.div(arg: INDArrayFloatStructure): INDArrayFloatStructure = arg.ndArray.rdivi(this).wrap() } class IntINDArrayRing(override val shape: IntArray, override val elementContext: Ring = IntRing) : From 23b2ba9950cb4fab33f0b53565ae762cfa2f7a45 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 29 Jun 2020 03:49:29 +0700 Subject: [PATCH 018/199] Optimize reverse division for FP INDArrayAlgebra --- .../src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt index 44d8f6611..f476af0d5 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt @@ -57,6 +57,7 @@ interface INDArrayRing : interface INDArrayField : NDField, INDArrayRing where F : Field, N : INDArrayStructure, N : MutableNDStructure { override fun divide(a: N, b: N): N = a.ndArray.divi(b.ndArray).wrap() + override fun Number.div(b: N): N = b.ndArray.rdivi(this).wrap() } class RealINDArrayField(override val shape: IntArray, override val elementContext: Field = RealField) : From d87dd3e717cc18851b7922d1e31b7ac81698c082 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 29 Jun 2020 21:31:08 +0700 Subject: [PATCH 019/199] Refactor array functions --- .../kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt | 11 +++++++---- .../scientifik.kmath.nd4j/INDArrayStructures.kt | 4 ++-- .../src/main/kotlin/scientifik.kmath.nd4j/arrays.kt | 4 ++-- .../scientifik/kmath/nd4j/INDArrayAlgebraTest.kt | 11 +++++++++++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt index 115c78cb9..bba5089a1 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt @@ -16,7 +16,7 @@ internal sealed class INDArrayIteratorBase(protected val iterateOver: INDArra else Shape.ind2sub(iterateOver, i++.toLong())!! - return narrowToIntArray(la) to getSingle(la) + return la.toIntArray() to getSingle(la) } } @@ -30,13 +30,16 @@ internal class INDArrayLongIterator(iterateOver: INDArray) : INDArrayIteratorBas override fun getSingle(indices: LongArray) = iterateOver.getLong(*indices) } -// TODO -//internal fun INDArray.longI +internal fun INDArray.longIterator(): INDArrayLongIterator = INDArrayLongIterator(this) internal class INDArrayIntIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { - override fun getSingle(indices: LongArray) = iterateOver.getInt(*narrowToIntArray(indices)) + override fun getSingle(indices: LongArray) = iterateOver.getInt(*indices.toIntArray()) } +internal fun INDArray.intIterator(): INDArrayIntIterator = INDArrayIntIterator(this) + internal class INDArrayFloatIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getFloat(*indices) } + +internal fun INDArray.floatIterator() = INDArrayFloatIterator(this) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt index 351110485..ef7436285 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt @@ -8,7 +8,7 @@ interface INDArrayStructure : NDStructure { val ndArray: INDArray override val shape: IntArray - get() = narrowToIntArray(ndArray.shape()) + get() = ndArray.shape().toIntArray() fun elementsIterator(): Iterator> override fun elements(): Sequence> = Sequence(::elementsIterator) @@ -24,7 +24,7 @@ fun INDArray.asIntStructure(): INDArrayIntStructure = INDArrayIntStructure(this) data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure { override fun elementsIterator(): Iterator> = INDArrayLongIterator(ndArray) - override fun get(index: IntArray): Long = ndArray.getLong(*widenToLongArray(index)) + override fun get(index: IntArray): Long = ndArray.getLong(*index.toLongArray()) } fun INDArray.asLongStructure(): INDArrayLongStructure = INDArrayLongStructure(this) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/arrays.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/arrays.kt index 3d5062a4f..269fc89c2 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/arrays.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/arrays.kt @@ -1,4 +1,4 @@ package scientifik.kmath.nd4j -internal fun widenToLongArray(ia: IntArray): LongArray = LongArray(ia.size) { ia[it].toLong() } -internal fun narrowToIntArray(la: LongArray): IntArray = IntArray(la.size) { la[it].toInt() } +internal fun IntArray.toLongArray(): LongArray = LongArray(size) { this[it].toLong() } +internal fun LongArray.toIntArray(): IntArray = IntArray(size) { this[it].toInt() } diff --git a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt index f971e7871..4aa40c233 100644 --- a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt @@ -27,4 +27,15 @@ internal class INDArrayAlgebraTest { expected[intArrayOf(1, 1)] = 3 assertEquals(expected, res) } + + @Test + fun testAdd() { + val res = (IntINDArrayRing(intArrayOf(2, 2))) { one + 25 } + val expected = Nd4j.create(2, 2)!!.asIntStructure() + expected[intArrayOf(0, 0)] = 26 + expected[intArrayOf(0, 1)] = 26 + expected[intArrayOf(1, 0)] = 26 + expected[intArrayOf(1, 1)] = 26 + assertEquals(expected, res) + } } From f54e5679cf261dceeff58531e929d3fd0bd04549 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 29 Jun 2020 22:06:13 +0700 Subject: [PATCH 020/199] Add README.md for kmath-nd4j --- kmath-nd4j/README.md | 73 +++++++++++++++++++ .../INDArrayStructures.kt | 8 +- 2 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 kmath-nd4j/README.md diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md new file mode 100644 index 000000000..63687a880 --- /dev/null +++ b/kmath-nd4j/README.md @@ -0,0 +1,73 @@ +# ND4J NDStructure implementation (`kmath-nd4j`) + +This subproject implements the following features: + +- NDStructure wrapper for INDArray. +- Optimized NDRing implementation for INDArray storing Ints. +- Optimized NDField implementation for INDArray storing Floats and Doubles. + +> #### Artifact: +> This module is distributed in the artifact `scientifik:kmath-nd4j:0.1.4-dev-8`. +> +> **Gradle:** +> +> ```gradle +> repositories { +> maven { url 'https://dl.bintray.com/mipt-npm/scientifik' } +> maven { url 'https://dl.bintray.com/mipt-npm/dev' } +> } +> +> dependencies { +> implementation 'scientifik:kmath-nd4j:0.1.4-dev-8' +> } +> ``` +> **Gradle Kotlin DSL:** +> +> ```kotlin +> repositories { +> maven("https://dl.bintray.com/mipt-npm/scientifik") +> maven("https://dl.bintray.com/mipt-npm/dev") +> } +> +> dependencies { +> implementation("scientifik:kmath-nd4j:0.1.4-dev-8") +> } +> ``` +> + +## Examples + +NDStructure wrapper for INDArray: + +```kotlin +import org.nd4j.linalg.factory.* +import scientifik.kmath.nd4j.* +import scientifik.kmath.structures.* + +val array = Nd4j.ones(2, 2)!!.asRealStructure() +println(array[0, 0]) // 1.0 +array[intArrayOf(0, 0)] = 24.0 +println(array[0, 0]) // 24.0 +``` + +Fast element-wise arithmetics for INDArray: + +```kotlin +import org.nd4j.linalg.factory.* +import scientifik.kmath.nd4j.* +import scientifik.kmath.operations.* + +val field = RealINDArrayField(intArrayOf(2, 2)) +val array = Nd4j.rand(2, 2)!!.asRealStructure() + +val res = field { + (25.0 / array + 20) * 4 +} + +println(res.ndArray) +// [[ 250.6449, 428.5840], +// [ 269.7913, 202.2077]] +``` + + +Contributed by [Iaroslav Postovalov](https://github.com/CommanderTvis). diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt index ef7436285..06b0354d8 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt @@ -15,7 +15,7 @@ interface INDArrayStructure : NDStructure { } data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { - override fun elementsIterator(): Iterator> = INDArrayIntIterator(ndArray) + override fun elementsIterator(): Iterator> = ndArray.intIterator() override fun get(index: IntArray): Int = ndArray.getInt(*index) override fun set(index: IntArray, value: Int): Unit = run { ndArray.putScalar(index, value) } } @@ -23,7 +23,7 @@ data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStruct fun INDArray.asIntStructure(): INDArrayIntStructure = INDArrayIntStructure(this) data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure { - override fun elementsIterator(): Iterator> = INDArrayLongIterator(ndArray) + override fun elementsIterator(): Iterator> = ndArray.longIterator() override fun get(index: IntArray): Long = ndArray.getLong(*index.toLongArray()) } @@ -31,7 +31,7 @@ fun INDArray.asLongStructure(): INDArrayLongStructure = INDArrayLongStructure(th data class INDArrayRealStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { - override fun elementsIterator(): Iterator> = INDArrayRealIterator(ndArray) + override fun elementsIterator(): Iterator> = ndArray.realIterator() override fun get(index: IntArray): Double = ndArray.getDouble(*index) override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) } } @@ -40,7 +40,7 @@ fun INDArray.asRealStructure(): INDArrayRealStructure = INDArrayRealStructure(th data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { - override fun elementsIterator(): Iterator> = INDArrayFloatIterator(ndArray) + override fun elementsIterator(): Iterator> = ndArray.floatIterator() override fun get(index: IntArray): Float = ndArray.getFloat(*index) override fun set(index: IntArray, value: Float): Unit = run { ndArray.putScalar(index, value) } } From bf071bcdc1f1040bf644fe9638827c3ffe36491e Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 29 Jun 2020 22:30:08 +0700 Subject: [PATCH 021/199] Minor refactor --- kmath-nd4j/README.md | 2 +- .../scientifik.kmath.nd4j/INDArrayAlgebra.kt | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 63687a880..ad76799c3 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -50,7 +50,7 @@ array[intArrayOf(0, 0)] = 24.0 println(array[0, 0]) // 24.0 ``` -Fast element-wise arithmetics for INDArray: +Fast element-wise and in-place arithmetics for INDArray: ```kotlin import org.nd4j.linalg.factory.* diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt index f476af0d5..14fe202c3 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt @@ -9,24 +9,22 @@ import scientifik.kmath.structures.NDRing interface INDArrayRing : NDRing where R : Ring, N : INDArrayStructure, N : MutableNDStructure { - fun INDArray.wrap(): N - override val zero: N get() = Nd4j.zeros(*shape).wrap() override val one: N get() = Nd4j.ones(*shape).wrap() + fun INDArray.wrap(): N + override fun produce(initializer: R.(IntArray) -> T): N { - val struct = Nd4j.create(*shape).wrap() + val struct = Nd4j.create(*shape)!!.wrap() struct.elements().map(Pair::first).forEach { struct[it] = elementContext.initializer(it) } return struct } override fun map(arg: N, transform: R.(T) -> T): N { - val new = Nd4j.create(*shape) - Nd4j.copy(arg.ndArray, new) - val newStruct = new.wrap() + val newStruct = arg.ndArray.dup().wrap() newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } return newStruct } @@ -52,6 +50,7 @@ interface INDArrayRing : override fun N.minus(b: Number): N = ndArray.subi(b).wrap() override fun N.plus(b: Number): N = ndArray.addi(b).wrap() override fun N.times(k: Number): N = ndArray.muli(k).wrap() + override fun Number.minus(b: N): N = b.ndArray.rsubi(this).wrap() } interface INDArrayField : NDField, @@ -61,13 +60,14 @@ interface INDArrayField : NDField, } class RealINDArrayField(override val shape: IntArray, override val elementContext: Field = RealField) : - INDArrayField, INDArrayRealStructure> { + INDArrayField, INDArrayRealStructure> { override fun INDArray.wrap(): INDArrayRealStructure = asRealStructure() override fun INDArrayRealStructure.div(arg: Double): INDArrayRealStructure = ndArray.divi(arg).wrap() override fun INDArrayRealStructure.plus(arg: Double): INDArrayRealStructure = ndArray.addi(arg).wrap() override fun INDArrayRealStructure.minus(arg: Double): INDArrayRealStructure = ndArray.subi(arg).wrap() override fun INDArrayRealStructure.times(arg: Double): INDArrayRealStructure = ndArray.muli(arg).wrap() override fun Double.div(arg: INDArrayRealStructure): INDArrayRealStructure = arg.ndArray.rdivi(this).wrap() + override fun Double.minus(arg: INDArrayRealStructure): INDArrayRealStructure = arg.ndArray.rsubi(this).wrap() } class FloatINDArrayField(override val shape: IntArray, override val elementContext: Field = FloatField) : @@ -78,6 +78,7 @@ class FloatINDArrayField(override val shape: IntArray, override val elementConte override fun INDArrayFloatStructure.minus(arg: Float): INDArrayFloatStructure = ndArray.subi(arg).wrap() override fun INDArrayFloatStructure.times(arg: Float): INDArrayFloatStructure = ndArray.muli(arg).wrap() override fun Float.div(arg: INDArrayFloatStructure): INDArrayFloatStructure = arg.ndArray.rdivi(this).wrap() + override fun Float.minus(arg: INDArrayFloatStructure): INDArrayFloatStructure = arg.ndArray.rsubi(this).wrap() } class IntINDArrayRing(override val shape: IntArray, override val elementContext: Ring = IntRing) : @@ -86,4 +87,5 @@ class IntINDArrayRing(override val shape: IntArray, override val elementContext: override fun INDArrayIntStructure.plus(arg: Int): INDArrayIntStructure = ndArray.addi(arg).wrap() override fun INDArrayIntStructure.minus(arg: Int): INDArrayIntStructure = ndArray.subi(arg).wrap() override fun INDArrayIntStructure.times(arg: Int): INDArrayIntStructure = ndArray.muli(arg).wrap() + override fun Int.minus(arg: INDArrayIntStructure): INDArrayIntStructure = arg.ndArray.rsubi(this).wrap() } From 5cd58a399d3e665c8f4972e1fbf58144f7ba89e6 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Tue, 11 Aug 2020 16:18:13 +0700 Subject: [PATCH 022/199] Add .space.kts --- .space.kts | 1 + 1 file changed, 1 insertion(+) create mode 100644 .space.kts diff --git a/.space.kts b/.space.kts new file mode 100644 index 000000000..9dda0cbf7 --- /dev/null +++ b/.space.kts @@ -0,0 +1 @@ +job("Build") { gradlew("openjdk:11", "build") } From 7157878485236ee88688053b6313b710891c0c03 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sat, 15 Aug 2020 18:35:16 +0700 Subject: [PATCH 023/199] Update changelog, document kmath-nd4j, refactor iterators, correct algebra mistakes, separate INDArrayStructureRing to Space, Ring and Algebra --- CHANGELOG.md | 1 + .../kmath/operations/AlgebraElements.kt | 6 +- .../kmath/structures/BufferedNDElement.kt | 6 +- .../scientifik/kmath/structures/NDAlgebra.kt | 170 ++++++++--- kmath-nd4j/README.md | 8 +- .../scientifik.kmath.nd4j/INDArrayAlgebra.kt | 286 ++++++++++++++---- .../INDArrayIterators.kt | 35 ++- .../INDArrayStructures.kt | 50 ++- 8 files changed, 448 insertions(+), 114 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26f9e33ec..e9afb6c26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Blocking chains in `kmath-coroutines` - Full hyperbolic functions support and default implementations within `ExtendedField` - Norm support for `Complex` +- ND4J support module submitting `NDStructure` and `NDAlgebra` over `INDArray`. ### Changed - BigInteger and BigDecimal algebra: JBigDecimalField has companion object with default math context; minor optimizations diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt index 197897c14..e1d50c4f0 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt @@ -74,9 +74,9 @@ interface SpaceElement, S : Space> : MathElement /** * The element of [Ring]. * - * @param T the type of space operation results. + * @param T the type of ring operation results. * @param I self type of the element. Needed for static type checking. - * @param R the type of space. + * @param R the type of ring. */ interface RingElement, R : Ring> : SpaceElement { /** @@ -91,7 +91,7 @@ interface RingElement, R : Ring> : SpaceElement>( override val context: BufferedNDField, override val buffer: Buffer ) : BufferedNDElement(), FieldElement, BufferedNDFieldElement, BufferedNDField> { - override fun unwrap(): NDBuffer = this override fun NDBuffer.wrap(): BufferedNDFieldElement { @@ -56,8 +55,9 @@ class BufferedNDFieldElement>( /** * Element by element application of any operation on elements to the whole array. Just like in numpy. */ -operator fun > Function1.invoke(ndElement: BufferedNDElement): MathElement> = - ndElement.context.run { map(ndElement) { invoke(it) }.toElement() } +operator fun > Function1.invoke( + ndElement: BufferedNDElement +): MathElement> = ndElement.context.run { map(ndElement) { invoke(it) }.toElement() } /* plus and minus */ diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt index f09db3c72..14c23a81a 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt @@ -5,56 +5,78 @@ import scientifik.kmath.operations.Field import scientifik.kmath.operations.Ring import scientifik.kmath.operations.Space - /** - * An exception is thrown when the expected ans actual shape of NDArray differs + * An exception is thrown when the expected ans actual shape of NDArray differs. + * + * @property expected the expected shape. + * @property actual the actual shape. */ -class ShapeMismatchException(val expected: IntArray, val actual: IntArray) : RuntimeException() - +class ShapeMismatchException(val expected: IntArray, val actual: IntArray) : + RuntimeException("Shape ${actual.contentToString()} doesn't fit in expected shape ${expected.contentToString()}.") /** - * The base interface for all nd-algebra implementations - * @param T the type of nd-structure element - * @param C the type of the element context - * @param N the type of the structure + * The base interface for all ND-algebra implementations. + * + * @param T the type of ND-structure element. + * @param C the type of the element context. + * @param N the type of the structure. */ interface NDAlgebra> { + /** + * The shape of ND-structures this algebra operates on. + */ val shape: IntArray + + /** + * The algebra over elements of ND structure. + */ val elementContext: C /** - * Produce a new [N] structure using given initializer function + * Produces a new [N] structure using given initializer function. */ fun produce(initializer: C.(IntArray) -> T): N /** - * Map elements from one structure to another one + * Maps elements from one structure to another one by applying [transform] to them. */ fun map(arg: N, transform: C.(T) -> T): N /** - * Map indexed elements + * Maps elements from one structure to another one by applying [transform] to them alongside with their indices. */ fun mapIndexed(arg: N, transform: C.(index: IntArray, T) -> T): N /** - * Combine two structures into one + * Combines two structures into one. */ fun combine(a: N, b: N, transform: C.(T, T) -> T): N /** - * Check if given elements are consistent with this context + * Checks if given element is consistent with this context. + * + * @param element the structure to check. + * @return the valid structure. */ - fun check(vararg elements: N) { - elements.forEach { - if (!shape.contentEquals(it.shape)) { - throw ShapeMismatchException(shape, it.shape) - } - } + fun check(element: N): N { + if (!element.shape.contentEquals(shape)) throw ShapeMismatchException(shape, element.shape) + return element } /** - * element-by-element invoke a function working on [T] on a [NDStructure] + * Checks if given elements are consistent with this context. + * + * @param elements the structures to check. + * @return the array of valid structures. + */ + fun check(vararg elements: N): Array = elements + .map(NDStructure::shape) + .singleOrNull { !shape.contentEquals(it) } + ?.let { throw ShapeMismatchException(shape, it) } + ?: elements + + /** + * Element-wise invocation of function working on [T] on a [NDStructure]. */ operator fun Function1.invoke(structure: N): N = map(structure) { value -> this@invoke(value) } @@ -62,43 +84,107 @@ interface NDAlgebra> { } /** - * An nd-space over element space + * Space of [NDStructure]. + * + * @param T the type of the element contained in ND structure. + * @param N the type of ND structure. + * @param S the type of space of structure elements. */ interface NDSpace, N : NDStructure> : Space, NDAlgebra { /** - * Element-by-element addition + * Element-wise addition. + * + * @param a the addend. + * @param b the augend. + * @return the sum. */ override fun add(a: N, b: N): N = combine(a, b) { aValue, bValue -> add(aValue, bValue) } /** - * Multiply all elements by constant + * Element-wise multiplication by scalar. + * + * @param a the multiplicand. + * @param k the multiplier. + * @return the product. */ override fun multiply(a: N, k: Number): N = map(a) { multiply(it, k) } - //TODO move to extensions after KEEP-176 + // TODO move to extensions after KEEP-176 + + /** + * Adds an ND structure to an element of it. + * + * @receiver the addend. + * @param arg the augend. + * @return the sum. + */ operator fun N.plus(arg: T): N = map(this) { value -> add(arg, value) } + /** + * Subtracts an element from ND structure of it. + * + * @receiver the dividend. + * @param arg the divisor. + * @return the quotient. + */ operator fun N.minus(arg: T): N = map(this) { value -> add(arg, -value) } + /** + * Adds an element to ND structure of it. + * + * @receiver the addend. + * @param arg the augend. + * @return the sum. + */ operator fun T.plus(arg: N): N = map(arg) { value -> add(this@plus, value) } + + /** + * Subtracts an ND structure from an element of it. + * + * @receiver the dividend. + * @param arg the divisor. + * @return the quotient. + */ operator fun T.minus(arg: N): N = map(arg) { value -> add(-this@minus, value) } companion object } /** - * An nd-ring over element ring + * Ring of [NDStructure]. + * + * @param T the type of the element contained in ND structure. + * @param N the type of ND structure. + * @param R the type of ring of structure elements. */ interface NDRing, N : NDStructure> : Ring, NDSpace { - /** - * Element-by-element multiplication + * Element-wise multiplication. + * + * @param a the multiplicand. + * @param b the multiplier. + * @return the product. */ override fun multiply(a: N, b: N): N = combine(a, b) { aValue, bValue -> multiply(aValue, bValue) } //TODO move to extensions after KEEP-176 + + /** + * Multiplies an ND structure by an element of it. + * + * @receiver the multiplicand. + * @param arg the multiplier. + * @return the product. + */ operator fun N.times(arg: T): N = map(this) { value -> multiply(arg, value) } + /** + * Multiplies an element by a ND structure of it. + * + * @receiver the multiplicand. + * @param arg the multiplier. + * @return the product. + */ operator fun T.times(arg: N): N = map(arg) { value -> multiply(this@times, value) } companion object @@ -109,31 +195,47 @@ interface NDRing, N : NDStructure> : Ring, NDSpace * * @param T the type of the element contained in ND structure. * @param N the type of ND structure. - * @param F field of structure elements. + * @param F the type field of structure elements. */ interface NDField, N : NDStructure> : Field, NDRing { - /** - * Element-by-element division + * Element-wise division. + * + * @param a the dividend. + * @param b the divisor. + * @return the quotient. */ override fun divide(a: N, b: N): N = combine(a, b) { aValue, bValue -> divide(aValue, bValue) } //TODO move to extensions after KEEP-176 + /** + * Divides an ND structure by an element of it. + * + * @receiver the dividend. + * @param arg the divisor. + * @return the quotient. + */ operator fun N.div(arg: T): N = map(this) { value -> divide(arg, value) } + /** + * Divides an element by an ND structure of it. + * + * @receiver the dividend. + * @param arg the divisor. + * @return the quotient. + */ operator fun T.div(arg: N): N = map(arg) { divide(it, this@div) } companion object { - - private val realNDFieldCache = HashMap() + private val realNDFieldCache: MutableMap = hashMapOf() /** - * Create a nd-field for [Double] values or pull it from cache if it was created previously + * Create a nd-field for [Double] values or pull it from cache if it was created previously. */ fun real(vararg shape: Int): RealNDField = realNDFieldCache.getOrPut(shape) { RealNDField(shape) } /** - * Create a nd-field with boxing generic buffer + * Create a ND field with boxing generic buffer. */ fun > boxing( field: F, diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index ad76799c3..f8ca5eed2 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -3,8 +3,8 @@ This subproject implements the following features: - NDStructure wrapper for INDArray. -- Optimized NDRing implementation for INDArray storing Ints. -- Optimized NDField implementation for INDArray storing Floats and Doubles. +- Optimized NDRing implementations for INDArray storing Ints and Longs. +- Optimized NDField implementations for INDArray storing Floats and Doubles. > #### Artifact: > This module is distributed in the artifact `scientifik:kmath-nd4j:0.1.4-dev-8`. @@ -44,7 +44,7 @@ import org.nd4j.linalg.factory.* import scientifik.kmath.nd4j.* import scientifik.kmath.structures.* -val array = Nd4j.ones(2, 2)!!.asRealStructure() +val array = Nd4j.ones(2, 2).asRealStructure() println(array[0, 0]) // 1.0 array[intArrayOf(0, 0)] = 24.0 println(array[0, 0]) // 24.0 @@ -58,7 +58,7 @@ import scientifik.kmath.nd4j.* import scientifik.kmath.operations.* val field = RealINDArrayField(intArrayOf(2, 2)) -val array = Nd4j.rand(2, 2)!!.asRealStructure() +val array = Nd4j.rand(2, 2).asRealStructure() val res = field { (25.0 / array + 20) * 4 diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt index 14fe202c3..c24e2ece6 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt @@ -3,89 +3,271 @@ package scientifik.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray import org.nd4j.linalg.factory.Nd4j import scientifik.kmath.operations.* -import scientifik.kmath.structures.MutableNDStructure -import scientifik.kmath.structures.NDField -import scientifik.kmath.structures.NDRing - -interface INDArrayRing : - NDRing where R : Ring, N : INDArrayStructure, N : MutableNDStructure { - override val zero: N - get() = Nd4j.zeros(*shape).wrap() - - override val one: N - get() = Nd4j.ones(*shape).wrap() +import scientifik.kmath.structures.* +/** + * Represents [NDAlgebra] over [INDArrayAlgebra]. + * + * @param T the type of ND-structure element. + * @param C the type of the element context. + * @param N the type of the structure. + */ +interface INDArrayAlgebra : NDAlgebra where N : INDArrayStructure, N : MutableNDStructure { + /** + * Wraps [INDArray] to [N]. + */ fun INDArray.wrap(): N - override fun produce(initializer: R.(IntArray) -> T): N { + override fun produce(initializer: C.(IntArray) -> T): N { val struct = Nd4j.create(*shape)!!.wrap() - struct.elements().map(Pair::first).forEach { struct[it] = elementContext.initializer(it) } + struct.indicesIterator().forEach { struct[it] = elementContext.initializer(it) } return struct } - override fun map(arg: N, transform: R.(T) -> T): N { + override fun map(arg: N, transform: C.(T) -> T): N { + check(arg) val newStruct = arg.ndArray.dup().wrap() newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } return newStruct } - override fun mapIndexed(arg: N, transform: R.(index: IntArray, T) -> T): N { + override fun mapIndexed(arg: N, transform: C.(index: IntArray, T) -> T): N { + check(arg) val new = Nd4j.create(*shape).wrap() - new.elements().forEach { (idx, _) -> new[idx] = elementContext.transform(idx, arg[idx]) } + new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(idx, arg[idx]) } return new } - override fun combine(a: N, b: N, transform: R.(T, T) -> T): N { + override fun combine(a: N, b: N, transform: C.(T, T) -> T): N { + check(a, b) val new = Nd4j.create(*shape).wrap() - new.elements().forEach { (idx, _) -> new[idx] = elementContext.transform(a[idx], b[idx]) } + new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(a[idx], b[idx]) } return new } - - override fun add(a: N, b: N): N = a.ndArray.addi(b.ndArray).wrap() - override fun N.minus(b: N): N = ndArray.subi(b.ndArray).wrap() - override fun N.unaryMinus(): N = ndArray.negi().wrap() - override fun multiply(a: N, b: N): N = a.ndArray.muli(b.ndArray).wrap() - override fun multiply(a: N, k: Number): N = a.ndArray.muli(k).wrap() - override fun N.div(k: Number): N = ndArray.divi(k).wrap() - override fun N.minus(b: Number): N = ndArray.subi(b).wrap() - override fun N.plus(b: Number): N = ndArray.addi(b).wrap() - override fun N.times(k: Number): N = ndArray.muli(k).wrap() - override fun Number.minus(b: N): N = b.ndArray.rsubi(this).wrap() } -interface INDArrayField : NDField, - INDArrayRing where F : Field, N : INDArrayStructure, N : MutableNDStructure { - override fun divide(a: N, b: N): N = a.ndArray.divi(b.ndArray).wrap() - override fun Number.div(b: N): N = b.ndArray.rdivi(this).wrap() +/** + * Represents [NDSpace] over [INDArrayStructure]. + * + * @param T the type of the element contained in ND structure. + * @param N the type of ND structure. + * @param S the type of space of structure elements. + */ +interface INDArraySpace : NDSpace, INDArrayAlgebra + where S : Space, N : INDArrayStructure, N : MutableNDStructure { + + override val zero: N + get() = Nd4j.zeros(*shape).wrap() + + override fun add(a: N, b: N): N { + check(a, b) + return a.ndArray.add(b.ndArray).wrap() + } + + override operator fun N.minus(b: N): N { + check(this, b) + return ndArray.sub(b.ndArray).wrap() + } + + override operator fun N.unaryMinus(): N { + check(this) + return ndArray.neg().wrap() + } + + override fun multiply(a: N, k: Number): N { + check(a) + return a.ndArray.mul(k).wrap() + } + + override operator fun N.div(k: Number): N { + check(this) + return ndArray.div(k).wrap() + } + + override operator fun N.times(k: Number): N { + check(this) + return ndArray.mul(k).wrap() + } } +/** + * Represents [NDRing] over [INDArrayStructure]. + * + * @param T the type of the element contained in ND structure. + * @param N the type of ND structure. + * @param R the type of ring of structure elements. + */ +interface INDArrayRing : NDRing, INDArraySpace + where R : Ring, N : INDArrayStructure, N : MutableNDStructure { + + override val one: N + get() = Nd4j.ones(*shape).wrap() + + override fun multiply(a: N, b: N): N { + check(a, b) + return a.ndArray.mul(b.ndArray).wrap() + } + + override operator fun N.minus(b: Number): N { + check(this) + return ndArray.sub(b).wrap() + } + + override operator fun N.plus(b: Number): N { + check(this) + return ndArray.add(b).wrap() + } + + override operator fun Number.minus(b: N): N { + check(b) + return b.ndArray.rsub(this).wrap() + } +} + +/** + * Represents [NDField] over [INDArrayStructure]. + * + * @param T the type of the element contained in ND structure. + * @param N the type of ND structure. + * @param F the type field of structure elements. + */ +interface INDArrayField : NDField, INDArrayRing + where F : Field, N : INDArrayStructure, N : MutableNDStructure { + override fun divide(a: N, b: N): N { + check(a, b) + return a.ndArray.div(b.ndArray).wrap() + } + + override operator fun Number.div(b: N): N { + check(b) + return b.ndArray.rdiv(this).wrap() + } +} + +/** + * Represents [NDField] over [INDArrayRealStructure]. + */ class RealINDArrayField(override val shape: IntArray, override val elementContext: Field = RealField) : INDArrayField, INDArrayRealStructure> { - override fun INDArray.wrap(): INDArrayRealStructure = asRealStructure() - override fun INDArrayRealStructure.div(arg: Double): INDArrayRealStructure = ndArray.divi(arg).wrap() - override fun INDArrayRealStructure.plus(arg: Double): INDArrayRealStructure = ndArray.addi(arg).wrap() - override fun INDArrayRealStructure.minus(arg: Double): INDArrayRealStructure = ndArray.subi(arg).wrap() - override fun INDArrayRealStructure.times(arg: Double): INDArrayRealStructure = ndArray.muli(arg).wrap() - override fun Double.div(arg: INDArrayRealStructure): INDArrayRealStructure = arg.ndArray.rdivi(this).wrap() - override fun Double.minus(arg: INDArrayRealStructure): INDArrayRealStructure = arg.ndArray.rsubi(this).wrap() + override fun INDArray.wrap(): INDArrayRealStructure = check(asRealStructure()) + override operator fun INDArrayRealStructure.div(arg: Double): INDArrayRealStructure { + check(this) + return ndArray.div(arg).wrap() + } + + override operator fun INDArrayRealStructure.plus(arg: Double): INDArrayRealStructure { + check(this) + return ndArray.add(arg).wrap() + } + + override operator fun INDArrayRealStructure.minus(arg: Double): INDArrayRealStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + override operator fun INDArrayRealStructure.times(arg: Double): INDArrayRealStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + override operator fun Double.div(arg: INDArrayRealStructure): INDArrayRealStructure { + check(arg) + return arg.ndArray.rdiv(this).wrap() + } + + override operator fun Double.minus(arg: INDArrayRealStructure): INDArrayRealStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } } +/** + * Represents [NDField] over [INDArrayFloatStructure]. + */ class FloatINDArrayField(override val shape: IntArray, override val elementContext: Field = FloatField) : INDArrayField, INDArrayFloatStructure> { - override fun INDArray.wrap(): INDArrayFloatStructure = asFloatStructure() - override fun INDArrayFloatStructure.div(arg: Float): INDArrayFloatStructure = ndArray.divi(arg).wrap() - override fun INDArrayFloatStructure.plus(arg: Float): INDArrayFloatStructure = ndArray.addi(arg).wrap() - override fun INDArrayFloatStructure.minus(arg: Float): INDArrayFloatStructure = ndArray.subi(arg).wrap() - override fun INDArrayFloatStructure.times(arg: Float): INDArrayFloatStructure = ndArray.muli(arg).wrap() - override fun Float.div(arg: INDArrayFloatStructure): INDArrayFloatStructure = arg.ndArray.rdivi(this).wrap() - override fun Float.minus(arg: INDArrayFloatStructure): INDArrayFloatStructure = arg.ndArray.rsubi(this).wrap() + override fun INDArray.wrap(): INDArrayFloatStructure = check(asFloatStructure()) + override operator fun INDArrayFloatStructure.div(arg: Float): INDArrayFloatStructure { + check(this) + return ndArray.div(arg).wrap() + } + + override operator fun INDArrayFloatStructure.plus(arg: Float): INDArrayFloatStructure { + check(this) + return ndArray.add(arg).wrap() + } + + override operator fun INDArrayFloatStructure.minus(arg: Float): INDArrayFloatStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + override operator fun INDArrayFloatStructure.times(arg: Float): INDArrayFloatStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + override operator fun Float.div(arg: INDArrayFloatStructure): INDArrayFloatStructure { + check(arg) + return arg.ndArray.rdiv(this).wrap() + } + + override operator fun Float.minus(arg: INDArrayFloatStructure): INDArrayFloatStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } } +/** + * Represents [NDRing] over [INDArrayIntStructure]. + */ class IntINDArrayRing(override val shape: IntArray, override val elementContext: Ring = IntRing) : INDArrayRing, INDArrayIntStructure> { - override fun INDArray.wrap(): INDArrayIntStructure = asIntStructure() - override fun INDArrayIntStructure.plus(arg: Int): INDArrayIntStructure = ndArray.addi(arg).wrap() - override fun INDArrayIntStructure.minus(arg: Int): INDArrayIntStructure = ndArray.subi(arg).wrap() - override fun INDArrayIntStructure.times(arg: Int): INDArrayIntStructure = ndArray.muli(arg).wrap() - override fun Int.minus(arg: INDArrayIntStructure): INDArrayIntStructure = arg.ndArray.rsubi(this).wrap() + override fun INDArray.wrap(): INDArrayIntStructure = check(asIntStructure()) + override operator fun INDArrayIntStructure.plus(arg: Int): INDArrayIntStructure { + check(this) + return ndArray.add(arg).wrap() + } + + override operator fun INDArrayIntStructure.minus(arg: Int): INDArrayIntStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + override operator fun INDArrayIntStructure.times(arg: Int): INDArrayIntStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + override operator fun Int.minus(arg: INDArrayIntStructure): INDArrayIntStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } +} + +/** + * Represents [NDRing] over [INDArrayLongStructure]. + */ +class LongINDArrayRing(override val shape: IntArray, override val elementContext: Ring = LongRing) : + INDArrayRing, INDArrayLongStructure> { + override fun INDArray.wrap(): INDArrayLongStructure = check(asLongStructure()) + override operator fun INDArrayLongStructure.plus(arg: Long): INDArrayLongStructure { + check(this) + return ndArray.add(arg).wrap() + } + + override operator fun INDArrayLongStructure.minus(arg: Long): INDArrayLongStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + override operator fun INDArrayLongStructure.times(arg: Long): INDArrayLongStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + override operator fun Long.minus(arg: INDArrayLongStructure): INDArrayLongStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } } diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt index bba5089a1..2759f9fdb 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt @@ -3,7 +3,24 @@ package scientifik.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray import org.nd4j.linalg.api.shape.Shape -internal sealed class INDArrayIteratorBase(protected val iterateOver: INDArray) : Iterator> { +private class INDArrayIndicesIterator(private val iterateOver: INDArray) : Iterator { + private var i: Int = 0 + + override fun hasNext(): Boolean = i < iterateOver.length() + + override fun next(): IntArray { + val la = if (iterateOver.ordering() == 'c') + Shape.ind2subC(iterateOver, i++.toLong())!! + else + Shape.ind2sub(iterateOver, i++.toLong())!! + + return la.toIntArray() + } +} + +internal fun INDArray.indicesIterator(): Iterator = INDArrayIndicesIterator(this) + +private sealed class INDArrayIteratorBase(protected val iterateOver: INDArray) : Iterator> { private var i: Int = 0 final override fun hasNext(): Boolean = i < iterateOver.length() @@ -20,26 +37,26 @@ internal sealed class INDArrayIteratorBase(protected val iterateOver: INDArra } } -internal class INDArrayRealIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { +private class INDArrayRealIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray): Double = iterateOver.getDouble(*indices) } -internal fun INDArray.realIterator(): INDArrayRealIterator = INDArrayRealIterator(this) +internal fun INDArray.realIterator(): Iterator> = INDArrayRealIterator(this) -internal class INDArrayLongIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { +private class INDArrayLongIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getLong(*indices) } -internal fun INDArray.longIterator(): INDArrayLongIterator = INDArrayLongIterator(this) +internal fun INDArray.longIterator(): Iterator> = INDArrayLongIterator(this) -internal class INDArrayIntIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { +private class INDArrayIntIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getInt(*indices.toIntArray()) } -internal fun INDArray.intIterator(): INDArrayIntIterator = INDArrayIntIterator(this) +internal fun INDArray.intIterator(): Iterator> = INDArrayIntIterator(this) -internal class INDArrayFloatIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { +private class INDArrayFloatIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getFloat(*indices) } -internal fun INDArray.floatIterator() = INDArrayFloatIterator(this) +internal fun INDArray.floatIterator(): Iterator> = INDArrayFloatIterator(this) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt index 06b0354d8..39cefee3d 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt +++ b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt @@ -4,45 +4,77 @@ import org.nd4j.linalg.api.ndarray.INDArray import scientifik.kmath.structures.MutableNDStructure import scientifik.kmath.structures.NDStructure -interface INDArrayStructure : NDStructure { - val ndArray: INDArray +/** + * Represents a [NDStructure] wrapping an [INDArray] object. + * + * @param T the type of items. + */ +sealed class INDArrayStructure : MutableNDStructure { + /** + * The wrapped [INDArray]. + */ + abstract val ndArray: INDArray override val shape: IntArray get() = ndArray.shape().toIntArray() - fun elementsIterator(): Iterator> + internal abstract fun elementsIterator(): Iterator> + internal fun indicesIterator(): Iterator = ndArray.indicesIterator() override fun elements(): Sequence> = Sequence(::elementsIterator) } -data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure, MutableNDStructure { +/** + * Represents a [NDStructure] over [INDArray] elements of which are accessed as ints. + */ +data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.intIterator() override fun get(index: IntArray): Int = ndArray.getInt(*index) override fun set(index: IntArray, value: Int): Unit = run { ndArray.putScalar(index, value) } } +/** + * Wraps this [INDArray] to [INDArrayIntStructure]. + */ fun INDArray.asIntStructure(): INDArrayIntStructure = INDArrayIntStructure(this) -data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure { +/** + * Represents a [NDStructure] over [INDArray] elements of which are accessed as longs. + */ +data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.longIterator() override fun get(index: IntArray): Long = ndArray.getLong(*index.toLongArray()) + override fun set(index: IntArray, value: Long): Unit = run { ndArray.putScalar(index, value.toDouble()) } } +/** + * Wraps this [INDArray] to [INDArrayLongStructure]. + */ fun INDArray.asLongStructure(): INDArrayLongStructure = INDArrayLongStructure(this) -data class INDArrayRealStructure(override val ndArray: INDArray) : INDArrayStructure, - MutableNDStructure { +/** + * Represents a [NDStructure] over [INDArray] elements of which are accessed as reals. + */ +data class INDArrayRealStructure(override val ndArray: INDArray) : INDArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.realIterator() override fun get(index: IntArray): Double = ndArray.getDouble(*index) override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) } } +/** + * Wraps this [INDArray] to [INDArrayRealStructure]. + */ fun INDArray.asRealStructure(): INDArrayRealStructure = INDArrayRealStructure(this) -data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure, - MutableNDStructure { +/** + * Represents a [NDStructure] over [INDArray] elements of which are accessed as floats. + */ +data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.floatIterator() override fun get(index: IntArray): Float = ndArray.getFloat(*index) override fun set(index: IntArray, value: Float): Unit = run { ndArray.putScalar(index, value) } } +/** + * Wraps this [INDArray] to [INDArrayFloatStructure]. + */ fun INDArray.asFloatStructure(): INDArrayFloatStructure = INDArrayFloatStructure(this) From 2bc62356d6da378f2aae87cc830a119f13f03af5 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 27 Aug 2020 16:44:58 +0700 Subject: [PATCH 024/199] Fix compilation issues --- .../kotlin/scientifik/kmath/structures/BoxingNDField.kt | 3 ++- .../kotlin/scientifik/kmath/structures/BoxingNDRing.kt | 3 ++- .../kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt index 4cbb565c1..29e0ba276 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt @@ -14,8 +14,9 @@ class BoxingNDField>( fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) - override fun check(vararg elements: NDBuffer) { + override fun check(vararg elements: NDBuffer): Array> { if (!elements.all { it.strides == this.strides }) error("Element strides are not the same as context strides") + return elements } override val zero: BufferedNDFieldElement by lazy { produce { zero } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt index f7be95736..8aabe169a 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt @@ -14,8 +14,9 @@ class BoxingNDRing>( fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) - override fun check(vararg elements: NDBuffer) { + override fun check(vararg elements: NDBuffer): Array> { if (!elements.all { it.strides == this.strides }) error("Element strides are not the same as context strides") + return elements } override val zero: BufferedNDRingElement by lazy { produce { zero } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt index 06922c56f..de8a150c6 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt @@ -5,8 +5,9 @@ import scientifik.kmath.operations.* interface BufferedNDAlgebra : NDAlgebra> { val strides: Strides - override fun check(vararg elements: NDBuffer) { + override fun check(vararg elements: NDBuffer): Array> { if (!elements.all { it.strides == this.strides }) error("Strides mismatch") + return elements } /** From 5e4522bb06c571880d257824143313b42405216c Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Tue, 8 Sep 2020 16:40:47 +0700 Subject: [PATCH 025/199] Upgrade build tools plugin to dev version; file reformat; change dependencies' versions; specify visibility explicitly at certain places (core, especially), make some interfaces `fun` --- build.gradle.kts | 17 +- examples/build.gradle.kts | 34 +-- .../structures/StructureReadBenchmark.kt | 2 +- .../structures/StructureWriteBenchmark.kt | 4 +- gradle/wrapper/gradle-wrapper.jar | Bin 58910 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- gradlew.bat | 21 +- kmath-ast/build.gradle.kts | 6 +- .../kotlin/scientifik/kmath/ast/MST.kt | 18 +- .../kotlin/scientifik/kmath/ast/MstAlgebra.kt | 4 +- .../scientifik/kmath/ast/MstExpression.kt | 23 +- .../kotlin/scientifik/kmath/ast/parser.kt | 18 +- .../kotlin/scientifik/kmath/asm/asm.kt | 6 +- kmath-commons/build.gradle.kts | 4 +- .../commons/expressions/DiffExpression.kt | 39 ++- kmath-core/build.gradle.kts | 9 +- .../kotlin/scientifik/kmath/domains/Domain.kt | 6 +- .../kmath/domains/HyperSquareDomain.kt | 2 +- .../scientifik/kmath/domains/RealDomain.kt | 14 +- .../kmath/domains/UnconstrainedDomain.kt | 2 +- .../kmath/domains/UnivariateDomain.kt | 4 +- .../kmath/expressions/Expression.kt | 22 +- .../FunctionalExpressionAlgebra.kt | 35 +-- .../{Builders.kt => expressionBuilders.kt} | 8 +- .../scientifik/kmath/linear/BufferMatrix.kt | 12 +- .../scientifik/kmath/linear/FeaturedMatrix.kt | 36 ++- .../kmath/linear/LUPDecomposition.kt | 59 ++-- .../scientifik/kmath/linear/LinearAlgebra.kt | 14 +- .../scientifik/kmath/linear/MatrixBuilder.kt | 14 +- .../scientifik/kmath/linear/MatrixContext.kt | 29 +- .../scientifik/kmath/linear/MatrixFeatures.kt | 30 +- .../scientifik/kmath/linear/VectorSpace.kt | 20 +- .../scientifik/kmath/linear/VirtualMatrix.kt | 25 +- .../kotlin/scientifik/kmath/misc/AutoDiff.kt | 48 +-- .../kotlin/scientifik/kmath/misc/Grids.kt | 10 +- .../scientifik/kmath/misc/cumulative.kt | 36 ++- .../scientifik/kmath/operations/Algebra.kt | 89 +++--- .../kmath/operations/AlgebraElements.kt | 28 +- .../kmath/operations/AlgebraExtensions.kt | 20 +- .../scientifik/kmath/operations/BigInt.kt | 276 ++++++++---------- .../scientifik/kmath/operations/Complex.kt | 35 ++- .../kmath/operations/NumberAlgebra.kt | 4 +- .../kmath/operations/OptionalOperations.kt | 122 ++++---- .../kmath/structures/BoxingNDField.kt | 8 +- .../kmath/structures/BoxingNDRing.kt | 6 +- .../kmath/structures/BufferAccessor2D.kt | 17 +- .../kmath/structures/BufferedNDAlgebra.kt | 22 +- .../kmath/structures/BufferedNDElement.kt | 18 +- .../scientifik/kmath/structures/Buffers.kt | 50 ++-- .../kmath/structures/ComplexNDField.kt | 24 +- .../kmath/structures/ExtendedNDField.kt | 2 +- .../kmath/structures/FlaggedBuffer.kt | 2 +- .../scientifik/kmath/structures/IntBuffer.kt | 2 +- .../scientifik/kmath/structures/LongBuffer.kt | 10 +- .../scientifik/kmath/structures/NDAlgebra.kt | 58 ++-- .../kmath/structures/RealNDField.kt | 12 +- .../kmath/structures/ShortBuffer.kt | 10 +- .../kmath/structures/ShortNDRing.kt | 18 +- .../kmath/structures/Structure2D.kt | 26 +- .../scientifik/kmath/operations/BigNumbers.kt | 8 +- kmath-coroutines/build.gradle.kts | 16 +- .../kotlin/scientifik/kmath/chains/Chain.kt | 38 ++- kmath-dimensions/build.gradle.kts | 12 +- .../scientifik/kmath/dimensions/Dimensions.kt | 22 +- .../kotlin/scientifik/kmath/dimensions/dim.kt | 4 +- .../kotlin/scientifik/kmath/dimensions/dim.kt | 4 +- kmath-for-real/build.gradle.kts | 9 +- .../scientifik/kmath/real/realMatrix.kt | 64 ++-- kmath-functions/build.gradle.kts | 9 +- .../scientifik/kmath/functions/Piecewise.kt | 16 +- .../scientifik/kmath/functions/Polynomial.kt | 27 +- .../scientifik/kmath/functions/functions.kt | 18 +- .../kmath/interpolation/Interpolator.kt | 12 +- .../kmath/interpolation/LinearInterpolator.kt | 2 +- .../kmath/interpolation/SplineInterpolator.kt | 4 +- .../kmath/interpolation/XYPointSet.kt | 21 +- .../interpolation/LinearInterpolatorTest.kt | 3 +- kmath-geometry/build.gradle.kts | 6 +- kmath-histograms/build.gradle.kts | 6 +- kmath-koma/build.gradle.kts | 11 +- kmath-memory/build.gradle.kts | 3 +- .../kotlin/scientifik/memory/Memory.kt | 58 ++-- .../kotlin/scientifik/memory/MemorySpec.kt | 16 +- .../scientifik/memory/DataViewMemory.kt | 4 +- .../scientifik/memory/ByteBufferMemory.kt | 8 +- kmath-prob/build.gradle.kts | 11 +- .../scientifik/kmath/prob/distributions.kt | 12 +- kmath-viktor/build.gradle.kts | 6 +- settings.gradle.kts | 23 +- 90 files changed, 905 insertions(+), 1042 deletions(-) rename kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/{Builders.kt => expressionBuilders.kt} (65%) diff --git a/build.gradle.kts b/build.gradle.kts index 8a2ba3617..3a9991443 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,11 +1,8 @@ -plugins { - id("scientifik.publish") apply false -} +plugins { id("ru.mipt.npm.publish") apply false } -val kmathVersion by extra("0.1.4-dev-8") - -val bintrayRepo by extra("scientifik") -val githubProject by extra("kmath") +val kmathVersion: String by extra("0.1.4-dev-8") +val bintrayRepo: String by extra("scientifik") +val githubProject: String by extra("kmath") allprojects { repositories { @@ -18,8 +15,4 @@ allprojects { version = kmathVersion } -subprojects { - if (name.startsWith("kmath")) { - apply(plugin = "scientifik.publish") - } -} \ No newline at end of file +subprojects { if (name.startsWith("kmath")) apply(plugin = "ru.mipt.npm.publish") } diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index f5a4d5831..9fd90d08b 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -1,16 +1,13 @@ -import org.jetbrains.kotlin.allopen.gradle.AllOpenExtension import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { java kotlin("jvm") - kotlin("plugin.allopen") version "1.3.72" - id("kotlinx.benchmark") version "0.2.0-dev-8" + kotlin("plugin.allopen") version "1.4.0" + id("kotlinx.benchmark") version "0.2.0-dev-20" } -configure { - annotation("org.openjdk.jmh.annotations.State") -} +allOpen.annotation("org.openjdk.jmh.annotations.State") repositories { maven("http://dl.bintray.com/kyonifer/maven") @@ -19,9 +16,7 @@ repositories { mavenCentral() } -sourceSets { - register("benchmarks") -} +sourceSets.register("benchmarks") dependencies { implementation(project(":kmath-ast")) @@ -34,25 +29,22 @@ dependencies { implementation(project(":kmath-dimensions")) implementation("com.kyonifer:koma-core-ejml:0.12") implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6") - implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-8") + implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20") "benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath } // Configure benchmark benchmark { // Setup configurations - targets { + targets // This one matches sourceSet name above - register("benchmarks") - } + .register("benchmarks") - configurations { - register("fast") { - warmups = 5 // 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 - } + configurations.register("fast") { + warmups = 5 // 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 } } @@ -65,7 +57,7 @@ kotlin.sourceSets.all { tasks.withType { kotlinOptions { - jvmTarget = Scientifik.JVM_TARGET.toString() + jvmTarget = "11" freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" } } diff --git a/examples/src/main/kotlin/scientifik/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/structures/StructureReadBenchmark.kt index a33fdb2c4..d5998cd0a 100644 --- a/examples/src/main/kotlin/scientifik/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/scientifik/kmath/structures/StructureReadBenchmark.kt @@ -2,7 +2,7 @@ package scientifik.kmath.structures import kotlin.system.measureTimeMillis -fun main(args: Array) { +fun main() { val n = 6000 val array = DoubleArray(n * n) { 1.0 } diff --git a/examples/src/main/kotlin/scientifik/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/structures/StructureWriteBenchmark.kt index 0241f12ad..ffcecbce2 100644 --- a/examples/src/main/kotlin/scientifik/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/scientifik/kmath/structures/StructureWriteBenchmark.kt @@ -2,9 +2,7 @@ package scientifik.kmath.structures import kotlin.system.measureTimeMillis - -fun main(args: Array) { - +fun main() { val n = 6000 val structure = NDStructure.build(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 62d4c053550b91381bbd28b1afc82d634bf73a8a..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 6656 zcmY+Ibx_pN*Z*PZ4(U#j1qtbvrOTyO8fghZ8kYJfEe%U|$dV!@ASKczEZq$fg48M@ z;LnHO_j#Uq?%bL4dY^md%$$4Y+&@nKC|1uHR&59YNhubGh72|a#ylPdh9V+akp|I; zPk^W-a00GrFMkz_NSADdv2G2-i6rb=cB_@WnG(**4ZO$=96R=t|NZ@|0_z&q3GwO^ ziUFcuj$a9QaZ3j?xt`5#q`sT-ufrtBP0nt3IA&dr*+VCsBzBVW?vZ6eZr0oD%t33z zm~-5IVsjy(F>;S~Pm@bxX85>Z*@(QL6i3JQc?1ryQFcC@X^2^mZWhFv|v? z49>l|nA&XNQ6#OvccUTyBMB*WO#NA;FW5|eE_K6dtVYP2G?uUZ09!`Iq1IF2gA(aS zLu@G^cQJmh=x?-YsYa@E6QnE5+1@ds&0f#OQRDl^GnIT_m84G5XY%W z;Ck6bk^Oeu*Ma-XmxI5GjqzWNbJMsQF4)WfMZEA{oxW0E32e)*JfG}3otPishIQBw zkBe6N#4pKPN>q1R6G1@5&(u#5yPEToMBB6_oEK|q z@(i5j!?;NNCv~=HvW%zF&1yWBq(nJa_#``G&SRmQvE|jePUPs{J!$TacM|e}Fsceb zx+76|mDp6@w>)^DIl{8?)6XYNRU|2plG8Jy&7(^9SdOWNKKJK&>0!z6XiN4J*Jkao z=E1y5x-XDC==Ub+8fLb#OW&{2ww{h^xlJFYAMOUd)}Xg@j?ak{7Kno6?9S~F?|6Df zHo|ijXX~`Sp;Vf!nR;m%vUhq>zvlRXsL0u*Tt?F#yR}3tF0#of{(UjitqST|!{aBA zicWh+URU}Jnc*sg9iMkf0pggpd?3TI*C-q$2QOdCC7rV+CHBmjS3O%a3VeZ$ZSs5ubJuJp%e%$LHgrj0niYjX;4kt z&2~j%@q3MO)-QGCA{>o%eZu){ou^MgC6~Z8Y=tc!qF=|TOlG3wJXbaLYr-;$Ch=2J z_UcE59Xzq&h0LsjLrcZrQSa}#=0~Lk|4?e4M z6d;v->NCC1oMti)RRc`Ys0?JXQjsZ@VdCy%Z)TptCrI>0Tte$pR!@yJesoU2dtyuW z7iFsE8)CkbiJP+OP28;(%?!9WddQZcAid@R@`*e%3W65$g9ee`zvwb(VPO+uVBq6p z{QDR%CR(2z@?&9Obm3xPi2lzvfip`7q`_7UDD|lRS}4=bsl3xQIOi0@GSvMuDQX}* z4B^(DI<${qUhcLqO`itJU;e<%%iS+R3I^_xIV1O%sp*x~;-dn` zt$8>RnSUh#rU3{-47067W^WNwTdq-t$-U>Hj%r!GD!gLa;kV zW5g6pCqV+!q8LgrI49(}fIc5K_`FLV4_E#XZ6{<>w8wzc%V9k!!Byg5-0WY+J?1*z%9~Aj4WQr1Jsn2(G!U8fFpi(wsy@JLg^d+IB0kl89 z0@Ssqf!L9JjYKK$J=978+NO*5^C)GPH2a%4hm$HROjM|N3g9ch9kDLh*nlwqy{mVM z`P(l#>3NnK%#O8tSb(VmZrG+`dRD#=Cc1P%(y5S?*Hj5E{vg&Eiw!YV>S#7_WRDVoFxT5m=gFi4)}y5V%KT8!xbsH_rmR& zsmM?%J}K$1l8d?2+m(}2c}-G`x>CY%Y&QBJRC$sKM}zN<9{IlF@yJEG<^0={$+`Hc zDodJ)gCADJ_bD#am(c2ojXKb|j+ENJ#58PAA&pZXufrFzBwnuuo+khfMgd!DMlU#v z9|JelQO~E2;d^w!RZJbt%IANIudpKSP)cssoWhq)>({nvcfCr0=9=FAIMuZm8Eo=} z|DND}8_PB5HqG(QwDvaM@orYBZ9kCkHV*rxKTy>q7n~0emErUwLbhq;VN<2nKT&*a2Ajz z;lKBzU2i8KLV`d)Y&ae)!HcGk$dO}Or%8KF@kE@jU1h@zwpw{6p4ME|uC$Za-ERR2 ztQvL&uOZLe(k{w_+J^ng+l}~N8MP>F1Z$fLu}D-WWaeu#XduP@#8JpmH(X>rIL)k3 zyXNyTIB1(IH%S&pQ{rWaTVfB$~-;RnlY z^(y7mR>@=brI>!TrA)BQsQ={b*6$=1Eqbuu6IdhJ&$YD$08AwtNr9*J?%-WT<;O1< zPl1<@yeqfZ>@s4azqTf<=I4(kU^+^Qkstm%WM-0_VLm({jFc8`5Df2Q1Y9zMZu0^! zsO_yh2Sz9K>Jq6fkYbBZocEJ6C!SdEzYDkiEtNJs{?!tA#e|oiN+VaaAobwKef_kUup&4scD?1+}Q8)DaekkMYn-FOS{J%NY za^mmJ^n`t*1p@hF*gl#L+5wr40*(ub4J#L|@oCl~@|4UvCjHBYDQv&S zhyGMAkRO^tF_dyi&XM)4mQ;k>kj?RgRo@-?==oD+ns*>bf@&fPXF|4U0&ib2 zo~1ZdmCPWf!W9#sGP@9X$;Rc`tjbz^&JY}z{}j9bl?;VC{x)TfQH$D^WowKL&4Zx@ zdSn+QV7H(e0xRfN6aBfH)Q=@weoD?dvu6^ZS)zqb>GwMmIuS8zJfaMUQx9>%k~w34 z3}_B2Jj~u=SnJ~vZPj*)UoDi_FtT=UAb#J^b4B%R6z3H%cj-1OCjU5F$ky>By1zsg z>2A0ccp29(Y<;my|J_g-r{1I@+*O$>!R3`_sFNP4e}LD1e1mM&SA`;;TR0I`_hESV zh4U*9ecK$0=lYk`{SR_cm$}iS*?yQR(}T-5ub?Wn^#RTe*^1~ya%`!xWq-F*WH@%nnZTNREA z3eUX2uM9b_w!Zo$nVTotEtzuL(88N)H~v_G=89|(@IFz~Wq6ME);z(!2^PkR2B&kE zxR)xV8PE|Hszyjp#jNf=ZIQ7JR~4Ls#Vd@mPF(7R5VO$akUq8JM+sn>ZVg(lJZ)5qjqdw(*7tuwjY#0tx+|!sTz9yV~%HOdrb#!5w9>*0LrCS z%wF$Yc6~hqVQZzoC^D<(-h0aOtk}kn<<*xF61HQr<5}efY{zXXA+PaJG7vT&{Oz(@Uu!V#Fp9%Ht!~@;6AcD z$lvlPu&yd(YnAHfpN51*)JN0aYw9gGk{NE7!Oqu4rBp}F30669;{zcH-a7w9KSpDQPIE_f9T zit? zJSjTKWbe{f{9BmSDAFO1(K0oqB4578tU0(oRBE^28X>xDA!1C&VJEiYak4_ZTM*7M`hv_ zw3;2ndv3X$zT!wa7TrId{gNE`Vxf}j5wsyX+;Kn<^$EJT`NzznjyYx=pYMkZjizEU zb;Gg8Pl_pqxg)9P)C)Hxh_-mQ;u-I_Ol>d^>q08zFF!>Z3j1-HmuME_TGZ*Ev;O0O z%e(edJfV<6t3&FKwtInnj9EeQhq9;o5oLJoiKwWF5bP2~Feh#P4oN()JT0pdq!9x* ze3D-1%AV#{G=Op$6q?*Z>s{qFn}cl@9#m@DK_Bs@fdwSN`Qe18_WnveRB583mdMG- z?<3pJC!YljOnO8=M=|Cg)jw;4>4sna`uI>Kh&F20jNOk9HX&}Ry|mHJ+?emHnbYLJ zwfkx@slh31+3nq-9G5FVDQBHWWY}&hJ-fpDf!lQdmw8dlTt#=)20X74S>c&kR(?PT zBg)Y%)q&|hW1K;`nJPAGF*c3{3`FvrhD9=Ld{3M*K&5$jRhXNsq$0CLXINax1AmXX ziF39vkNtcK6i^+G^AEY!WalGazOQ$_#tx?BQ{YY$&V&42sICVl8@AI6yv;sGnT;@f zL=}rZcJqNwrEEA=GDdEe8Z=f9>^?($oS8xGdFf1eUWTYtZF<3tu2V%noPBnd=thZ+ zO&xoc?jvXG7Xt!RTw#5VN50UjgqSntw9Y35*~pxz=8OzkXg{@S2J%+{l3Q>B_qbnl z20Deb7JM&ZSp`%X>xWpb>FF8q7Nq&4#a1}A-(-!aMDmVbz05D!NpUzVe{~72h%cOh zwQFNai2a$K|hFgDk(oPF_tuf{BV!=m0*xqSzGAJ(~XUh8rk#{YOg0ReK>4eJl z;-~u5v$}DM)#vER>F)-}y(X6rGkp<{AkiPM7rFgAV^)FUX8XmCKKaWlS4;MSEagj$ z#pvH`vLX1q{&eOm>htnk4hmv=_)ao!MCp}9ql5yfre&Py!~hBAGNBa}PH&J8K=~<% z&?!J-QaH|0bq_uo6rt*r-M>d7jm1cbW^T>s)S?L{n8v`^?VIPA+qi^6e@cM|5boqEO!p1e|_{7U3Yl6K?0xMN1bbjf0@$TE-T))w> zFe?E?g$PUT-)AJ(PS^By^D^Ed!K5iv$*_eW~VA(I3~UMy*ZcgVu0$XZC*_0PgDmUL)qTCn927LD~p$yXR_GCJ&iQ; z4*`%l-dC5pALH!y*nmhdHRh02QjW1vZL4ySucz*w3f|#`=u@@YvMV1?i!&DIa2+S< z8z!gvN3FV4I;%fl;ruFeV{jKjI~?GlgkmGBuJ<7vY|l3xMOc?S@Q#C(zo*m&JLrjT2rU9PYOniB8O~yO5<1CCcQz# z17B2m1Z{R!Y)UO#CU-Y&mOlv4*Gz%rC_YkRcO)jTUEWHDvv!GWmEihE>OKPx1J?Av z8J{-#7NsT>>R#*7**=QL)1@IR77G9JGZZiVt!=jD+i(oRV;I`JkiTSZkAXuHm-VG1 z+2-LD!!2dNEk@1@Rp|C$MD9mH^)H*G*wI(i*Rc6Vvdik+BDycYQ*=0JA3dxxha|Zg zCIW1Ye-DdpMGTEwbA^6hVC<(@0FL4dkDOYcxxC5c%MJQ^)zpA%>>~Q|Y=@)XW!px; z_Fx+xOo7>sz4QX|Ef~igE+uFnzFWP<-#||*V0`0p7E*+n5+awuOWmvR{-M*chIXgo zYiZvQMond#{F8+4Zh_;>MsaZUuhp=onH@P!7W>sq|CWv|u}Wg0vo&f4UtmLzhCwwu zJaR=IO;sQxS}h(K>9VZjnED+>9rGgB3ks+AwTy_EYH{oc)mo`451n&YH%A1@WC{;1 z=fB6n zIYp46_&u`COM&Di?$P}pPAlAF*Ss<)2Xc?=@_2|EMO?(A1u!Vc=-%bDAP#zDiYQvJ z0}+}3GaLxsMIlh6?f=iRs0K=RyvMOcWl*xqe-IBLv?K{S^hP)@K|$I+h_)pdD9r~! zxhw2u66+F(E`&6hY}B_qe>wil|#*0R0B;<@E?L zVrhXKfwRg0l8r>LuNs1QqW&39ME0sOXe8zycivGVqUOjEWpU)h|9fwp@d(8=M-WxY zeazSz6x5e`k821fgylLIbdqx~Kdh^Oj`Q!4vc*Km)^Tr-qRxPHozdvvU^#xNsKVr6aw8={70&S4y*5xeoF@Q^y596*09`XF56-N z1=Rm5?-An178o?$ix}y7gizQ9gEmGHF5AW+92DYaOcwEHnjAr~!vI>CK%h`E_tO8L Yte!%o?r4GTrVtxD61Ym!|5fq-1K$0e!T1w z1SC8j)_dObefzK9b=~*c&wBRW>;B{VGKiBofK!FMN5oJBE0V;;!kWUz!jc1W?5KdY zyZ3mCBHprpchz-9{ASiJJh&&h1|4rdw6wxD2+9= z#6#}Uq8&^1F3wgvGFoNDo?bIeEQXpcuAR0-+w$JWoK-@yUal1M&~W_O)r+Rx;{@hWH5n^oQWR36GMYBDDZyPK4L@WVjRrF+XlSzi4X4!_!U%Uujl6LHQ#|l(sUU%{ zefYd8jnVYP91K}Qn-OmmSLYFK1h~_}RPS~>+Xdz%dpvpJ{ll!IKX=JN99qowqslbO zV3DmqPZ}6>KB!9>jEObpi$u5oGPfO3O5!o3N2Mn`ozpje<}1I1H)m2rJDcB7AwXc6 z6j)tnPiql7#)r+b+p9?MVahp&=qJ^$oG+a^C*);FoJ!+V*^W+|2Olx5{*&$bXth)U zejc7mU6cBp?^Rj|dd{GL-0eHRTBi6_yJ&GLP5kIncv^z{?=0AVy^5{S8_n=rtua!J zFGY=A(yV^ZhB}1J_y(F`3QTu+zkHlw;1GiFeP&pw0N1k%NShHlO(4W+(!wy5phcg4 zA-|}(lE_1@@e6y`veg;v7m;q%(PFG&K3#}eRhJioXUU0jg_8{kn$;KVwf;zpL2X_( zC*_R#5*PaBaY73(x*oZ}oE#HPLJQRQ7brNK=v!lsu==lSG1(&q>F)`adBT~d*lMS| z%!%7(p~<7kWNmpZ5-N31*e=8`kih|g5lVrI%2wnLF-2D+G4k6@FrYsJ_80AJ}KMRi>) z-kIeHp{maorNWkF81v0FKgB==_6blyaF$5GaW)B!i4v*jNk6r)vU6?G$0pV8(Y+UK z5lgRVt%;N_gWp)^osv=h+^07UY6+$4^#t=M3>0i0`{`aEkFLL#a)93uXhYO+aKTtu zckg2T9S&GKNtZmdAS^8PzvDva-%-K&g9eqPXQ4$dM^inr@6Zl z{!Cq&C_+V;g*{>!0cZP}?ogDb$#ZS=n@NHE{>k@84lOkl&$Bt2NF)W%GClViJq14_ zQIfa^q+0aq){}CO8j%g%R9|;G0uJuND*HO$2i&U_uW_a5xJ33~(Vy?;%6_(2_Cuq1 zLhThN@xH7-BaNtkKTn^taQHrs$<<)euc6z(dhps>SM;^Wx=7;O&IfNVJq3wk4<1VS z-`*7W4DR_i^W4=dRh>AXi~J$K>`UqP>CKVVH&+T(ODhRJZO7DScU$F7D)di-%^8?O z6)Ux`zdrVOe1GNkPo0FgrrxSu1AGQkJe@pqu}8LkBDm+V!N_1l}`tjLW8${rgDLv3m@E*#zappt-Mm zSC<$o+6UO~w0C=(0$&*y**@nKe_Q{|eAuD!(0YL0_a{z%+sdfSyP={Nyd$re6Rzbp zvsgTY7~VflX0^Vf7qqomYZ_$ryrFVV2$sFyzw2r%Q8*uYDA+)iQdfKms_5(>!s#!( z!P5S(N0i9CKQKaqg(U%Gk#V3*?)lO6dLv`8KB~F<-%VhbtL8Rl>mEz+PN=qx&t*|= zQHV=qG)YKlPk4iCyWIUGjC?kpeA>hIBK*A?B0)rB=RqAal#D%1C9yVQwBcz${#Jb5 zR{TRmMrOrJsLc&6x9qDo@FJ^=do_Y?3oU0G^nV5_EU&+DS+VA7Tp{^TAF>yZbyM3c zf*1CqHY9T|aL_lyY7c)i!_MtGPA!sdy3|mrsKVj1mi&>dms@-ozSa}OZ?2I*tAndg z@S7er$t^d^-;!wLQbG60nWd@1pQVD7tw-G_B#OscoYyremiZ_hj8*sXqQdchuD^!R zpXGuSj5psk+jR>3rWu3^`17>j&*^9^rWbszP=Mf@5KIEj%b=z98v=Ymp%$FYt>%Ld zm8})EDbNOJu9n)gwhz_RS``#Ag)fr)3<*?(!9O~mTQWeh;8c;0@o=iBLQNqx3d_2#W7S9#FXzr6VXfs>4 z;QXw}-STvK9_-7H=uqgal2{GkbjVLN+=D5ddd)4^WvX;(NYA*X*(JxTdiUzqVJopd zQg#~psX4o<)cF>r=rxP`(Xsf<+HG-pf&7aFPL8z|-&B*P?Vmsu5d>Nlg^2$WRY!S@#`g2{81;(1w#o5HsvN}5pFZi});>|VK^kL{Zkx~wgn ztlZp;HW`H8(GdRfIwc~?#N6}o#h158ohI*GIsK%56I_9sf2k_K@4vD!l{(dX9E7PJ;w>$|Y;-VBJSO4@){07bo-89^LZ9g<<%;dOl zyIq{s8`8Ltp*GDwu(l_Z$6sA2nam$BM$Q~6TpZg)w2TtW?G5whV(lRwaf$6EU86is zBP9Rs&vS_~sk?Nn_b}^HkM8LiO@>J}=g(T4hLmvH@5Jj#2aHa~K)lD9VB0k>$V2BP zgh;(=y9Op(KQ=H5vj+%qs>?s4tYN~-Q|fyQePA)s?HrF~;l!+@t8VMzqUpqMLudFT z)=o~s!MM4XkgbetIsODwtQ=FF$IcIp&!pjh6Q6{tL+l*7GQ%8Wsg(tC#qU3oW$~n) zL=>XIxI}Hi7HS0F_mmi+(c%1HDuKiWm>|6Xa}nW7ei55ggru9)xjBvC#JcEIN*#cp zv*ACvr=HTC?dX9NNo9Yhulu_gX5Z~}QQ2&QZ&C77{(>Y3_ z6j5Z1Uc5FtPEpS_31HsgmSLHZijGb_p$WlRJ1p^_1!ZLP8kr6OtCEK7Qh267o$H>e zf<4cNGQRk{g5h$XfvTFQ@`qm@iju83-~}ebAYpZryARHVR$AEt3229U{y@Fp4 z-8FBBtGG&(hTyUdx5ZOfiz`c=<0F%+w|Fl=rWk{K7>70k04SN?RU(^mrKSeKDqA!K^Hsv8C?#ioj4@WUL zC*?{hTai6q0%_oBTqDHygp_Kl;({sAScYQIwMDM1U>{x0ww zve?_}E;DG?+|zsUrsph5X_G7l#Y~vqkq3@NNDabbw7|`eJBmn`Qrlr%?`va=mm$Mc{+FBbQbogAZ6{MuzT|P%QZZotd21eb1hfj|;GYAX&>bx#D5EB+=XMj2XJkpnyMUykaVo) zj3ZLqEl1&)Rturc8m@+uUuD^vaNaSxGwP4dq0-OSb~62lPv8E_K4usLvG{Qg zdR%z8dd2H!{JaT|X_bfm{##*W$YM;_J8Y8&Z)*ImOAf4+| zEyi)qK%Ld1bHuqD+}-WiCnjszDeC-%8g+8JRpG1bOc!xUGB?@?6f~FTrI%U#5R~YF z%t5(S2Q>?0`(XNHa8xKdTEZ~Z4SJOheit#ldfdg63}#W6j8kO;SjQD`vftxS+#x1B zYu|5szEvkyz|}|B3x|DNlyi$;+n+cW$Hu+?)=X1!sa%{H-^;oBO9XACZJ}wkQ!sTa zQ#J3h|HX{{&WwIG3h7d6aWktuJaO)ie6&=KJBoX@w(rBWfin`*a6OmCC5M0HzL(gv zY<*e4hmW>SWVhxk-`UGOAbD%Hk+uu<^7zJ_ytVXamfqCd0$g+W08>?QAB}Cv{b}eM z@X}ILg+uT%>-6`A25p@uhS3%;u>ccSq}8|H_^o&`nBT5S0y z;2H0I^(4MO*S+(4l$gULc4KSeKvidto5Nl0P|%9CqQ*ikY!w_GUlo}sb9HYB=L^oFpJ zfTQskXW!LFVnUo4(OHPDaZSf3zB|3{RGu1>ueE$(+dr?tT zp!SGlqDU8vu{5xLWSvj+j$arHglg54#Lx&TvuO3LIIU>hF9Uoj&=-b*Q?uYr`#V?xz?2 zhirZrv^eA{k%{hFh%9LYVXEYWd5#PuUd1QqaqB*J!CMXEM>fEB$@#1>mtB`Bfil}t zhhTIObqh5HRvT+4q_Do$Q*Jika?qV=Np-DtPkU z(KoXyWLfPwr@UY1)hBAvR3nCBZgd|CevTG?H~HqDF}dzy%2sd2`f{^CBbTk*^K~RO zN~O0+2EjAJlywF%SjgYz810l&G5AqzI<=Ber{912^PpSPRJl3dm8W@dKHL}7_@k3)Y!SXYkyxQy>Q4I2o zr`ev7fLF$1t96h|sH<-#*YzGD-b^3$_!#wsh(Yw;)b@udLz9mm`mFYh z1Zz24KIQJ(*_-E0(3&1InqG;U?wF)GYd>DFo(em`#|UaaYmkA9;GTX7b?0@C@QkTVpGD#mf$dQoRNV=n{^Zi_W*ps;3?^$s`0;ER7;==~OmQ~9 zS5P=FjxE5%|;xq6h4@!_h?@|aK&FYI2IT(OHXv2%1 zWEo-v!L7x^YT(xLVHlpJttcwaF@1Y;-S*q3CRa!g7xdzl|Jan>2#dI0`LKl!T1GMk zRKe4|bQO&ET}Z^Aiym*HII>cSxIzl|F~JEUGxz;+DB=8fxXhnBI4R12q6ews$lA`Jfi}r@A@-)6TOAUMNYFYJ zZ-Zd?lxFTyjN3mXnL!%#>Z%$0gJ4*9g;e;@zSmQ{eGGDaRRNM3s@6!;hYuVc=c+3B z=qzNNS~n^EsJU4aOGE|mdy={C^lPKEfPL-IJAsTpQsDgZ@~s+eHZYmp9yb=YW_4r?lqQaYZQ`nau){W`LY#P)>i zq^wHEuOYs#FlPZeMuT@Etb@~A6feCebq`miJE3w+gAL%bVF_s*5e*@)?xmKSo%I3? zLELHVdWia$}~s6 zr!^LfxSSB4Td&9iTXrzQpl5ZDo#SdmNr;23QsPHQ!x!UT9xtb!Ycz^JF8x)%cFOXK z^EXw%dRz_VD}7?RU^4{)1+xFO=z!EI8IUa3U*rag=1BpHX$Xi<__kSbS{y_xa*MJv z_`thq0Z^sPzjAk48ssDQj}!$N8Q$XC84(bU$t_Bm69Jf+C!h_}ep zwzpQj9sRA94<{x3{~z&ix-DwX;RAzka)4-#6ZHJqKh|SVuO|>Yrv+m30+!|sK<-|E z=)5E->#y<_1V|T1f%Af!ZYqXg}`O zI$qKOWdnclF`%_Z`WGOe{`A`l-#a?s=Q1a#@BOWmExH2;Wl`OB!B-%lq3nO{4=WO& z#k_x|N&(qzm*6S{G*|GCegF2N2ulC+(58z2DG~yUs}i8zvRf&$CJCaexJ6Xu!`qz( z)*v8*kAE#D0KCo*s{8^Rbg=`*E2MzeIt0|x55%n-gO&yX#$l=3W7-_~&(G8j1E(XB hw}tl`5K!1C(72%nnjQrp<7@!WCh47rWB+@R{{wClNUHz< diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bb8b2fc26..12d38de6a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index fbd7c5158..4f906e0c8 100755 --- a/gradlew +++ b/gradlew @@ -130,7 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 5093609d5..107acd32c 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,21 +64,6 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line @@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 86b10bdc7..c376154b5 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,8 +1,6 @@ -plugins { id("scientifik.mpp") } +plugins { id("ru.mipt.npm.mpp") } kotlin.sourceSets { - all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } - commonMain { dependencies { api(project(":kmath-core")) @@ -17,4 +15,4 @@ kotlin.sourceSets { implementation(kotlin("reflect")) } } -} \ No newline at end of file +} diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt index 0e8151c04..798172799 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt @@ -7,20 +7,20 @@ import scientifik.kmath.operations.RealField /** * A Mathematical Syntax Tree node for mathematical expressions. */ -sealed class MST { +public sealed class MST { /** * A node containing raw string. * * @property value the value of this node. */ - data class Symbolic(val value: String) : MST() + public data class Symbolic(val value: String) : MST() /** * A node containing a numeric value or scalar. * * @property value the value of this number. */ - data class Numeric(val value: Number) : MST() + public data class Numeric(val value: Number) : MST() /** * A node containing an unary operation. @@ -28,9 +28,7 @@ sealed class MST { * @property operation the identifier of operation. * @property value the argument of this operation. */ - data class Unary(val operation: String, val value: MST) : MST() { - companion object - } + public data class Unary(val operation: String, val value: MST) : MST() /** * A node containing binary operation. @@ -39,9 +37,7 @@ sealed class MST { * @property left the left operand. * @property right the right operand. */ - data class Binary(val operation: String, val left: MST, val right: MST) : MST() { - companion object - } + public data class Binary(val operation: String, val left: MST, val right: MST) : MST() } // TODO add a function with named arguments @@ -53,7 +49,7 @@ sealed class MST { * @param node the node to evaluate. * @return the value of expression. */ -fun Algebra.evaluate(node: MST): T = when (node) { +public fun Algebra.evaluate(node: MST): T = when (node) { is MST.Numeric -> (this as? NumericAlgebra)?.number(node.value) ?: error("Numeric nodes are not supported by $this") is MST.Symbolic -> symbol(node.value) @@ -84,4 +80,4 @@ fun Algebra.evaluate(node: MST): T = when (node) { * @param algebra the algebra that provides operations. * @return the value of expression. */ -fun MST.interpret(algebra: Algebra): T = algebra.evaluate(this) +public fun MST.interpret(algebra: Algebra): T = algebra.evaluate(this) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt index 23deae24b..e4480e608 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt @@ -5,7 +5,7 @@ import scientifik.kmath.operations.* /** * [Algebra] over [MST] nodes. */ -object MstAlgebra : NumericAlgebra { +public object MstAlgebra : NumericAlgebra { override fun number(value: Number): MST = MST.Numeric(value) override fun symbol(value: String): MST = MST.Symbolic(value) @@ -20,7 +20,7 @@ object MstAlgebra : NumericAlgebra { /** * [Space] over [MST] nodes. */ -object MstSpace : Space, NumericAlgebra { +public object MstSpace : Space, NumericAlgebra { override val zero: MST = number(0.0) override fun number(value: Number): MST = MstAlgebra.number(value) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt index 3cee33956..9d8a6a804 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt @@ -2,7 +2,6 @@ package scientifik.kmath.ast import scientifik.kmath.expressions.* import scientifik.kmath.operations.* -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -13,7 +12,7 @@ import kotlin.contracts.contract * @property algebra the algebra that provides operations. * @property mst the [MST] node. */ -class MstExpression(val algebra: Algebra, val mst: MST) : Expression { +public class MstExpression(public val algebra: Algebra, public val mst: MST) : Expression { private inner class InnerAlgebra(val arguments: Map) : NumericAlgebra { override fun symbol(value: String): T = arguments[value] ?: algebra.symbol(value) override fun unaryOperation(operation: String, arg: T): T = algebra.unaryOperation(operation, arg) @@ -33,7 +32,7 @@ class MstExpression(val algebra: Algebra, val mst: MST) : Expression { /** * Builds [MstExpression] over [Algebra]. */ -inline fun , E : Algebra> A.mst( +public inline fun , E : Algebra> A.mst( mstAlgebra: E, block: E.() -> MST ): MstExpression = MstExpression(this, mstAlgebra.block()) @@ -41,7 +40,7 @@ inline fun , E : Algebra> A.mst( /** * Builds [MstExpression] over [Space]. */ -inline fun Space.mstInSpace(block: MstSpace.() -> MST): MstExpression { +public inline fun Space.mstInSpace(block: MstSpace.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return MstExpression(this, MstSpace.block()) } @@ -49,7 +48,7 @@ inline fun Space.mstInSpace(block: MstSpace.() -> MST): Mst /** * Builds [MstExpression] over [Ring]. */ -inline fun Ring.mstInRing(block: MstRing.() -> MST): MstExpression { +public inline fun Ring.mstInRing(block: MstRing.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return MstExpression(this, MstRing.block()) } @@ -57,7 +56,7 @@ inline fun Ring.mstInRing(block: MstRing.() -> MST): MstExp /** * Builds [MstExpression] over [Field]. */ -inline fun Field.mstInField(block: MstField.() -> MST): MstExpression { +public inline fun Field.mstInField(block: MstField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return MstExpression(this, MstField.block()) } @@ -65,7 +64,7 @@ inline fun Field.mstInField(block: MstField.() -> MST): Mst /** * Builds [MstExpression] over [ExtendedField]. */ -inline fun Field.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression { +public inline fun Field.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return MstExpression(this, MstExtendedField.block()) } @@ -73,7 +72,7 @@ inline fun Field.mstInExtendedField(block: MstExtendedField /** * Builds [MstExpression] over [FunctionalExpressionSpace]. */ -inline fun > FunctionalExpressionSpace.mstInSpace(block: MstSpace.() -> MST): MstExpression { +public inline fun > FunctionalExpressionSpace.mstInSpace(block: MstSpace.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return algebra.mstInSpace(block) } @@ -81,7 +80,7 @@ inline fun > FunctionalExpressionSpace.mstIn /** * Builds [MstExpression] over [FunctionalExpressionRing]. */ -inline fun > FunctionalExpressionRing.mstInRing(block: MstRing.() -> MST): MstExpression { +public inline fun > FunctionalExpressionRing.mstInRing(block: MstRing.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return algebra.mstInRing(block) } @@ -89,7 +88,7 @@ inline fun > FunctionalExpressionRing.mstInRi /** * Builds [MstExpression] over [FunctionalExpressionField]. */ -inline fun > FunctionalExpressionField.mstInField(block: MstField.() -> MST): MstExpression { +public inline fun > FunctionalExpressionField.mstInField(block: MstField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return algebra.mstInField(block) } @@ -97,7 +96,9 @@ inline fun > FunctionalExpressionField.mstIn /** * Builds [MstExpression] over [FunctionalExpressionExtendedField]. */ -inline fun > FunctionalExpressionExtendedField.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression { +public inline fun > FunctionalExpressionExtendedField.mstInExtendedField( + block: MstExtendedField.() -> MST +): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return algebra.mstInExtendedField(block) } diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt index cba335a8d..5733649e4 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt @@ -18,7 +18,7 @@ import scientifik.kmath.operations.SpaceOperations /** * TODO move to core */ -object ArithmeticsEvaluator : Grammar() { +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+)?") private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*") @@ -35,23 +35,23 @@ object ArithmeticsEvaluator : Grammar() { private val number: Parser by num use { MST.Numeric(text.toDouble()) } private val singular: Parser by id use { MST.Symbolic(text) } - private val unaryFunction: Parser by (id and skip(lpar) and parser(::subSumChain) and skip(rpar)) + private val unaryFunction: Parser by (id and -lpar and parser(::subSumChain) and -rpar) .map { (id, term) -> MST.Unary(id.text, term) } private val binaryFunction: Parser by id - .and(skip(lpar)) + .and(-lpar) .and(parser(::subSumChain)) - .and(skip(comma)) + .and(-comma) .and(parser(::subSumChain)) - .and(skip(rpar)) + .and(-rpar) .map { (id, left, right) -> MST.Binary(id.text, left, right) } private val term: Parser by number .or(binaryFunction) .or(unaryFunction) .or(singular) - .or(skip(minus) and parser(::term) map { MST.Unary(SpaceOperations.MINUS_OPERATION, it) }) - .or(skip(lpar) and parser(::subSumChain) and skip(rpar)) + .or(-minus and parser(::term) map { MST.Unary(SpaceOperations.MINUS_OPERATION, it) }) + .or(-lpar and parser(::subSumChain) and -rpar) private val powChain: Parser by leftAssociative(term = term, operator = pow) { a, _, b -> MST.Binary(PowerOperations.POW_OPERATION, a, b) @@ -86,7 +86,7 @@ object ArithmeticsEvaluator : Grammar() { * @receiver the string to parse. * @return the [MST] node. */ -fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryParseToEnd(this) +public fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryParseToEnd(this) /** * Parses the string into [MST]. @@ -94,4 +94,4 @@ fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryParseToEnd * @receiver the string to parse. * @return the [MST] node. */ -fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this) +public fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this) diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt index ee0ea15ff..5d563aceb 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt @@ -13,7 +13,7 @@ import kotlin.reflect.KClass /** * Compile given MST to an Expression using AST compiler */ -fun MST.compileWith(type: KClass, algebra: Algebra): Expression { +public fun MST.compileWith(type: KClass, algebra: Algebra): Expression { fun AsmBuilder.visit(node: MST) { when (node) { is MST.Symbolic -> { @@ -56,9 +56,9 @@ fun MST.compileWith(type: KClass, algebra: Algebra): Expression< /** * Compile an [MST] to ASM using given algebra */ -inline fun Algebra.expression(mst: MST): Expression = mst.compileWith(T::class, this) +public inline fun Algebra.expression(mst: MST): Expression = mst.compileWith(T::class, this) /** * Optimize performance of an [MstExpression] using ASM codegen */ -inline fun MstExpression.compile(): Expression = mst.compileWith(T::class, algebra) +public inline fun MstExpression.compile(): Expression = mst.compileWith(T::class, algebra) diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 63c832b7c..45eee7765 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -1,4 +1,4 @@ -plugins { id("scientifik.jvm") } +plugins { id("ru.mipt.npm.jvm") } description = "Commons math binding for kmath" dependencies { @@ -8,5 +8,3 @@ dependencies { api(project(":kmath-functions")) api("org.apache.commons:commons-math3:3.6.1") } - -kotlin.sourceSets.all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt index 9119991e5..a6f905471 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt +++ b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt @@ -7,14 +7,13 @@ import scientifik.kmath.operations.ExtendedField import scientifik.kmath.operations.Field import scientifik.kmath.operations.invoke import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty /** * A field wrapping commons-math derivative structures */ -class DerivativeStructureField( - val order: Int, - val parameters: Map +public class DerivativeStructureField( + public val order: Int, + public val parameters: Map ) : ExtendedField { override val zero: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size) } override val one: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size, 1.0) } @@ -23,25 +22,24 @@ class DerivativeStructureField( DerivativeStructure(parameters.size, order, parameters.keys.indexOf(key), value) } - val variable: ReadOnlyProperty = object : ReadOnlyProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): DerivativeStructure = - variables[property.name] ?: error("A variable with name ${property.name} does not exist") + public val variable: ReadOnlyProperty = ReadOnlyProperty { _, property -> + variables[property.name] ?: error("A variable with name ${property.name} does not exist") } - fun variable(name: String, default: DerivativeStructure? = null): DerivativeStructure = + public fun variable(name: String, default: DerivativeStructure? = null): DerivativeStructure = variables[name] ?: default ?: error("A variable with name $name does not exist") - fun Number.const(): DerivativeStructure = DerivativeStructure(order, parameters.size, toDouble()) + public fun Number.const(): DerivativeStructure = DerivativeStructure(order, parameters.size, toDouble()) - fun DerivativeStructure.deriv(parName: String, order: Int = 1): Double { + public fun DerivativeStructure.deriv(parName: String, order: Int = 1): Double { return deriv(mapOf(parName to order)) } - fun DerivativeStructure.deriv(orders: Map): Double { + public fun DerivativeStructure.deriv(orders: Map): Double { return getPartialDerivative(*parameters.keys.map { orders[it] ?: 0 }.toIntArray()) } - fun DerivativeStructure.deriv(vararg orders: Pair): Double = deriv(mapOf(*orders)) + public fun DerivativeStructure.deriv(vararg orders: Pair): Double = deriv(mapOf(*orders)) override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b) @@ -61,7 +59,6 @@ class DerivativeStructureField( override fun asin(arg: DerivativeStructure): DerivativeStructure = arg.asin() override fun acos(arg: DerivativeStructure): DerivativeStructure = arg.acos() override fun atan(arg: DerivativeStructure): DerivativeStructure = arg.atan() - override fun sinh(arg: DerivativeStructure): DerivativeStructure = arg.sinh() override fun cosh(arg: DerivativeStructure): DerivativeStructure = arg.cosh() override fun tanh(arg: DerivativeStructure): DerivativeStructure = arg.tanh() @@ -75,7 +72,7 @@ class DerivativeStructureField( else -> arg.pow(pow.toDouble()) } - fun power(arg: DerivativeStructure, pow: DerivativeStructure): DerivativeStructure = arg.pow(pow) + public fun power(arg: DerivativeStructure, pow: DerivativeStructure): DerivativeStructure = arg.pow(pow) override fun exp(arg: DerivativeStructure): DerivativeStructure = arg.exp() override fun ln(arg: DerivativeStructure): DerivativeStructure = arg.log() @@ -88,7 +85,8 @@ class DerivativeStructureField( /** * A constructs that creates a derivative structure with required order on-demand */ -class DiffExpression(val function: DerivativeStructureField.() -> DerivativeStructure) : Expression { +public class DiffExpression(public val function: DerivativeStructureField.() -> DerivativeStructure) : + Expression { override operator fun invoke(arguments: Map): Double = DerivativeStructureField( 0, arguments @@ -98,21 +96,20 @@ class DiffExpression(val function: DerivativeStructureField.() -> DerivativeStru * Get the derivative expression with given orders * TODO make result [DiffExpression] */ - fun derivative(orders: Map): Expression = object : Expression { - override operator fun invoke(arguments: Map): Double = - (DerivativeStructureField(orders.values.max() ?: 0, arguments)) { function().deriv(orders) } + public fun derivative(orders: Map): Expression = Expression { arguments -> + (DerivativeStructureField(orders.values.max() ?: 0, arguments)) { function().deriv(orders) } } //TODO add gradient and maybe other vector operators } -fun DiffExpression.derivative(vararg orders: Pair): Expression = derivative(mapOf(*orders)) -fun DiffExpression.derivative(name: String): Expression = derivative(name to 1) +public fun DiffExpression.derivative(vararg orders: Pair): Expression = derivative(mapOf(*orders)) +public fun DiffExpression.derivative(name: String): Expression = derivative(name to 1) /** * A context for [DiffExpression] (not to be confused with [DerivativeStructure]) */ -object DiffExpressionAlgebra : ExpressionAlgebra, Field { +public object DiffExpressionAlgebra : ExpressionAlgebra, Field { override fun variable(name: String, default: Double?): DiffExpression = DiffExpression { variable(name, default?.const()) } diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 7f9922de4..e315e1640 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,6 +1,7 @@ -plugins { id("scientifik.mpp") } +plugins { id("ru.mipt.npm.mpp") } -kotlin.sourceSets { - all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } - commonMain { dependencies { api(project(":kmath-memory")) } } +kotlin.sourceSets.commonMain { + dependencies { + api(project(":kmath-memory")) + } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/Domain.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/Domain.kt index 341383bfb..c4c823bf2 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/Domain.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/Domain.kt @@ -7,14 +7,14 @@ import scientifik.kmath.linear.Point * * @param T the type of element of this domain. */ -interface Domain { +public interface Domain { /** * Checks if the specified point is contained in this domain. */ - operator fun contains(point: Point): Boolean + public operator fun contains(point: Point): Boolean /** * Number of hyperspace dimensions. */ - val dimension: Int + public val dimension: Int } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt index 66798c42f..e118282bf 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt @@ -25,7 +25,7 @@ import scientifik.kmath.structures.indices * * @author Alexander Nozik */ -class HyperSquareDomain(private val lower: RealBuffer, private val upper: RealBuffer) : RealDomain { +public class HyperSquareDomain(private val lower: RealBuffer, private val upper: RealBuffer) : RealDomain { override operator fun contains(point: Point): Boolean = point.indices.all { i -> point[i] in lower[i]..upper[i] diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/RealDomain.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/RealDomain.kt index 7507ccd59..b1da63519 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/RealDomain.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/RealDomain.kt @@ -22,8 +22,8 @@ import scientifik.kmath.linear.Point * * @author Alexander Nozik */ -interface RealDomain : Domain { - fun nearestInDomain(point: Point): Point +public interface RealDomain : Domain { + public fun nearestInDomain(point: Point): Point /** * The lower edge for the domain going down from point @@ -31,7 +31,7 @@ interface RealDomain : Domain { * @param point * @return */ - fun getLowerBound(num: Int, point: Point): Double? + public fun getLowerBound(num: Int, point: Point): Double? /** * The upper edge of the domain going up from point @@ -39,25 +39,25 @@ interface RealDomain : Domain { * @param point * @return */ - fun getUpperBound(num: Int, point: Point): Double? + public fun getUpperBound(num: Int, point: Point): Double? /** * Global lower edge * @param num * @return */ - fun getLowerBound(num: Int): Double? + public fun getLowerBound(num: Int): Double? /** * Global upper edge * @param num * @return */ - fun getUpperBound(num: Int): Double? + public fun getUpperBound(num: Int): Double? /** * Hyper volume * @return */ - fun volume(): Double + public fun volume(): Double } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt index 595a3dbe7..5c9170663 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt @@ -17,7 +17,7 @@ package scientifik.kmath.domains import scientifik.kmath.linear.Point -class UnconstrainedDomain(override val dimension: Int) : RealDomain { +public class UnconstrainedDomain(override val dimension: Int) : RealDomain { override operator fun contains(point: Point): Boolean = true override fun getLowerBound(num: Int, point: Point): Double? = Double.NEGATIVE_INFINITY diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt index 280dc7d66..5b47476d8 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt @@ -3,8 +3,8 @@ package scientifik.kmath.domains import scientifik.kmath.linear.Point import scientifik.kmath.structures.asBuffer -inline class UnivariateDomain(val range: ClosedFloatingPointRange) : RealDomain { - operator fun contains(d: Double): Boolean = range.contains(d) +public inline class UnivariateDomain(public val range: ClosedFloatingPointRange) : RealDomain { + public operator fun contains(d: Double): Boolean = range.contains(d) override operator fun contains(point: Point): Boolean { require(point.size == 0) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt index fd11c246d..a21735f27 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt @@ -5,45 +5,37 @@ import scientifik.kmath.operations.Algebra /** * An elementary function that could be invoked on a map of arguments */ -interface Expression { +public fun interface Expression { /** * Calls this expression from arguments. * * @param arguments the map of arguments. * @return the value. */ - operator fun invoke(arguments: Map): T + public operator fun invoke(arguments: Map): T - companion object + public companion object } -/** - * Create simple lazily evaluated expression inside given algebra - */ -fun Algebra.expression(block: Algebra.(arguments: Map) -> T): Expression = - object : Expression { - override operator fun invoke(arguments: Map): T = block(arguments) - } - /** * Calls this expression from arguments. * * @param pairs the pair of arguments' names to values. * @return the value. */ -operator fun Expression.invoke(vararg pairs: Pair): T = invoke(mapOf(*pairs)) +public operator fun Expression.invoke(vararg pairs: Pair): T = invoke(mapOf(*pairs)) /** * A context for expression construction */ -interface ExpressionAlgebra : Algebra { +public interface ExpressionAlgebra : Algebra { /** * Introduce a variable into expression context */ - fun variable(name: String, default: T? = null): E + public fun variable(name: String, default: T? = null): E /** * A constant expression which does not depend on arguments */ - fun const(value: T): E + public fun const(value: T): E } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt index d36c31a0d..58f874671 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -39,7 +39,8 @@ internal class FunctionalConstProductExpression( * * @param algebra The algebra to provide for Expressions built. */ -abstract class FunctionalExpressionAlgebra>(val algebra: A) : ExpressionAlgebra> { +public abstract class FunctionalExpressionAlgebra>(public val algebra: A) : + ExpressionAlgebra> { /** * Builds an Expression of constant expression which does not depend on arguments. */ @@ -66,7 +67,7 @@ abstract class FunctionalExpressionAlgebra>(val algebra: A) : /** * A context class for [Expression] construction for [Space] algebras. */ -open class FunctionalExpressionSpace>(algebra: A) : +public open class FunctionalExpressionSpace>(algebra: A) : FunctionalExpressionAlgebra(algebra), Space> { override val zero: Expression get() = const(algebra.zero) @@ -82,10 +83,10 @@ open class FunctionalExpressionSpace>(algebra: A) : override fun multiply(a: Expression, k: Number): Expression = FunctionalConstProductExpression(algebra, a, k) - operator fun Expression.plus(arg: T): Expression = this + const(arg) - operator fun Expression.minus(arg: T): Expression = this - const(arg) - operator fun T.plus(arg: Expression): Expression = arg + this - operator fun T.minus(arg: Expression): Expression = arg - this + public operator fun Expression.plus(arg: T): Expression = this + const(arg) + public operator fun Expression.minus(arg: T): Expression = this - const(arg) + public operator fun T.plus(arg: Expression): Expression = arg + this + public operator fun T.minus(arg: Expression): Expression = arg - this override fun unaryOperation(operation: String, arg: Expression): Expression = super.unaryOperation(operation, arg) @@ -94,7 +95,7 @@ open class FunctionalExpressionSpace>(algebra: A) : super.binaryOperation(operation, left, right) } -open class FunctionalExpressionRing(algebra: A) : FunctionalExpressionSpace(algebra), +public open class FunctionalExpressionRing(algebra: A) : FunctionalExpressionSpace(algebra), Ring> where A : Ring, A : NumericAlgebra { override val one: Expression get() = const(algebra.one) @@ -105,8 +106,8 @@ open class FunctionalExpressionRing(algebra: A) : FunctionalExpressionSpac override fun multiply(a: Expression, b: Expression): Expression = binaryOperation(RingOperations.TIMES_OPERATION, a, b) - operator fun Expression.times(arg: T): Expression = this * const(arg) - operator fun T.times(arg: Expression): Expression = arg * this + public operator fun Expression.times(arg: T): Expression = this * const(arg) + public operator fun T.times(arg: Expression): Expression = arg * this override fun unaryOperation(operation: String, arg: Expression): Expression = super.unaryOperation(operation, arg) @@ -115,7 +116,7 @@ open class FunctionalExpressionRing(algebra: A) : FunctionalExpressionSpac super.binaryOperation(operation, left, right) } -open class FunctionalExpressionField(algebra: A) : +public open class FunctionalExpressionField(algebra: A) : FunctionalExpressionRing(algebra), Field> where A : Field, A : NumericAlgebra { /** @@ -124,8 +125,8 @@ open class FunctionalExpressionField(algebra: A) : override fun divide(a: Expression, b: Expression): Expression = binaryOperation(FieldOperations.DIV_OPERATION, a, b) - operator fun Expression.div(arg: T): Expression = this / const(arg) - operator fun T.div(arg: Expression): Expression = arg / this + public operator fun Expression.div(arg: T): Expression = this / const(arg) + public operator fun T.div(arg: Expression): Expression = arg / this override fun unaryOperation(operation: String, arg: Expression): Expression = super.unaryOperation(operation, arg) @@ -134,7 +135,7 @@ open class FunctionalExpressionField(algebra: A) : super.binaryOperation(operation, left, right) } -open class FunctionalExpressionExtendedField(algebra: A) : +public open class FunctionalExpressionExtendedField(algebra: A) : FunctionalExpressionField(algebra), ExtendedField> where A : ExtendedField, A : NumericAlgebra { override fun sin(arg: Expression): Expression = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) @@ -156,14 +157,14 @@ open class FunctionalExpressionExtendedField(algebra: A) : super.binaryOperation(operation, left, right) } -inline fun > A.expressionInSpace(block: FunctionalExpressionSpace.() -> Expression): Expression = +public inline fun > A.expressionInSpace(block: FunctionalExpressionSpace.() -> Expression): Expression = FunctionalExpressionSpace(this).block() -inline fun > A.expressionInRing(block: FunctionalExpressionRing.() -> Expression): Expression = +public inline fun > A.expressionInRing(block: FunctionalExpressionRing.() -> Expression): Expression = FunctionalExpressionRing(this).block() -inline fun > A.expressionInField(block: FunctionalExpressionField.() -> Expression): Expression = +public inline fun > A.expressionInField(block: FunctionalExpressionField.() -> Expression): Expression = FunctionalExpressionField(this).block() -inline fun > A.expressionInExtendedField(block: FunctionalExpressionExtendedField.() -> Expression): Expression = +public inline fun > A.expressionInExtendedField(block: FunctionalExpressionExtendedField.() -> Expression): Expression = FunctionalExpressionExtendedField(this).block() diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/expressionBuilders.kt similarity index 65% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/expressionBuilders.kt index 8d0b82a89..737f94b38 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/expressionBuilders.kt @@ -11,7 +11,7 @@ import kotlin.contracts.contract /** * Creates a functional expression with this [Space]. */ -inline fun Space.spaceExpression(block: FunctionalExpressionSpace>.() -> Expression): Expression { +public inline fun Space.spaceExpression(block: FunctionalExpressionSpace>.() -> Expression): Expression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return FunctionalExpressionSpace(this).block() } @@ -19,7 +19,7 @@ inline fun Space.spaceExpression(block: FunctionalExpressionSpace Ring.ringExpression(block: FunctionalExpressionRing>.() -> Expression): Expression { +public inline fun Ring.ringExpression(block: FunctionalExpressionRing>.() -> Expression): Expression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return FunctionalExpressionRing(this).block() } @@ -27,7 +27,7 @@ inline fun Ring.ringExpression(block: FunctionalExpressionRing /** * Creates a functional expression with this [Field]. */ -inline fun Field.fieldExpression(block: FunctionalExpressionField>.() -> Expression): Expression { +public inline fun Field.fieldExpression(block: FunctionalExpressionField>.() -> Expression): Expression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return FunctionalExpressionField(this).block() } @@ -35,7 +35,7 @@ inline fun Field.fieldExpression(block: FunctionalExpressionField ExtendedField.extendedFieldExpression(block: FunctionalExpressionExtendedField>.() -> Expression): Expression { +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/scientifik/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt index 343b8287e..c28cc5ab7 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt @@ -7,7 +7,7 @@ import scientifik.kmath.structures.* /** * Basic implementation of Matrix space based on [NDStructure] */ -class BufferMatrixContext>( +public class BufferMatrixContext>( override val elementContext: R, private val bufferFactory: BufferFactory ) : GenericMatrixContext { @@ -19,11 +19,11 @@ class BufferMatrixContext>( override fun point(size: Int, initializer: (Int) -> T): Point = bufferFactory(size, initializer) - companion object + public companion object } @Suppress("OVERRIDE_BY_INLINE") -object RealMatrixContext : GenericMatrixContext { +public object RealMatrixContext : GenericMatrixContext { override val elementContext: RealField get() = RealField @@ -35,10 +35,10 @@ object RealMatrixContext : GenericMatrixContext { override inline fun point(size: Int, initializer: (Int) -> Double): Point = RealBuffer(size, initializer) } -class BufferMatrix( +public class BufferMatrix( override val rowNum: Int, override val colNum: Int, - val buffer: Buffer, + public val buffer: Buffer, override val features: Set = emptySet() ) : FeaturedMatrix { @@ -90,7 +90,7 @@ class BufferMatrix( /** * Optimized dot product for real matrices */ -infix fun BufferMatrix.dot(other: BufferMatrix): BufferMatrix { +public infix fun BufferMatrix.dot(other: BufferMatrix): BufferMatrix { require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } val array = DoubleArray(this.rowNum * other.colNum) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt index 9b60bf719..3e5116435 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt @@ -11,11 +11,9 @@ import kotlin.math.sqrt /** * A 2d structure plus optional matrix-specific features */ -interface FeaturedMatrix : Matrix { - +public interface FeaturedMatrix : Matrix { override val shape: IntArray get() = intArrayOf(rowNum, colNum) - - val features: Set + public val features: Set /** * Suggest new feature for this matrix. The result is the new matrix that may or may not reuse existing data structure. @@ -23,12 +21,12 @@ interface FeaturedMatrix : Matrix { * The implementation does not guarantee to check that matrix actually have the feature, so one should be careful to * add only those features that are valid. */ - fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix + public fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix - companion object + public companion object } -inline fun Structure2D.Companion.real(rows: Int, columns: Int, initializer: (Int, Int) -> Double): Matrix { +public inline fun Structure2D.Companion.real(rows: Int, columns: Int, initializer: (Int, Int) -> Double): Matrix { contract { callsInPlace(initializer) } return MatrixContext.real.produce(rows, columns, initializer) } @@ -36,31 +34,31 @@ inline fun Structure2D.Companion.real(rows: Int, columns: Int, initializer: (Int /** * Build a square matrix from given elements. */ -fun Structure2D.Companion.square(vararg elements: T): FeaturedMatrix { +public fun Structure2D.Companion.square(vararg elements: T): FeaturedMatrix { val size: Int = sqrt(elements.size.toDouble()).toInt() require(size * size == elements.size) { "The number of elements ${elements.size} is not a full square" } val buffer = elements.asBuffer() return BufferMatrix(size, size, buffer) } -val Matrix<*>.features: Set get() = (this as? FeaturedMatrix)?.features ?: emptySet() +public val Matrix<*>.features: Set get() = (this as? FeaturedMatrix)?.features ?: emptySet() /** * Check if matrix has the given feature class */ -inline fun Matrix<*>.hasFeature(): Boolean = +public inline fun Matrix<*>.hasFeature(): Boolean = features.find { it is T } != null /** * Get the first feature matching given class. Does not guarantee that matrix has only one feature matching the criteria */ -inline fun Matrix<*>.getFeature(): T? = +public inline fun Matrix<*>.getFeature(): T? = features.filterIsInstance().firstOrNull() /** * Diagonal matrix of ones. The matrix is virtual no actual matrix is created */ -fun > GenericMatrixContext.one(rows: Int, columns: Int): FeaturedMatrix = +public fun > GenericMatrixContext.one(rows: Int, columns: Int): FeaturedMatrix = VirtualMatrix(rows, columns, DiagonalFeature) { i, j -> if (i == j) elementContext.one else elementContext.zero } @@ -69,20 +67,20 @@ fun > GenericMatrixContext.one(rows: Int, columns: In /** * A virtual matrix of zeroes */ -fun > GenericMatrixContext.zero(rows: Int, columns: Int): FeaturedMatrix = +public fun > GenericMatrixContext.zero(rows: Int, columns: Int): FeaturedMatrix = VirtualMatrix(rows, columns) { _, _ -> elementContext.zero } -class TransposedFeature(val original: Matrix) : MatrixFeature +public class TransposedFeature(public val original: Matrix) : MatrixFeature /** * Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A` */ -fun Matrix.transpose(): Matrix { - return this.getFeature>()?.original ?: VirtualMatrix( - this.colNum, - this.rowNum, +public fun Matrix.transpose(): Matrix { + return getFeature>()?.original ?: VirtualMatrix( + colNum, + rowNum, setOf(TransposedFeature(this)) ) { i, j -> get(j, i) } } -infix fun Matrix.dot(other: Matrix): Matrix = with(MatrixContext.real) { dot(other) } +public infix fun Matrix.dot(other: Matrix): Matrix = with(MatrixContext.real) { dot(other) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt index f3e4f648f..2bad1aa46 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt @@ -7,19 +7,20 @@ import scientifik.kmath.operations.invoke import scientifik.kmath.structures.BufferAccessor2D import scientifik.kmath.structures.Matrix import scientifik.kmath.structures.Structure2D +import kotlin.contracts.contract import kotlin.reflect.KClass /** * Common implementation of [LUPDecompositionFeature] */ -class LUPDecomposition( - val context: GenericMatrixContext>, - val lu: Structure2D, - val pivot: IntArray, +public class LUPDecomposition( + public val context: GenericMatrixContext>, + public val lu: Structure2D, + public val pivot: IntArray, private val even: Boolean ) : LUPDecompositionFeature, DeterminantFeature { - - val elementContext: Field get() = context.elementContext + public val elementContext: Field + get() = context.elementContext /** * Returns the matrix L of the decomposition. @@ -44,7 +45,6 @@ class LUPDecomposition( if (j >= i) lu[i, j] else elementContext.zero } - /** * Returns the P rows permutation matrix. * @@ -55,7 +55,6 @@ class LUPDecomposition( if (j == pivot[i]) elementContext.one else elementContext.zero } - /** * Return the determinant of the matrix * @return determinant of the matrix @@ -66,22 +65,19 @@ class LUPDecomposition( } -fun , F : Field> GenericMatrixContext.abs(value: T): T = +public fun , F : Field> GenericMatrixContext.abs(value: T): T = if (value > elementContext.zero) value else elementContext { -value } - /** * Create a lup decomposition of generic matrix */ -fun , F : Field> GenericMatrixContext.lup( +public inline fun , F : Field> GenericMatrixContext.lup( type: KClass, matrix: Matrix, checkSingular: (T) -> Boolean ): LUPDecomposition { - if (matrix.rowNum != matrix.colNum) { - error("LU decomposition supports only square matrices") - } - + contract { callsInPlace(checkSingular) } + require(matrix.rowNum == matrix.colNum) { "LU decomposition supports only square matrices" } val m = matrix.colNum val pivot = IntArray(matrix.rowNum) @@ -154,15 +150,18 @@ fun , F : Field> GenericMatrixContext.lup( } } -inline fun , F : Field> GenericMatrixContext.lup( +public inline fun , F : Field> GenericMatrixContext.lup( matrix: Matrix, - noinline checkSingular: (T) -> Boolean -): LUPDecomposition = lup(T::class, matrix, checkSingular) + checkSingular: (T) -> Boolean +): LUPDecomposition { + contract { callsInPlace(checkSingular) } + return lup(T::class, matrix, checkSingular) +} -fun GenericMatrixContext.lup(matrix: Matrix): LUPDecomposition = +public fun GenericMatrixContext.lup(matrix: Matrix): LUPDecomposition = lup(Double::class, matrix) { it < 1e-11 } -fun LUPDecomposition.solve(type: KClass, matrix: Matrix): Matrix { +public fun LUPDecomposition.solve(type: KClass, matrix: Matrix): Matrix { require(matrix.rowNum == pivot.size) { "Matrix dimension mismatch. Expected ${pivot.size}, but got ${matrix.colNum}" } BufferAccessor2D(type, matrix.rowNum, matrix.colNum).run { @@ -207,27 +206,31 @@ fun LUPDecomposition.solve(type: KClass, matrix: Matrix): Mat } } -inline fun LUPDecomposition.solve(matrix: Matrix): Matrix = solve(T::class, matrix) +public inline fun LUPDecomposition.solve(matrix: Matrix): Matrix = solve(T::class, matrix) /** * Solve a linear equation **a*x = b** */ -inline fun , F : Field> GenericMatrixContext.solve( +public inline fun , F : Field> GenericMatrixContext.solve( a: Matrix, b: Matrix, - noinline checkSingular: (T) -> Boolean + checkSingular: (T) -> Boolean ): Matrix { + contract { callsInPlace(checkSingular) } // Use existing decomposition if it is provided by matrix val decomposition = a.getFeature() ?: lup(T::class, a, checkSingular) return decomposition.solve(T::class, b) } -fun RealMatrixContext.solve(a: Matrix, b: Matrix): Matrix = solve(a, b) { it < 1e-11 } +public fun RealMatrixContext.solve(a: Matrix, b: Matrix): Matrix = solve(a, b) { it < 1e-11 } -inline fun , F : Field> GenericMatrixContext.inverse( +public inline fun , F : Field> GenericMatrixContext.inverse( matrix: Matrix, - noinline checkSingular: (T) -> Boolean -): Matrix = solve(matrix, one(matrix.rowNum, matrix.colNum), checkSingular) + checkSingular: (T) -> Boolean +): Matrix { + contract { callsInPlace(checkSingular) } + return solve(matrix, one(matrix.rowNum, matrix.colNum), checkSingular) +} -fun RealMatrixContext.inverse(matrix: Matrix): Matrix = +public fun RealMatrixContext.inverse(matrix: Matrix): Matrix = solve(matrix, one(matrix.rowNum, matrix.colNum)) { it < 1e-11 } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt index fb49d18ed..4daa03e5d 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt @@ -4,25 +4,25 @@ import scientifik.kmath.structures.Buffer import scientifik.kmath.structures.Matrix import scientifik.kmath.structures.VirtualBuffer -typealias Point = Buffer +public typealias Point = Buffer /** * A group of methods to resolve equation A dot X = B, where A and B are matrices or vectors */ -interface LinearSolver { - fun solve(a: Matrix, b: Matrix): Matrix - fun solve(a: Matrix, b: Point): Point = solve(a, b.asMatrix()).asPoint() - fun inverse(a: Matrix): Matrix +public interface LinearSolver { + public fun solve(a: Matrix, b: Matrix): Matrix + public fun solve(a: Matrix, b: Point): Point = solve(a, b.asMatrix()).asPoint() + public fun inverse(a: Matrix): Matrix } /** * Convert matrix to vector if it is possible */ -fun Matrix.asPoint(): Point = +public fun Matrix.asPoint(): Point = if (this.colNum == 1) { VirtualBuffer(rowNum) { get(it, 0) } } else { error("Can't convert matrix with more than one column to vector") } -fun Point.asMatrix(): VirtualMatrix = VirtualMatrix(size, 1) { i, _ -> get(i) } +public fun Point.asMatrix(): VirtualMatrix = VirtualMatrix(size, 1) { i, _ -> get(i) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixBuilder.kt index 390362f8c..5efa53bc2 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixBuilder.kt @@ -5,8 +5,8 @@ import scientifik.kmath.structures.BufferFactory import scientifik.kmath.structures.Structure2D import scientifik.kmath.structures.asBuffer -class MatrixBuilder(val rows: Int, val columns: Int) { - operator fun invoke(vararg elements: T): FeaturedMatrix { +public class MatrixBuilder(public val rows: Int, public val columns: Int) { + public operator fun invoke(vararg elements: T): FeaturedMatrix { require(rows * columns == elements.size) { "The number of elements ${elements.size} is not equal $rows * $columns" } val buffer = elements.asBuffer() return BufferMatrix(rows, columns, buffer) @@ -15,14 +15,14 @@ class MatrixBuilder(val rows: Int, val columns: Int) { //TODO add specific matrix builder functions like diagonal, etc } -fun Structure2D.Companion.build(rows: Int, columns: Int): MatrixBuilder = MatrixBuilder(rows, columns) +public fun Structure2D.Companion.build(rows: Int, columns: Int): MatrixBuilder = MatrixBuilder(rows, columns) -fun Structure2D.Companion.row(vararg values: T): FeaturedMatrix { +public fun Structure2D.Companion.row(vararg values: T): FeaturedMatrix { val buffer = values.asBuffer() return BufferMatrix(1, values.size, buffer) } -inline fun Structure2D.Companion.row( +public inline fun Structure2D.Companion.row( size: Int, factory: BufferFactory = Buffer.Companion::auto, noinline builder: (Int) -> T @@ -31,12 +31,12 @@ inline fun Structure2D.Companion.row( return BufferMatrix(1, size, buffer) } -fun Structure2D.Companion.column(vararg values: T): FeaturedMatrix { +public fun Structure2D.Companion.column(vararg values: T): FeaturedMatrix { val buffer = values.asBuffer() return BufferMatrix(values.size, 1, buffer) } -inline fun Structure2D.Companion.column( +public inline fun Structure2D.Companion.column( size: Int, factory: BufferFactory = Buffer.Companion::auto, noinline builder: (Int) -> T diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt index 763bb1615..13d4e68b9 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt @@ -12,30 +12,31 @@ import scientifik.kmath.structures.asSequence /** * Basic operations on matrices. Operates on [Matrix] */ -interface MatrixContext : SpaceOperations> { +public interface MatrixContext : SpaceOperations> { /** * Produce a matrix with this context and given dimensions */ - fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): Matrix + public fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): Matrix - infix fun Matrix.dot(other: Matrix): Matrix + public infix fun Matrix.dot(other: Matrix): Matrix - infix fun Matrix.dot(vector: Point): Point + public infix fun Matrix.dot(vector: Point): Point - operator fun Matrix.times(value: T): Matrix + public operator fun Matrix.times(value: T): Matrix - operator fun T.times(m: Matrix): Matrix = m * this + public operator fun T.times(m: Matrix): Matrix = m * this - companion object { + public companion object { /** * Non-boxing double matrix */ - val real: RealMatrixContext = RealMatrixContext + public val real: RealMatrixContext + get() = RealMatrixContext /** * A structured matrix with custom buffer */ - fun > buffered( + public fun > buffered( ring: R, bufferFactory: BufferFactory = Buffer.Companion::boxing ): GenericMatrixContext = BufferMatrixContext(ring, bufferFactory) @@ -43,21 +44,21 @@ interface MatrixContext : SpaceOperations> { /** * Automatic buffered matrix, unboxed if it is possible */ - inline fun > auto(ring: R): GenericMatrixContext = + public inline fun > auto(ring: R): GenericMatrixContext = buffered(ring, Buffer.Companion::auto) } } -interface GenericMatrixContext> : MatrixContext { +public interface GenericMatrixContext> : MatrixContext { /** * The ring context for matrix elements */ - val elementContext: R + public val elementContext: R /** * Produce a point compatible with matrix space */ - fun point(size: Int, initializer: (Int) -> T): Point + public fun point(size: Int, initializer: (Int) -> T): Point override infix fun Matrix.dot(other: Matrix): Matrix { //TODO add typed error @@ -102,7 +103,7 @@ interface GenericMatrixContext> : MatrixContext { override fun multiply(a: Matrix, k: Number): Matrix = produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } } - operator fun Number.times(matrix: FeaturedMatrix): Matrix = matrix * this + public operator fun Number.times(matrix: FeaturedMatrix): Matrix = matrix * this override operator fun Matrix.times(value: T): Matrix = produce(rowNum, colNum) { i, j -> elementContext { get(i, j) * value } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixFeatures.kt index 87cfe21b0..3448a2e7c 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixFeatures.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixFeatures.kt @@ -4,59 +4,59 @@ package scientifik.kmath.linear * A marker interface representing some matrix feature like diagonal, sparse, zero, etc. Features used to optimize matrix * operations performance in some cases. */ -interface MatrixFeature +public interface MatrixFeature /** * The matrix with this feature is considered to have only diagonal non-null elements */ -object DiagonalFeature : MatrixFeature +public object DiagonalFeature : MatrixFeature /** * Matrix with this feature has all zero elements */ -object ZeroFeature : MatrixFeature +public object ZeroFeature : MatrixFeature /** * Matrix with this feature have unit elements on diagonal and zero elements in all other places */ -object UnitFeature : MatrixFeature +public object UnitFeature : MatrixFeature /** * Inverted matrix feature */ -interface InverseMatrixFeature : MatrixFeature { - val inverse: FeaturedMatrix +public interface InverseMatrixFeature : MatrixFeature { + public val inverse: FeaturedMatrix } /** * A determinant container */ -interface DeterminantFeature : MatrixFeature { - val determinant: T +public interface DeterminantFeature : MatrixFeature { + public val determinant: T } @Suppress("FunctionName") -fun DeterminantFeature(determinant: T): DeterminantFeature = object : DeterminantFeature { +public fun DeterminantFeature(determinant: T): DeterminantFeature = object : DeterminantFeature { override val determinant: T = determinant } /** * Lower triangular matrix */ -object LFeature : MatrixFeature +public object LFeature : MatrixFeature /** * Upper triangular feature */ -object UFeature : MatrixFeature +public object UFeature : MatrixFeature /** * TODO add documentation */ -interface LUPDecompositionFeature : MatrixFeature { - val l: FeaturedMatrix - val u: FeaturedMatrix - val p: FeaturedMatrix +public interface LUPDecompositionFeature : MatrixFeature { + public val l: FeaturedMatrix + public val u: FeaturedMatrix + public val p: FeaturedMatrix } //TODO add sparse matrix feature diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VectorSpace.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VectorSpace.kt index 82e5c7ef6..a75523f7c 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VectorSpace.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VectorSpace.kt @@ -10,12 +10,12 @@ import scientifik.kmath.structures.BufferFactory * A linear space for vectors. * Could be used on any point-like structure */ -interface VectorSpace> : Space> { - val size: Int - val space: S +public interface VectorSpace> : Space> { + public val size: Int + public val space: S override val zero: Point get() = produce { space.zero } - fun produce(initializer: (Int) -> T): Point + public fun produce(initializer: (Int) -> T): Point /** * Produce a space-element of this vector space for expressions @@ -28,13 +28,13 @@ interface VectorSpace> : Space> { //TODO add basis - companion object { + public companion object { private val realSpaceCache: MutableMap> = hashMapOf() /** * Non-boxing double vector space */ - fun real(size: Int): BufferVectorSpace = realSpaceCache.getOrPut(size) { + public fun real(size: Int): BufferVectorSpace = realSpaceCache.getOrPut(size) { BufferVectorSpace( size, RealField, @@ -45,7 +45,7 @@ interface VectorSpace> : Space> { /** * A structured vector space with custom buffer */ - fun > buffered( + public fun > buffered( size: Int, space: S, bufferFactory: BufferFactory = Buffer.Companion::boxing @@ -54,16 +54,16 @@ interface VectorSpace> : Space> { /** * Automatic buffered vector, unboxed if it is possible */ - inline fun > auto(size: Int, space: S): VectorSpace = + public inline fun > auto(size: Int, space: S): VectorSpace = buffered(size, space, Buffer.Companion::auto) } } -class BufferVectorSpace>( +public class BufferVectorSpace>( override val size: Int, override val space: S, - val bufferFactory: BufferFactory + public val bufferFactory: BufferFactory ) : VectorSpace { override fun produce(initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) //override fun produceElement(initializer: (Int) -> T): Vector = BufferVector(this, produce(initializer)) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt index 5266dc884..f6794ce01 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt @@ -2,14 +2,18 @@ package scientifik.kmath.linear import scientifik.kmath.structures.Matrix -class VirtualMatrix( +public class VirtualMatrix( override val rowNum: Int, override val colNum: Int, override val features: Set = emptySet(), - val generator: (i: Int, j: Int) -> T + public val generator: (i: Int, j: Int) -> T ) : FeaturedMatrix { - - constructor(rowNum: Int, colNum: Int, vararg features: MatrixFeature, generator: (i: Int, j: Int) -> T) : this( + public constructor( + rowNum: Int, + colNum: Int, + vararg features: MatrixFeature, + generator: (i: Int, j: Int) -> T + ) : this( rowNum, colNum, setOf(*features), @@ -42,18 +46,15 @@ class VirtualMatrix( } - companion object { + public companion object { /** * Wrap a matrix adding additional features to it */ - fun wrap(matrix: Matrix, vararg features: MatrixFeature): FeaturedMatrix { - return if (matrix is VirtualMatrix) { + public fun wrap(matrix: Matrix, vararg features: MatrixFeature): FeaturedMatrix { + return if (matrix is VirtualMatrix) VirtualMatrix(matrix.rowNum, matrix.colNum, matrix.features + features, matrix.generator) - } else { - VirtualMatrix(matrix.rowNum, matrix.colNum, matrix.features + features) { i, j -> - matrix[i, j] - } - } + else + VirtualMatrix(matrix.rowNum, matrix.colNum, matrix.features + features) { i, j -> matrix[i, j] } } } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt index be222783e..6bed19456 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt @@ -19,24 +19,24 @@ import kotlin.contracts.contract * Differentiable variable with value and derivative of differentiation ([deriv]) result * with respect to this variable. */ -open class Variable(val value: T) +public open class Variable(public val value: T) -class DerivationResult( +public class DerivationResult( value: T, - val deriv: Map, T>, - val context: Field + public val deriv: Map, T>, + public val context: Field ) : Variable(value) { - fun deriv(variable: Variable): T = deriv[variable] ?: context.zero + public fun deriv(variable: Variable): T = deriv[variable] ?: context.zero /** * compute divergence */ - fun div(): T = context { sum(deriv.values) } + public fun div(): T = context { sum(deriv.values) } /** * Compute a gradient for variables in given order */ - fun grad(vararg variables: Variable): Point { + public fun grad(vararg variables: Variable): Point { check(variables.isNotEmpty()) { "Variable order is not provided for gradient construction" } return variables.map(::deriv).asBuffer() } @@ -55,7 +55,7 @@ class DerivationResult( * assertEquals(9.0, x.d) // dy/dx * ``` */ -inline fun > F.deriv(body: AutoDiffField.() -> Variable): DerivationResult { +public inline fun > F.deriv(body: AutoDiffField.() -> Variable): DerivationResult { contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) } return (AutoDiffContext(this)) { @@ -67,14 +67,14 @@ inline fun > F.deriv(body: AutoDiffField.() -> Varia } -abstract class AutoDiffField> : Field> { - abstract val context: F +public abstract class AutoDiffField> : Field> { + public abstract val context: F /** * A variable accessing inner state of derivatives. * Use this function in inner builders to avoid creating additional derivative bindings */ - abstract var Variable.d: T + public abstract var Variable.d: T /** * Performs update of derivative after the rest of the formula in the back-pass. @@ -87,11 +87,11 @@ abstract class AutoDiffField> : Field> { * } * ``` */ - abstract fun derive(value: R, block: F.(R) -> Unit): R + public abstract fun derive(value: R, block: F.(R) -> Unit): R - abstract fun variable(value: T): Variable + public abstract fun variable(value: T): Variable - inline fun variable(block: F.() -> T): Variable = variable(context.block()) + public inline fun variable(block: F.() -> T): Variable = variable(context.block()) // Overloads for Double constants @@ -153,7 +153,6 @@ internal class AutoDiffContext>(override val context: F) : // Basic math (+, -, *, /) - override fun add(a: Variable, b: Variable): Variable = derive(variable { a.value + b.value }) { z -> a.d += z.d b.d += z.d @@ -177,35 +176,36 @@ internal class AutoDiffContext>(override val context: F) : // Extensions for differentiation of various basic mathematical functions // x ^ 2 -fun > AutoDiffField.sqr(x: Variable): Variable = +public fun > AutoDiffField.sqr(x: Variable): Variable = derive(variable { x.value * x.value }) { z -> x.d += z.d * 2 * x.value } // x ^ 1/2 -fun > AutoDiffField.sqrt(x: Variable): Variable = +public fun > AutoDiffField.sqrt(x: Variable): Variable = derive(variable { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value } // x ^ y (const) -fun > AutoDiffField.pow(x: Variable, y: Double): Variable = +public fun > AutoDiffField.pow(x: Variable, y: Double): Variable = derive(variable { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) } -fun > AutoDiffField.pow(x: Variable, y: Int): Variable = pow(x, y.toDouble()) +public fun > AutoDiffField.pow(x: Variable, y: Int): Variable = + pow(x, y.toDouble()) // exp(x) -fun > AutoDiffField.exp(x: Variable): Variable = +public fun > AutoDiffField.exp(x: Variable): Variable = derive(variable { exp(x.value) }) { z -> x.d += z.d * z.value } // ln(x) -fun > AutoDiffField.ln(x: Variable): Variable = +public fun > AutoDiffField.ln(x: Variable): Variable = derive(variable { ln(x.value) }) { z -> x.d += z.d / x.value } // x ^ y (any) -fun > AutoDiffField.pow(x: Variable, y: Variable): Variable = +public fun > AutoDiffField.pow(x: Variable, y: Variable): Variable = exp(y * ln(x)) // sin(x) -fun > AutoDiffField.sin(x: Variable): Variable = +public fun > AutoDiffField.sin(x: Variable): Variable = derive(variable { sin(x.value) }) { z -> x.d += z.d * cos(x.value) } // cos(x) -fun > AutoDiffField.cos(x: Variable): Variable = +public fun > AutoDiffField.cos(x: Variable): Variable = derive(variable { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Grids.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Grids.kt index 1272ddd1c..cf3e93895 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Grids.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Grids.kt @@ -10,17 +10,21 @@ import kotlin.math.abs * * If step is negative, the same goes from upper boundary downwards */ -fun ClosedFloatingPointRange.toSequenceWithStep(step: Double): Sequence = when { +public fun ClosedFloatingPointRange.toSequenceWithStep(step: Double): Sequence = when { step == 0.0 -> error("Zero step in double progression") + step > 0 -> sequence { var current = start + while (current <= endInclusive) { yield(current) current += step } } + else -> sequence { var current = endInclusive + while (current >= start) { yield(current) current += step @@ -31,7 +35,7 @@ fun ClosedFloatingPointRange.toSequenceWithStep(step: Double): Sequence< /** * Convert double range to sequence with the fixed number of points */ -fun ClosedFloatingPointRange.toSequenceWithPoints(numPoints: Int): Sequence { +public fun ClosedFloatingPointRange.toSequenceWithPoints(numPoints: Int): Sequence { require(numPoints > 1) { "The number of points should be more than 2" } return toSequenceWithStep(abs(endInclusive - start) / (numPoints - 1)) } @@ -40,7 +44,7 @@ fun ClosedFloatingPointRange.toSequenceWithPoints(numPoints: Int): Seque * Convert double range to array of evenly spaced doubles, where the size of array equals [numPoints] */ @Deprecated("Replace by 'toSequenceWithPoints'") -fun ClosedFloatingPointRange.toGrid(numPoints: Int): DoubleArray { +public fun ClosedFloatingPointRange.toGrid(numPoints: Int): DoubleArray { require(numPoints >= 2) { "Can't create generic grid with less than two points" } return DoubleArray(numPoints) { i -> start + (endInclusive - start) / (numPoints - 1) * i } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt index e11adc135..f7dfcd781 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt @@ -2,7 +2,6 @@ package scientifik.kmath.misc import scientifik.kmath.operations.Space import scientifik.kmath.operations.invoke -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.jvm.JvmName @@ -13,7 +12,7 @@ import kotlin.jvm.JvmName * @param R the type of resulting iterable. * @param initial lazy evaluated. */ -inline fun Iterator.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterator { +public inline fun Iterator.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterator { contract { callsInPlace(operation) } return object : Iterator { @@ -28,14 +27,13 @@ inline fun Iterator.cumulative(initial: R, crossinline operation: (R, } } -inline fun Iterable.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterable = +public inline fun Iterable.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterable = Iterable { this@cumulative.iterator().cumulative(initial, operation) } -inline fun Sequence.cumulative(initial: R, crossinline operation: (R, T) -> R): Sequence = Sequence { - this@cumulative.iterator().cumulative(initial, operation) -} +public inline fun Sequence.cumulative(initial: R, crossinline operation: (R, T) -> R): Sequence = + Sequence { this@cumulative.iterator().cumulative(initial, operation) } -fun List.cumulative(initial: R, operation: (R, T) -> R): List = +public fun List.cumulative(initial: R, operation: (R, T) -> R): List = iterator().cumulative(initial, operation).asSequence().toList() //Cumulative sum @@ -43,38 +41,38 @@ fun List.cumulative(initial: R, operation: (R, T) -> R): List = /** * Cumulative sum with custom space */ -fun Iterable.cumulativeSum(space: Space): Iterable = +public fun Iterable.cumulativeSum(space: Space): Iterable = space { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") -fun Iterable.cumulativeSum(): Iterable = cumulative(0.0) { element, sum -> sum + element } +public fun Iterable.cumulativeSum(): Iterable = cumulative(0.0) { element, sum -> sum + element } @JvmName("cumulativeSumOfInt") -fun Iterable.cumulativeSum(): Iterable = cumulative(0) { element, sum -> sum + element } +public fun Iterable.cumulativeSum(): Iterable = cumulative(0) { element, sum -> sum + element } @JvmName("cumulativeSumOfLong") -fun Iterable.cumulativeSum(): Iterable = cumulative(0L) { element, sum -> sum + element } +public fun Iterable.cumulativeSum(): Iterable = cumulative(0L) { element, sum -> sum + element } -fun Sequence.cumulativeSum(space: Space): Sequence = +public fun Sequence.cumulativeSum(space: Space): Sequence = space { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") -fun Sequence.cumulativeSum(): Sequence = cumulative(0.0) { element, sum -> sum + element } +public fun Sequence.cumulativeSum(): Sequence = cumulative(0.0) { element, sum -> sum + element } @JvmName("cumulativeSumOfInt") -fun Sequence.cumulativeSum(): Sequence = cumulative(0) { element, sum -> sum + element } +public fun Sequence.cumulativeSum(): Sequence = cumulative(0) { element, sum -> sum + element } @JvmName("cumulativeSumOfLong") -fun Sequence.cumulativeSum(): Sequence = cumulative(0L) { element, sum -> sum + element } +public fun Sequence.cumulativeSum(): Sequence = cumulative(0L) { element, sum -> sum + element } -fun List.cumulativeSum(space: Space): List = +public fun List.cumulativeSum(space: Space): List = space { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") -fun List.cumulativeSum(): List = cumulative(0.0) { element, sum -> sum + element } +public fun List.cumulativeSum(): List = cumulative(0.0) { element, sum -> sum + element } @JvmName("cumulativeSumOfInt") -fun List.cumulativeSum(): List = cumulative(0) { element, sum -> sum + element } +public fun List.cumulativeSum(): List = cumulative(0) { element, sum -> sum + element } @JvmName("cumulativeSumOfLong") -fun List.cumulativeSum(): List = cumulative(0L) { element, sum -> sum + element } +public fun List.cumulativeSum(): List = cumulative(0L) { element, sum -> sum + element } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt index f18bde597..40f974096 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt @@ -4,28 +4,28 @@ package scientifik.kmath.operations * Stub for DSL the [Algebra] is. */ @DslMarker -annotation class KMathContext +public annotation class KMathContext /** * Represents an algebraic structure. * * @param T the type of element of this structure. */ -interface Algebra { +public interface Algebra { /** * Wrap raw string or variable */ - fun symbol(value: String): T = error("Wrapping of '$value' is not supported in $this") + public fun symbol(value: String): T = error("Wrapping of '$value' is not supported in $this") /** * Dynamic call of unary operation with name [operation] on [arg] */ - fun unaryOperation(operation: String, arg: T): T + public fun unaryOperation(operation: String, arg: T): T /** * Dynamic call of binary operation [operation] on [left] and [right] */ - fun binaryOperation(operation: String, left: T, right: T): T + public fun binaryOperation(operation: String, left: T, right: T): T } /** @@ -33,29 +33,30 @@ interface Algebra { * * @param T the type of element of this structure. */ -interface NumericAlgebra : Algebra { +public interface NumericAlgebra : Algebra { /** * Wraps a number. */ - fun number(value: Number): T + public fun number(value: Number): T /** * Dynamic call of binary operation [operation] on [left] and [right] where left element is [Number]. */ - fun leftSideNumberOperation(operation: String, left: Number, right: T): T = + public fun leftSideNumberOperation(operation: String, left: Number, right: T): T = binaryOperation(operation, number(left), right) /** * Dynamic call of binary operation [operation] on [left] and [right] where right element is [Number]. */ - fun rightSideNumberOperation(operation: String, left: T, right: Number): T = + public fun rightSideNumberOperation(operation: String, left: T, right: Number): T = leftSideNumberOperation(operation, right, left) } /** * Call a block with an [Algebra] as receiver. */ -inline operator fun , R> A.invoke(block: A.() -> R): R = run(block) +// TODO add contract when KT-32313 is fixed +public inline operator fun , R> A.invoke(block: A.() -> R): R = block() /** * Represents "semispace", i.e. algebraic structure with associative binary operation called "addition" as well as @@ -63,7 +64,7 @@ inline operator fun , R> A.invoke(block: A.() -> R): R = run(bloc * * @param T the type of element of this semispace. */ -interface SpaceOperations : Algebra { +public interface SpaceOperations : Algebra { /** * Addition of two elements. * @@ -71,7 +72,7 @@ interface SpaceOperations : Algebra { * @param b the augend. * @return the sum. */ - fun add(a: T, b: T): T + public fun add(a: T, b: T): T /** * Multiplication of element by scalar. @@ -80,7 +81,7 @@ interface SpaceOperations : Algebra { * @param k the multiplicand. * @return the produce. */ - fun multiply(a: T, k: Number): T + public fun multiply(a: T, k: Number): T // Operations to be performed in this context. Could be moved to extensions in case of KEEP-176 @@ -90,7 +91,7 @@ interface SpaceOperations : Algebra { * @receiver this value. * @return the additive inverse of this value. */ - operator fun T.unaryMinus(): T = multiply(this, -1.0) + public operator fun T.unaryMinus(): T = multiply(this, -1.0) /** * Returns this value. @@ -98,7 +99,7 @@ interface SpaceOperations : Algebra { * @receiver this value. * @return this value. */ - operator fun T.unaryPlus(): T = this + public operator fun T.unaryPlus(): T = this /** * Addition of two elements. @@ -107,7 +108,7 @@ interface SpaceOperations : Algebra { * @param b the augend. * @return the sum. */ - operator fun T.plus(b: T): T = add(this, b) + public operator fun T.plus(b: T): T = add(this, b) /** * Subtraction of two elements. @@ -116,7 +117,7 @@ interface SpaceOperations : Algebra { * @param b the subtrahend. * @return the difference. */ - operator fun T.minus(b: T): T = add(this, -b) + public operator fun T.minus(b: T): T = add(this, -b) /** * Multiplication of this element by a scalar. @@ -125,7 +126,7 @@ interface SpaceOperations : Algebra { * @param k the multiplicand. * @return the product. */ - operator fun T.times(k: Number): T = multiply(this, k.toDouble()) + public operator fun T.times(k: Number): T = multiply(this, k.toDouble()) /** * Division of this element by scalar. @@ -134,7 +135,7 @@ interface SpaceOperations : Algebra { * @param k the divisor. * @return the quotient. */ - operator fun T.div(k: Number): T = multiply(this, 1.0 / k.toDouble()) + public operator fun T.div(k: Number): T = multiply(this, 1.0 / k.toDouble()) /** * Multiplication of this number by element. @@ -143,7 +144,7 @@ interface SpaceOperations : Algebra { * @param b the multiplicand. * @return the product. */ - operator fun Number.times(b: T): T = b * this + public operator fun Number.times(b: T): T = b * this override fun unaryOperation(operation: String, arg: T): T = when (operation) { PLUS_OPERATION -> arg @@ -157,18 +158,16 @@ interface SpaceOperations : Algebra { else -> error("Binary operation $operation not defined in $this") } - companion object { + public companion object { /** * The identifier of addition. */ - const val PLUS_OPERATION: String = "+" + public const val PLUS_OPERATION: String = "+" /** * The identifier of subtraction (and negation). */ - const val MINUS_OPERATION: String = "-" - - const val NOT_OPERATION: String = "!" + public const val MINUS_OPERATION: String = "-" } } @@ -178,11 +177,11 @@ interface SpaceOperations : Algebra { * * @param T the type of element of this group. */ -interface Space : SpaceOperations { +public interface Space : SpaceOperations { /** * The neutral element of addition. */ - val zero: T + public val zero: T } /** @@ -191,14 +190,14 @@ interface Space : SpaceOperations { * * @param T the type of element of this semiring. */ -interface RingOperations : SpaceOperations { +public interface RingOperations : SpaceOperations { /** * Multiplies two elements. * * @param a the multiplier. * @param b the multiplicand. */ - fun multiply(a: T, b: T): T + public fun multiply(a: T, b: T): T /** * Multiplies this element by scalar. @@ -206,18 +205,18 @@ interface RingOperations : SpaceOperations { * @receiver the multiplier. * @param b the multiplicand. */ - operator fun T.times(b: T): T = multiply(this, b) + public operator fun T.times(b: T): T = multiply(this, b) override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) { TIMES_OPERATION -> multiply(left, right) else -> super.binaryOperation(operation, left, right) } - companion object { + public companion object { /** * The identifier of multiplication. */ - const val TIMES_OPERATION: String = "*" + public const val TIMES_OPERATION: String = "*" } } @@ -227,11 +226,11 @@ interface RingOperations : SpaceOperations { * * @param T the type of element of this ring. */ -interface Ring : Space, RingOperations, NumericAlgebra { +public interface Ring : Space, RingOperations, NumericAlgebra { /** * neutral operation for multiplication */ - val one: T + public val one: T override fun number(value: Number): T = one * value.toDouble() @@ -255,7 +254,7 @@ interface Ring : Space, RingOperations, NumericAlgebra { * @receiver the addend. * @param b the augend. */ - operator fun T.plus(b: Number): T = this + number(b) + public operator fun T.plus(b: Number): T = this + number(b) /** * Addition of scalar and element. @@ -263,7 +262,7 @@ interface Ring : Space, RingOperations, NumericAlgebra { * @receiver the addend. * @param b the augend. */ - operator fun Number.plus(b: T): T = b + this + public operator fun Number.plus(b: T): T = b + this /** * Subtraction of element from number. @@ -272,7 +271,7 @@ interface Ring : Space, RingOperations, NumericAlgebra { * @param b the subtrahend. * @receiver the difference. */ - operator fun T.minus(b: Number): T = this - number(b) + public operator fun T.minus(b: Number): T = this - number(b) /** * Subtraction of number from element. @@ -281,7 +280,7 @@ interface Ring : Space, RingOperations, NumericAlgebra { * @param b the subtrahend. * @receiver the difference. */ - operator fun Number.minus(b: T): T = -b + this + public operator fun Number.minus(b: T): T = -b + this } /** @@ -290,7 +289,7 @@ interface Ring : Space, RingOperations, NumericAlgebra { * * @param T the type of element of this semifield. */ -interface FieldOperations : RingOperations { +public interface FieldOperations : RingOperations { /** * Division of two elements. * @@ -298,7 +297,7 @@ interface FieldOperations : RingOperations { * @param b the divisor. * @return the quotient. */ - fun divide(a: T, b: T): T + public fun divide(a: T, b: T): T /** * Division of two elements. @@ -307,18 +306,18 @@ interface FieldOperations : RingOperations { * @param b the divisor. * @return the quotient. */ - operator fun T.div(b: T): T = divide(this, b) + public operator fun T.div(b: T): T = divide(this, b) override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) { DIV_OPERATION -> divide(left, right) else -> super.binaryOperation(operation, left, right) } - companion object { + public companion object { /** * The identifier of division. */ - const val DIV_OPERATION: String = "/" + public const val DIV_OPERATION: String = "/" } } @@ -328,7 +327,7 @@ interface FieldOperations : RingOperations { * * @param T the type of element of this semifield. */ -interface Field : Ring, FieldOperations { +public interface Field : Ring, FieldOperations { /** * Division of element by scalar. * @@ -336,5 +335,5 @@ interface Field : Ring, FieldOperations { * @param b the divisor. * @return the quotient. */ - operator fun Number.div(b: T): T = this * divide(one, b) + public operator fun Number.div(b: T): T = this * divide(one, b) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt index 197897c14..4ed1be0ee 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt @@ -5,11 +5,11 @@ package scientifik.kmath.operations * * @param C the type of mathematical context for this element. */ -interface MathElement { +public interface MathElement { /** * The context this element belongs to. */ - val context: C + public val context: C } /** @@ -18,16 +18,16 @@ interface MathElement { * @param T the type wrapped by this wrapper. * @param I the type of this wrapper. */ -interface MathWrapper { +public interface MathWrapper { /** * Unwraps [I] to [T]. */ - fun unwrap(): T + public fun unwrap(): T /** * Wraps [T] to [I]. */ - fun T.wrap(): I + public fun T.wrap(): I } /** @@ -37,14 +37,14 @@ interface MathWrapper { * @param I self type of the element. Needed for static type checking. * @param S the type of space. */ -interface SpaceElement, S : Space> : MathElement, MathWrapper { +public interface SpaceElement, S : Space> : MathElement, MathWrapper { /** * Adds element to this one. * * @param b the augend. * @return the sum. */ - operator fun plus(b: T): I = context.add(unwrap(), b).wrap() + public operator fun plus(b: T): I = context.add(unwrap(), b).wrap() /** * Subtracts element from this one. @@ -52,7 +52,7 @@ interface SpaceElement, S : Space> : MathElement * @param b the subtrahend. * @return the difference. */ - operator fun minus(b: T): I = context.add(unwrap(), context.multiply(b, -1.0)).wrap() + public operator fun minus(b: T): I = context.add(unwrap(), context.multiply(b, -1.0)).wrap() /** * Multiplies this element by number. @@ -60,7 +60,7 @@ interface SpaceElement, S : Space> : MathElement * @param k the multiplicand. * @return the product. */ - operator fun times(k: Number): I = context.multiply(unwrap(), k.toDouble()).wrap() + public operator fun times(k: Number): I = context.multiply(unwrap(), k.toDouble()).wrap() /** * Divides this element by number. @@ -68,7 +68,7 @@ interface SpaceElement, S : Space> : MathElement * @param k the divisor. * @return the quotient. */ - operator fun div(k: Number): I = context.multiply(unwrap(), 1.0 / k.toDouble()).wrap() + public operator fun div(k: Number): I = context.multiply(unwrap(), 1.0 / k.toDouble()).wrap() } /** @@ -78,14 +78,14 @@ interface SpaceElement, S : Space> : MathElement * @param I self type of the element. Needed for static type checking. * @param R the type of space. */ -interface RingElement, R : Ring> : SpaceElement { +public interface RingElement, R : Ring> : SpaceElement { /** * Multiplies this element by another one. * * @param b the multiplicand. * @return the product. */ - operator fun times(b: T): I = context.multiply(unwrap(), b).wrap() + public operator fun times(b: T): I = context.multiply(unwrap(), b).wrap() } /** @@ -95,7 +95,7 @@ interface RingElement, R : Ring> : SpaceElement, F : Field> : RingElement { +public interface FieldElement, F : Field> : RingElement { override val context: F /** @@ -104,5 +104,5 @@ interface FieldElement, F : Field> : RingElement * @param b the divisor. * @return the quotient. */ - operator fun div(b: T): I = context.divide(unwrap(), b).wrap() + public operator fun div(b: T): I = context.divide(unwrap(), b).wrap() } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt index 00b16dc98..b80e7582d 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt @@ -7,7 +7,7 @@ package scientifik.kmath.operations * @param data the iterable to sum up. * @return the sum. */ -fun Space.sum(data: Iterable): T = data.fold(zero) { left, right -> add(left, right) } +public fun Space.sum(data: Iterable): T = data.fold(zero) { left, right -> add(left, right) } /** * Returns the sum of all elements in the sequence in this [Space]. @@ -16,7 +16,7 @@ fun Space.sum(data: Iterable): T = data.fold(zero) { left, right -> ad * @param data the sequence to sum up. * @return the sum. */ -fun Space.sum(data: Sequence): T = data.fold(zero) { left, right -> add(left, right) } +public fun Space.sum(data: Sequence): T = data.fold(zero) { left, right -> add(left, right) } /** * Returns an average value of elements in the iterable in this [Space]. @@ -25,7 +25,7 @@ fun Space.sum(data: Sequence): T = data.fold(zero) { left, right -> ad * @param data the iterable to find average. * @return the average value. */ -fun Space.average(data: Iterable): T = sum(data) / data.count() +public fun Space.average(data: Iterable): T = sum(data) / data.count() /** * Returns an average value of elements in the sequence in this [Space]. @@ -34,7 +34,7 @@ fun Space.average(data: Iterable): T = sum(data) / data.count() * @param data the sequence to find average. * @return the average value. */ -fun Space.average(data: Sequence): T = sum(data) / data.count() +public fun Space.average(data: Sequence): T = sum(data) / data.count() /** * Returns the sum of all elements in the iterable in provided space. @@ -43,7 +43,7 @@ fun Space.average(data: Sequence): T = sum(data) / data.count() * @param space the algebra that provides addition. * @return the sum. */ -fun Iterable.sumWith(space: Space): T = space.sum(this) +public fun Iterable.sumWith(space: Space): T = space.sum(this) /** * Returns the sum of all elements in the sequence in provided space. @@ -52,7 +52,7 @@ fun Iterable.sumWith(space: Space): T = space.sum(this) * @param space the algebra that provides addition. * @return the sum. */ -fun Sequence.sumWith(space: Space): T = space.sum(this) +public fun Sequence.sumWith(space: Space): T = space.sum(this) /** * Returns an average value of elements in the iterable in this [Space]. @@ -61,7 +61,7 @@ fun Sequence.sumWith(space: Space): T = space.sum(this) * @param space the algebra that provides addition and division. * @return the average value. */ -fun Iterable.averageWith(space: Space): T = space.average(this) +public fun Iterable.averageWith(space: Space): T = space.average(this) /** * Returns an average value of elements in the sequence in this [Space]. @@ -70,7 +70,7 @@ fun Iterable.averageWith(space: Space): T = space.average(this) * @param space the algebra that provides addition and division. * @return the average value. */ -fun Sequence.averageWith(space: Space): T = space.average(this) +public fun Sequence.averageWith(space: Space): T = space.average(this) //TODO optimized power operation @@ -82,7 +82,7 @@ fun Sequence.averageWith(space: Space): T = space.average(this) * @param power the exponent. * @return the base raised to the power. */ -fun Ring.power(arg: T, power: Int): T { +public fun Ring.power(arg: T, power: Int): T { require(power >= 0) { "The power can't be negative." } require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." } if (power == 0) return one @@ -99,7 +99,7 @@ fun Ring.power(arg: T, power: Int): T { * @param power the exponent. * @return the base raised to the power. */ -fun Field.power(arg: T, power: Int): T { +public fun Field.power(arg: T, power: Int): T { require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." } if (power == 0) return one if (power < 0) return one / (this as Ring).power(arg, -power) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt index 0eed7132e..56ec84f0b 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt @@ -3,22 +3,21 @@ package scientifik.kmath.operations import scientifik.kmath.operations.BigInt.Companion.BASE import scientifik.kmath.operations.BigInt.Companion.BASE_SIZE import scientifik.kmath.structures.* -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.math.log2 import kotlin.math.max import kotlin.math.min import kotlin.math.sign -typealias Magnitude = UIntArray -typealias TBase = ULong +public typealias Magnitude = UIntArray +public typealias TBase = ULong /** * Kotlin Multiplatform implementation of Big Integer numbers (KBigInteger). * * @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai) */ -object BigIntField : Field { +public object BigIntField : Field { override val zero: BigInt = BigInt.ZERO override val one: BigInt = BigInt.ONE @@ -29,113 +28,93 @@ object BigIntField : Field { override fun multiply(a: BigInt, b: BigInt): BigInt = a.times(b) - operator fun String.unaryPlus(): BigInt = this.parseBigInteger() ?: error("Can't parse $this as big integer") + public operator fun String.unaryPlus(): BigInt = this.parseBigInteger() ?: error("Can't parse $this as big integer") - operator fun String.unaryMinus(): BigInt = + public operator fun String.unaryMinus(): BigInt = -(this.parseBigInteger() ?: error("Can't parse $this as big integer")) override fun divide(a: BigInt, b: BigInt): BigInt = a.div(b) } -class BigInt internal constructor( +public class BigInt internal constructor( private val sign: Byte, private val magnitude: Magnitude ) : Comparable { - override fun compareTo(other: BigInt): Int { - return when { - (this.sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0 - this.sign < other.sign -> -1 - this.sign > other.sign -> 1 - else -> this.sign * compareMagnitudes(this.magnitude, other.magnitude) + override fun compareTo(other: BigInt): Int = when { + (this.sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0 + this.sign < other.sign -> -1 + this.sign > other.sign -> 1 + else -> this.sign * compareMagnitudes(this.magnitude, other.magnitude) + } + + override fun equals(other: Any?): Boolean = + if (other is BigInt) compareTo(other) == 0 else error("Can't compare KBigInteger to a different type") + + override fun hashCode(): Int = magnitude.hashCode() + sign + + public fun abs(): BigInt = if (sign == 0.toByte()) this else BigInt(1, magnitude) + + public operator fun unaryMinus(): BigInt = + if (this.sign == 0.toByte()) this else BigInt((-this.sign).toByte(), this.magnitude) + + public operator fun plus(b: BigInt): BigInt = when { + b.sign == 0.toByte() -> this + sign == 0.toByte() -> b + this == -b -> ZERO + sign == b.sign -> BigInt(sign, addMagnitudes(magnitude, b.magnitude)) + + else -> { + val comp = compareMagnitudes(magnitude, b.magnitude) + + if (comp == 1) + BigInt(sign, subtractMagnitudes(magnitude, b.magnitude)) + else + BigInt((-sign).toByte(), subtractMagnitudes(b.magnitude, magnitude)) } } - override fun equals(other: Any?): Boolean { - if (other is BigInt) { - return this.compareTo(other) == 0 - } else error("Can't compare KBigInteger to a different type") - } + public operator fun minus(b: BigInt): BigInt = this + (-b) - override fun hashCode(): Int { - return magnitude.hashCode() + this.sign - } - - fun abs(): BigInt = if (sign == 0.toByte()) this else BigInt(1, magnitude) - - operator fun unaryMinus(): BigInt { - return if (this.sign == 0.toByte()) this else BigInt((-this.sign).toByte(), this.magnitude) - } - - operator fun plus(b: BigInt): BigInt { - return when { - b.sign == 0.toByte() -> this - this.sign == 0.toByte() -> b - this == -b -> ZERO - this.sign == b.sign -> BigInt(this.sign, addMagnitudes(this.magnitude, b.magnitude)) - else -> { - val comp: Int = compareMagnitudes(this.magnitude, b.magnitude) - - if (comp == 1) { - BigInt(this.sign, subtractMagnitudes(this.magnitude, b.magnitude)) - } else { - BigInt((-this.sign).toByte(), subtractMagnitudes(b.magnitude, this.magnitude)) - } - } - } - } - - operator fun minus(b: BigInt): BigInt { - return this + (-b) - } - - operator fun times(b: BigInt): BigInt { - return when { - this.sign == 0.toByte() -> ZERO - b.sign == 0.toByte() -> ZERO + public operator fun times(b: BigInt): BigInt = when { + this.sign == 0.toByte() -> ZERO + b.sign == 0.toByte() -> ZERO // TODO: Karatsuba - else -> BigInt((this.sign * b.sign).toByte(), multiplyMagnitudes(this.magnitude, b.magnitude)) - } + else -> BigInt((this.sign * b.sign).toByte(), multiplyMagnitudes(this.magnitude, b.magnitude)) } - operator fun times(other: UInt): BigInt { - return when { - this.sign == 0.toByte() -> ZERO - other == 0U -> ZERO - else -> BigInt(this.sign, multiplyMagnitudeByUInt(this.magnitude, other)) - } + public operator fun times(other: UInt): BigInt = when { + sign == 0.toByte() -> ZERO + other == 0U -> ZERO + else -> BigInt(sign, multiplyMagnitudeByUInt(magnitude, other)) } - operator fun times(other: Int): BigInt { - return if (other > 0) - this * kotlin.math.abs(other).toUInt() - else - -this * kotlin.math.abs(other).toUInt() - } + public operator fun times(other: Int): BigInt = if (other > 0) + this * kotlin.math.abs(other).toUInt() + else + -this * kotlin.math.abs(other).toUInt() - operator fun div(other: UInt): BigInt { - return BigInt(this.sign, divideMagnitudeByUInt(this.magnitude, other)) - } + public operator fun div(other: UInt): BigInt = BigInt(this.sign, divideMagnitudeByUInt(this.magnitude, other)) - operator fun div(other: Int): BigInt { - return BigInt( - (this.sign * other.sign).toByte(), - divideMagnitudeByUInt(this.magnitude, kotlin.math.abs(other).toUInt()) - ) - } + public operator fun div(other: Int): BigInt = BigInt( + (this.sign * other.sign).toByte(), + divideMagnitudeByUInt(this.magnitude, kotlin.math.abs(other).toUInt()) + ) private fun division(other: BigInt): Pair { // Long division algorithm: // https://en.wikipedia.org/wiki/Division_algorithm#Integer_division_(unsigned)_with_remainder // TODO: Implement more effective algorithm - var q: BigInt = ZERO - var r: BigInt = ZERO + var q = ZERO + var r = ZERO val bitSize = (BASE_SIZE * (this.magnitude.size - 1) + log2(this.magnitude.lastOrNull()?.toFloat() ?: 0f + 1)).toInt() + for (i in bitSize downTo 0) { r = r shl 1 r = r or ((abs(this) shr i) and ONE) + if (r >= abs(other)) { r -= abs(other) q += (ONE shl i) @@ -145,99 +124,84 @@ class BigInt internal constructor( return Pair(BigInt((this.sign * other.sign).toByte(), q.magnitude), r) } - operator fun div(other: BigInt): BigInt { - return this.division(other).first - } + public operator fun div(other: BigInt): BigInt = this.division(other).first - infix fun shl(i: Int): BigInt { + public infix fun shl(i: Int): BigInt { if (this == ZERO) return ZERO if (i == 0) return this - val fullShifts = i / BASE_SIZE + 1 val relShift = i % BASE_SIZE val shiftLeft = { x: UInt -> if (relShift >= 32) 0U else x shl relShift } val shiftRight = { x: UInt -> if (BASE_SIZE - relShift >= 32) 0U else x shr (BASE_SIZE - relShift) } - - val newMagnitude: Magnitude = Magnitude(this.magnitude.size + fullShifts) + val newMagnitude = Magnitude(this.magnitude.size + fullShifts) for (j in this.magnitude.indices) { newMagnitude[j + fullShifts - 1] = shiftLeft(this.magnitude[j]) - if (j != 0) { + + if (j != 0) newMagnitude[j + fullShifts - 1] = newMagnitude[j + fullShifts - 1] or shiftRight(this.magnitude[j - 1]) - } } newMagnitude[this.magnitude.size + fullShifts - 1] = shiftRight(this.magnitude.last()) - return BigInt(this.sign, stripLeadingZeros(newMagnitude)) } - infix fun shr(i: Int): BigInt { + public infix fun shr(i: Int): BigInt { if (this == ZERO) return ZERO if (i == 0) return this - val fullShifts = i / BASE_SIZE val relShift = i % BASE_SIZE val shiftRight = { x: UInt -> if (relShift >= 32) 0U else x shr relShift } val shiftLeft = { x: UInt -> if (BASE_SIZE - relShift >= 32) 0U else x shl (BASE_SIZE - relShift) } - if (this.magnitude.size - fullShifts <= 0) { - return ZERO - } + if (this.magnitude.size - fullShifts <= 0) return ZERO val newMagnitude: Magnitude = Magnitude(this.magnitude.size - fullShifts) for (j in fullShifts until this.magnitude.size) { newMagnitude[j - fullShifts] = shiftRight(this.magnitude[j]) - if (j != this.magnitude.size - 1) { + + if (j != this.magnitude.size - 1) newMagnitude[j - fullShifts] = newMagnitude[j - fullShifts] or shiftLeft(this.magnitude[j + 1]) - } } return BigInt(this.sign, stripLeadingZeros(newMagnitude)) } - infix fun or(other: BigInt): BigInt { + public infix fun or(other: BigInt): BigInt { if (this == ZERO) return other if (other == ZERO) return this val resSize = max(this.magnitude.size, other.magnitude.size) val newMagnitude: Magnitude = Magnitude(resSize) + for (i in 0 until resSize) { - if (i < this.magnitude.size) { - newMagnitude[i] = newMagnitude[i] or this.magnitude[i] - } - if (i < other.magnitude.size) { - newMagnitude[i] = newMagnitude[i] or other.magnitude[i] - } + if (i < this.magnitude.size) newMagnitude[i] = newMagnitude[i] or this.magnitude[i] + if (i < other.magnitude.size) newMagnitude[i] = newMagnitude[i] or other.magnitude[i] } + return BigInt(1, stripLeadingZeros(newMagnitude)) } - infix fun and(other: BigInt): BigInt { + public infix fun and(other: BigInt): BigInt { if ((this == ZERO) or (other == ZERO)) return ZERO val resSize = min(this.magnitude.size, other.magnitude.size) val newMagnitude: Magnitude = Magnitude(resSize) - for (i in 0 until resSize) { - newMagnitude[i] = this.magnitude[i] and other.magnitude[i] - } + for (i in 0 until resSize) newMagnitude[i] = this.magnitude[i] and other.magnitude[i] return BigInt(1, stripLeadingZeros(newMagnitude)) } - operator fun rem(other: Int): Int { + public operator fun rem(other: Int): Int { val res = this - (this / other) * other return if (res == ZERO) 0 else res.sign * res.magnitude[0].toInt() } - operator fun rem(other: BigInt): BigInt { - return this - (this / other) * other - } + public operator fun rem(other: BigInt): BigInt = this - (this / other) * other - fun modPow(exponent: BigInt, m: BigInt): BigInt { - return when { - exponent == ZERO -> ONE - exponent % 2 == 1 -> (this * modPow(exponent - ONE, m)) % m - else -> { - val sqRoot = modPow(exponent / 2, m) - (sqRoot * sqRoot) % m - } + public fun modPow(exponent: BigInt, m: BigInt): BigInt = when { + exponent == ZERO -> ONE + exponent % 2 == 1 -> (this * modPow(exponent - ONE, m)) % m + + else -> { + val sqRoot = modPow(exponent / 2, m) + (sqRoot * sqRoot) % m } } @@ -261,11 +225,11 @@ class BigInt internal constructor( return res } - companion object { - const val BASE: ULong = 0xffffffffUL - const val BASE_SIZE: Int = 32 - val ZERO: BigInt = BigInt(0, uintArrayOf()) - val ONE: BigInt = BigInt(1, uintArrayOf(1u)) + public companion object { + public const val BASE: ULong = 0xffffffffUL + public const val BASE_SIZE: Int = 32 + public val ZERO: BigInt = BigInt(0, uintArrayOf()) + public val ONE: BigInt = BigInt(1, uintArrayOf(1u)) private val hexMapping: HashMap = hashMapOf( 0U to "0", 1U to "1", 2U to "2", 3U to "3", @@ -349,11 +313,13 @@ class BigInt internal constructor( for (i in mag1.indices) { var carry: ULong = 0UL + for (j in mag2.indices) { val cur: ULong = result[i + j].toULong() + mag1[i].toULong() * mag2[j].toULong() + carry result[i + j] = (cur and BASE.toULong()).toUInt() carry = cur shr BASE_SIZE } + result[i + mag2.size] = (carry and BASE).toUInt() } @@ -361,15 +327,16 @@ class BigInt internal constructor( } private fun divideMagnitudeByUInt(mag: Magnitude, x: UInt): Magnitude { - val resultLength: Int = mag.size + val resultLength = mag.size val result = Magnitude(resultLength) - var carry: ULong = 0UL + var carry = 0uL for (i in mag.size - 1 downTo 0) { val cur: ULong = mag[i].toULong() + (carry shl BASE_SIZE) result[i] = (cur / x).toUInt() carry = cur % x } + return stripLeadingZeros(result) } @@ -377,31 +344,29 @@ class BigInt internal constructor( } - private fun stripLeadingZeros(mag: Magnitude): Magnitude { - if (mag.isEmpty() || mag.last() != 0U) { - return mag - } - var resSize: Int = mag.size - 1 + if (mag.isEmpty() || mag.last() != 0U) return mag + var resSize = mag.size - 1 + while (mag[resSize] == 0U) { - if (resSize == 0) - break + if (resSize == 0) break resSize -= 1 } + return mag.sliceArray(IntRange(0, resSize)) } -fun abs(x: BigInt): BigInt = x.abs() +public fun abs(x: BigInt): BigInt = x.abs() /** * Convert this [Int] to [BigInt] */ -fun Int.toBigInt(): BigInt = BigInt(sign.toByte(), uintArrayOf(kotlin.math.abs(this).toUInt())) +public fun Int.toBigInt(): BigInt = BigInt(sign.toByte(), uintArrayOf(kotlin.math.abs(this).toUInt())) /** * Convert this [Long] to [BigInt] */ -fun Long.toBigInt(): BigInt = BigInt( +public fun Long.toBigInt(): BigInt = BigInt( sign.toByte(), stripLeadingZeros( uintArrayOf( (kotlin.math.abs(this).toULong() and BASE).toUInt(), @@ -413,13 +378,14 @@ fun Long.toBigInt(): BigInt = BigInt( /** * Convert UInt to [BigInt] */ -fun UInt.toBigInt(): BigInt = BigInt(1, uintArrayOf(this)) +public fun UInt.toBigInt(): BigInt = BigInt(1, uintArrayOf(this)) /** * Convert ULong to [BigInt] */ -fun ULong.toBigInt(): BigInt = BigInt( +public fun ULong.toBigInt(): BigInt = BigInt( 1, + stripLeadingZeros( uintArrayOf( (this and BASE).toUInt(), @@ -431,12 +397,12 @@ fun ULong.toBigInt(): BigInt = BigInt( /** * Create a [BigInt] with this array of magnitudes with protective copy */ -fun UIntArray.toBigInt(sign: Byte): BigInt { +public fun UIntArray.toBigInt(sign: Byte): BigInt { require(sign != 0.toByte() || !isNotEmpty()) return BigInt(sign, copyOf()) } -val hexChToInt: MutableMap = hashMapOf( +private val hexChToInt: MutableMap = hashMapOf( '0' to 0, '1' to 1, '2' to 2, '3' to 3, '4' to 4, '5' to 5, '6' to 6, '7' to 7, '8' to 8, '9' to 9, 'A' to 10, 'B' to 11, @@ -446,9 +412,10 @@ val hexChToInt: MutableMap = hashMapOf( /** * Returns null if a valid number can not be read from a string */ -fun String.parseBigInteger(): BigInt? { +public fun String.parseBigInteger(): BigInt? { val sign: Int val sPositive: String + when { this[0] == '+' -> { sign = +1 @@ -463,43 +430,46 @@ fun String.parseBigInteger(): BigInt? { sign = +1 } } + var res = BigInt.ZERO var digitValue = BigInt.ONE val sPositiveUpper = sPositive.toUpperCase() + if (sPositiveUpper.startsWith("0X")) { // hex representation val sHex = sPositiveUpper.substring(2) + for (ch in sHex.reversed()) { if (ch == '_') continue res += digitValue * (hexChToInt[ch] ?: return null) digitValue *= 16.toBigInt() } - } else { // decimal representation - for (ch in sPositiveUpper.reversed()) { - if (ch == '_') continue - if (ch !in '0'..'9') { - return null - } - res += digitValue * (ch.toInt() - '0'.toInt()) - digitValue *= 10.toBigInt() + } else for (ch in sPositiveUpper.reversed()) { + // decimal representation + if (ch == '_') continue + if (ch !in '0'..'9') { + return null } + res += digitValue * (ch.toInt() - '0'.toInt()) + digitValue *= 10.toBigInt() } + return res * sign } -inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer { +public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer { contract { callsInPlace(initializer) } return boxing(size, initializer) } -inline fun MutableBuffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): MutableBuffer { +public inline fun MutableBuffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): MutableBuffer { contract { callsInPlace(initializer) } return boxing(size, initializer) } -fun NDAlgebra.Companion.bigInt(vararg shape: Int): BoxingNDRing = +public fun NDAlgebra.Companion.bigInt(vararg shape: Int): BoxingNDRing = BoxingNDRing(shape, BigIntField, Buffer.Companion::bigInt) -fun NDElement.Companion.bigInt( +public fun NDElement.Companion.bigInt( vararg shape: Int, initializer: BigIntField.(IntArray) -> BigInt ): BufferedNDRingElement = NDAlgebra.bigInt(*shape).produce(initializer) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt index dcfd97d1a..facc2ad26 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt @@ -6,20 +6,19 @@ import scientifik.kmath.structures.MutableBuffer import scientifik.memory.MemoryReader import scientifik.memory.MemorySpec import scientifik.memory.MemoryWriter -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.math.* /** * This complex's conjugate. */ -val Complex.conjugate: Complex +public val Complex.conjugate: Complex get() = Complex(re, -im) /** * This complex's reciprocal. */ -val Complex.reciprocal: Complex +public val Complex.reciprocal: Complex get() { val scale = re * re + im * im return Complex(re / scale, -im / scale) @@ -28,13 +27,13 @@ val Complex.reciprocal: Complex /** * Absolute value of complex number. */ -val Complex.r: Double +public val Complex.r: Double get() = sqrt(re * re + im * im) /** * An angle between vector represented by complex number and X axis. */ -val Complex.theta: Double +public val Complex.theta: Double get() = atan(im / re) private val PI_DIV_2 = Complex(PI / 2, 0) @@ -42,14 +41,14 @@ private val PI_DIV_2 = Complex(PI / 2, 0) /** * A field of [Complex]. */ -object ComplexField : ExtendedField, Norm { +public object ComplexField : ExtendedField, Norm { override val zero: Complex = 0.0.toComplex() override val one: Complex = 1.0.toComplex() /** * The imaginary unit. */ - val i: Complex = Complex(0.0, 1.0) + public val i: Complex = Complex(0.0, 1.0) override fun add(a: Complex, b: Complex): Complex = Complex(a.re + b.re, a.im + b.im) @@ -117,7 +116,7 @@ object ComplexField : ExtendedField, Norm { * @param c the augend. * @return the sum. */ - operator fun Double.plus(c: Complex): Complex = add(this.toComplex(), c) + public operator fun Double.plus(c: Complex): Complex = add(this.toComplex(), c) /** * Subtracts complex number from real one. @@ -126,7 +125,7 @@ object ComplexField : ExtendedField, Norm { * @param c the subtrahend. * @return the difference. */ - operator fun Double.minus(c: Complex): Complex = add(this.toComplex(), -c) + public operator fun Double.minus(c: Complex): Complex = add(this.toComplex(), -c) /** * Adds real number to complex one. @@ -135,7 +134,7 @@ object ComplexField : ExtendedField, Norm { * @param d the augend. * @return the sum. */ - operator fun Complex.plus(d: Double): Complex = d + this + public operator fun Complex.plus(d: Double): Complex = d + this /** * Subtracts real number from complex one. @@ -144,7 +143,7 @@ object ComplexField : ExtendedField, Norm { * @param d the subtrahend. * @return the difference. */ - operator fun Complex.minus(d: Double): Complex = add(this, -d.toComplex()) + public operator fun Complex.minus(d: Double): Complex = add(this, -d.toComplex()) /** * Multiplies real number by complex one. @@ -153,7 +152,7 @@ object ComplexField : ExtendedField, Norm { * @param c the multiplicand. * @receiver the product. */ - operator fun Double.times(c: Complex): Complex = Complex(c.re * this, c.im * this) + public operator fun Double.times(c: Complex): Complex = Complex(c.re * this, c.im * this) override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg) @@ -166,8 +165,8 @@ object ComplexField : ExtendedField, Norm { * @property re The real part. * @property im The imaginary part. */ -data class Complex(val re: Double, val im: Double) : FieldElement, Comparable { - constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble()) +public data class Complex(val re: Double, val im: Double) : FieldElement, Comparable { + public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble()) override val context: ComplexField get() = ComplexField @@ -177,7 +176,7 @@ data class Complex(val re: Double, val im: Double) : FieldElement { + public companion object : MemorySpec { override val objectSize: Int = 16 override fun MemoryReader.read(offset: Int): Complex = @@ -196,14 +195,14 @@ data class Complex(val re: Double, val im: Double) : FieldElement Complex): Buffer { +public inline fun Buffer.Companion.complex(size: Int, crossinline init: (Int) -> Complex): Buffer { contract { callsInPlace(init) } return MemoryBuffer.create(Complex, size, init) } -inline fun MutableBuffer.Companion.complex(size: Int, crossinline init: (Int) -> Complex): Buffer { +public inline fun MutableBuffer.Companion.complex(size: Int, crossinline init: (Int) -> Complex): Buffer { contract { callsInPlace(init) } return MemoryBuffer.create(Complex, size, init) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt index 0735a96da..54460a0da 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt @@ -7,7 +7,7 @@ import kotlin.math.pow as kpow /** * Advanced Number-like semifield that implements basic operations. */ -interface ExtendedFieldOperations : +public interface ExtendedFieldOperations : FieldOperations, TrigonometricOperations, HyperbolicOperations, @@ -41,7 +41,7 @@ interface ExtendedFieldOperations : /** * Advanced Number-like field that implements basic operations. */ -interface ExtendedField : ExtendedFieldOperations, Field { +public interface ExtendedField : ExtendedFieldOperations, Field { override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2 override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2 override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg)) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/OptionalOperations.kt index 1dac649aa..101f62293 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/OptionalOperations.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/OptionalOperations.kt @@ -5,230 +5,230 @@ package scientifik.kmath.operations * * @param T the type of element of this structure. */ -interface TrigonometricOperations : Algebra { +public interface TrigonometricOperations : Algebra { /** * Computes the sine of [arg]. */ - fun sin(arg: T): T + public fun sin(arg: T): T /** * Computes the cosine of [arg]. */ - fun cos(arg: T): T + public fun cos(arg: T): T /** * Computes the tangent of [arg]. */ - fun tan(arg: T): T + public fun tan(arg: T): T /** * Computes the inverse sine of [arg]. */ - fun asin(arg: T): T + public fun asin(arg: T): T /** * Computes the inverse cosine of [arg]. */ - fun acos(arg: T): T + public fun acos(arg: T): T /** * Computes the inverse tangent of [arg]. */ - fun atan(arg: T): T + public fun atan(arg: T): T - companion object { + public companion object { /** * The identifier of sine. */ - const val SIN_OPERATION: String = "sin" + public const val SIN_OPERATION: String = "sin" /** * The identifier of cosine. */ - const val COS_OPERATION: String = "cos" + public const val COS_OPERATION: String = "cos" /** * The identifier of tangent. */ - const val TAN_OPERATION: String = "tan" + public const val TAN_OPERATION: String = "tan" /** * The identifier of inverse sine. */ - const val ASIN_OPERATION: String = "asin" + public const val ASIN_OPERATION: String = "asin" /** * The identifier of inverse cosine. */ - const val ACOS_OPERATION: String = "acos" + public const val ACOS_OPERATION: String = "acos" /** * The identifier of inverse tangent. */ - const val ATAN_OPERATION: String = "atan" + public const val ATAN_OPERATION: String = "atan" } } /** * Computes the sine of [arg]. */ -fun >> sin(arg: T): T = arg.context.sin(arg) +public fun >> sin(arg: T): T = arg.context.sin(arg) /** * Computes the cosine of [arg]. */ -fun >> cos(arg: T): T = arg.context.cos(arg) +public fun >> cos(arg: T): T = arg.context.cos(arg) /** * Computes the tangent of [arg]. */ -fun >> tan(arg: T): T = arg.context.tan(arg) +public fun >> tan(arg: T): T = arg.context.tan(arg) /** * Computes the inverse sine of [arg]. */ -fun >> asin(arg: T): T = arg.context.asin(arg) +public fun >> asin(arg: T): T = arg.context.asin(arg) /** * Computes the inverse cosine of [arg]. */ -fun >> acos(arg: T): T = arg.context.acos(arg) +public fun >> acos(arg: T): T = arg.context.acos(arg) /** * Computes the inverse tangent of [arg]. */ -fun >> atan(arg: T): T = arg.context.atan(arg) +public fun >> atan(arg: T): T = arg.context.atan(arg) /** * A container for hyperbolic trigonometric operations for specific type. * * @param T the type of element of this structure. */ -interface HyperbolicOperations : Algebra { +public interface HyperbolicOperations : Algebra { /** * Computes the hyperbolic sine of [arg]. */ - fun sinh(arg: T): T + public fun sinh(arg: T): T /** * Computes the hyperbolic cosine of [arg]. */ - fun cosh(arg: T): T + public fun cosh(arg: T): T /** * Computes the hyperbolic tangent of [arg]. */ - fun tanh(arg: T): T + public fun tanh(arg: T): T /** * Computes the inverse hyperbolic sine of [arg]. */ - fun asinh(arg: T): T + public fun asinh(arg: T): T /** * Computes the inverse hyperbolic cosine of [arg]. */ - fun acosh(arg: T): T + public fun acosh(arg: T): T /** * Computes the inverse hyperbolic tangent of [arg]. */ - fun atanh(arg: T): T + public fun atanh(arg: T): T - companion object { + public companion object { /** * The identifier of hyperbolic sine. */ - const val SINH_OPERATION: String = "sinh" + public const val SINH_OPERATION: String = "sinh" /** * The identifier of hyperbolic cosine. */ - const val COSH_OPERATION: String = "cosh" + public const val COSH_OPERATION: String = "cosh" /** * The identifier of hyperbolic tangent. */ - const val TANH_OPERATION: String = "tanh" + public const val TANH_OPERATION: String = "tanh" /** * The identifier of inverse hyperbolic sine. */ - const val ASINH_OPERATION: String = "asinh" + public const val ASINH_OPERATION: String = "asinh" /** * The identifier of inverse hyperbolic cosine. */ - const val ACOSH_OPERATION: String = "acosh" + public const val ACOSH_OPERATION: String = "acosh" /** * The identifier of inverse hyperbolic tangent. */ - const val ATANH_OPERATION: String = "atanh" + public const val ATANH_OPERATION: String = "atanh" } } /** * Computes the hyperbolic sine of [arg]. */ -fun >> sinh(arg: T): T = arg.context.sinh(arg) +public fun >> sinh(arg: T): T = arg.context.sinh(arg) /** * Computes the hyperbolic cosine of [arg]. */ -fun >> cosh(arg: T): T = arg.context.cosh(arg) +public fun >> cosh(arg: T): T = arg.context.cosh(arg) /** * Computes the hyperbolic tangent of [arg]. */ -fun >> tanh(arg: T): T = arg.context.tanh(arg) +public fun >> tanh(arg: T): T = arg.context.tanh(arg) /** * Computes the inverse hyperbolic sine of [arg]. */ -fun >> asinh(arg: T): T = arg.context.asinh(arg) +public fun >> asinh(arg: T): T = arg.context.asinh(arg) /** * Computes the inverse hyperbolic cosine of [arg]. */ -fun >> acosh(arg: T): T = arg.context.acosh(arg) +public fun >> acosh(arg: T): T = arg.context.acosh(arg) /** * Computes the inverse hyperbolic tangent of [arg]. */ -fun >> atanh(arg: T): T = arg.context.atanh(arg) +public fun >> atanh(arg: T): T = arg.context.atanh(arg) /** * A context extension to include power operations based on exponentiation. * * @param T the type of element of this structure. */ -interface PowerOperations : Algebra { +public interface PowerOperations : Algebra { /** * Raises [arg] to the power [pow]. */ - fun power(arg: T, pow: Number): T + public fun power(arg: T, pow: Number): T /** * Computes the square root of the value [arg]. */ - fun sqrt(arg: T): T = power(arg, 0.5) + public fun sqrt(arg: T): T = power(arg, 0.5) /** * Raises this value to the power [pow]. */ - infix fun T.pow(pow: Number): T = power(this, pow) + public infix fun T.pow(pow: Number): T = power(this, pow) - companion object { + public companion object { /** * The identifier of exponentiation. */ - const val POW_OPERATION: String = "pow" + public const val POW_OPERATION: String = "pow" /** * The identifier of square root. */ - const val SQRT_OPERATION: String = "sqrt" + public const val SQRT_OPERATION: String = "sqrt" } } @@ -239,56 +239,56 @@ interface PowerOperations : Algebra { * @param power the exponent. * @return the base raised to the power. */ -infix fun >> T.pow(power: Double): T = context.power(this, power) +public infix fun >> T.pow(power: Double): T = context.power(this, power) /** * Computes the square root of the value [arg]. */ -fun >> sqrt(arg: T): T = arg pow 0.5 +public fun >> sqrt(arg: T): T = arg pow 0.5 /** * Computes the square of the value [arg]. */ -fun >> sqr(arg: T): T = arg pow 2.0 +public fun >> sqr(arg: T): T = arg pow 2.0 /** * A container for operations related to `exp` and `ln` functions. * * @param T the type of element of this structure. */ -interface ExponentialOperations : Algebra { +public interface ExponentialOperations : Algebra { /** * Computes Euler's number `e` raised to the power of the value [arg]. */ - fun exp(arg: T): T + public fun exp(arg: T): T /** * Computes the natural logarithm (base `e`) of the value [arg]. */ - fun ln(arg: T): T + public fun ln(arg: T): T - companion object { + public companion object { /** * The identifier of exponential function. */ - const val EXP_OPERATION: String = "exp" + public const val EXP_OPERATION: String = "exp" /** * The identifier of natural logarithm. */ - const val LN_OPERATION: String = "ln" + public const val LN_OPERATION: String = "ln" } } /** * The identifier of exponential function. */ -fun >> exp(arg: T): T = arg.context.exp(arg) +public fun >> exp(arg: T): T = arg.context.exp(arg) /** * The identifier of natural logarithm. */ -fun >> ln(arg: T): T = arg.context.ln(arg) +public fun >> ln(arg: T): T = arg.context.ln(arg) /** * A container for norm functional on element. @@ -296,14 +296,14 @@ fun >> ln(arg: T): T = arg.context. * @param T the type of element having norm defined. * @param R the type of norm. */ -interface Norm { +public interface Norm { /** * Computes the norm of [arg] (i.e. absolute value or vector length). */ - fun norm(arg: T): R + public fun norm(arg: T): R } /** * Computes the norm of [arg] (i.e. absolute value or vector length). */ -fun >, R> norm(arg: T): R = arg.context.norm(arg) +public fun >, R> norm(arg: T): R = arg.context.norm(arg) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt index be71645d1..5950532e1 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt @@ -3,16 +3,16 @@ package scientifik.kmath.structures import scientifik.kmath.operations.Field import scientifik.kmath.operations.FieldElement -class BoxingNDField>( +public class BoxingNDField>( override val shape: IntArray, override val elementContext: F, - val bufferFactory: BufferFactory + public val bufferFactory: BufferFactory ) : BufferedNDField { override val zero: BufferedNDFieldElement by lazy { produce { zero } } override val one: BufferedNDFieldElement by lazy { produce { one } } override val strides: Strides = DefaultStrides(shape) - fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer = + public fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) override fun check(vararg elements: NDBuffer) { @@ -70,7 +70,7 @@ class BoxingNDField>( BufferedNDFieldElement(this@BoxingNDField, buffer) } -inline fun , R> F.nd( +public inline fun , R> F.nd( noinline bufferFactory: BufferFactory, vararg shape: Int, action: NDField.() -> R diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt index 91b945e79..9e44e38aa 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt @@ -3,16 +3,16 @@ package scientifik.kmath.structures import scientifik.kmath.operations.Ring import scientifik.kmath.operations.RingElement -class BoxingNDRing>( +public class BoxingNDRing>( override val shape: IntArray, override val elementContext: R, - val bufferFactory: BufferFactory + public val bufferFactory: BufferFactory ) : BufferedNDRing { override val strides: Strides = DefaultStrides(shape) override val zero: BufferedNDRingElement by lazy { produce { zero } } override val one: BufferedNDRingElement by lazy { produce { one } } - fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) + public fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) override fun check(vararg elements: NDBuffer) { require(elements.all { it.strides == strides }) { "Element strides are not the same as context strides" } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferAccessor2D.kt index 2c3d69094..0a02fdc8f 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferAccessor2D.kt @@ -5,24 +5,23 @@ import kotlin.reflect.KClass /** * A context that allows to operate on a [MutableBuffer] as on 2d array */ -class BufferAccessor2D(val type: KClass, val rowNum: Int, val colNum: Int) { - operator fun Buffer.get(i: Int, j: Int): T = get(i + colNum * j) +public class BufferAccessor2D(public val type: KClass, public val rowNum: Int, public val colNum: Int) { + public operator fun Buffer.get(i: Int, j: Int): T = get(i + colNum * j) - operator fun MutableBuffer.set(i: Int, j: Int, value: T) { + public operator fun MutableBuffer.set(i: Int, j: Int, value: T) { set(i + colNum * j, value) } - inline fun create(init: (i: Int, j: Int) -> T): MutableBuffer = + public inline fun create(init: (i: Int, j: Int) -> T): MutableBuffer = MutableBuffer.auto(type, rowNum * colNum) { offset -> init(offset / colNum, offset % colNum) } - fun create(mat: Structure2D): MutableBuffer = create { i, j -> mat[i, j] } + public fun create(mat: Structure2D): MutableBuffer = create { i, j -> mat[i, j] } //TODO optimize wrapper - fun MutableBuffer.collect(): Structure2D = + public fun MutableBuffer.collect(): Structure2D = NDStructure.auto(type, rowNum, colNum) { (i, j) -> get(i, j) }.as2D() - - inner class Row(val buffer: MutableBuffer, val rowIndex: Int) : MutableBuffer { + public inner class Row(public val buffer: MutableBuffer, public val rowIndex: Int) : MutableBuffer { override val size: Int get() = colNum override operator fun get(index: Int): T = buffer[rowIndex, index] @@ -39,5 +38,5 @@ class BufferAccessor2D(val type: KClass, val rowNum: Int, val colNum /** * Get row */ - fun MutableBuffer.row(i: Int): Row = Row(this, i) + public fun MutableBuffer.row(i: Int): Row = Row(this, i) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt index 2c0c2021f..ac8ca0db4 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt @@ -2,8 +2,8 @@ package scientifik.kmath.structures import scientifik.kmath.operations.* -interface BufferedNDAlgebra : NDAlgebra> { - val strides: Strides +public interface BufferedNDAlgebra : NDAlgebra> { + public val strides: Strides override fun check(vararg elements: NDBuffer): Unit = require(elements.all { it.strides == strides }) { ("Strides mismatch") } @@ -15,29 +15,27 @@ interface BufferedNDAlgebra : NDAlgebra> { * * If the argument is [NDBuffer] with different strides structure, the new element will be produced. */ - fun NDStructure.toBuffer(): NDBuffer { - return if (this is NDBuffer && this.strides == this@BufferedNDAlgebra.strides) { + public fun NDStructure.toBuffer(): NDBuffer = + if (this is NDBuffer && this.strides == this@BufferedNDAlgebra.strides) this - } else { - produce { index -> get(index) } - } - } + else + produce { index -> this@toBuffer[index] } /** * Convert a buffer to element of this algebra */ - fun NDBuffer.toElement(): MathElement> + public fun NDBuffer.toElement(): MathElement> } -interface BufferedNDSpace> : NDSpace>, BufferedNDAlgebra { +public interface BufferedNDSpace> : NDSpace>, BufferedNDAlgebra { override fun NDBuffer.toElement(): SpaceElement, *, out BufferedNDSpace> } -interface BufferedNDRing> : NDRing>, BufferedNDSpace { +public interface BufferedNDRing> : NDRing>, BufferedNDSpace { override fun NDBuffer.toElement(): RingElement, *, out BufferedNDRing> } -interface BufferedNDField> : NDField>, BufferedNDRing { +public interface BufferedNDField> : NDField>, BufferedNDRing { override fun NDBuffer.toElement(): FieldElement, *, out BufferedNDField> } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDElement.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDElement.kt index 20e34fadd..4de31d101 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDElement.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDElement.kt @@ -5,7 +5,7 @@ import scientifik.kmath.operations.* /** * Base class for an element with context, containing strides */ -abstract class BufferedNDElement : NDBuffer(), NDElement> { +public abstract class BufferedNDElement : NDBuffer(), NDElement> { abstract override val context: BufferedNDAlgebra override val strides: Strides get() = context.strides @@ -13,7 +13,7 @@ abstract class BufferedNDElement : NDBuffer(), NDElement>( +public class BufferedNDSpaceElement>( override val context: BufferedNDSpace, override val buffer: Buffer ) : BufferedNDElement(), SpaceElement, BufferedNDSpaceElement, BufferedNDSpace> { @@ -26,7 +26,7 @@ class BufferedNDSpaceElement>( } } -class BufferedNDRingElement>( +public class BufferedNDRingElement>( override val context: BufferedNDRing, override val buffer: Buffer ) : BufferedNDElement(), RingElement, BufferedNDRingElement, BufferedNDRing> { @@ -38,7 +38,7 @@ class BufferedNDRingElement>( } } -class BufferedNDFieldElement>( +public class BufferedNDFieldElement>( override val context: BufferedNDField, override val buffer: Buffer ) : BufferedNDElement(), FieldElement, BufferedNDFieldElement, BufferedNDField> { @@ -54,7 +54,7 @@ class BufferedNDFieldElement>( /** * Element by element application of any operation on elements to the whole array. Just like in numpy. */ -operator fun > Function1.invoke(ndElement: BufferedNDElement): MathElement> = +public operator fun > Function1.invoke(ndElement: BufferedNDElement): MathElement> = ndElement.context.run { map(ndElement) { invoke(it) }.toElement() } /* plus and minus */ @@ -62,13 +62,13 @@ operator fun > Function1.invoke(ndElement: BufferedN /** * Summation operation for [BufferedNDElement] and single element */ -operator fun > BufferedNDElement.plus(arg: T): NDElement> = +public operator fun > BufferedNDElement.plus(arg: T): NDElement> = context.map(this) { it + arg }.wrap() /** * Subtraction operation between [BufferedNDElement] and single element */ -operator fun > BufferedNDElement.minus(arg: T): NDElement> = +public operator fun > BufferedNDElement.minus(arg: T): NDElement> = context.map(this) { it - arg }.wrap() /* prod and div */ @@ -76,11 +76,11 @@ operator fun > BufferedNDElement.minus(arg: T): NDEl /** * Product operation for [BufferedNDElement] and single element */ -operator fun > BufferedNDElement.times(arg: T): NDElement> = +public operator fun > BufferedNDElement.times(arg: T): NDElement> = context.map(this) { it * arg }.wrap() /** * Division operation between [BufferedNDElement] and single element */ -operator fun > BufferedNDElement.div(arg: T): NDElement> = +public operator fun > BufferedNDElement.div(arg: T): NDElement> = context.map(this) { it / arg }.wrap() diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt index 4afaa63ab..48d15d50a 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt @@ -11,44 +11,44 @@ import kotlin.reflect.KClass * * @param T the type of buffer. */ -typealias BufferFactory = (Int, (Int) -> T) -> Buffer +public typealias BufferFactory = (Int, (Int) -> T) -> Buffer /** * Function that produces [MutableBuffer] from its size and function that supplies values. * * @param T the type of buffer. */ -typealias MutableBufferFactory = (Int, (Int) -> T) -> MutableBuffer +public typealias MutableBufferFactory = (Int, (Int) -> T) -> MutableBuffer /** * A generic immutable random-access structure for both primitives and objects. * * @param T the type of elements contained in the buffer. */ -interface Buffer { +public interface Buffer { /** * The size of this buffer. */ - val size: Int + public val size: Int /** * Gets element at given index. */ - operator fun get(index: Int): T + public operator fun get(index: Int): T /** * Iterates over all elements. */ - operator fun iterator(): Iterator + public operator fun iterator(): Iterator /** * Checks content equality with another buffer. */ - fun contentEquals(other: Buffer<*>): Boolean = + public fun contentEquals(other: Buffer<*>): Boolean = asSequence().mapIndexed { index, value -> value == other[index] }.all { it } - companion object { - inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer { + public companion object { + public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer { val array = DoubleArray(size) { initializer(it) } return RealBuffer(array) } @@ -56,10 +56,10 @@ interface Buffer { /** * Create a boxing buffer of given type */ - inline fun boxing(size: Int, initializer: (Int) -> T): Buffer = ListBuffer(List(size, initializer)) + public inline fun boxing(size: Int, initializer: (Int) -> T): Buffer = ListBuffer(List(size, initializer)) @Suppress("UNCHECKED_CAST") - inline fun auto(type: KClass, size: Int, crossinline initializer: (Int) -> T): Buffer { + public inline fun auto(type: KClass, size: Int, crossinline initializer: (Int) -> T): Buffer { //TODO add resolution based on Annotation or companion resolution return when (type) { Double::class -> RealBuffer(DoubleArray(size) { initializer(it) as Double }) as Buffer @@ -75,7 +75,7 @@ interface Buffer { * Create most appropriate immutable buffer for given type avoiding boxing wherever possible */ @Suppress("UNCHECKED_CAST") - inline fun auto(size: Int, crossinline initializer: (Int) -> T): Buffer = + public inline fun auto(size: Int, crossinline initializer: (Int) -> T): Buffer = auto(T::class, size, initializer) } } @@ -83,35 +83,35 @@ interface Buffer { /** * Creates a sequence that returns all elements from this [Buffer]. */ -fun Buffer.asSequence(): Sequence = Sequence(::iterator) +public fun Buffer.asSequence(): Sequence = Sequence(::iterator) /** * Creates an iterable that returns all elements from this [Buffer]. */ -fun Buffer.asIterable(): Iterable = Iterable(::iterator) +public fun Buffer.asIterable(): Iterable = Iterable(::iterator) /** * Returns an [IntRange] of the valid indices for this [Buffer]. */ -val Buffer<*>.indices: IntRange get() = 0 until size +public val Buffer<*>.indices: IntRange get() = 0 until size /** * A generic mutable random-access structure for both primitives and objects. * * @param T the type of elements contained in the buffer. */ -interface MutableBuffer : Buffer { +public interface MutableBuffer : Buffer { /** * Sets the array element at the specified [index] to the specified [value]. */ - operator fun set(index: Int, value: T) + public operator fun set(index: Int, value: T) /** * Returns a shallow copy of the buffer. */ - fun copy(): MutableBuffer + public fun copy(): MutableBuffer - companion object { + public companion object { /** * Create a boxing mutable buffer of given type */ @@ -216,7 +216,7 @@ class ArrayBuffer(private val array: Array) : MutableBuffer { /** * Returns an [ArrayBuffer] that wraps the original array. */ -fun Array.asBuffer(): ArrayBuffer = ArrayBuffer(this) +public fun Array.asBuffer(): ArrayBuffer = ArrayBuffer(this) /** * Immutable wrapper for [MutableBuffer]. @@ -224,7 +224,7 @@ fun Array.asBuffer(): ArrayBuffer = ArrayBuffer(this) * @param T the type of elements contained in the buffer. * @property buffer The underlying buffer. */ -inline class ReadOnlyBuffer(val buffer: MutableBuffer) : Buffer { +public inline class ReadOnlyBuffer(public val buffer: MutableBuffer) : Buffer { override val size: Int get() = buffer.size override operator fun get(index: Int): T = buffer[index] @@ -238,7 +238,7 @@ inline class ReadOnlyBuffer(val buffer: MutableBuffer) : Buffer { * * @param T the type of elements provided by the buffer. */ -class VirtualBuffer(override val size: Int, private val generator: (Int) -> T) : Buffer { +public class VirtualBuffer(override val size: Int, private val generator: (Int) -> T) : Buffer { 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 generator(index) @@ -258,14 +258,14 @@ class VirtualBuffer(override val size: Int, private val generator: (Int) -> T /** * Convert this buffer to read-only buffer. */ -fun Buffer.asReadOnly(): Buffer = if (this is MutableBuffer) ReadOnlyBuffer(this) else this +public fun Buffer.asReadOnly(): Buffer = if (this is MutableBuffer) ReadOnlyBuffer(this) else this /** * Typealias for buffer transformations. */ -typealias BufferTransform = (Buffer) -> Buffer +public typealias BufferTransform = (Buffer) -> Buffer /** * Typealias for buffer transformations with suspend function. */ -typealias SuspendBufferTransform = suspend (Buffer) -> Buffer +public typealias SuspendBufferTransform = suspend (Buffer) -> Buffer diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt index 2c6e3a5c7..56fe2a5ac 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt @@ -8,12 +8,12 @@ import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract -typealias ComplexNDElement = BufferedNDFieldElement +public typealias ComplexNDElement = BufferedNDFieldElement /** * An optimized nd-field for complex numbers */ -class ComplexNDField(override val shape: IntArray) : +public class ComplexNDField(override val shape: IntArray) : BufferedNDField, ExtendedNDField> { @@ -22,7 +22,7 @@ class ComplexNDField(override val shape: IntArray) : override val zero: ComplexNDElement by lazy { produce { zero } } override val one: ComplexNDElement by lazy { produce { one } } - inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Complex): Buffer = + public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Complex): Buffer = Buffer.complex(size) { initializer(it) } /** @@ -130,29 +130,25 @@ operator fun Function1.invoke(ndElement: ComplexNDElement): Co /** * Summation operation for [BufferedNDElement] and single element */ -operator fun ComplexNDElement.plus(arg: Complex): ComplexNDElement = map { it + arg } +public operator fun ComplexNDElement.plus(arg: Complex): ComplexNDElement = map { it + arg } /** * Subtraction operation between [BufferedNDElement] and single element */ -operator fun ComplexNDElement.minus(arg: Complex): ComplexNDElement = - map { it - arg } +public operator fun ComplexNDElement.minus(arg: Complex): ComplexNDElement = map { it - arg } -operator fun ComplexNDElement.plus(arg: Double): ComplexNDElement = - map { it + arg } +public operator fun ComplexNDElement.plus(arg: Double): ComplexNDElement = map { it + arg } +public operator fun ComplexNDElement.minus(arg: Double): ComplexNDElement = map { it - arg } -operator fun ComplexNDElement.minus(arg: Double): ComplexNDElement = - map { it - arg } +public fun NDField.Companion.complex(vararg shape: Int): ComplexNDField = ComplexNDField(shape) -fun NDField.Companion.complex(vararg shape: Int): ComplexNDField = ComplexNDField(shape) - -fun NDElement.Companion.complex(vararg shape: Int, initializer: ComplexField.(IntArray) -> Complex): ComplexNDElement = +public fun NDElement.Companion.complex(vararg shape: Int, initializer: ComplexField.(IntArray) -> Complex): ComplexNDElement = NDField.complex(*shape).produce(initializer) /** * Produce a context for n-dimensional operations inside this real field */ -inline fun ComplexField.nd(vararg shape: Int, action: ComplexNDField.() -> R): R { +public inline fun ComplexField.nd(vararg shape: Int, action: ComplexNDField.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } return NDField.complex(*shape).action() } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ExtendedNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ExtendedNDField.kt index 24aa48c6b..12731ff86 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ExtendedNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ExtendedNDField.kt @@ -9,7 +9,7 @@ import scientifik.kmath.operations.ExtendedField * @param N the type of ND structure. * @param F the extended field of structure elements. */ -interface ExtendedNDField, N : NDStructure> : NDField, ExtendedField +public interface ExtendedNDField, N : NDStructure> : NDField, ExtendedField ///** // * NDField that supports [ExtendedField] operations on its elements diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt index 9c32aa31b..314f9fd63 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt @@ -9,7 +9,7 @@ import kotlin.experimental.and * * @property mask bit mask value of this flag. */ -enum class ValueFlag(val mask: Byte) { +public enum class ValueFlag(public val mask: Byte) { /** * Reports the value is NaN. */ diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt index 95651c547..88a3bd39d 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt @@ -9,7 +9,7 @@ import kotlin.contracts.contract * * @property array the underlying array. */ -inline class IntBuffer(val array: IntArray) : MutableBuffer { +public inline class IntBuffer(public val array: IntArray) : MutableBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Int = array[index] diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt index a44109f8a..17f161d19 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt @@ -8,7 +8,7 @@ import kotlin.contracts.contract * * @property array the underlying array. */ -inline class LongBuffer(val array: LongArray) : MutableBuffer { +public inline class LongBuffer(public val array: LongArray) : MutableBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Long = array[index] @@ -31,7 +31,7 @@ inline class LongBuffer(val array: LongArray) : MutableBuffer { * The function [init] is called for each array element sequentially starting from the first one. * It should return the value for an buffer element given its index. */ -inline fun LongBuffer(size: Int, init: (Int) -> Long): LongBuffer { +public inline fun LongBuffer(size: Int, init: (Int) -> Long): LongBuffer { contract { callsInPlace(init) } return LongBuffer(LongArray(size) { init(it) }) } @@ -39,12 +39,12 @@ inline fun LongBuffer(size: Int, init: (Int) -> Long): LongBuffer { /** * Returns a new [LongBuffer] of given elements. */ -fun LongBuffer(vararg longs: Long): LongBuffer = LongBuffer(longs) +public fun LongBuffer(vararg longs: Long): LongBuffer = LongBuffer(longs) /** * Returns a [IntArray] containing all of the elements of this [MutableBuffer]. */ -val MutableBuffer.array: LongArray +public val MutableBuffer.array: LongArray get() = (if (this is LongBuffer) array else LongArray(size) { get(it) }) /** @@ -53,4 +53,4 @@ val MutableBuffer.array: LongArray * @receiver the array. * @return the new buffer. */ -fun LongArray.asBuffer(): LongBuffer = LongBuffer(this) +public fun LongArray.asBuffer(): LongBuffer = LongBuffer(this) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt index f09db3c72..a28eda9b9 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt @@ -5,12 +5,10 @@ import scientifik.kmath.operations.Field import scientifik.kmath.operations.Ring import scientifik.kmath.operations.Space - /** * An exception is thrown when the expected ans actual shape of NDArray differs */ -class ShapeMismatchException(val expected: IntArray, val actual: IntArray) : RuntimeException() - +public class ShapeMismatchException(public val expected: IntArray, public val actual: IntArray) : RuntimeException() /** * The base interface for all nd-algebra implementations @@ -18,53 +16,49 @@ class ShapeMismatchException(val expected: IntArray, val actual: IntArray) : Run * @param C the type of the element context * @param N the type of the structure */ -interface NDAlgebra> { - val shape: IntArray - val elementContext: C +public interface NDAlgebra> { + public val shape: IntArray + public val elementContext: C /** * Produce a new [N] structure using given initializer function */ - fun produce(initializer: C.(IntArray) -> T): N + public fun produce(initializer: C.(IntArray) -> T): N /** * Map elements from one structure to another one */ - fun map(arg: N, transform: C.(T) -> T): N + public fun map(arg: N, transform: C.(T) -> T): N /** * Map indexed elements */ - fun mapIndexed(arg: N, transform: C.(index: IntArray, T) -> T): N + public fun mapIndexed(arg: N, transform: C.(index: IntArray, T) -> T): N /** * Combine two structures into one */ - fun combine(a: N, b: N, transform: C.(T, T) -> T): N + public fun combine(a: N, b: N, transform: C.(T, T) -> T): N /** * Check if given elements are consistent with this context */ - fun check(vararg elements: N) { - elements.forEach { - if (!shape.contentEquals(it.shape)) { - throw ShapeMismatchException(shape, it.shape) - } - } + public fun check(vararg elements: N): Unit = elements.forEach { + if (!shape.contentEquals(it.shape)) throw ShapeMismatchException(shape, it.shape) } /** * element-by-element invoke a function working on [T] on a [NDStructure] */ - operator fun Function1.invoke(structure: N): N = map(structure) { value -> this@invoke(value) } + public operator fun Function1.invoke(structure: N): N = map(structure) { value -> this@invoke(value) } - companion object + public companion object } /** * An nd-space over element space */ -interface NDSpace, N : NDStructure> : Space, NDAlgebra { +public interface NDSpace, N : NDStructure> : Space, NDAlgebra { /** * Element-by-element addition */ @@ -76,32 +70,31 @@ interface NDSpace, N : NDStructure> : Space, NDAlgebra add(arg, value) } + public operator fun N.plus(arg: T): N = map(this) { value -> add(arg, value) } - operator fun N.minus(arg: T): N = map(this) { value -> add(arg, -value) } + public operator fun N.minus(arg: T): N = map(this) { value -> add(arg, -value) } - operator fun T.plus(arg: N): N = map(arg) { value -> add(this@plus, value) } - operator fun T.minus(arg: N): N = map(arg) { value -> add(-this@minus, value) } + public operator fun T.plus(arg: N): N = map(arg) { value -> add(this@plus, value) } + public operator fun T.minus(arg: N): N = map(arg) { value -> add(-this@minus, value) } - companion object + public companion object } /** * An nd-ring over element ring */ -interface NDRing, N : NDStructure> : Ring, NDSpace { - +public interface NDRing, N : NDStructure> : Ring, NDSpace { /** * Element-by-element multiplication */ override fun multiply(a: N, b: N): N = combine(a, b) { aValue, bValue -> multiply(aValue, bValue) } //TODO move to extensions after KEEP-176 - operator fun N.times(arg: T): N = map(this) { value -> multiply(arg, value) } + public operator fun N.times(arg: T): N = map(this) { value -> multiply(arg, value) } - operator fun T.times(arg: N): N = map(arg) { value -> multiply(this@times, value) } + public operator fun T.times(arg: N): N = map(arg) { value -> multiply(this@times, value) } - companion object + public companion object } /** @@ -111,17 +104,16 @@ interface NDRing, N : NDStructure> : Ring, NDSpace * @param N the type of ND structure. * @param F field of structure elements. */ -interface NDField, N : NDStructure> : Field, NDRing { - +public interface NDField, N : NDStructure> : Field, NDRing { /** * Element-by-element division */ override fun divide(a: N, b: N): N = combine(a, b) { aValue, bValue -> divide(aValue, bValue) } //TODO move to extensions after KEEP-176 - operator fun N.div(arg: T): N = map(this) { value -> divide(arg, value) } + public operator fun N.div(arg: T): N = map(this) { value -> divide(arg, value) } - operator fun T.div(arg: N): N = map(arg) { divide(it, this@div) } + public operator fun T.div(arg: N): N = map(arg) { divide(it, this@div) } companion object { diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt index 6533f64be..ac2adbe9b 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt @@ -3,9 +3,9 @@ package scientifik.kmath.structures import scientifik.kmath.operations.FieldElement import scientifik.kmath.operations.RealField -typealias RealNDElement = BufferedNDFieldElement +public typealias RealNDElement = BufferedNDFieldElement -class RealNDField(override val shape: IntArray) : +public class RealNDField(override val shape: IntArray) : BufferedNDField, ExtendedNDField> { @@ -15,7 +15,7 @@ class RealNDField(override val shape: IntArray) : override val zero: RealNDElement by lazy { produce { zero } } override val one: RealNDElement by lazy { produce { one } } - inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer = + public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer = RealBuffer(DoubleArray(size) { initializer(it) }) /** @@ -90,7 +90,7 @@ class RealNDField(override val shape: IntArray) : /** * Fast element production using function inlining */ -inline fun BufferedNDField.produceInline(crossinline initializer: RealField.(Int) -> Double): RealNDElement { +public inline fun BufferedNDField.produceInline(crossinline initializer: RealField.(Int) -> Double): RealNDElement { val array = DoubleArray(strides.linearSize) { offset -> RealField.initializer(offset) } return BufferedNDFieldElement(this, RealBuffer(array)) } @@ -98,13 +98,13 @@ inline fun BufferedNDField.produceInline(crossinline initiali /** * Map one [RealNDElement] using function with indices. */ -inline fun RealNDElement.mapIndexed(crossinline transform: RealField.(index: IntArray, Double) -> Double): RealNDElement = +public inline fun RealNDElement.mapIndexed(crossinline transform: RealField.(index: IntArray, Double) -> Double): RealNDElement = context.produceInline { offset -> transform(strides.index(offset), buffer[offset]) } /** * Map one [RealNDElement] using function without indices. */ -inline fun RealNDElement.map(crossinline transform: RealField.(Double) -> Double): RealNDElement { +public inline fun RealNDElement.map(crossinline transform: RealField.(Double) -> Double): RealNDElement { val array = DoubleArray(strides.linearSize) { offset -> RealField.transform(buffer[offset]) } return BufferedNDFieldElement(context, RealBuffer(array)) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt index 9aa674177..82deb9275 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt @@ -8,7 +8,7 @@ import kotlin.contracts.contract * * @property array the underlying array. */ -inline class ShortBuffer(val array: ShortArray) : MutableBuffer { +public inline class ShortBuffer(public val array: ShortArray) : MutableBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Short = array[index] @@ -30,7 +30,7 @@ inline class ShortBuffer(val array: ShortArray) : MutableBuffer { * The function [init] is called for each array element sequentially starting from the first one. * It should return the value for an buffer element given its index. */ -inline fun ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer { +public inline fun ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer { contract { callsInPlace(init) } return ShortBuffer(ShortArray(size) { init(it) }) } @@ -38,12 +38,12 @@ inline fun ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer { /** * Returns a new [ShortBuffer] of given elements. */ -fun ShortBuffer(vararg shorts: Short): ShortBuffer = ShortBuffer(shorts) +public fun ShortBuffer(vararg shorts: Short): ShortBuffer = ShortBuffer(shorts) /** * Returns a [ShortArray] containing all of the elements of this [MutableBuffer]. */ -val MutableBuffer.array: ShortArray +public val MutableBuffer.array: ShortArray get() = (if (this is ShortBuffer) array else ShortArray(size) { get(it) }) /** @@ -52,4 +52,4 @@ val MutableBuffer.array: ShortArray * @receiver the array. * @return the new buffer. */ -fun ShortArray.asBuffer(): ShortBuffer = ShortBuffer(this) +public fun ShortArray.asBuffer(): ShortBuffer = ShortBuffer(this) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt index f404a2a27..9a2ec1c88 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt @@ -2,20 +2,19 @@ package scientifik.kmath.structures import scientifik.kmath.operations.RingElement import scientifik.kmath.operations.ShortRing +import kotlin.contracts.contract +public typealias ShortNDElement = BufferedNDRingElement -typealias ShortNDElement = BufferedNDRingElement - -class ShortNDRing(override val shape: IntArray) : +public class ShortNDRing(override val shape: IntArray) : BufferedNDRing { override val strides: Strides = DefaultStrides(shape) - override val elementContext: ShortRing get() = ShortRing override val zero: ShortNDElement by lazy { produce { zero } } override val one: ShortNDElement by lazy { produce { one } } - inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Short): Buffer = + public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Short): Buffer = ShortBuffer(ShortArray(size) { initializer(it) }) /** @@ -70,7 +69,8 @@ class ShortNDRing(override val shape: IntArray) : /** * Fast element production using function inlining. */ -inline fun BufferedNDRing.produceInline(crossinline initializer: ShortRing.(Int) -> Short): ShortNDElement { +public inline fun BufferedNDRing.produceInline(crossinline initializer: ShortRing.(Int) -> Short): ShortNDElement { + contract { callsInPlace(initializer) } val array = ShortArray(strides.linearSize) { offset -> ShortRing.initializer(offset) } return BufferedNDRingElement(this, ShortBuffer(array)) } @@ -78,7 +78,7 @@ inline fun BufferedNDRing.produceInline(crossinline initialize /** * Element by element application of any operation on elements to the whole array. */ -operator fun Function1.invoke(ndElement: ShortNDElement): ShortNDElement = +public operator fun Function1.invoke(ndElement: ShortNDElement): ShortNDElement = ndElement.context.produceInline { i -> invoke(ndElement.buffer[i]) } @@ -87,11 +87,11 @@ operator fun Function1.invoke(ndElement: ShortNDElement): ShortNDE /** * Summation operation for [ShortNDElement] and single element. */ -operator fun ShortNDElement.plus(arg: Short): ShortNDElement = +public operator fun ShortNDElement.plus(arg: Short): ShortNDElement = context.produceInline { i -> (buffer[i] + arg).toShort() } /** * Subtraction operation between [ShortNDElement] and single element. */ -operator fun ShortNDElement.minus(arg: Short): ShortNDElement = +public operator fun ShortNDElement.minus(arg: Short): ShortNDElement = context.produceInline { i -> (buffer[i] - arg).toShort() } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt index eeb6bd3dc..e0ae4d4a2 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt @@ -3,26 +3,22 @@ package scientifik.kmath.structures /** * A structure that is guaranteed to be two-dimensional */ -interface Structure2D : NDStructure { - val rowNum: Int get() = shape[0] - val colNum: Int get() = shape[1] +public interface Structure2D : NDStructure { + public val rowNum: Int get() = shape[0] + public val colNum: Int get() = shape[1] - operator fun get(i: Int, j: Int): T + public operator fun get(i: Int, j: Int): T override operator fun get(index: IntArray): T { require(index.size == 2) { "Index dimension mismatch. Expected 2 but found ${index.size}" } return get(index[0], index[1]) } - val rows: Buffer> - get() = VirtualBuffer(rowNum) { i -> - VirtualBuffer(colNum) { j -> get(i, j) } - } + public val rows: Buffer> + get() = VirtualBuffer(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } } - val columns: Buffer> - get() = VirtualBuffer(colNum) { j -> - VirtualBuffer(rowNum) { i -> get(i, j) } - } + public val columns: Buffer> + get() = VirtualBuffer(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } } override fun elements(): Sequence> = sequence { for (i in (0 until rowNum)) { @@ -32,7 +28,7 @@ interface Structure2D : NDStructure { } } - companion object + public companion object } /** @@ -49,10 +45,10 @@ private inline class Structure2DWrapper(val structure: NDStructure) : Stru /** * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch */ -fun NDStructure.as2D(): Structure2D = if (shape.size == 2) { +public fun NDStructure.as2D(): Structure2D = if (shape.size == 2) { Structure2DWrapper(this) } else { error("Can't create 2d-structure from ${shape.size}d-structure") } -typealias Matrix = Structure2D +public typealias Matrix = Structure2D diff --git a/kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt b/kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt index f10ef24da..e5ec374c9 100644 --- a/kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt +++ b/kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt @@ -7,7 +7,7 @@ import java.math.MathContext /** * A field over [BigInteger]. */ -object JBigIntegerField : Field { +public object JBigIntegerField : Field { override val zero: BigInteger get() = BigInteger.ZERO @@ -28,7 +28,7 @@ object JBigIntegerField : Field { * * @property mathContext the [MathContext] to use. */ -abstract class JBigDecimalFieldBase internal constructor(val mathContext: MathContext = MathContext.DECIMAL64) : +public abstract class JBigDecimalFieldBase internal constructor(public val mathContext: MathContext = MathContext.DECIMAL64) : Field, PowerOperations { override val zero: BigDecimal @@ -54,6 +54,6 @@ abstract class JBigDecimalFieldBase internal constructor(val mathContext: MathCo /** * A field over [BigDecimal]. */ -class JBigDecimalField(mathContext: MathContext = MathContext.DECIMAL64) : JBigDecimalFieldBase(mathContext) { - companion object : JBigDecimalFieldBase() +public class JBigDecimalField(mathContext: MathContext = MathContext.DECIMAL64) : JBigDecimalFieldBase(mathContext) { + public companion object : JBigDecimalFieldBase() } diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 4469a9ef6..e108c2755 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -1,12 +1,8 @@ -plugins { - id("scientifik.mpp") - //id("scientifik.atomic") -} +plugins { id("ru.mipt.npm.mpp") } kotlin.sourceSets { all { with(languageSettings) { - useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") useExperimentalAnnotation("kotlinx.coroutines.InternalCoroutinesApi") useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi") useExperimentalAnnotation("kotlinx.coroutines.FlowPreview") @@ -16,15 +12,7 @@ kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-core")) - api("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:${Scientifik.coroutinesVersion}") + api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${ru.mipt.npm.gradle.KScienceVersions.coroutinesVersion}") } } - - jvmMain { - dependencies { api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Scientifik.coroutinesVersion}") } - } - - jsMain { - dependencies { api("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:${Scientifik.coroutinesVersion}") } - } } diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt index f0ffd13cd..e899f8ece 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt @@ -26,31 +26,31 @@ import kotlinx.coroutines.sync.withLock * A not-necessary-Markov chain of some type * @param R - the chain element type */ -interface Chain : Flow { +public interface Chain : Flow { /** * Generate next value, changing state if needed */ - suspend fun next(): R + public suspend fun next(): R /** * Create a copy of current chain state. Consuming resulting chain does not affect initial chain */ - fun fork(): Chain + public fun fork(): Chain override suspend fun collect(collector: FlowCollector): Unit = flow { while (true) emit(next()) }.collect(collector) - companion object + public companion object } -fun Iterator.asChain(): Chain = SimpleChain { next() } -fun Sequence.asChain(): Chain = iterator().asChain() +public fun Iterator.asChain(): Chain = SimpleChain { next() } +public fun Sequence.asChain(): Chain = iterator().asChain() /** * A simple chain of independent tokens */ -class SimpleChain(private val gen: suspend () -> R) : Chain { +public class SimpleChain(private val gen: suspend () -> R) : Chain { override suspend fun next(): R = gen() override fun fork(): Chain = this } @@ -58,13 +58,13 @@ class SimpleChain(private val gen: suspend () -> R) : Chain { /** * A stateless Markov chain */ -class MarkovChain(private val seed: suspend () -> R, private val gen: suspend (R) -> R) : Chain { +public class MarkovChain(private val seed: suspend () -> R, private val gen: suspend (R) -> R) : Chain { private val mutex = Mutex() private var value: R? = null - fun value(): R? = value + public fun value(): R? = value override suspend fun next(): R { mutex.withLock { @@ -84,7 +84,7 @@ class MarkovChain(private val seed: suspend () -> R, private val ge * @param S - the state of the chain * @param forkState - the function to copy current state without modifying it */ -class StatefulChain( +public class StatefulChain( private val state: S, private val seed: S.() -> R, private val forkState: ((S) -> S), @@ -94,7 +94,7 @@ class StatefulChain( private var value: R? = null - fun value(): R? = value + public fun value(): R? = value override suspend fun next(): R { mutex.withLock { @@ -110,19 +110,17 @@ class StatefulChain( /** * A chain that repeats the same value */ -class ConstantChain(val value: T) : Chain { +public class ConstantChain(public val value: T) : Chain { override suspend fun next(): T = value - override fun fork(): Chain { - return this - } + override fun fork(): Chain = this } /** * Map the chain result using suspended transformation. Initial chain result can no longer be safely consumed * since mapped chain consumes tokens. Accepts regular transformation function */ -fun Chain.map(func: suspend (T) -> R): Chain = object : Chain { +public fun Chain.map(func: suspend (T) -> R): Chain = object : Chain { override suspend fun next(): R = func(this@map.next()) override fun fork(): Chain = this@map.fork().map(func) } @@ -130,7 +128,7 @@ fun Chain.map(func: suspend (T) -> R): Chain = object : Chain { /** * [block] must be a pure function or at least not use external random variables, otherwise fork could be broken */ -fun Chain.filter(block: (T) -> Boolean): Chain = object : Chain { +public fun Chain.filter(block: (T) -> Boolean): Chain = object : Chain { override suspend fun next(): T { var next: T @@ -146,12 +144,12 @@ fun Chain.filter(block: (T) -> Boolean): Chain = object : Chain { /** * Map the whole chain */ -fun Chain.collect(mapper: suspend (Chain) -> R): Chain = object : Chain { +public fun Chain.collect(mapper: suspend (Chain) -> R): Chain = object : Chain { override suspend fun next(): R = mapper(this@collect) override fun fork(): Chain = this@collect.fork().collect(mapper) } -fun Chain.collectWithState(state: S, stateFork: (S) -> S, mapper: suspend S.(Chain) -> R): Chain = +public fun Chain.collectWithState(state: S, stateFork: (S) -> S, mapper: suspend S.(Chain) -> R): Chain = object : Chain { override suspend fun next(): R = state.mapper(this@collectWithState) @@ -162,7 +160,7 @@ fun Chain.collectWithState(state: S, stateFork: (S) -> S, mapper: s /** * Zip two chains together using given transformation */ -fun Chain.zip(other: Chain, block: suspend (T, U) -> R): Chain = object : Chain { +public fun Chain.zip(other: Chain, block: suspend (T, U) -> R): Chain = object : Chain { override suspend fun next(): R = block(this@zip.next(), other.next()) override fun fork(): Chain = this@zip.fork().zip(other.fork(), block) } diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index dda6cd2f0..0a36e4435 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -1,8 +1,6 @@ -plugins { - id("scientifik.mpp") -} +plugins { id("ru.mipt.npm.mpp") } -description = "A proof of concept module for adding typ-safe dimensions to structures" +description = "A proof of concept module for adding type-safe dimensions to structures" kotlin.sourceSets { commonMain { @@ -11,9 +9,9 @@ kotlin.sourceSets { } } - jvmMain{ - dependencies{ + jvmMain { + dependencies { api(kotlin("reflect")) } } -} \ No newline at end of file +} diff --git a/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Dimensions.kt b/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Dimensions.kt index f40483cfd..e96367443 100644 --- a/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Dimensions.kt +++ b/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Dimensions.kt @@ -6,30 +6,28 @@ import kotlin.reflect.KClass * An abstract class which is not used in runtime. Designates a size of some structure. * Could be replaced later by fully inline constructs */ -interface Dimension { +public interface Dimension { + public val dim: UInt - val dim: UInt - companion object { - - } + public companion object } -fun KClass.dim(): UInt = Dimension.resolve(this).dim +public fun KClass.dim(): UInt = Dimension.resolve(this).dim -expect fun Dimension.Companion.resolve(type: KClass): D +public expect fun Dimension.Companion.resolve(type: KClass): D -expect fun Dimension.Companion.of(dim: UInt): Dimension +public expect fun Dimension.Companion.of(dim: UInt): Dimension -inline fun Dimension.Companion.dim(): UInt = D::class.dim() +public inline fun Dimension.Companion.dim(): UInt = D::class.dim() -object D1 : Dimension { +public object D1 : Dimension { override val dim: UInt get() = 1U } -object D2 : Dimension { +public object D2 : Dimension { override val dim: UInt get() = 2U } -object D3 : Dimension { +public object D3 : Dimension { override val dim: UInt get() = 3U } diff --git a/kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt b/kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt index bbd580629..e5cc451d1 100644 --- a/kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt +++ b/kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt @@ -9,11 +9,11 @@ private val dimensionMap = hashMapOf( ) @Suppress("UNCHECKED_CAST") -actual fun Dimension.Companion.resolve(type: KClass): D { +public actual fun Dimension.Companion.resolve(type: KClass): D { return dimensionMap.entries.find { it.value::class == type }?.value as? D ?: error("Can't resolve dimension $type") } -actual fun Dimension.Companion.of(dim: UInt): Dimension { +public actual fun Dimension.Companion.of(dim: UInt): Dimension { return dimensionMap.getOrPut(dim) { object : Dimension { override val dim: UInt get() = dim diff --git a/kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt b/kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt index e8fe8f59b..42310cb3a 100644 --- a/kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt +++ b/kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt @@ -2,11 +2,11 @@ package scientifik.kmath.dimensions import kotlin.reflect.KClass -actual fun Dimension.Companion.resolve(type: KClass): D{ +public actual fun Dimension.Companion.resolve(type: KClass): D{ return type.objectInstance ?: error("No object instance for dimension class") } -actual fun Dimension.Companion.of(dim: UInt): Dimension{ +public actual fun Dimension.Companion.of(dim: UInt): Dimension{ return when(dim){ 1u -> D1 2u -> D2 diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 46d2682f7..00abcb934 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -1,6 +1,7 @@ -plugins { id("scientifik.mpp") } +plugins { id("ru.mipt.npm.mpp") } -kotlin.sourceSets { - all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } - commonMain { dependencies { api(project(":kmath-core")) } } +kotlin.sourceSets.commonMain { + dependencies { + api(project(":kmath-core")) + } } diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt index 3752fc3ca..a3b41288a 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt @@ -25,20 +25,20 @@ import kotlin.math.pow * Functions that help create a real (Double) matrix */ -typealias RealMatrix = Matrix +public typealias RealMatrix = Matrix -fun realMatrix(rowNum: Int, colNum: Int, initializer: (i: Int, j: Int) -> Double): RealMatrix = +public fun realMatrix(rowNum: Int, colNum: Int, initializer: (i: Int, j: Int) -> Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum, initializer) -fun Array.toMatrix(): RealMatrix { +public fun Array.toMatrix(): RealMatrix { return MatrixContext.real.produce(size, this[0].size) { row, col -> this[row][col] } } -fun Sequence.toMatrix(): RealMatrix = toList().let { +public fun Sequence.toMatrix(): RealMatrix = toList().let { MatrixContext.real.produce(it.size, it[0].size) { row, col -> it[row][col] } } -fun Matrix.repeatStackVertical(n: Int): RealMatrix = +public fun Matrix.repeatStackVertical(n: Int): RealMatrix = VirtualMatrix(rowNum * n, colNum) { row, col -> get(if (row == 0) 0 else row % rowNum, col) } @@ -47,37 +47,37 @@ fun Matrix.repeatStackVertical(n: Int): RealMatrix = * Operations for matrix and real number */ -operator fun Matrix.times(double: Double): RealMatrix = +public operator fun Matrix.times(double: Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] * double } -operator fun Matrix.plus(double: Double): RealMatrix = +public operator fun Matrix.plus(double: Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] + double } -operator fun Matrix.minus(double: Double): RealMatrix = +public operator fun Matrix.minus(double: Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] - double } -operator fun Matrix.div(double: Double): RealMatrix = +public operator fun Matrix.div(double: Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] / double } -operator fun Double.times(matrix: Matrix): RealMatrix = +public operator fun Double.times(matrix: Matrix): RealMatrix = MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col -> this * matrix[row, col] } -operator fun Double.plus(matrix: Matrix): RealMatrix = +public operator fun Double.plus(matrix: Matrix): RealMatrix = MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col -> this + matrix[row, col] } -operator fun Double.minus(matrix: Matrix): RealMatrix = +public operator fun Double.minus(matrix: Matrix): RealMatrix = MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col -> this - matrix[row, col] } @@ -91,11 +91,11 @@ operator fun Double.minus(matrix: Matrix): RealMatrix = * Per-element (!) square and power operations */ -fun Matrix.square(): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> +public fun Matrix.square(): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col].pow(2) } -fun Matrix.pow(n: Int): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { i, j -> +public fun Matrix.pow(n: Int): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { i, j -> this[i, j].pow(n) } @@ -103,24 +103,20 @@ fun Matrix.pow(n: Int): RealMatrix = MatrixContext.real.produce(rowNum, * Operations on two matrices (per-element!) */ -operator fun Matrix.times(other: Matrix): RealMatrix = - MatrixContext.real.produce(rowNum, colNum) { row, col -> - this[row, col] * other[row, col] - } +public operator fun Matrix.times(other: Matrix): RealMatrix = + MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] * other[row, col] } -operator fun Matrix.plus(other: Matrix): RealMatrix = +public operator fun Matrix.plus(other: Matrix): RealMatrix = MatrixContext.real.add(this, other) -operator fun Matrix.minus(other: Matrix): RealMatrix = - MatrixContext.real.produce(rowNum, colNum) { row, col -> - this[row, col] - other[row, col] - } +public operator fun Matrix.minus(other: Matrix): RealMatrix = + MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] - other[row, col] } /* * Operations on columns */ -inline fun Matrix.appendColumn(crossinline mapper: (Buffer) -> Double): Matrix { +public inline fun Matrix.appendColumn(crossinline mapper: (Buffer) -> Double): Matrix { contract { callsInPlace(mapper) } return MatrixContext.real.produce(rowNum, colNum + 1) { row, col -> @@ -131,28 +127,28 @@ inline fun Matrix.appendColumn(crossinline mapper: (Buffer) -> D } } -fun Matrix.extractColumns(columnRange: IntRange): RealMatrix = +public fun Matrix.extractColumns(columnRange: IntRange): RealMatrix = MatrixContext.real.produce(rowNum, columnRange.count()) { row, col -> this[row, columnRange.first + col] } -fun Matrix.extractColumn(columnIndex: Int): RealMatrix = +public fun Matrix.extractColumn(columnIndex: Int): RealMatrix = extractColumns(columnIndex..columnIndex) -fun Matrix.sumByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun Matrix.sumByColumn(): RealBuffer = RealBuffer(colNum) { j -> val column = columns[j] elementContext { sum(column.asIterable()) } } -fun Matrix.minByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun Matrix.minByColumn(): RealBuffer = RealBuffer(colNum) { j -> columns[j].asIterable().min() ?: error("Cannot produce min on empty column") } -fun Matrix.maxByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun Matrix.maxByColumn(): RealBuffer = RealBuffer(colNum) { j -> columns[j].asIterable().max() ?: error("Cannot produce min on empty column") } -fun Matrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun Matrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j -> columns[j].asIterable().average() } @@ -160,7 +156,7 @@ fun Matrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j -> * Operations processing all elements */ -fun Matrix.sum(): Double = elements().map { (_, value) -> value }.sum() -fun Matrix.min(): Double? = elements().map { (_, value) -> value }.min() -fun Matrix.max(): Double? = elements().map { (_, value) -> value }.max() -fun Matrix.average(): Double = elements().map { (_, value) -> value }.average() +public fun Matrix.sum(): Double = elements().map { (_, value) -> value }.sum() +public fun Matrix.min(): Double? = elements().map { (_, value) -> value }.min() +public fun Matrix.max(): Double? = elements().map { (_, value) -> value }.max() +public fun Matrix.average(): Double = elements().map { (_, value) -> value }.average() diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 46d2682f7..00abcb934 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -1,6 +1,7 @@ -plugins { id("scientifik.mpp") } +plugins { id("ru.mipt.npm.mpp") } -kotlin.sourceSets { - all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } - commonMain { dependencies { api(project(":kmath-core")) } } +kotlin.sourceSets.commonMain { + dependencies { + api(project(":kmath-core")) + } } diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt index 16f8aa12b..b11469ccf 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt @@ -2,17 +2,17 @@ package scientifik.kmath.functions import scientifik.kmath.operations.Ring -interface Piecewise { - fun findPiece(arg: T): R? +public fun interface Piecewise { + public fun findPiece(arg: T): R? } -interface PiecewisePolynomial : +public fun interface PiecewisePolynomial : Piecewise> /** * Ordered list of pieces in piecewise function */ -class OrderedPiecewisePolynomial>(delimeter: T) : +public class OrderedPiecewisePolynomial>(delimeter: T) : PiecewisePolynomial { private val delimiters: ArrayList = arrayListOf(delimeter) @@ -22,13 +22,13 @@ class OrderedPiecewisePolynomial>(delimeter: T) : * Dynamically add a piece to the "right" side (beyond maximum argument value of previous piece) * @param right new rightmost position. If is less then current rightmost position, a error is thrown. */ - fun putRight(right: T, piece: Polynomial) { + public fun putRight(right: T, piece: Polynomial) { require(right > delimiters.last()) { "New delimiter should be to the right of old one" } delimiters.add(right) pieces.add(piece) } - fun putLeft(left: T, piece: Polynomial) { + public fun putLeft(left: T, piece: Polynomial) { require(left < delimiters.first()) { "New delimiter should be to the left of old one" } delimiters.add(0, left) pieces.add(0, piece) @@ -51,7 +51,7 @@ class OrderedPiecewisePolynomial>(delimeter: T) : /** * Return a value of polynomial function with given [ring] an given [arg] or null if argument is outside of piecewise definition. */ -fun , C : Ring> PiecewisePolynomial.value(ring: C, arg: T): T? = +public fun , C : Ring> PiecewisePolynomial.value(ring: C, arg: T): T? = findPiece(arg)?.value(ring, arg) -fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { value(ring, it) } \ No newline at end of file +public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { value(ring, it) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt index c4470ad27..35f1a1e16 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt @@ -3,7 +3,6 @@ package scientifik.kmath.functions import scientifik.kmath.operations.Ring import scientifik.kmath.operations.Space import scientifik.kmath.operations.invoke -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.math.max @@ -13,14 +12,14 @@ import kotlin.math.pow * Polynomial coefficients without fixation on specific context they are applied to * @param coefficients constant is the leftmost coefficient */ -inline class Polynomial(val coefficients: List) { - constructor(vararg coefficients: T) : this(coefficients.toList()) +public inline class Polynomial(public val coefficients: List) { + public constructor(vararg coefficients: T) : this(coefficients.toList()) } -fun Polynomial.value(): Double = +public fun Polynomial.value(): Double = coefficients.reduceIndexed { index: Int, acc: Double, d: Double -> acc + d.pow(index) } -fun > Polynomial.value(ring: C, arg: T): T = ring { +public fun > Polynomial.value(ring: C, arg: T): T = ring { if (coefficients.isEmpty()) return@ring zero var res = coefficients.first() var powerArg = arg @@ -37,20 +36,19 @@ fun > Polynomial.value(ring: C, arg: T): T = ring { /** * Represent a polynomial as a context-dependent function */ -fun > Polynomial.asMathFunction(): MathFunction = object : - MathFunction { - override operator fun C.invoke(arg: T): T = value(this, arg) -} +public fun > Polynomial.asMathFunction(): MathFunction = + MathFunction { arg -> value(this, arg) } /** * Represent the polynomial as a regular context-less function */ -fun > Polynomial.asFunction(ring: C): (T) -> T = { value(ring, it) } +public fun > Polynomial.asFunction(ring: C): (T) -> T = { value(ring, it) } /** * An algebra for polynomials */ -class PolynomialSpace>(val ring: C) : Space> { +public class PolynomialSpace>(public val ring: C) : Space> { + override val zero: Polynomial = Polynomial(emptyList()) override fun add(a: Polynomial, b: Polynomial): Polynomial { val dim = max(a.coefficients.size, b.coefficients.size) @@ -65,13 +63,10 @@ class PolynomialSpace>(val ring: C) : Space> override fun multiply(a: Polynomial, k: Number): Polynomial = ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * k }) } - override val zero: Polynomial = - Polynomial(emptyList()) - - operator fun Polynomial.invoke(arg: T): T = value(ring, arg) + public operator fun Polynomial.invoke(arg: T): T = value(ring, arg) } -inline fun , R> C.polynomial(block: PolynomialSpace.() -> R): R { +public inline fun , R> C.polynomial(block: PolynomialSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return PolynomialSpace(this).block() } diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt index 2b822b3ba..ce6156c0b 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt @@ -9,25 +9,25 @@ import scientifik.kmath.operations.RealField * @param C source algebra constraint * @param R result type */ -interface MathFunction, R> { - operator fun C.invoke(arg: T): R +public fun interface MathFunction, R> { + public operator fun C.invoke(arg: T): R } -fun MathFunction.invoke(arg: Double): R = RealField.invoke(arg) +public fun MathFunction.invoke(arg: Double): R = RealField.invoke(arg) /** * A suspendable function defined in algebraic context */ -interface SuspendableMathFunction, R> { - suspend operator fun C.invoke(arg: T): R +// TODO make fun interface, when the new JVM IR is enabled +public interface SuspendableMathFunction, R> { + public suspend operator fun C.invoke(arg: T): R } -suspend fun SuspendableMathFunction.invoke(arg: Double) = RealField.invoke(arg) - +public suspend fun SuspendableMathFunction.invoke(arg: Double) = RealField.invoke(arg) /** * A parametric function with parameter */ -interface ParametricFunction> { - operator fun C.invoke(arg: T, parameter: P): T +public fun interface ParametricFunction> { + public operator fun C.invoke(arg: T, parameter: P): T } diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt index 8d83e4198..95e734da8 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt @@ -6,16 +6,16 @@ import scientifik.kmath.operations.Ring import scientifik.kmath.structures.Buffer import scientifik.kmath.structures.asBuffer -interface Interpolator { - fun interpolate(points: XYPointSet): (X) -> Y +public fun interface Interpolator { + public fun interpolate(points: XYPointSet): (X) -> Y } -interface PolynomialInterpolator> : Interpolator { - val algebra: Ring +public interface PolynomialInterpolator> : Interpolator { + public val algebra: Ring - fun getDefaultValue(): T = error("Out of bounds") + public fun getDefaultValue(): T = error("Out of bounds") - fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial + public fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial override fun interpolate(points: XYPointSet): (T) -> T = { x -> interpolatePolynomials(points).value(algebra, x) ?: getDefaultValue() diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt index a7925180d..03a4625fc 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt @@ -9,7 +9,7 @@ import scientifik.kmath.operations.invoke /** * Reference JVM implementation: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/analysis/interpolation/LinearInterpolator.java */ -class LinearInterpolator>(override val algebra: Field) : PolynomialInterpolator { +public class LinearInterpolator>(override val algebra: Field) : PolynomialInterpolator { override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { require(points.size > 0) { "Point array should not be empty" } insureSorted(points) diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt index b709c4e87..c8ab42bf4 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt @@ -11,9 +11,9 @@ import scientifik.kmath.structures.MutableBufferFactory * Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type specific ones. * Based on https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java */ -class SplineInterpolator>( +public class SplineInterpolator>( override val algebra: Field, - val bufferFactory: MutableBufferFactory + public val bufferFactory: MutableBufferFactory ) : PolynomialInterpolator { //TODO possibly optimize zeroed buffers diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt index 56953f9fc..19297036b 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt @@ -3,21 +3,21 @@ package scientifik.kmath.interpolation import scientifik.kmath.structures.Buffer import scientifik.kmath.structures.Structure2D -interface XYPointSet { - val size: Int - val x: Buffer - val y: Buffer +public interface XYPointSet { + public val size: Int + public val x: Buffer + public val y: Buffer } -interface XYZPointSet : XYPointSet { - val z: Buffer +public interface XYZPointSet : XYPointSet { + public val z: Buffer } internal fun > insureSorted(points: XYPointSet) { for (i in 0 until points.size - 1) require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" } } -class NDStructureColumn(val structure: Structure2D, val column: Int) : Buffer { +public class NDStructureColumn(public val structure: Structure2D, public val column: Int) : Buffer { init { require(column < structure.colNum) { "Column index is outside of structure column range" } } @@ -33,7 +33,7 @@ class NDStructureColumn(val structure: Structure2D, val column: Int) : Buf }.iterator() } -class BufferXYPointSet(override val x: Buffer, override val y: Buffer) : XYPointSet { +public class BufferXYPointSet(override val x: Buffer, override val y: Buffer) : XYPointSet { init { require(x.size == y.size) { "Sizes of x and y buffers should be the same" } } @@ -42,11 +42,12 @@ class BufferXYPointSet(override val x: Buffer, override val y: Buffer Structure2D.asXYPointSet(): XYPointSet { +public fun Structure2D.asXYPointSet(): XYPointSet { require(shape[1] == 2) { "Structure second dimension should be of size 2" } + return object : XYPointSet { override val size: Int get() = this@asXYPointSet.shape[0] override val x: Buffer get() = NDStructureColumn(this@asXYPointSet, 0) override val y: Buffer get() = NDStructureColumn(this@asXYPointSet, 1) } -} \ No newline at end of file +} diff --git a/kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt index 23acd835c..540494caf 100644 --- a/kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt @@ -6,7 +6,6 @@ import scientifik.kmath.operations.RealField import kotlin.test.Test import kotlin.test.assertEquals - class LinearInterpolatorTest { @Test fun testInterpolation() { @@ -24,4 +23,4 @@ class LinearInterpolatorTest { assertEquals(2.0, function(1.5)) assertEquals(3.0, function(2.0)) } -} \ No newline at end of file +} diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index 39aa833ad..00abcb934 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -1,9 +1,7 @@ -plugins { - id("scientifik.mpp") -} +plugins { id("ru.mipt.npm.mpp") } kotlin.sourceSets.commonMain { dependencies { api(project(":kmath-core")) } -} \ No newline at end of file +} diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index 993bfed8e..7de21ad89 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -1,10 +1,8 @@ -plugins { - id("scientifik.mpp") -} +plugins { id("ru.mipt.npm.mpp") } kotlin.sourceSets.commonMain { dependencies { api(project(":kmath-core")) api(project(":kmath-for-real")) } -} \ No newline at end of file +} diff --git a/kmath-koma/build.gradle.kts b/kmath-koma/build.gradle.kts index 26955bca7..606113e75 100644 --- a/kmath-koma/build.gradle.kts +++ b/kmath-koma/build.gradle.kts @@ -1,10 +1,6 @@ -plugins { - id("scientifik.mpp") -} +plugins { id("ru.mipt.npm.mpp") } -repositories { - maven("http://dl.bintray.com/kyonifer/maven") -} +repositories.maven("http://dl.bintray.com/kyonifer/maven") kotlin.sourceSets { commonMain { @@ -13,16 +9,19 @@ kotlin.sourceSets { api("com.kyonifer:koma-core-api-common:0.12") } } + jvmMain { dependencies { api("com.kyonifer:koma-core-api-jvm:0.12") } } + jvmTest { dependencies { implementation("com.kyonifer:koma-core-ejml:0.12") } } + jsMain { dependencies { api("com.kyonifer:koma-core-api-js:0.12") diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 44a5ae24d..94527a6a3 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1,2 +1 @@ -plugins { id("scientifik.mpp") } -kotlin.sourceSets.all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } +plugins { id("ru.mipt.npm.mpp") } diff --git a/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt b/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt index 177c6b46b..9b6eb0435 100644 --- a/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt +++ b/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt @@ -6,84 +6,84 @@ import kotlin.contracts.contract /** * Represents a display of certain memory structure. */ -interface Memory { +public interface Memory { /** * The length of this memory in bytes. */ - val size: Int + public val size: Int /** * Get a projection of this memory (it reflects the changes in the parent memory block). */ - fun view(offset: Int, length: Int): Memory + public fun view(offset: Int, length: Int): Memory /** * Creates an independent copy of this memory. */ - fun copy(): Memory + public fun copy(): Memory /** * Gets or creates a reader of this memory. */ - fun reader(): MemoryReader + public fun reader(): MemoryReader /** * Gets or creates a writer of this memory. */ - fun writer(): MemoryWriter + public fun writer(): MemoryWriter - companion object + public companion object } /** * The interface to read primitive types in this memory. */ -interface MemoryReader { +public interface MemoryReader { /** * The underlying memory. */ - val memory: Memory + public val memory: Memory /** * Reads [Double] at certain [offset]. */ - fun readDouble(offset: Int): Double + public fun readDouble(offset: Int): Double /** * Reads [Float] at certain [offset]. */ - fun readFloat(offset: Int): Float + public fun readFloat(offset: Int): Float /** * Reads [Byte] at certain [offset]. */ - fun readByte(offset: Int): Byte + public fun readByte(offset: Int): Byte /** * Reads [Short] at certain [offset]. */ - fun readShort(offset: Int): Short + public fun readShort(offset: Int): Short /** * Reads [Int] at certain [offset]. */ - fun readInt(offset: Int): Int + public fun readInt(offset: Int): Int /** * Reads [Long] at certain [offset]. */ - fun readLong(offset: Int): Long + public fun readLong(offset: Int): Long /** * Disposes this reader if needed. */ - fun release() + public fun release() } /** * Uses the memory for read then releases the reader. */ -inline fun Memory.read(block: MemoryReader.() -> R): R { +public inline fun Memory.read(block: MemoryReader.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } val reader = reader() val result = reader.block() @@ -94,52 +94,52 @@ inline fun Memory.read(block: MemoryReader.() -> R): R { /** * The interface to write primitive types into this memory. */ -interface MemoryWriter { +public interface MemoryWriter { /** * The underlying memory. */ - val memory: Memory + public val memory: Memory /** * Writes [Double] at certain [offset]. */ - fun writeDouble(offset: Int, value: Double) + public fun writeDouble(offset: Int, value: Double) /** * Writes [Float] at certain [offset]. */ - fun writeFloat(offset: Int, value: Float) + public fun writeFloat(offset: Int, value: Float) /** * Writes [Byte] at certain [offset]. */ - fun writeByte(offset: Int, value: Byte) + public fun writeByte(offset: Int, value: Byte) /** * Writes [Short] at certain [offset]. */ - fun writeShort(offset: Int, value: Short) + public fun writeShort(offset: Int, value: Short) /** * Writes [Int] at certain [offset]. */ - fun writeInt(offset: Int, value: Int) + public fun writeInt(offset: Int, value: Int) /** * Writes [Long] at certain [offset]. */ - fun writeLong(offset: Int, value: Long) + public fun writeLong(offset: Int, value: Long) /** * Disposes this writer if needed. */ - fun release() + public fun release() } /** * Uses the memory for write then releases the writer. */ -inline fun Memory.write(block: MemoryWriter.() -> Unit) { +public inline fun Memory.write(block: MemoryWriter.() -> Unit) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } writer().apply(block).release() } @@ -147,10 +147,10 @@ inline fun Memory.write(block: MemoryWriter.() -> Unit) { /** * Allocates the most effective platform-specific memory. */ -expect fun Memory.Companion.allocate(length: Int): Memory +public expect fun Memory.Companion.allocate(length: Int): Memory /** * Wraps a [Memory] around existing [ByteArray]. This operation is unsafe since the array is not copied * and could be mutated independently from the resulting [Memory]. */ -expect fun Memory.Companion.wrap(array: ByteArray): Memory +public expect fun Memory.Companion.wrap(array: ByteArray): Memory diff --git a/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt b/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt index 1381afbec..5bb163bc1 100644 --- a/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt +++ b/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt @@ -5,45 +5,45 @@ package scientifik.memory * * @param T the type of object this spec manages. */ -interface MemorySpec { +public interface MemorySpec { /** * Size of [T] in bytes after serialization. */ - val objectSize: Int + public val objectSize: Int /** * Reads the object starting from [offset]. */ - fun MemoryReader.read(offset: Int): T + public fun MemoryReader.read(offset: Int): T // TODO consider thread safety /** * Writes the object [value] starting from [offset]. */ - fun MemoryWriter.write(offset: Int, value: T) + public fun MemoryWriter.write(offset: Int, value: T) } /** * Reads the object with [spec] starting from [offset]. */ -fun MemoryReader.read(spec: MemorySpec, offset: Int): T = with(spec) { read(offset) } +public fun MemoryReader.read(spec: MemorySpec, offset: Int): T = with(spec) { read(offset) } /** * Writes the object [value] with [spec] starting from [offset]. */ -fun MemoryWriter.write(spec: MemorySpec, offset: Int, value: T): Unit = with(spec) { write(offset, value) } +public fun MemoryWriter.write(spec: MemorySpec, offset: Int, value: T): Unit = with(spec) { write(offset, value) } /** * Reads array of [size] objects mapped by [spec] at certain [offset]. */ -inline fun MemoryReader.readArray(spec: MemorySpec, offset: Int, size: Int): Array = +public inline fun MemoryReader.readArray(spec: MemorySpec, offset: Int, size: Int): Array = Array(size) { i -> with(spec) { read(offset + i * objectSize) } } /** * Writes [array] of objects mapped by [spec] at certain [offset]. */ -fun MemoryWriter.writeArray(spec: MemorySpec, offset: Int, array: Array): Unit = +public fun MemoryWriter.writeArray(spec: MemorySpec, offset: Int, array: Array): Unit = with(spec) { array.indices.forEach { i -> write(offset + i * objectSize, array[i]) } } // TODO It is possible to add elastic MemorySpec with unknown object size diff --git a/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt b/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt index 974750502..452ef1fea 100644 --- a/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt +++ b/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt @@ -83,7 +83,7 @@ private class DataViewMemory(val view: DataView) : Memory { /** * Allocates memory based on a [DataView]. */ -actual fun Memory.Companion.allocate(length: Int): Memory { +public actual fun Memory.Companion.allocate(length: Int): Memory { val buffer = ArrayBuffer(length) return DataViewMemory(DataView(buffer, 0, length)) } @@ -92,7 +92,7 @@ actual fun Memory.Companion.allocate(length: Int): Memory { * Wraps a [Memory] around existing [ByteArray]. This operation is unsafe since the array is not copied * and could be mutated independently from the resulting [Memory]. */ -actual fun Memory.Companion.wrap(array: ByteArray): Memory { +public actual fun Memory.Companion.wrap(array: ByteArray): Memory { @Suppress("CAST_NEVER_SUCCEEDS") val int8Array = array as Int8Array return DataViewMemory(DataView(int8Array.buffer, int8Array.byteOffset, int8Array.length)) } diff --git a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt index f4967bf5c..e98340a44 100644 --- a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt @@ -94,14 +94,14 @@ internal class ByteBufferMemory( /** * Allocates memory based on a [ByteBuffer]. */ -actual fun Memory.Companion.allocate(length: Int): Memory = +public actual fun Memory.Companion.allocate(length: Int): Memory = ByteBufferMemory(checkNotNull(ByteBuffer.allocate(length))) /** * Wraps a [Memory] around existing [ByteArray]. This operation is unsafe since the array is not copied * and could be mutated independently from the resulting [Memory]. */ -actual fun Memory.Companion.wrap(array: ByteArray): Memory = ByteBufferMemory(checkNotNull(ByteBuffer.wrap(array))) +public actual fun Memory.Companion.wrap(array: ByteArray): Memory = ByteBufferMemory(checkNotNull(ByteBuffer.wrap(array))) /** * Wraps this [ByteBuffer] to [Memory] object. @@ -111,14 +111,14 @@ actual fun Memory.Companion.wrap(array: ByteArray): Memory = ByteBufferMemory(ch * @param size the size of memory to map. * @return the [Memory] object. */ -fun ByteBuffer.asMemory(startOffset: Int = 0, size: Int = limit()): Memory = +public fun ByteBuffer.asMemory(startOffset: Int = 0, size: Int = limit()): Memory = ByteBufferMemory(this, startOffset, size) /** * Uses direct memory-mapped buffer from file to read something and close it afterwards. */ @Throws(IOException::class) -inline fun Path.readAsMemory(position: Long = 0, size: Long = Files.size(this), block: Memory.() -> R): R { +public inline fun Path.readAsMemory(position: Long = 0, size: Long = Files.size(this), block: Memory.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return FileChannel diff --git a/kmath-prob/build.gradle.kts b/kmath-prob/build.gradle.kts index a69d61b73..4c9663e5f 100644 --- a/kmath-prob/build.gradle.kts +++ b/kmath-prob/build.gradle.kts @@ -1,6 +1,4 @@ -plugins { - id("scientifik.mpp") -} +plugins { id("ru.mipt.npm.mpp") } kotlin.sourceSets { commonMain { @@ -8,10 +6,11 @@ kotlin.sourceSets { api(project(":kmath-coroutines")) } } - jvmMain{ - dependencies{ + + jvmMain { + dependencies { api("org.apache.commons:commons-rng-sampling:1.3") api("org.apache.commons:commons-rng-simple:1.3") } } -} \ No newline at end of file +} diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt index 412454994..ddb50ef42 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt +++ b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt @@ -11,7 +11,7 @@ import kotlin.math.exp import kotlin.math.pow import kotlin.math.sqrt -abstract class ContinuousSamplerDistribution : Distribution { +public abstract class ContinuousSamplerDistribution : Distribution { private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingRealChain() { private val sampler = buildCMSampler(generator) @@ -26,7 +26,7 @@ abstract class ContinuousSamplerDistribution : Distribution { override fun sample(generator: RandomGenerator): BlockingRealChain = ContinuousSamplerChain(generator) } -abstract class DiscreteSamplerDistribution : Distribution { +public abstract class DiscreteSamplerDistribution : Distribution { private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingIntChain() { private val sampler = buildSampler(generator) @@ -41,7 +41,7 @@ abstract class DiscreteSamplerDistribution : Distribution { override fun sample(generator: RandomGenerator): BlockingIntChain = ContinuousSamplerChain(generator) } -enum class NormalSamplerMethod { +public enum class NormalSamplerMethod { BoxMuller, Marsaglia, Ziggurat @@ -54,7 +54,7 @@ private fun normalSampler(method: NormalSamplerMethod, provider: UniformRandomPr NormalSamplerMethod.Ziggurat -> ZigguratNormalizedGaussianSampler(provider) } -fun Distribution.Companion.normal( +public fun Distribution.Companion.normal( method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat ): Distribution = object : ContinuousSamplerDistribution() { override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { @@ -67,7 +67,7 @@ fun Distribution.Companion.normal( } } -fun Distribution.Companion.normal( +public fun Distribution.Companion.normal( mean: Double, sigma: Double, method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat @@ -86,7 +86,7 @@ fun Distribution.Companion.normal( } } -fun Distribution.Companion.poisson( +public fun Distribution.Companion.poisson( lambda: Double ): DiscreteSamplerDistribution = object : DiscreteSamplerDistribution() { diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 52ee7c497..6fe8ad878 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -1,10 +1,8 @@ -plugins { - id("scientifik.jvm") -} +plugins { id("ru.mipt.npm.jvm") } description = "Binding for https://github.com/JetBrains-Research/viktor" dependencies { api(project(":kmath-core")) api("org.jetbrains.bio:viktor:1.0.1") -} \ No newline at end of file +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 487e1d87f..102cde93f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,14 +1,12 @@ pluginManagement { - - val toolsVersion = "0.5.0" + val toolsVersion = "0.6.0-dev-3" plugins { - id("kotlinx.benchmark") version "0.2.0-dev-8" - id("scientifik.mpp") version toolsVersion - id("scientifik.jvm") version toolsVersion - id("scientifik.atomic") version toolsVersion - id("scientifik.publish") version toolsVersion - kotlin("plugin.allopen") version "1.3.72" + id("kotlinx.benchmark") version "0.2.0-dev-20" + id("ru.mipt.npm.mpp") version toolsVersion + id("ru.mipt.npm.jvm") version toolsVersion + id("ru.mipt.npm.publish") version toolsVersion + kotlin("plugin.allopen") version "1.4.0" } repositories { @@ -20,17 +18,10 @@ pluginManagement { maven("https://dl.bintray.com/mipt-npm/dev") maven("https://dl.bintray.com/kotlin/kotlinx") } - - resolutionStrategy { - eachPlugin { - when (requested.id.id) { - "scientifik.mpp", "scientifik.jvm", "scientifik.publish" -> useModule("scientifik:gradle-tools:$toolsVersion") - } - } - } } rootProject.name = "kmath" + include( ":kmath-memory", ":kmath-core", From 6b79e79d218fb382b1f5b1fd6a7a8c740480394e Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 9 Sep 2020 09:55:26 +0700 Subject: [PATCH 026/199] Update tools and Kotlin, specify `public` explicitly, minor contracts refactor --- examples/build.gradle.kts | 10 +- .../kotlin/scientifik/kmath/ast/MstAlgebra.kt | 24 ++--- .../kmath/domains/HyperSquareDomain.kt | 27 +++--- .../kmath/domains/UnconstrainedDomain.kt | 16 ++-- .../kmath/domains/UnivariateDomain.kt | 20 ++-- .../FunctionalExpressionAlgebra.kt | 63 ++++++------- .../scientifik/kmath/linear/BufferMatrix.kt | 71 +++++++------- .../scientifik/kmath/linear/FeaturedMatrix.kt | 6 +- .../kmath/linear/LUPDecomposition.kt | 12 +-- .../scientifik/kmath/linear/LinearAlgebra.kt | 5 +- .../scientifik/kmath/misc/cumulative.kt | 7 +- .../scientifik/kmath/operations/Algebra.kt | 2 + .../scientifik/kmath/operations/BigInt.kt | 19 ++-- .../scientifik/kmath/operations/Complex.kt | 16 ++-- .../kmath/operations/NumberAlgebra.kt | 16 ++-- .../kmath/structures/BoxingNDRing.kt | 1 + .../kmath/structures/BufferedNDAlgebra.kt | 4 +- .../scientifik/kmath/structures/Buffers.kt | 29 +++--- .../kmath/structures/ComplexNDField.kt | 17 ++-- .../kmath/structures/FlaggedBuffer.kt | 18 ++-- .../kmath/structures/FloatBuffer.kt | 13 +-- .../scientifik/kmath/structures/IntBuffer.kt | 15 +-- .../scientifik/kmath/structures/LongBuffer.kt | 5 +- .../kmath/structures/MemoryBuffer.kt | 36 +++----- .../scientifik/kmath/structures/NDAlgebra.kt | 11 +-- .../scientifik/kmath/structures/NDElement.kt | 39 ++++---- .../kmath/structures/NDStructure.kt | 92 +++++++++---------- .../scientifik/kmath/structures/RealBuffer.kt | 16 +--- .../kmath/structures/RealBufferField.kt | 32 ++++--- .../kmath/structures/RealNDField.kt | 12 +-- .../kmath/structures/ShortBuffer.kt | 6 +- .../kmath/structures/ShortNDRing.kt | 8 +- .../kmath/structures/Structure1D.kt | 19 ++-- .../kmath/structures/Structure2D.kt | 12 +-- .../kmath/coroutines/coroutinesExtra.kt | 43 ++++----- .../kmath/structures/LazyNDStructure.kt | 39 ++++---- .../scientifik/kmath/dimensions/Wrappers.kt | 67 +++++++------- .../scientifik/kmath/real/realMatrix.kt | 7 +- .../scientifik/kmath/functions/Piecewise.kt | 18 ++-- .../scientifik/kmath/functions/Polynomial.kt | 6 +- .../kmath/interpolation/Interpolator.kt | 8 +- .../kmath/interpolation/LinearInterpolator.kt | 4 +- .../kmath/interpolation/SplineInterpolator.kt | 7 +- .../kmath/interpolation/XYPointSet.kt | 28 +++--- .../interpolation/LinearInterpolatorTest.kt | 4 +- .../scientifik/kmath/viktor/ViktorBuffer.kt | 15 ++- settings.gradle.kts | 5 +- 47 files changed, 422 insertions(+), 528 deletions(-) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 9fd90d08b..9f173a046 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { java kotlin("jvm") - kotlin("plugin.allopen") version "1.4.0" + kotlin("plugin.allopen") version "1.4.20-dev-3898-14" id("kotlinx.benchmark") version "0.2.0-dev-20" } @@ -13,6 +13,7 @@ repositories { maven("http://dl.bintray.com/kyonifer/maven") maven("https://dl.bintray.com/mipt-npm/scientifik") maven("https://dl.bintray.com/mipt-npm/dev") + maven("https://dl.bintray.com/kotlin/kotlin-dev/") mavenCentral() } @@ -55,9 +56,4 @@ kotlin.sourceSets.all { } } -tasks.withType { - kotlinOptions { - jvmTarget = "11" - freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" - } -} +tasks.withType { kotlinOptions.jvmTarget = "11" } diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt index e4480e608..7d13a2b25 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt @@ -37,7 +37,7 @@ public object MstSpace : Space, NumericAlgebra { /** * [Ring] over [MST] nodes. */ -object MstRing : Ring, NumericAlgebra { +public object MstRing : Ring, NumericAlgebra { override val zero: MST = number(0.0) override val one: MST = number(1.0) @@ -58,18 +58,18 @@ object MstRing : Ring, NumericAlgebra { /** * [Field] over [MST] nodes. */ -object MstField : Field { - override val zero: MST = number(0.0) - override val one: MST = number(1.0) +public object MstField : Field { + public override val zero: MST = number(0.0) + public override val one: MST = number(1.0) - override fun symbol(value: String): MST = MstRing.symbol(value) - override fun number(value: Number): MST = MstRing.number(value) - override fun add(a: MST, b: MST): MST = MstRing.add(a, b) - override fun multiply(a: MST, k: Number): MST = MstRing.multiply(a, k) - override fun multiply(a: MST, b: MST): MST = MstRing.multiply(a, b) - override fun divide(a: MST, b: MST): MST = binaryOperation(FieldOperations.DIV_OPERATION, a, b) + public override fun symbol(value: String): MST = MstRing.symbol(value) + public override fun number(value: Number): MST = MstRing.number(value) + public override fun add(a: MST, b: MST): MST = MstRing.add(a, b) + public override fun multiply(a: MST, k: Number): MST = MstRing.multiply(a, k) + public override fun multiply(a: MST, b: MST): MST = MstRing.multiply(a, b) + public override fun divide(a: MST, b: MST): MST = binaryOperation(FieldOperations.DIV_OPERATION, a, b) - override fun binaryOperation(operation: String, left: MST, right: MST): MST = + public override fun binaryOperation(operation: String, left: MST, right: MST): MST = MstRing.binaryOperation(operation, left, right) override fun unaryOperation(operation: String, arg: MST): MST = MstRing.unaryOperation(operation, arg) @@ -78,7 +78,7 @@ object MstField : Field { /** * [ExtendedField] over [MST] nodes. */ -object MstExtendedField : ExtendedField { +public object MstExtendedField : ExtendedField { override val zero: MST = number(0.0) override val one: MST = number(1.0) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt index e118282bf..61d443ff3 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt @@ -26,22 +26,21 @@ import scientifik.kmath.structures.indices * @author Alexander Nozik */ public class HyperSquareDomain(private val lower: RealBuffer, private val upper: RealBuffer) : RealDomain { + public override val dimension: Int get() = lower.size - override operator fun contains(point: Point): Boolean = point.indices.all { i -> + public override operator fun contains(point: Point): Boolean = point.indices.all { i -> point[i] in lower[i]..upper[i] } - override val dimension: Int get() = lower.size + public override fun getLowerBound(num: Int, point: Point): Double? = lower[num] - override fun getLowerBound(num: Int, point: Point): Double? = lower[num] + public override fun getLowerBound(num: Int): Double? = lower[num] - override fun getLowerBound(num: Int): Double? = lower[num] + public override fun getUpperBound(num: Int, point: Point): Double? = upper[num] - override fun getUpperBound(num: Int, point: Point): Double? = upper[num] + public override fun getUpperBound(num: Int): Double? = upper[num] - override fun getUpperBound(num: Int): Double? = upper[num] - - override fun nearestInDomain(point: Point): Point { + public override fun nearestInDomain(point: Point): Point { val res = DoubleArray(point.size) { i -> when { point[i] < lower[i] -> lower[i] @@ -53,16 +52,14 @@ public class HyperSquareDomain(private val lower: RealBuffer, private val upper: return RealBuffer(*res) } - override fun volume(): Double { + public override fun volume(): Double { var res = 1.0 + for (i in 0 until dimension) { - if (lower[i].isInfinite() || upper[i].isInfinite()) { - return Double.POSITIVE_INFINITY - } - if (upper[i] > lower[i]) { - res *= upper[i] - lower[i] - } + if (lower[i].isInfinite() || upper[i].isInfinite()) return Double.POSITIVE_INFINITY + if (upper[i] > lower[i]) res *= upper[i] - lower[i] } + return res } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt index 5c9170663..c637795df 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt @@ -17,18 +17,18 @@ package scientifik.kmath.domains import scientifik.kmath.linear.Point -public class UnconstrainedDomain(override val dimension: Int) : RealDomain { - override operator fun contains(point: Point): Boolean = true +public class UnconstrainedDomain(public override val dimension: Int) : RealDomain { + public override operator fun contains(point: Point): Boolean = true - override fun getLowerBound(num: Int, point: Point): Double? = Double.NEGATIVE_INFINITY + public override fun getLowerBound(num: Int, point: Point): Double? = Double.NEGATIVE_INFINITY - override fun getLowerBound(num: Int): Double? = Double.NEGATIVE_INFINITY + public override fun getLowerBound(num: Int): Double? = Double.NEGATIVE_INFINITY - override fun getUpperBound(num: Int, point: Point): Double? = Double.POSITIVE_INFINITY + public override fun getUpperBound(num: Int, point: Point): Double? = Double.POSITIVE_INFINITY - override fun getUpperBound(num: Int): Double? = Double.POSITIVE_INFINITY + public override fun getUpperBound(num: Int): Double? = Double.POSITIVE_INFINITY - override fun nearestInDomain(point: Point): Point = point + public override fun nearestInDomain(point: Point): Point = point - override fun volume(): Double = Double.POSITIVE_INFINITY + public override fun volume(): Double = Double.POSITIVE_INFINITY } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt index 5b47476d8..066a8ae25 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt @@ -4,16 +4,20 @@ import scientifik.kmath.linear.Point import scientifik.kmath.structures.asBuffer public inline class UnivariateDomain(public val range: ClosedFloatingPointRange) : RealDomain { + public override val dimension: Int + get() = 1 + public operator fun contains(d: Double): Boolean = range.contains(d) - override operator fun contains(point: Point): Boolean { + public override operator fun contains(point: Point): Boolean { require(point.size == 0) return contains(point[0]) } - override fun nearestInDomain(point: Point): Point { + public override fun nearestInDomain(point: Point): Point { require(point.size == 1) val value = point[0] + return when { value in range -> point value >= range.endInclusive -> doubleArrayOf(range.endInclusive).asBuffer() @@ -21,27 +25,25 @@ public inline class UnivariateDomain(public val range: ClosedFloatingPointRange< } } - override fun getLowerBound(num: Int, point: Point): Double? { + public override fun getLowerBound(num: Int, point: Point): Double? { require(num == 0) return range.start } - override fun getUpperBound(num: Int, point: Point): Double? { + public override fun getUpperBound(num: Int, point: Point): Double? { require(num == 0) return range.endInclusive } - override fun getLowerBound(num: Int): Double? { + public override fun getLowerBound(num: Int): Double? { require(num == 0) return range.start } - override fun getUpperBound(num: Int): Double? { + public override fun getUpperBound(num: Int): Double? { require(num == 0) return range.endInclusive } - override fun volume(): Double = range.endInclusive - range.start - - override val dimension: Int get() = 1 + public override fun volume(): Double = range.endInclusive - range.start } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt index 58f874671..3804819e6 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -4,7 +4,8 @@ import scientifik.kmath.operations.* internal class FunctionalUnaryOperation(val context: Algebra, val name: String, private val expr: Expression) : Expression { - override operator fun invoke(arguments: Map): T = context.unaryOperation(name, expr.invoke(arguments)) + public override operator fun invoke(arguments: Map): T = + context.unaryOperation(name, expr.invoke(arguments)) } internal class FunctionalBinaryOperation( @@ -13,17 +14,17 @@ internal class FunctionalBinaryOperation( val first: Expression, val second: Expression ) : Expression { - override operator fun invoke(arguments: Map): T = + public override operator fun invoke(arguments: Map): T = context.binaryOperation(name, first.invoke(arguments), second.invoke(arguments)) } internal class FunctionalVariableExpression(val name: String, val default: T? = null) : Expression { - override operator fun invoke(arguments: Map): T = + public override operator fun invoke(arguments: Map): T = arguments[name] ?: default ?: error("Parameter not found: $name") } internal class FunctionalConstantExpression(val value: T) : Expression { - override operator fun invoke(arguments: Map): T = value + public override operator fun invoke(arguments: Map): T = value } internal class FunctionalConstProductExpression( @@ -31,7 +32,7 @@ internal class FunctionalConstProductExpression( private val expr: Expression, val const: Number ) : Expression { - override operator fun invoke(arguments: Map): T = context.multiply(expr.invoke(arguments), const) + public override operator fun invoke(arguments: Map): T = context.multiply(expr.invoke(arguments), const) } /** @@ -44,23 +45,23 @@ public abstract class FunctionalExpressionAlgebra>(public val /** * Builds an Expression of constant expression which does not depend on arguments. */ - override fun const(value: T): Expression = FunctionalConstantExpression(value) + public override fun const(value: T): Expression = FunctionalConstantExpression(value) /** * Builds an Expression to access a variable. */ - override fun variable(name: String, default: T?): Expression = FunctionalVariableExpression(name, default) + public override fun variable(name: String, default: T?): Expression = FunctionalVariableExpression(name, default) /** * Builds an Expression of dynamic call of binary operation [operation] on [left] and [right]. */ - override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = + public override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = FunctionalBinaryOperation(algebra, operation, left, right) /** * Builds an Expression of dynamic call of unary operation with name [operation] on [arg]. */ - override fun unaryOperation(operation: String, arg: Expression): Expression = + public override fun unaryOperation(operation: String, arg: Expression): Expression = FunctionalUnaryOperation(algebra, operation, arg) } @@ -69,18 +70,18 @@ public abstract class FunctionalExpressionAlgebra>(public val */ public open class FunctionalExpressionSpace>(algebra: A) : FunctionalExpressionAlgebra(algebra), Space> { - override val zero: Expression get() = const(algebra.zero) + public override val zero: Expression get() = const(algebra.zero) /** * Builds an Expression of addition of two another expressions. */ - override fun add(a: Expression, b: Expression): Expression = + public override fun add(a: Expression, b: Expression): Expression = binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) /** * Builds an Expression of multiplication of expression by number. */ - override fun multiply(a: Expression, k: Number): Expression = + public override fun multiply(a: Expression, k: Number): Expression = FunctionalConstProductExpression(algebra, a, k) public operator fun Expression.plus(arg: T): Expression = this + const(arg) @@ -88,31 +89,31 @@ public open class FunctionalExpressionSpace>(algebra: A) : public operator fun T.plus(arg: Expression): Expression = arg + this public operator fun T.minus(arg: Expression): Expression = arg - this - override fun unaryOperation(operation: String, arg: Expression): Expression = + public override fun unaryOperation(operation: String, arg: Expression): Expression = super.unaryOperation(operation, arg) - override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = + public override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = super.binaryOperation(operation, left, right) } public open class FunctionalExpressionRing(algebra: A) : FunctionalExpressionSpace(algebra), Ring> where A : Ring, A : NumericAlgebra { - override val one: Expression + public override val one: Expression get() = const(algebra.one) /** * Builds an Expression of multiplication of two expressions. */ - override fun multiply(a: Expression, b: Expression): Expression = + public override fun multiply(a: Expression, b: Expression): Expression = binaryOperation(RingOperations.TIMES_OPERATION, a, b) public operator fun Expression.times(arg: T): Expression = this * const(arg) public operator fun T.times(arg: Expression): Expression = arg * this - override fun unaryOperation(operation: String, arg: Expression): Expression = + public override fun unaryOperation(operation: String, arg: Expression): Expression = super.unaryOperation(operation, arg) - override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = + public override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = super.binaryOperation(operation, left, right) } @@ -122,38 +123,38 @@ public open class FunctionalExpressionField(algebra: A) : /** * Builds an Expression of division an expression by another one. */ - override fun divide(a: Expression, b: Expression): Expression = + public override fun divide(a: Expression, b: Expression): Expression = binaryOperation(FieldOperations.DIV_OPERATION, a, b) public operator fun Expression.div(arg: T): Expression = this / const(arg) public operator fun T.div(arg: Expression): Expression = arg / this - override fun unaryOperation(operation: String, arg: Expression): Expression = + public override fun unaryOperation(operation: String, arg: Expression): Expression = super.unaryOperation(operation, arg) - override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = + public override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = super.binaryOperation(operation, left, right) } public open class FunctionalExpressionExtendedField(algebra: A) : FunctionalExpressionField(algebra), ExtendedField> where A : ExtendedField, A : NumericAlgebra { - override fun sin(arg: Expression): Expression = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) - override fun cos(arg: Expression): Expression = unaryOperation(TrigonometricOperations.COS_OPERATION, arg) - override fun asin(arg: Expression): Expression = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg) - override fun acos(arg: Expression): Expression = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg) - override fun atan(arg: Expression): Expression = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg) + public override fun sin(arg: Expression): Expression = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) + public override fun cos(arg: Expression): Expression = unaryOperation(TrigonometricOperations.COS_OPERATION, arg) + public override fun asin(arg: Expression): Expression = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg) + public override fun acos(arg: Expression): Expression = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg) + public override fun atan(arg: Expression): Expression = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg) - override fun power(arg: Expression, pow: Number): Expression = + public override fun power(arg: Expression, pow: Number): Expression = binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow)) - override fun exp(arg: Expression): Expression = unaryOperation(ExponentialOperations.EXP_OPERATION, arg) - override fun ln(arg: Expression): Expression = unaryOperation(ExponentialOperations.LN_OPERATION, arg) + public override fun exp(arg: Expression): Expression = unaryOperation(ExponentialOperations.EXP_OPERATION, arg) + public override fun ln(arg: Expression): Expression = unaryOperation(ExponentialOperations.LN_OPERATION, arg) - override fun unaryOperation(operation: String, arg: Expression): Expression = + public override fun unaryOperation(operation: String, arg: Expression): Expression = super.unaryOperation(operation, arg) - override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = + public override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = super.binaryOperation(operation, left, right) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt index c28cc5ab7..d053f016c 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt @@ -8,82 +8,82 @@ import scientifik.kmath.structures.* * Basic implementation of Matrix space based on [NDStructure] */ public class BufferMatrixContext>( - override val elementContext: R, + public override val elementContext: R, private val bufferFactory: BufferFactory ) : GenericMatrixContext { - - override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix { + public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix { val buffer = bufferFactory(rows * columns) { offset -> initializer(offset / columns, offset % columns) } return BufferMatrix(rows, columns, buffer) } - override fun point(size: Int, initializer: (Int) -> T): Point = bufferFactory(size, initializer) + public override fun point(size: Int, initializer: (Int) -> T): Point = bufferFactory(size, initializer) public companion object } @Suppress("OVERRIDE_BY_INLINE") public object RealMatrixContext : GenericMatrixContext { + public override val elementContext: RealField + get() = RealField - override val elementContext: RealField get() = RealField - - override inline fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): Matrix { + public override inline fun produce( + rows: Int, + columns: Int, + initializer: (i: Int, j: Int) -> Double + ): Matrix { val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) } return BufferMatrix(rows, columns, buffer) } - override inline fun point(size: Int, initializer: (Int) -> Double): Point = RealBuffer(size, initializer) + public override inline fun point(size: Int, initializer: (Int) -> Double): Point = + RealBuffer(size, initializer) } public class BufferMatrix( - override val rowNum: Int, - override val colNum: Int, + public override val rowNum: Int, + public override val colNum: Int, public val buffer: Buffer, - override val features: Set = emptySet() + public override val features: Set = emptySet() ) : FeaturedMatrix { + override val shape: IntArray + get() = intArrayOf(rowNum, colNum) init { - if (buffer.size != rowNum * colNum) { - error("Dimension mismatch for matrix structure") - } + require(buffer.size == rowNum * colNum) { "Dimension mismatch for matrix structure" } } - override val shape: IntArray get() = intArrayOf(rowNum, colNum) - - override fun suggestFeature(vararg features: MatrixFeature): BufferMatrix = + public override fun suggestFeature(vararg features: MatrixFeature): BufferMatrix = BufferMatrix(rowNum, colNum, buffer, this.features + features) - override operator fun get(index: IntArray): T = get(index[0], index[1]) + public override operator fun get(index: IntArray): T = get(index[0], index[1]) + public override operator fun get(i: Int, j: Int): T = buffer[i * colNum + j] - override operator fun get(i: Int, j: Int): T = buffer[i * colNum + j] - - override fun elements(): Sequence> = sequence { + public 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)) } - override fun equals(other: Any?): Boolean { + public override fun equals(other: Any?): Boolean { if (this === other) return true + return when (other) { is NDStructure<*> -> return NDStructure.equals(this, other) else -> false } } - override fun hashCode(): Int { + public override fun hashCode(): Int { var result = buffer.hashCode() result = 31 * result + features.hashCode() return result } - override fun toString(): String { - return if (rowNum <= 5 && colNum <= 5) { + public override fun toString(): String { + return if (rowNum <= 5 && colNum <= 5) "Matrix(rowsNum = $rowNum, colNum = $colNum, features=$features)\n" + rows.asSequence().joinToString(prefix = "(", postfix = ")", separator = "\n ") { buffer -> buffer.asSequence().joinToString(separator = "\t") { it.toString() } } - } else { - "Matrix(rowsNum = $rowNum, colNum = $colNum, features=$features)" - } + else "Matrix(rowsNum = $rowNum, colNum = $colNum, features=$features)" } } @@ -92,26 +92,21 @@ public class BufferMatrix( */ public infix fun BufferMatrix.dot(other: BufferMatrix): BufferMatrix { require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } - val array = DoubleArray(this.rowNum * other.colNum) //convert to array to insure there is not memory indirection - fun Buffer.unsafeArray(): DoubleArray = if (this is RealBuffer) { + fun Buffer.unsafeArray() = if (this is RealBuffer) array - } else { + else DoubleArray(size) { get(it) } - } val a = this.buffer.unsafeArray() val b = other.buffer.unsafeArray() - for (i in (0 until rowNum)) { - for (j in (0 until other.colNum)) { - for (k in (0 until colNum)) { + for (i in (0 until rowNum)) + for (j in (0 until other.colNum)) + for (k in (0 until colNum)) array[i * other.colNum + j] += a[i * colNum + k] * b[k * other.colNum + j] - } - } - } val buffer = RealBuffer(array) return BufferMatrix(rowNum, other.colNum, buffer) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt index 3e5116435..2cd507078 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt @@ -26,10 +26,8 @@ public interface FeaturedMatrix : Matrix { public companion object } -public inline fun Structure2D.Companion.real(rows: Int, columns: Int, initializer: (Int, Int) -> Double): Matrix { - contract { callsInPlace(initializer) } - return MatrixContext.real.produce(rows, columns, initializer) -} +public inline fun Structure2D.Companion.real(rows: Int, columns: Int, initializer: (Int, Int) -> Double): Matrix = + MatrixContext.real.produce(rows, columns, initializer) /** * Build a square matrix from given elements. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt index 2bad1aa46..ab23afff0 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt @@ -76,7 +76,6 @@ public inline fun , F : Field> GenericMatrixContext.l matrix: Matrix, checkSingular: (T) -> Boolean ): LUPDecomposition { - contract { callsInPlace(checkSingular) } require(matrix.rowNum == matrix.colNum) { "LU decomposition supports only square matrices" } val m = matrix.colNum val pivot = IntArray(matrix.rowNum) @@ -153,10 +152,7 @@ public inline fun , F : Field> GenericMatrixContext.l public inline fun , F : Field> GenericMatrixContext.lup( matrix: Matrix, checkSingular: (T) -> Boolean -): LUPDecomposition { - contract { callsInPlace(checkSingular) } - return lup(T::class, matrix, checkSingular) -} +): LUPDecomposition = lup(T::class, matrix, checkSingular) public fun GenericMatrixContext.lup(matrix: Matrix): LUPDecomposition = lup(Double::class, matrix) { it < 1e-11 } @@ -216,7 +212,6 @@ public inline fun , F : Field> GenericMatrixContext b: Matrix, checkSingular: (T) -> Boolean ): Matrix { - contract { callsInPlace(checkSingular) } // Use existing decomposition if it is provided by matrix val decomposition = a.getFeature() ?: lup(T::class, a, checkSingular) return decomposition.solve(T::class, b) @@ -227,10 +222,7 @@ public fun RealMatrixContext.solve(a: Matrix, b: Matrix): Matrix public inline fun , F : Field> GenericMatrixContext.inverse( matrix: Matrix, checkSingular: (T) -> Boolean -): Matrix { - contract { callsInPlace(checkSingular) } - return solve(matrix, one(matrix.rowNum, matrix.colNum), checkSingular) -} +): Matrix = solve(matrix, one(matrix.rowNum, matrix.colNum), checkSingular) public fun RealMatrixContext.inverse(matrix: Matrix): Matrix = solve(matrix, one(matrix.rowNum, matrix.colNum)) { it < 1e-11 } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt index 4daa03e5d..607d63bb1 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt @@ -19,10 +19,9 @@ public interface LinearSolver { * Convert matrix to vector if it is possible */ public fun Matrix.asPoint(): Point = - if (this.colNum == 1) { + if (this.colNum == 1) VirtualBuffer(rowNum) { get(it, 0) } - } else { + else error("Can't convert matrix with more than one column to vector") - } public fun Point.asMatrix(): VirtualMatrix = VirtualMatrix(size, 1) { i, _ -> get(i) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt index f7dfcd781..1712fef58 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt @@ -12,10 +12,8 @@ import kotlin.jvm.JvmName * @param R the type of resulting iterable. * @param initial lazy evaluated. */ -public inline fun Iterator.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterator { - contract { callsInPlace(operation) } - - return object : Iterator { +public inline fun Iterator.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterator = + object : Iterator { var state: R = initial override fun hasNext(): Boolean = this@cumulative.hasNext() @@ -25,7 +23,6 @@ public inline fun Iterator.cumulative(initial: R, crossinline operatio return state } } -} public inline fun Iterable.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterable = Iterable { this@cumulative.iterator().cumulative(initial, operation) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt index 40f974096..1ea105f67 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt @@ -1,5 +1,7 @@ package scientifik.kmath.operations +import kotlin.contracts.contract + /** * Stub for DSL the [Algebra] is. */ diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt index 56ec84f0b..cbee88e38 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt @@ -40,18 +40,17 @@ public class BigInt internal constructor( private val sign: Byte, private val magnitude: Magnitude ) : Comparable { - - override fun compareTo(other: BigInt): Int = when { + public override fun compareTo(other: BigInt): Int = when { (this.sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0 this.sign < other.sign -> -1 this.sign > other.sign -> 1 else -> this.sign * compareMagnitudes(this.magnitude, other.magnitude) } - override fun equals(other: Any?): Boolean = + public override fun equals(other: Any?): Boolean = if (other is BigInt) compareTo(other) == 0 else error("Can't compare KBigInteger to a different type") - override fun hashCode(): Int = magnitude.hashCode() + sign + public override fun hashCode(): Int = magnitude.hashCode() + sign public fun abs(): BigInt = if (sign == 0.toByte()) this else BigInt(1, magnitude) @@ -456,15 +455,11 @@ public fun String.parseBigInteger(): BigInt? { return res * sign } -public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer { - contract { callsInPlace(initializer) } - return boxing(size, initializer) -} +public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer = + boxing(size, initializer) -public inline fun MutableBuffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): MutableBuffer { - contract { callsInPlace(initializer) } - return boxing(size, initializer) -} +public inline fun MutableBuffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): MutableBuffer = + boxing(size, initializer) public fun NDAlgebra.Companion.bigInt(vararg shape: Int): BoxingNDRing = BoxingNDRing(shape, BigIntField, Buffer.Companion::bigInt) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt index facc2ad26..20decf0e0 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt @@ -6,7 +6,6 @@ import scientifik.kmath.structures.MutableBuffer import scientifik.memory.MemoryReader import scientifik.memory.MemorySpec import scientifik.memory.MemoryWriter -import kotlin.contracts.contract import kotlin.math.* /** @@ -165,7 +164,8 @@ public object ComplexField : ExtendedField, Norm { * @property re The real part. * @property im The imaginary part. */ -public data class Complex(val re: Double, val im: Double) : FieldElement, Comparable { +public data class Complex(val re: Double, val im: Double) : FieldElement, + Comparable { public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble()) override val context: ComplexField get() = ComplexField @@ -197,12 +197,8 @@ public data class Complex(val re: Double, val im: Double) : FieldElement Complex): Buffer { - contract { callsInPlace(init) } - return MemoryBuffer.create(Complex, size, init) -} +public inline fun Buffer.Companion.complex(size: Int, init: (Int) -> Complex): Buffer = + MemoryBuffer.create(Complex, size, init) -public inline fun MutableBuffer.Companion.complex(size: Int, crossinline init: (Int) -> Complex): Buffer { - contract { callsInPlace(init) } - return MemoryBuffer.create(Complex, size, init) -} +public inline fun MutableBuffer.Companion.complex(size: Int, init: (Int) -> Complex): Buffer = + MemoryBuffer.create(Complex, size, init) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt index 54460a0da..052e32bb9 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt @@ -62,7 +62,7 @@ public interface ExtendedField : ExtendedFieldOperations, Field { * * TODO inline does not work due to compiler bug. Waiting for fix for KT-27586 */ -inline class Real(val value: Double) : FieldElement { +public inline class Real(public val value: Double) : FieldElement { override val context: RealField get() = RealField @@ -70,14 +70,14 @@ inline class Real(val value: Double) : FieldElement { override fun Double.wrap(): Real = Real(value) - companion object + public companion object } /** * A field for [Double] without boxing. Does not produce appropriate field element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object RealField : ExtendedField, Norm { +public object RealField : ExtendedField, Norm { override val zero: Double get() = 0.0 @@ -127,7 +127,7 @@ object RealField : ExtendedField, Norm { * A field for [Float] without boxing. Does not produce appropriate field element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object FloatField : ExtendedField, Norm { +public object FloatField : ExtendedField, Norm { override val zero: Float get() = 0.0f @@ -177,7 +177,7 @@ object FloatField : ExtendedField, Norm { * A field for [Int] without boxing. Does not produce corresponding ring element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object IntRing : Ring, Norm { +public object IntRing : Ring, Norm { override val zero: Int get() = 0 @@ -201,7 +201,7 @@ object IntRing : Ring, Norm { * A field for [Short] without boxing. Does not produce appropriate ring element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object ShortRing : Ring, Norm { +public object ShortRing : Ring, Norm { override val zero: Short get() = 0 @@ -225,7 +225,7 @@ object ShortRing : Ring, Norm { * A field for [Byte] without boxing. Does not produce appropriate ring element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object ByteRing : Ring, Norm { +public object ByteRing : Ring, Norm { override val zero: Byte get() = 0 @@ -249,7 +249,7 @@ object ByteRing : Ring, Norm { * A field for [Double] without boxing. Does not produce appropriate ring element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object LongRing : Ring, Norm { +public object LongRing : Ring, Norm { override val zero: Long get() = 0 diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt index 9e44e38aa..de83768a0 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt @@ -59,6 +59,7 @@ public class BoxingNDRing>( transform: R.(T, T) -> T ): BufferedNDRingElement { check(a, b) + return BufferedNDRingElement( this, buildBuffer(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) }) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt index ac8ca0db4..4b1a67805 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt @@ -5,7 +5,7 @@ import scientifik.kmath.operations.* public interface BufferedNDAlgebra : NDAlgebra> { public val strides: Strides - override fun check(vararg elements: NDBuffer): Unit = + public override fun check(vararg elements: NDBuffer): Unit = require(elements.all { it.strides == strides }) { ("Strides mismatch") } /** @@ -29,7 +29,7 @@ public interface BufferedNDAlgebra : NDAlgebra> { public interface BufferedNDSpace> : NDSpace>, BufferedNDAlgebra { - override fun NDBuffer.toElement(): SpaceElement, *, out BufferedNDSpace> + public override fun NDBuffer.toElement(): SpaceElement, *, out BufferedNDSpace> } public interface BufferedNDRing> : NDRing>, BufferedNDSpace { diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt index 48d15d50a..d44100037 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt @@ -2,8 +2,6 @@ package scientifik.kmath.structures import scientifik.kmath.operations.Complex import scientifik.kmath.operations.complex -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract import kotlin.reflect.KClass /** @@ -56,7 +54,8 @@ public interface Buffer { /** * Create a boxing buffer of given type */ - public inline fun boxing(size: Int, initializer: (Int) -> T): Buffer = ListBuffer(List(size, initializer)) + public inline fun boxing(size: Int, initializer: (Int) -> T): Buffer = + ListBuffer(List(size, initializer)) @Suppress("UNCHECKED_CAST") public inline fun auto(type: KClass, size: Int, crossinline initializer: (Int) -> T): Buffer { @@ -115,11 +114,11 @@ public interface MutableBuffer : Buffer { /** * Create a boxing mutable buffer of given type */ - inline fun boxing(size: Int, initializer: (Int) -> T): MutableBuffer = + public inline fun boxing(size: Int, initializer: (Int) -> T): MutableBuffer = MutableListBuffer(MutableList(size, initializer)) @Suppress("UNCHECKED_CAST") - inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): MutableBuffer = + public inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): MutableBuffer = when (type) { Double::class -> RealBuffer(DoubleArray(size) { initializer(it) as Double }) as MutableBuffer Short::class -> ShortBuffer(ShortArray(size) { initializer(it) as Short }) as MutableBuffer @@ -132,12 +131,11 @@ public interface MutableBuffer : Buffer { * Create most appropriate mutable buffer for given type avoiding boxing wherever possible */ @Suppress("UNCHECKED_CAST") - inline fun auto(size: Int, initializer: (Int) -> T): MutableBuffer = + public inline fun auto(size: Int, initializer: (Int) -> T): MutableBuffer = auto(T::class, size, initializer) - val real: MutableBufferFactory = { size: Int, initializer: (Int) -> Double -> - RealBuffer(DoubleArray(size) { initializer(it) }) - } + public val real: MutableBufferFactory = + { size, initializer -> RealBuffer(DoubleArray(size) { initializer(it) }) } } } @@ -147,7 +145,7 @@ public interface MutableBuffer : Buffer { * @param T the type of elements contained in the buffer. * @property list The underlying list. */ -inline class ListBuffer(val list: List) : Buffer { +public inline class ListBuffer(public val list: List) : Buffer { override val size: Int get() = list.size @@ -158,7 +156,7 @@ inline class ListBuffer(val list: List) : Buffer { /** * Returns an [ListBuffer] that wraps the original list. */ -fun List.asBuffer(): ListBuffer = ListBuffer(this) +public fun List.asBuffer(): ListBuffer = ListBuffer(this) /** * Creates a new [ListBuffer] with the specified [size], where each element is calculated by calling the specified @@ -167,10 +165,7 @@ fun List.asBuffer(): ListBuffer = ListBuffer(this) * The function [init] is called for each array element sequentially starting from the first one. * It should return the value for an array element given its index. */ -inline fun ListBuffer(size: Int, init: (Int) -> T): ListBuffer { - contract { callsInPlace(init) } - return List(size, init).asBuffer() -} +public inline fun ListBuffer(size: Int, init: (Int) -> T): ListBuffer = List(size, init).asBuffer() /** * [MutableBuffer] implementation over [MutableList]. @@ -178,7 +173,7 @@ inline fun ListBuffer(size: Int, init: (Int) -> T): ListBuffer { * @param T the type of elements contained in the buffer. * @property list The underlying list. */ -inline class MutableListBuffer(val list: MutableList) : MutableBuffer { +public inline class MutableListBuffer(public val list: MutableList) : MutableBuffer { override val size: Int get() = list.size @@ -198,7 +193,7 @@ inline class MutableListBuffer(val list: MutableList) : MutableBuffer { * @param T the type of elements contained in the buffer. * @property array The underlying array. */ -class ArrayBuffer(private val array: Array) : MutableBuffer { +public class ArrayBuffer(private val array: Array) : MutableBuffer { // Can't inline because array is invariant override val size: Int get() = array.size diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt index 56fe2a5ac..87dd11f59 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt @@ -4,7 +4,6 @@ import scientifik.kmath.operations.Complex import scientifik.kmath.operations.ComplexField import scientifik.kmath.operations.FieldElement import scientifik.kmath.operations.complex -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -98,7 +97,7 @@ public class ComplexNDField(override val shape: IntArray) : /** * Fast element production using function inlining */ -inline fun BufferedNDField.produceInline(crossinline initializer: ComplexField.(Int) -> Complex): ComplexNDElement { +public inline fun BufferedNDField.produceInline(initializer: ComplexField.(Int) -> Complex): ComplexNDElement { val buffer = Buffer.complex(strides.linearSize) { offset -> ComplexField.initializer(offset) } return BufferedNDFieldElement(this, buffer) } @@ -106,14 +105,13 @@ inline fun BufferedNDField.produceInline(crossinline init /** * Map one [ComplexNDElement] using function with indices. */ -inline fun ComplexNDElement.mapIndexed(crossinline transform: ComplexField.(index: IntArray, Complex) -> Complex): ComplexNDElement = +public inline fun ComplexNDElement.mapIndexed(transform: ComplexField.(index: IntArray, Complex) -> Complex): ComplexNDElement = context.produceInline { offset -> transform(strides.index(offset), buffer[offset]) } /** * Map one [ComplexNDElement] using function without indices. */ -inline fun ComplexNDElement.map(crossinline transform: ComplexField.(Complex) -> Complex): ComplexNDElement { - contract { callsInPlace(transform) } +public inline fun ComplexNDElement.map(transform: ComplexField.(Complex) -> Complex): ComplexNDElement { val buffer = Buffer.complex(strides.linearSize) { offset -> ComplexField.transform(buffer[offset]) } return BufferedNDFieldElement(context, buffer) } @@ -121,10 +119,9 @@ inline fun ComplexNDElement.map(crossinline transform: ComplexField.(Complex) -> /** * Element by element application of any operation on elements to the whole array. Just like in numpy */ -operator fun Function1.invoke(ndElement: ComplexNDElement): ComplexNDElement = +public operator fun Function1.invoke(ndElement: ComplexNDElement): ComplexNDElement = ndElement.map { this@invoke(it) } - /* plus and minus */ /** @@ -142,8 +139,10 @@ public operator fun ComplexNDElement.minus(arg: Double): ComplexNDElement = map public fun NDField.Companion.complex(vararg shape: Int): ComplexNDField = ComplexNDField(shape) -public fun NDElement.Companion.complex(vararg shape: Int, initializer: ComplexField.(IntArray) -> Complex): ComplexNDElement = - NDField.complex(*shape).produce(initializer) +public fun NDElement.Companion.complex( + vararg shape: Int, + initializer: ComplexField.(IntArray) -> Complex +): ComplexNDElement = NDField.complex(*shape).produce(initializer) /** * Produce a context for n-dimensional operations inside this real field diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt index 314f9fd63..d1165b895 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt @@ -1,7 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract import kotlin.experimental.and /** @@ -34,23 +32,23 @@ public enum class ValueFlag(public val mask: Byte) { /** * A buffer with flagged values. */ -interface FlaggedBuffer : Buffer { - fun getFlag(index: Int): Byte +public interface FlaggedBuffer : Buffer { + public fun getFlag(index: Int): Byte } /** * The value is valid if all flags are down */ -fun FlaggedBuffer<*>.isValid(index: Int): Boolean = getFlag(index) != 0.toByte() +public fun FlaggedBuffer<*>.isValid(index: Int): Boolean = getFlag(index) != 0.toByte() -fun FlaggedBuffer<*>.hasFlag(index: Int, flag: ValueFlag): Boolean = (getFlag(index) and flag.mask) != 0.toByte() +public fun FlaggedBuffer<*>.hasFlag(index: Int, flag: ValueFlag): Boolean = (getFlag(index) and flag.mask) != 0.toByte() -fun FlaggedBuffer<*>.isMissing(index: Int): Boolean = hasFlag(index, ValueFlag.MISSING) +public fun FlaggedBuffer<*>.isMissing(index: Int): Boolean = hasFlag(index, ValueFlag.MISSING) /** * A real buffer which supports flags for each value like NaN or Missing */ -class FlaggedRealBuffer(val values: DoubleArray, val flags: ByteArray) : FlaggedBuffer, Buffer { +public class FlaggedRealBuffer(public val values: DoubleArray, public val flags: ByteArray) : FlaggedBuffer, Buffer { init { require(values.size == flags.size) { "Values and flags must have the same dimensions" } } @@ -66,9 +64,7 @@ class FlaggedRealBuffer(val values: DoubleArray, val flags: ByteArray) : Flagged }.iterator() } -inline fun FlaggedRealBuffer.forEachValid(block: (Double) -> Unit) { - contract { callsInPlace(block) } - +public inline fun FlaggedRealBuffer.forEachValid(block: (Double) -> Unit) { indices .asSequence() .filter(::isValid) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt index 9e974c644..48947b8d7 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt @@ -8,7 +8,7 @@ import kotlin.contracts.contract * * @property array the underlying array. */ -inline class FloatBuffer(val array: FloatArray) : MutableBuffer { +public inline class FloatBuffer(public val array: FloatArray) : MutableBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Float = array[index] @@ -30,20 +30,17 @@ inline class FloatBuffer(val array: FloatArray) : MutableBuffer { * The function [init] is called for each array element sequentially starting from the first one. * It should return the value for an buffer element given its index. */ -inline fun FloatBuffer(size: Int, init: (Int) -> Float): FloatBuffer { - contract { callsInPlace(init) } - return FloatBuffer(FloatArray(size) { init(it) }) -} +public inline fun FloatBuffer(size: Int, init: (Int) -> Float): FloatBuffer = FloatBuffer(FloatArray(size) { init(it) }) /** * Returns a new [FloatBuffer] of given elements. */ -fun FloatBuffer(vararg floats: Float): FloatBuffer = FloatBuffer(floats) +public fun FloatBuffer(vararg floats: Float): FloatBuffer = FloatBuffer(floats) /** * Returns a [FloatArray] containing all of the elements of this [MutableBuffer]. */ -val MutableBuffer.array: FloatArray +public val MutableBuffer.array: FloatArray get() = (if (this is FloatBuffer) array else FloatArray(size) { get(it) }) /** @@ -52,4 +49,4 @@ val MutableBuffer.array: FloatArray * @receiver the array. * @return the new buffer. */ -fun FloatArray.asBuffer(): FloatBuffer = FloatBuffer(this) +public fun FloatArray.asBuffer(): FloatBuffer = FloatBuffer(this) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt index 88a3bd39d..49cc06755 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt @@ -1,9 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - /** * Specialized [MutableBuffer] implementation over [IntArray]. * @@ -31,20 +27,17 @@ public inline class IntBuffer(public val array: IntArray) : MutableBuffer { * The function [init] is called for each array element sequentially starting from the first one. * It should return the value for an buffer element given its index. */ -inline fun IntBuffer(size: Int, init: (Int) -> Int): IntBuffer { - contract { callsInPlace(init) } - return IntBuffer(IntArray(size) { init(it) }) -} +public inline fun IntBuffer(size: Int, init: (Int) -> Int): IntBuffer = IntBuffer(IntArray(size) { init(it) }) /** * Returns a new [IntBuffer] of given elements. */ -fun IntBuffer(vararg ints: Int): IntBuffer = IntBuffer(ints) +public fun IntBuffer(vararg ints: Int): IntBuffer = IntBuffer(ints) /** * Returns a [IntArray] containing all of the elements of this [MutableBuffer]. */ -val MutableBuffer.array: IntArray +public val MutableBuffer.array: IntArray get() = (if (this is IntBuffer) array else IntArray(size) { get(it) }) /** @@ -53,4 +46,4 @@ val MutableBuffer.array: IntArray * @receiver the array. * @return the new buffer. */ -fun IntArray.asBuffer(): IntBuffer = IntBuffer(this) +public fun IntArray.asBuffer(): IntBuffer = IntBuffer(this) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt index 17f161d19..0fe975e42 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt @@ -31,10 +31,7 @@ public inline class LongBuffer(public val array: LongArray) : MutableBuffer Long): LongBuffer { - contract { callsInPlace(init) } - return LongBuffer(LongArray(size) { init(it) }) -} +public inline fun LongBuffer(size: Int, init: (Int) -> Long): LongBuffer = LongBuffer(LongArray(size) { init(it) }) /** * Returns a new [LongBuffer] of given elements. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/MemoryBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/MemoryBuffer.kt index 83c50b14b..2936932d0 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/MemoryBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/MemoryBuffer.kt @@ -9,7 +9,7 @@ import scientifik.memory.* * @property memory the underlying memory segment. * @property spec the spec of [T] type. */ -open class MemoryBuffer(protected val memory: Memory, protected val spec: MemorySpec) : Buffer { +public open class MemoryBuffer(protected val memory: Memory, protected val spec: MemorySpec) : Buffer { override val size: Int get() = memory.size / spec.objectSize private val reader: MemoryReader = memory.reader() @@ -17,20 +17,17 @@ open class MemoryBuffer(protected val memory: Memory, protected val spe override operator fun get(index: Int): T = reader.read(spec, spec.objectSize * index) override operator fun iterator(): Iterator = (0 until size).asSequence().map { get(it) }.iterator() - companion object { - fun create(spec: MemorySpec, size: Int): MemoryBuffer = + public companion object { + public fun create(spec: MemorySpec, size: Int): MemoryBuffer = MemoryBuffer(Memory.allocate(size * spec.objectSize), spec) - inline fun create( + public inline fun create( spec: MemorySpec, size: Int, - crossinline initializer: (Int) -> T - ): MemoryBuffer = - MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer -> - (0 until size).forEach { - buffer[it] = initializer(it) - } - } + initializer: (Int) -> T + ): MemoryBuffer = MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer -> + (0 until size).forEach { buffer[it] = initializer(it) } + } } } @@ -41,7 +38,7 @@ open class MemoryBuffer(protected val memory: Memory, protected val spe * @property memory the underlying memory segment. * @property spec the spec of [T] type. */ -class MutableMemoryBuffer(memory: Memory, spec: MemorySpec) : MemoryBuffer(memory, spec), +public class MutableMemoryBuffer(memory: Memory, spec: MemorySpec) : MemoryBuffer(memory, spec), MutableBuffer { private val writer: MemoryWriter = memory.writer() @@ -49,19 +46,16 @@ class MutableMemoryBuffer(memory: Memory, spec: MemorySpec) : Memory override operator fun set(index: Int, value: T): Unit = writer.write(spec, spec.objectSize * index, value) override fun copy(): MutableBuffer = MutableMemoryBuffer(memory.copy(), spec) - companion object { - fun create(spec: MemorySpec, size: Int): MutableMemoryBuffer = + public companion object { + public fun create(spec: MemorySpec, size: Int): MutableMemoryBuffer = MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec) - inline fun create( + public inline fun create( spec: MemorySpec, size: Int, crossinline initializer: (Int) -> T - ): MutableMemoryBuffer = - MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer -> - (0 until size).forEach { - buffer[it] = initializer(it) - } - } + ): MutableMemoryBuffer = MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer -> + (0 until size).forEach { buffer[it] = initializer(it) } + } } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt index a28eda9b9..a6212469d 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt @@ -115,19 +115,18 @@ public interface NDField, N : NDStructure> : Field, NDRing public operator fun T.div(arg: N): N = map(arg) { divide(it, this@div) } - companion object { - - private val realNDFieldCache = HashMap() + public companion object { + private val realNDFieldCache: MutableMap = hashMapOf() /** * Create a nd-field for [Double] values or pull it from cache if it was created previously */ - fun real(vararg shape: Int): RealNDField = realNDFieldCache.getOrPut(shape) { RealNDField(shape) } + public fun real(vararg shape: Int): RealNDField = realNDFieldCache.getOrPut(shape) { RealNDField(shape) } /** * Create a nd-field with boxing generic buffer */ - fun > boxing( + public fun > boxing( field: F, vararg shape: Int, bufferFactory: BufferFactory = Buffer.Companion::boxing @@ -137,7 +136,7 @@ public interface NDField, N : NDStructure> : Field, NDRing * Create a most suitable implementation for nd-field using reified class. */ @Suppress("UNCHECKED_CAST") - inline fun > auto(field: F, vararg shape: Int): BufferedNDField = + public inline fun > auto(field: F, vararg shape: Int): BufferedNDField = when { T::class == Double::class -> real(*shape) as BufferedNDField T::class == Complex::class -> complex(*shape) as BufferedNDField diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt index 6cc0a72c0..99a87f374 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt @@ -4,6 +4,7 @@ import scientifik.kmath.operations.Field import scientifik.kmath.operations.RealField import scientifik.kmath.operations.Ring import scientifik.kmath.operations.Space +import kotlin.contracts.contract /** * The root for all [NDStructure] based algebra elements. Does not implement algebra element root because of problems with recursive self-types @@ -11,31 +12,30 @@ import scientifik.kmath.operations.Space * @param C the type of the context for the element * @param N the type of the underlying [NDStructure] */ -interface NDElement> : NDStructure { +public interface NDElement> : NDStructure { + public val context: NDAlgebra - val context: NDAlgebra + public fun unwrap(): N - fun unwrap(): N + public fun N.wrap(): NDElement - fun N.wrap(): NDElement - - companion object { + public companion object { /** * Create a optimized NDArray of doubles */ - fun real(shape: IntArray, initializer: RealField.(IntArray) -> Double = { 0.0 }): RealNDElement = + public fun real(shape: IntArray, initializer: RealField.(IntArray) -> Double = { 0.0 }): RealNDElement = NDField.real(*shape).produce(initializer) - inline fun real1D(dim: Int, crossinline initializer: (Int) -> Double = { _ -> 0.0 }): RealNDElement = + public inline fun real1D(dim: Int, crossinline initializer: (Int) -> Double = { _ -> 0.0 }): RealNDElement = real(intArrayOf(dim)) { initializer(it[0]) } - inline fun real2D( + public inline fun real2D( dim1: Int, dim2: Int, crossinline initializer: (Int, Int) -> Double = { _, _ -> 0.0 } ): RealNDElement = real(intArrayOf(dim1, dim2)) { initializer(it[0], it[1]) } - inline fun real3D( + public inline fun real3D( dim1: Int, dim2: Int, dim3: Int, @@ -46,7 +46,7 @@ interface NDElement> : NDStructure { /** * Simple boxing NDArray */ - fun > boxing( + public fun > boxing( shape: IntArray, field: F, initializer: F.(IntArray) -> T @@ -55,7 +55,7 @@ interface NDElement> : NDStructure { return ndField.produce(initializer) } - inline fun > auto( + public inline fun > auto( shape: IntArray, field: F, noinline initializer: F.(IntArray) -> T @@ -66,17 +66,16 @@ interface NDElement> : NDStructure { } } - -fun > NDElement.mapIndexed(transform: C.(index: IntArray, T) -> T): NDElement = +public fun > NDElement.mapIndexed(transform: C.(index: IntArray, T) -> T): NDElement = context.mapIndexed(unwrap(), transform).wrap() -fun > NDElement.map(transform: C.(T) -> T): NDElement = +public fun > NDElement.map(transform: C.(T) -> T): NDElement = context.map(unwrap(), transform).wrap() /** * Element by element application of any operation on elements to the whole [NDElement] */ -operator fun > Function1.invoke(ndElement: NDElement): NDElement = +public operator fun > Function1.invoke(ndElement: NDElement): NDElement = ndElement.map { value -> this@invoke(value) } /* plus and minus */ @@ -84,13 +83,13 @@ operator fun > Function1.invoke(ndElement: NDElem /** * Summation operation for [NDElement] and single element */ -operator fun , N : NDStructure> NDElement.plus(arg: T): NDElement = +public operator fun , N : NDStructure> NDElement.plus(arg: T): NDElement = map { value -> arg + value } /** * Subtraction operation between [NDElement] and single element */ -operator fun , N : NDStructure> NDElement.minus(arg: T): NDElement = +public operator fun , N : NDStructure> NDElement.minus(arg: T): NDElement = map { value -> arg - value } /* prod and div */ @@ -98,13 +97,13 @@ operator fun , N : NDStructure> NDElement.minus(arg: /** * Product operation for [NDElement] and single element */ -operator fun , N : NDStructure> NDElement.times(arg: T): NDElement = +public operator fun , N : NDStructure> NDElement.times(arg: T): NDElement = map { value -> arg * value } /** * Division operation between [NDElement] and single element */ -operator fun , N : NDStructure> NDElement.div(arg: T): NDElement = +public operator fun , N : NDStructure> NDElement.div(arg: T): NDElement = map { value -> arg / value } // /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt index f4eb93b9e..d3007bb09 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt @@ -1,6 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.jvm.JvmName import kotlin.reflect.KClass @@ -12,17 +11,17 @@ import kotlin.reflect.KClass * * @param T the type of items. */ -interface NDStructure { +public interface NDStructure { /** * The shape of structure, i.e. non-empty sequence of non-negative integers that specify sizes of dimensions of * this structure. */ - val shape: IntArray + public val shape: IntArray /** * The count of dimensions in this structure. It should be equal to size of [shape]. */ - val dimension: Int get() = shape.size + public val dimension: Int get() = shape.size /** * Returns the value at the specified indices. @@ -30,24 +29,24 @@ interface NDStructure { * @param index the indices. * @return the value. */ - operator fun get(index: IntArray): T + public operator fun get(index: IntArray): T /** * Returns the sequence of all the elements associated by their indices. * * @return the lazy sequence of pairs of indices to values. */ - fun elements(): Sequence> + public fun elements(): Sequence> override fun equals(other: Any?): Boolean override fun hashCode(): Int - companion object { + public companion object { /** * Indicates whether some [NDStructure] is equal to another one. */ - fun equals(st1: NDStructure<*>, st2: NDStructure<*>): Boolean { + public fun equals(st1: NDStructure<*>, st2: NDStructure<*>): Boolean { if (st1 === st2) return true // fast comparison of buffers if possible @@ -68,7 +67,7 @@ interface NDStructure { * * Strides should be reused if possible. */ - fun build( + public fun build( strides: Strides, bufferFactory: BufferFactory = Buffer.Companion::boxing, initializer: (IntArray) -> T @@ -78,39 +77,39 @@ interface NDStructure { /** * Inline create NDStructure with non-boxing buffer implementation if it is possible */ - inline fun auto( + public inline fun auto( strides: Strides, crossinline initializer: (IntArray) -> T ): BufferNDStructure = BufferNDStructure(strides, Buffer.auto(strides.linearSize) { i -> initializer(strides.index(i)) }) - inline fun auto( + public inline fun auto( type: KClass, strides: Strides, crossinline initializer: (IntArray) -> T ): BufferNDStructure = BufferNDStructure(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) }) - fun build( + public fun build( shape: IntArray, bufferFactory: BufferFactory = Buffer.Companion::boxing, initializer: (IntArray) -> T ): BufferNDStructure = build(DefaultStrides(shape), bufferFactory, initializer) - inline fun auto( + public inline fun auto( shape: IntArray, crossinline initializer: (IntArray) -> T ): BufferNDStructure = auto(DefaultStrides(shape), initializer) @JvmName("autoVarArg") - inline fun auto( + public inline fun auto( vararg shape: Int, crossinline initializer: (IntArray) -> T ): BufferNDStructure = auto(DefaultStrides(shape), initializer) - inline fun auto( + public inline fun auto( type: KClass, vararg shape: Int, crossinline initializer: (IntArray) -> T @@ -125,68 +124,68 @@ interface NDStructure { * @param index the indices. * @return the value. */ -operator fun NDStructure.get(vararg index: Int): T = get(index) +public operator fun NDStructure.get(vararg index: Int): T = get(index) /** * Represents mutable [NDStructure]. */ -interface MutableNDStructure : NDStructure { +public interface MutableNDStructure : NDStructure { /** * Inserts an item at the specified indices. * * @param index the indices. * @param value the value. */ - operator fun set(index: IntArray, value: T) + public operator fun set(index: IntArray, value: T) } -inline fun MutableNDStructure.mapInPlace(action: (IntArray, T) -> T) { - contract { callsInPlace(action) } +public inline fun MutableNDStructure.mapInPlace(action: (IntArray, T) -> T): Unit = elements().forEach { (index, oldValue) -> this[index] = action(index, oldValue) } -} /** * A way to convert ND index to linear one and back. */ -interface Strides { +public interface Strides { /** * Shape of NDstructure */ - val shape: IntArray + public val shape: IntArray /** * Array strides */ - val strides: List + public val strides: List /** * Get linear index from multidimensional index */ - fun offset(index: IntArray): Int + public fun offset(index: IntArray): Int /** * Get multidimensional from linear */ - fun index(offset: Int): IntArray + public fun index(offset: Int): IntArray /** * The size of linear buffer to accommodate all elements of ND-structure corresponding to strides */ - val linearSize: Int + public val linearSize: Int + + // TODO introduce a fast way to calculate index of the next element? /** * Iterate over ND indices in a natural order */ - fun indices(): Sequence { - //TODO introduce a fast way to calculate index of the next element? - return (0 until linearSize).asSequence().map { index(it) } - } + public fun indices(): Sequence = (0 until linearSize).asSequence().map { index(it) } } /** * Simple implementation of [Strides]. */ -class DefaultStrides private constructor(override val shape: IntArray) : Strides { +public class DefaultStrides private constructor(override val shape: IntArray) : Strides { + override val linearSize: Int + get() = strides[shape.size] + /** * Strides for memory access */ @@ -194,6 +193,7 @@ class DefaultStrides private constructor(override val shape: IntArray) : Strides sequence { var current = 1 yield(1) + shape.forEach { current *= it yield(current) @@ -212,17 +212,16 @@ class DefaultStrides private constructor(override val shape: IntArray) : Strides val res = IntArray(shape.size) var current = offset var strideIndex = strides.size - 2 + while (strideIndex >= 0) { res[strideIndex] = (current / strides[strideIndex]) current %= strides[strideIndex] strideIndex-- } + return res } - override val linearSize: Int - get() = strides[shape.size] - override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is DefaultStrides) return false @@ -232,13 +231,14 @@ class DefaultStrides private constructor(override val shape: IntArray) : Strides override fun hashCode(): Int = shape.contentHashCode() - companion object { + public companion object { private val defaultStridesCache = HashMap() /** * Cached builder for default strides */ - operator fun invoke(shape: IntArray): Strides = defaultStridesCache.getOrPut(shape) { DefaultStrides(shape) } + public operator fun invoke(shape: IntArray): Strides = + defaultStridesCache.getOrPut(shape) { DefaultStrides(shape) } } } @@ -247,16 +247,16 @@ class DefaultStrides private constructor(override val shape: IntArray) : Strides * * @param T the type of items. */ -abstract class NDBuffer : NDStructure { +public abstract class NDBuffer : NDStructure { /** * The underlying buffer. */ - abstract val buffer: Buffer + public abstract val buffer: Buffer /** * The strides to access elements of [Buffer] by linear indices. */ - abstract val strides: Strides + public abstract val strides: Strides override operator fun get(index: IntArray): T = buffer[strides.offset(index)] @@ -278,7 +278,7 @@ abstract class NDBuffer : NDStructure { /** * Boxing generic [NDStructure] */ -class BufferNDStructure( +public class BufferNDStructure( override val strides: Strides, override val buffer: Buffer ) : NDBuffer() { @@ -292,13 +292,13 @@ class BufferNDStructure( /** * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferNDStructure] */ -inline fun NDStructure.mapToBuffer( +public inline fun NDStructure.mapToBuffer( factory: BufferFactory = Buffer.Companion::auto, crossinline transform: (T) -> R ): BufferNDStructure { - return if (this is BufferNDStructure) { + return if (this is BufferNDStructure) BufferNDStructure(this.strides, factory.invoke(strides.linearSize) { transform(buffer[it]) }) - } else { + else { val strides = DefaultStrides(shape) BufferNDStructure(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) } @@ -307,7 +307,7 @@ inline fun NDStructure.mapToBuffer( /** * Mutable ND buffer based on linear [MutableBuffer]. */ -class MutableBufferNDStructure( +public class MutableBufferNDStructure( override val strides: Strides, override val buffer: MutableBuffer ) : NDBuffer(), MutableNDStructure { @@ -321,7 +321,7 @@ class MutableBufferNDStructure( override operator fun set(index: IntArray, value: T): Unit = buffer.set(strides.offset(index), value) } -inline fun NDStructure.combine( +public inline fun NDStructure.combine( struct: NDStructure, crossinline block: (T, T) -> T ): NDStructure { diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt index cba8e9689..050e5eddb 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt @@ -1,14 +1,11 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract - /** * Specialized [MutableBuffer] implementation over [DoubleArray]. * * @property array the underlying array. */ -inline class RealBuffer(val array: DoubleArray) : MutableBuffer { +public inline class RealBuffer(public val array: DoubleArray) : MutableBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Double = array[index] @@ -30,20 +27,17 @@ inline class RealBuffer(val array: DoubleArray) : MutableBuffer { * The function [init] is called for each array element sequentially starting from the first one. * It should return the value for an buffer element given its index. */ -inline fun RealBuffer(size: Int, init: (Int) -> Double): RealBuffer { - contract { callsInPlace(init) } - return RealBuffer(DoubleArray(size) { init(it) }) -} +public inline fun RealBuffer(size: Int, init: (Int) -> Double): RealBuffer = RealBuffer(DoubleArray(size) { init(it) }) /** * Returns a new [RealBuffer] of given elements. */ -fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles) +public fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles) /** * Returns a [DoubleArray] containing all of the elements of this [MutableBuffer]. */ -val MutableBuffer.array: DoubleArray +public val MutableBuffer.array: DoubleArray get() = (if (this is RealBuffer) array else DoubleArray(size) { get(it) }) /** @@ -52,4 +46,4 @@ val MutableBuffer.array: DoubleArray * @receiver the array. * @return the new buffer. */ -fun DoubleArray.asBuffer(): RealBuffer = RealBuffer(this) +public fun DoubleArray.asBuffer(): RealBuffer = RealBuffer(this) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt index a11826e7e..db79c6b78 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt @@ -4,11 +4,10 @@ import scientifik.kmath.operations.ExtendedField import scientifik.kmath.operations.ExtendedFieldOperations import kotlin.math.* - /** * [ExtendedFieldOperations] over [RealBuffer]. */ -object RealBufferFieldOperations : ExtendedFieldOperations> { +public object RealBufferFieldOperations : ExtendedFieldOperations> { override fun add(a: Buffer, b: Buffer): RealBuffer { require(b.size == a.size) { "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " @@ -73,9 +72,8 @@ object RealBufferFieldOperations : ExtendedFieldOperations> { override fun asin(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { asin(array[it]) }) - } else { + } else RealBuffer(DoubleArray(arg.size) { asin(arg[it]) }) - } override fun acos(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array @@ -92,37 +90,44 @@ object RealBufferFieldOperations : ExtendedFieldOperations> { override fun sinh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { sinh(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { sinh(arg[it]) }) + } else + RealBuffer(DoubleArray(arg.size) { sinh(arg[it]) }) override fun cosh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { cosh(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { cosh(arg[it]) }) + } else + RealBuffer(DoubleArray(arg.size) { cosh(arg[it]) }) override fun tanh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { tanh(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { tanh(arg[it]) }) + } else + RealBuffer(DoubleArray(arg.size) { tanh(arg[it]) }) override fun asinh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { asinh(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { asinh(arg[it]) }) + } else + RealBuffer(DoubleArray(arg.size) { asinh(arg[it]) }) override fun acosh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { acosh(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { acosh(arg[it]) }) + } else + RealBuffer(DoubleArray(arg.size) { acosh(arg[it]) }) override fun atanh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { atanh(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { atanh(arg[it]) }) + } else + RealBuffer(DoubleArray(arg.size) { atanh(arg[it]) }) override fun power(arg: Buffer, pow: Number): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { array[it].pow(pow.toDouble()) }) - } else RealBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) }) + } else + RealBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) }) override fun exp(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array @@ -132,7 +137,8 @@ object RealBufferFieldOperations : ExtendedFieldOperations> { override fun ln(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { ln(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { ln(arg[it]) }) + } else + RealBuffer(DoubleArray(arg.size) { ln(arg[it]) }) } /** @@ -140,7 +146,7 @@ object RealBufferFieldOperations : ExtendedFieldOperations> { * * @property size the size of buffers to operate on. */ -class RealBufferField(val size: Int) : ExtendedField> { +public class RealBufferField(public val size: Int) : ExtendedField> { override val zero: Buffer by lazy { RealBuffer(size) { 0.0 } } override val one: Buffer by lazy { RealBuffer(size) { 1.0 } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt index ac2adbe9b..94855d670 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt @@ -112,26 +112,22 @@ public inline fun RealNDElement.map(crossinline transform: RealField.(Double) -> /** * Element by element application of any operation on elements to the whole array. Just like in numpy. */ -operator fun Function1.invoke(ndElement: RealNDElement): RealNDElement = +public operator fun Function1.invoke(ndElement: RealNDElement): RealNDElement = ndElement.map { this@invoke(it) } - /* plus and minus */ /** * Summation operation for [BufferedNDElement] and single element */ -operator fun RealNDElement.plus(arg: Double): RealNDElement = - map { it + arg } +public operator fun RealNDElement.plus(arg: Double): RealNDElement = map { it + arg } /** * Subtraction operation between [BufferedNDElement] and single element */ -operator fun RealNDElement.minus(arg: Double): RealNDElement = - map { it - arg } +public operator fun RealNDElement.minus(arg: Double): RealNDElement = map { it - arg } /** * Produce a context for n-dimensional operations inside this real field */ - -inline fun RealField.nd(vararg shape: Int, action: RealNDField.() -> R): R = NDField.real(*shape).run(action) +public inline fun RealField.nd(vararg shape: Int, action: RealNDField.() -> R): R = NDField.real(*shape).run(action) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt index 82deb9275..d1a725556 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt @@ -1,6 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract /** @@ -30,10 +29,7 @@ public inline class ShortBuffer(public val array: ShortArray) : MutableBuffer Short): ShortBuffer { - contract { callsInPlace(init) } - return ShortBuffer(ShortArray(size) { init(it) }) -} +public inline fun ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer = ShortBuffer(ShortArray(size) { init(it) }) /** * Returns a new [ShortBuffer] of given elements. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt index 9a2ec1c88..30e87fd6a 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt @@ -2,7 +2,6 @@ package scientifik.kmath.structures import scientifik.kmath.operations.RingElement import scientifik.kmath.operations.ShortRing -import kotlin.contracts.contract public typealias ShortNDElement = BufferedNDRingElement @@ -69,11 +68,8 @@ public class ShortNDRing(override val shape: IntArray) : /** * Fast element production using function inlining. */ -public inline fun BufferedNDRing.produceInline(crossinline initializer: ShortRing.(Int) -> Short): ShortNDElement { - contract { callsInPlace(initializer) } - val array = ShortArray(strides.linearSize) { offset -> ShortRing.initializer(offset) } - return BufferedNDRingElement(this, ShortBuffer(array)) -} +public inline fun BufferedNDRing.produceInline(crossinline initializer: ShortRing.(Int) -> Short): ShortNDElement = + BufferedNDRingElement(this, ShortBuffer(ShortArray(strides.linearSize) { offset -> ShortRing.initializer(offset) })) /** * Element by element application of any operation on elements to the whole array. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt index a796c2037..22d0c4750 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt @@ -3,7 +3,7 @@ package scientifik.kmath.structures /** * A structure that is guaranteed to be one-dimensional */ -interface Structure1D : NDStructure, Buffer { +public interface Structure1D : NDStructure, Buffer { override val dimension: Int get() = 1 override operator fun get(index: IntArray): T { @@ -11,14 +11,13 @@ interface Structure1D : NDStructure, Buffer { return get(index[0]) } - override operator fun iterator(): Iterator = (0 until size).asSequence().map { get(it) }.iterator() + override operator fun iterator(): Iterator = (0 until size).asSequence().map(::get).iterator() } /** * A 1D wrapper for nd-structure */ private inline class Structure1DWrapper(val structure: NDStructure) : Structure1D { - override val shape: IntArray get() = structure.shape override val size: Int get() = structure.shape[0] @@ -45,18 +44,12 @@ private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D /** * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch */ -fun NDStructure.as1D(): Structure1D = if (shape.size == 1) { - if (this is NDBuffer) { - Buffer1DWrapper(this.buffer) - } else { - Structure1DWrapper(this) - } -} else { +public fun NDStructure.as1D(): Structure1D = if (shape.size == 1) { + if (this is NDBuffer) Buffer1DWrapper(this.buffer) else Structure1DWrapper(this) +} else error("Can't create 1d-structure from ${shape.size}d-structure") -} - /** * Represent this buffer as 1D structure */ -fun Buffer.asND(): Structure1D = Buffer1DWrapper(this) +public fun Buffer.asND(): Structure1D = Buffer1DWrapper(this) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt index e0ae4d4a2..7633d8898 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt @@ -21,11 +21,8 @@ public interface Structure2D : NDStructure { get() = VirtualBuffer(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } } 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)) - } - } + for (i in (0 until rowNum)) + for (j in (0 until colNum)) yield(intArrayOf(i, j) to get(i, j)) } public companion object @@ -45,10 +42,9 @@ private inline class Structure2DWrapper(val structure: NDStructure) : Stru /** * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch */ -public fun NDStructure.as2D(): Structure2D = if (shape.size == 2) { +public fun NDStructure.as2D(): Structure2D = if (shape.size == 2) Structure2DWrapper(this) -} else { +else error("Can't create 2d-structure from ${shape.size}d-structure") -} public typealias Matrix = Structure2D diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/coroutines/coroutinesExtra.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/coroutines/coroutinesExtra.kt index 692f89589..86bc2d6e3 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/coroutines/coroutinesExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/coroutines/coroutinesExtra.kt @@ -3,9 +3,8 @@ package scientifik.kmath.coroutines import kotlinx.coroutines.* import kotlinx.coroutines.channels.produce import kotlinx.coroutines.flow.* -import kotlin.contracts.contract -val Dispatchers.Math: CoroutineDispatcher +public val Dispatchers.Math: CoroutineDispatcher get() = Default /** @@ -15,31 +14,25 @@ internal class LazyDeferred(val dispatcher: CoroutineDispatcher, val block: s private var deferred: Deferred? = null internal fun start(scope: CoroutineScope) { - if (deferred == null) { - deferred = scope.async(dispatcher, block = block) - } + if (deferred == null) deferred = scope.async(dispatcher, block = block) } suspend fun await(): T = deferred?.await() ?: error("Coroutine not started") } -class AsyncFlow internal constructor(internal val deferredFlow: Flow>) : Flow { - override suspend fun collect(collector: FlowCollector) { - deferredFlow.collect { collector.emit((it.await())) } - } +public class AsyncFlow internal constructor(internal val deferredFlow: Flow>) : Flow { + override suspend fun collect(collector: FlowCollector): Unit = deferredFlow.collect { collector.emit((it.await())) } } -fun Flow.async( +public fun Flow.async( dispatcher: CoroutineDispatcher = Dispatchers.Default, block: suspend CoroutineScope.(T) -> R ): AsyncFlow { - val flow = map { - LazyDeferred(dispatcher) { block(it) } - } + val flow = map { LazyDeferred(dispatcher) { block(it) } } return AsyncFlow(flow) } -fun AsyncFlow.map(action: (T) -> R): AsyncFlow = +public fun AsyncFlow.map(action: (T) -> R): AsyncFlow = AsyncFlow(deferredFlow.map { input -> //TODO add function composition LazyDeferred(input.dispatcher) { @@ -48,7 +41,7 @@ fun AsyncFlow.map(action: (T) -> R): AsyncFlow = } }) -suspend fun AsyncFlow.collect(concurrency: Int, collector: FlowCollector) { +public suspend fun AsyncFlow.collect(concurrency: Int, collector: FlowCollector) { require(concurrency >= 1) { "Buffer size should be more than 1, but was $concurrency" } coroutineScope { @@ -76,18 +69,14 @@ suspend fun AsyncFlow.collect(concurrency: Int, collector: FlowCollector< } } -suspend inline fun AsyncFlow.collect(concurrency: Int, crossinline action: suspend (value: T) -> Unit) { - contract { callsInPlace(action) } +public suspend inline fun AsyncFlow.collect( + concurrency: Int, + crossinline action: suspend (value: T) -> Unit +): Unit = collect(concurrency, object : FlowCollector { + override suspend fun emit(value: T): Unit = action(value) +}) - collect(concurrency, object : FlowCollector { - override suspend fun emit(value: T): Unit = action(value) - }) -} - -inline fun Flow.mapParallel( +public inline fun Flow.mapParallel( dispatcher: CoroutineDispatcher = Dispatchers.Default, crossinline transform: suspend (T) -> R -): Flow { - contract { callsInPlace(transform) } - return flatMapMerge { value -> flow { emit(transform(value)) } }.flowOn(dispatcher) -} +): Flow = flatMapMerge { value -> flow { emit(transform(value)) } }.flowOn(dispatcher) diff --git a/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt b/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt index ff732a06b..a607d2d85 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt @@ -3,38 +3,31 @@ package scientifik.kmath.structures import kotlinx.coroutines.* import scientifik.kmath.coroutines.Math -class LazyNDStructure( - val scope: CoroutineScope, - override val shape: IntArray, - val function: suspend (IntArray) -> T +public class LazyNDStructure( + public val scope: CoroutineScope, + public override val shape: IntArray, + public val function: suspend (IntArray) -> T ) : NDStructure { private val cache: MutableMap> = hashMapOf() - fun deferred(index: IntArray): Deferred = cache.getOrPut(index) { - scope.async(context = Dispatchers.Math) { - function(index) - } + public fun deferred(index: IntArray): Deferred = cache.getOrPut(index) { + scope.async(context = Dispatchers.Math) { function(index) } } - suspend fun await(index: IntArray): T = deferred(index).await() + public suspend fun await(index: IntArray): T = deferred(index).await() + public override operator fun get(index: IntArray): T = runBlocking { deferred(index).await() } - override operator fun get(index: IntArray): T = runBlocking { - deferred(index).await() - } - - override fun elements(): Sequence> { + public override fun elements(): Sequence> { val strides = DefaultStrides(shape) - val res = runBlocking { - strides.indices().toList().map { index -> index to await(index) } - } + val res = runBlocking { strides.indices().toList().map { index -> index to await(index) } } return res.asSequence() } - override fun equals(other: Any?): Boolean { + public override fun equals(other: Any?): Boolean { return NDStructure.equals(this, other as? NDStructure<*> ?: return false) } - override fun hashCode(): Int { + public override fun hashCode(): Int { var result = scope.hashCode() result = 31 * result + shape.contentHashCode() result = 31 * result + function.hashCode() @@ -43,21 +36,21 @@ class LazyNDStructure( } } -fun NDStructure.deferred(index: IntArray): Deferred = +public fun NDStructure.deferred(index: IntArray): Deferred = if (this is LazyNDStructure) this.deferred(index) else CompletableDeferred(get(index)) -suspend fun NDStructure.await(index: IntArray): T = +public suspend fun NDStructure.await(index: IntArray): T = if (this is LazyNDStructure) this.await(index) else get(index) /** * PENDING would benefit from KEEP-176 */ -inline fun NDStructure.mapAsyncIndexed( +public inline fun NDStructure.mapAsyncIndexed( scope: CoroutineScope, crossinline function: suspend (T, index: IntArray) -> R ): LazyNDStructure = LazyNDStructure(scope, shape) { index -> function(get(index), index) } -inline fun NDStructure.mapAsync( +public inline fun NDStructure.mapAsync( scope: CoroutineScope, crossinline function: suspend (T) -> R ): LazyNDStructure = LazyNDStructure(scope, shape) { index -> function(get(index)) } diff --git a/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt index 7b0244bdf..8ebbf47c0 100644 --- a/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt @@ -13,35 +13,36 @@ import scientifik.kmath.structures.Structure2D /** * A matrix with compile-time controlled dimension */ -interface DMatrix : Structure2D { - companion object { +public interface DMatrix : Structure2D { + public companion object { /** * Coerces a regular matrix to a matrix with type-safe dimensions and throws a error if coercion failed */ - inline fun coerce(structure: Structure2D): DMatrix { - if (structure.rowNum != Dimension.dim().toInt()) { - error("Row number mismatch: expected ${Dimension.dim()} but found ${structure.rowNum}") + public inline fun coerce(structure: Structure2D): DMatrix { + require(structure.rowNum == Dimension.dim().toInt()) { + "Row number mismatch: expected ${Dimension.dim()} but found ${structure.rowNum}" } - if (structure.colNum != Dimension.dim().toInt()) { - error("Column number mismatch: expected ${Dimension.dim()} but found ${structure.colNum}") + + require(structure.colNum == Dimension.dim().toInt()) { + "Column number mismatch: expected ${Dimension.dim()} but found ${structure.colNum}" } + return DMatrixWrapper(structure) } /** - * The same as [coerce] but without dimension checks. Use with caution + * The same as [DMatrix.coerce] but without dimension checks. Use with caution */ - fun coerceUnsafe(structure: Structure2D): DMatrix { - return DMatrixWrapper(structure) - } + public fun coerceUnsafe(structure: Structure2D): DMatrix = + DMatrixWrapper(structure) } } /** * An inline wrapper for a Matrix */ -inline class DMatrixWrapper( - val structure: Structure2D +public inline class DMatrixWrapper( + public val structure: Structure2D ) : DMatrix { override val shape: IntArray get() = structure.shape override operator fun get(i: Int, j: Int): T = structure[i, j] @@ -50,25 +51,24 @@ inline class DMatrixWrapper( /** * Dimension-safe point */ -interface DPoint : Point { - companion object { - inline fun coerce(point: Point): DPoint { - if (point.size != Dimension.dim().toInt()) { - error("Vector dimension mismatch: expected ${Dimension.dim()}, but found ${point.size}") +public interface DPoint : Point { + public companion object { + public inline fun coerce(point: Point): DPoint { + require(point.size == Dimension.dim().toInt()) { + "Vector dimension mismatch: expected ${Dimension.dim()}, but found ${point.size}" } + return DPointWrapper(point) } - fun coerceUnsafe(point: Point): DPoint { - return DPointWrapper(point) - } + public fun coerceUnsafe(point: Point): DPoint = DPointWrapper(point) } } /** * Dimension-safe point wrapper */ -inline class DPointWrapper(val point: Point) : +public inline class DPointWrapper(public val point: Point) : DPoint { override val size: Int get() = point.size @@ -81,16 +81,15 @@ inline class DPointWrapper(val point: Point) : /** * Basic operations on dimension-safe matrices. Operates on [Matrix] */ -inline class DMatrixContext>(val context: GenericMatrixContext) { +public inline class DMatrixContext>(public val context: GenericMatrixContext) { + public inline fun Matrix.coerce(): DMatrix { + require(rowNum == Dimension.dim().toInt()) { + "Row number mismatch: expected ${Dimension.dim()} but found $rowNum" + } - inline fun Matrix.coerce(): DMatrix { - check( - rowNum == Dimension.dim().toInt() - ) { "Row number mismatch: expected ${Dimension.dim()} but found $rowNum" } - - check( - colNum == Dimension.dim().toInt() - ) { "Column number mismatch: expected ${Dimension.dim()} but found $colNum" } + require(colNum == Dimension.dim().toInt()) { + "Column number mismatch: expected ${Dimension.dim()} but found $colNum" + } return DMatrix.coerceUnsafe(this) } @@ -98,13 +97,13 @@ inline class DMatrixContext>(val context: GenericMatrixCon /** * Produce a matrix with this context and given dimensions */ - inline fun produce(noinline initializer: (i: Int, j: Int) -> T): DMatrix { + public inline fun produce(noinline initializer: (i: Int, j: Int) -> T): DMatrix { val rows = Dimension.dim() val cols = Dimension.dim() return context.produce(rows.toInt(), cols.toInt(), initializer).coerce() } - inline fun point(noinline initializer: (Int) -> T): DPoint { + public inline fun point(noinline initializer: (Int) -> T): DPoint { val size = Dimension.dim() return DPoint.coerceUnsafe( @@ -115,7 +114,7 @@ inline class DMatrixContext>(val context: GenericMatrixCon ) } - inline infix fun DMatrix.dot( + public inline infix fun DMatrix.dot( other: DMatrix ): DMatrix = context { this@dot dot other }.coerce() diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt index a3b41288a..5cecafd2e 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt @@ -116,16 +116,13 @@ public operator fun Matrix.minus(other: Matrix): RealMatrix = * Operations on columns */ -public inline fun Matrix.appendColumn(crossinline mapper: (Buffer) -> Double): Matrix { - contract { callsInPlace(mapper) } - - return MatrixContext.real.produce(rowNum, colNum + 1) { row, col -> +public inline fun Matrix.appendColumn(crossinline mapper: (Buffer) -> Double): Matrix = + MatrixContext.real.produce(rowNum, colNum + 1) { row, col -> if (col < colNum) this[row, col] else mapper(rows[row]) } -} public fun Matrix.extractColumns(columnRange: IntRange): RealMatrix = MatrixContext.real.produce(rowNum, columnRange.count()) { row, col -> diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt index b11469ccf..52030f0fd 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt @@ -12,11 +12,10 @@ public fun interface PiecewisePolynomial : /** * Ordered list of pieces in piecewise function */ -public class OrderedPiecewisePolynomial>(delimeter: T) : +public class OrderedPiecewisePolynomial>(delimiter: T) : PiecewisePolynomial { - - private val delimiters: ArrayList = arrayListOf(delimeter) - private val pieces: ArrayList> = ArrayList() + private val delimiters: MutableList = arrayListOf(delimiter) + private val pieces: MutableList> = arrayListOf() /** * Dynamically add a piece to the "right" side (beyond maximum argument value of previous piece) @@ -35,14 +34,13 @@ public class OrderedPiecewisePolynomial>(delimeter: T) : } override fun findPiece(arg: T): Polynomial? { - if (arg < delimiters.first() || arg >= delimiters.last()) { + if (arg < delimiters.first() || arg >= delimiters.last()) return null - } else { - for (index in 1 until delimiters.size) { - if (arg < delimiters[index]) { + else { + for (index in 1 until delimiters.size) + if (arg < delimiters[index]) return pieces[index - 1] - } - } + error("Piece not found") } } diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt index 35f1a1e16..25a9a9421 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt @@ -48,9 +48,9 @@ public fun > Polynomial.asFunction(ring: C): (T) -> T = * An algebra for polynomials */ public class PolynomialSpace>(public val ring: C) : Space> { - override val zero: Polynomial = Polynomial(emptyList()) + public override val zero: Polynomial = Polynomial(emptyList()) - override fun add(a: Polynomial, b: Polynomial): Polynomial { + public override fun add(a: Polynomial, b: Polynomial): Polynomial { val dim = max(a.coefficients.size, b.coefficients.size) return ring { @@ -60,7 +60,7 @@ public class PolynomialSpace>(public val ring: C) : Space

, k: Number): Polynomial = + public override fun multiply(a: Polynomial, k: Number): Polynomial = ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * k }) } public operator fun Polynomial.invoke(arg: T): T = value(ring, arg) diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt index 95e734da8..a53cafece 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt @@ -22,7 +22,7 @@ public interface PolynomialInterpolator> : Interpolator } } -fun > PolynomialInterpolator.interpolatePolynomials( +public fun > PolynomialInterpolator.interpolatePolynomials( x: Buffer, y: Buffer ): PiecewisePolynomial { @@ -30,16 +30,16 @@ fun > PolynomialInterpolator.interpolatePolynomials( return interpolatePolynomials(pointSet) } -fun > PolynomialInterpolator.interpolatePolynomials( +public fun > PolynomialInterpolator.interpolatePolynomials( data: Map ): PiecewisePolynomial { val pointSet = BufferXYPointSet(data.keys.toList().asBuffer(), data.values.toList().asBuffer()) return interpolatePolynomials(pointSet) } -fun > PolynomialInterpolator.interpolatePolynomials( +public fun > PolynomialInterpolator.interpolatePolynomials( data: List> ): PiecewisePolynomial { val pointSet = BufferXYPointSet(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer()) return interpolatePolynomials(pointSet) -} \ No newline at end of file +} diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt index 03a4625fc..4fac86693 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt @@ -9,8 +9,8 @@ import scientifik.kmath.operations.invoke /** * Reference JVM implementation: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/analysis/interpolation/LinearInterpolator.java */ -public class LinearInterpolator>(override val algebra: Field) : PolynomialInterpolator { - override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { +public class LinearInterpolator>(public override val algebra: Field) : PolynomialInterpolator { + public override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { require(points.size > 0) { "Point array should not be empty" } insureSorted(points) diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt index c8ab42bf4..eec61159d 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt @@ -12,13 +12,13 @@ import scientifik.kmath.structures.MutableBufferFactory * Based on https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java */ public class SplineInterpolator>( - override val algebra: Field, + public override val algebra: Field, public val bufferFactory: MutableBufferFactory ) : PolynomialInterpolator { //TODO possibly optimize zeroed buffers - override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { + public override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { if (points.size < 3) { error("Can't use spline interpolator with less than 3 points") } @@ -41,8 +41,9 @@ public class SplineInterpolator>( // cubic spline coefficients -- b is linear, c quadratic, d is cubic (original y's are constants) - OrderedPiecewisePolynomial(points.x[points.size - 1]).apply { + OrderedPiecewisePolynomial(points.x[points.size - 1]).apply { var cOld = zero + for (j in n - 1 downTo 0) { val c = z[j] - mu[j] * cOld val a = points.y[j] diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt index 19297036b..3c45223d9 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt @@ -14,32 +14,32 @@ public interface XYZPointSet : XYPointSet { } internal fun > insureSorted(points: XYPointSet) { - for (i in 0 until points.size - 1) require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" } + for (i in 0 until points.size - 1) + require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" } } public class NDStructureColumn(public val structure: Structure2D, public val column: Int) : Buffer { + public override val size: Int + get() = structure.rowNum + init { require(column < structure.colNum) { "Column index is outside of structure column range" } } - override val size: Int get() = structure.rowNum - - override operator fun get(index: Int): T = structure[index, column] - - override operator fun iterator(): Iterator = sequence { - repeat(size) { - yield(get(it)) - } - }.iterator() + public override operator fun get(index: Int): T = structure[index, column] + public override operator fun iterator(): Iterator = sequence { repeat(size) { yield(get(it)) } }.iterator() } -public class BufferXYPointSet(override val x: Buffer, override val y: Buffer) : XYPointSet { +public class BufferXYPointSet( + public override val x: Buffer, + public override val y: Buffer +) : XYPointSet { + public override val size: Int + get() = x.size + init { require(x.size == y.size) { "Sizes of x and y buffers should be the same" } } - - override val size: Int - get() = x.size } public fun Structure2D.asXYPointSet(): XYPointSet { diff --git a/kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt index 540494caf..3d39de4c9 100644 --- a/kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt @@ -6,7 +6,7 @@ import scientifik.kmath.operations.RealField import kotlin.test.Test import kotlin.test.assertEquals -class LinearInterpolatorTest { +internal class LinearInterpolatorTest { @Test fun testInterpolation() { val data = listOf( @@ -15,9 +15,9 @@ class LinearInterpolatorTest { 2.0 to 3.0, 3.0 to 4.0 ) + val polynomial: PiecewisePolynomial = LinearInterpolator(RealField).interpolatePolynomials(data) val function = polynomial.asFunction(RealField) - assertEquals(null, function(-1.0)) assertEquals(0.5, function(0.5)) assertEquals(2.0, function(1.5)) diff --git a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt b/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt index 551b877a7..be5bf5740 100644 --- a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt +++ b/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt @@ -4,17 +4,16 @@ import org.jetbrains.bio.viktor.F64FlatArray import scientifik.kmath.structures.MutableBuffer @Suppress("NOTHING_TO_INLINE", "OVERRIDE_BY_INLINE") -inline class ViktorBuffer(val flatArray: F64FlatArray) : MutableBuffer { - override val size: Int get() = flatArray.size +public inline class ViktorBuffer(public val flatArray: F64FlatArray) : MutableBuffer { + public override val size: Int + get() = flatArray.size + + public override inline fun get(index: Int): Double = flatArray[index] - override inline fun get(index: Int): Double = flatArray[index] override inline fun set(index: Int, value: Double) { flatArray[index] = value } - override fun copy(): MutableBuffer { - return ViktorBuffer(flatArray.copy().flatten()) - } - - override operator fun iterator(): Iterator = flatArray.data.iterator() + public override fun copy(): MutableBuffer = ViktorBuffer(flatArray.copy().flatten()) + public override operator fun iterator(): Iterator = flatArray.data.iterator() } diff --git a/settings.gradle.kts b/settings.gradle.kts index 102cde93f..a09e4e144 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,12 +1,12 @@ pluginManagement { - val toolsVersion = "0.6.0-dev-3" + val toolsVersion = "0.6.0-dev-5" plugins { id("kotlinx.benchmark") version "0.2.0-dev-20" id("ru.mipt.npm.mpp") version toolsVersion id("ru.mipt.npm.jvm") version toolsVersion id("ru.mipt.npm.publish") version toolsVersion - kotlin("plugin.allopen") version "1.4.0" + kotlin("plugin.allopen") version "1.4.20-dev-3898-14" } repositories { @@ -17,6 +17,7 @@ pluginManagement { maven("https://dl.bintray.com/mipt-npm/scientifik") maven("https://dl.bintray.com/mipt-npm/dev") maven("https://dl.bintray.com/kotlin/kotlinx") + maven("https://dl.bintray.com/kotlin/kotlin-dev/") } } From f567f73d19d7f0d7e4646890586833101a863e3c Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 9 Sep 2020 11:28:54 +0700 Subject: [PATCH 027/199] Specify explicit API visbility, minor refactoring (error handling, etc.) --- examples/build.gradle.kts | 2 +- .../kmath/operations/NumberAlgebra.kt | 222 +++++++++--------- .../kmath/structures/BoxingNDField.kt | 22 +- .../scientifik/kmath/structures/LongBuffer.kt | 1 - .../kmath/structures/RealBufferField.kt | 80 +++---- .../kmath/structures/ShortBuffer.kt | 14 +- .../kmath/structures/Structure1D.kt | 10 +- .../scientifik/kmath/operations/BigNumbers.kt | 40 ++-- .../kmath/chains/BlockingIntChain.kt | 6 +- .../kmath/chains/BlockingRealChain.kt | 6 +- .../scientifik/kmath/chains/flowExtra.kt | 11 +- .../scientifik/kmath/streaming/BufferFlow.kt | 22 +- .../scientifik/kmath/streaming/RingBuffer.kt | 30 +-- .../scientifik/kmath/dimensions/Wrappers.kt | 22 +- .../scientifik/kmath/real/RealVector.kt | 27 +-- .../scientifik/kmath/real/realBuffer.kt | 2 +- .../scientifik/kmath/real/realMatrix.kt | 8 +- .../scientifik/kmath/functions/Polynomial.kt | 6 +- .../scientifik/kmath/functions/functions.kt | 3 +- .../kmath/interpolation/SplineInterpolator.kt | 9 +- .../scientifik/kmath/histogram/Counters.kt | 22 +- .../scientifik/kmath/histogram/Histogram.kt | 30 ++- .../kmath/histogram/RealHistogram.kt | 69 +++--- .../histogram/MultivariateHistogramTest.kt | 2 +- .../scientifik/kmath/histogram/Counters.kt | 28 ++- .../scientifik/kmath/histogram/Counters.kt | 4 +- .../kmath/histogram/UnivariateHistogram.kt | 41 ++-- .../scientifik/kmath/prob/Distribution.kt | 23 +- .../scientifik/kmath/prob/distributions.kt | 51 ++-- settings.gradle.kts | 3 +- 30 files changed, 401 insertions(+), 415 deletions(-) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 9f173a046..2c51574e5 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -20,7 +20,7 @@ repositories { sourceSets.register("benchmarks") dependencies { - implementation(project(":kmath-ast")) +// implementation(project(":kmath-ast")) implementation(project(":kmath-core")) implementation(project(":kmath-coroutines")) implementation(project(":kmath-commons")) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt index 052e32bb9..150a0d582 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt @@ -1,6 +1,5 @@ package scientifik.kmath.operations -import scientifik.kmath.operations.RealField.pow import kotlin.math.abs import kotlin.math.pow as kpow @@ -13,11 +12,10 @@ public interface ExtendedFieldOperations : HyperbolicOperations, PowerOperations, ExponentialOperations { + public override fun tan(arg: T): T = sin(arg) / cos(arg) + public override fun tanh(arg: T): T = sinh(arg) / cosh(arg) - override fun tan(arg: T): T = sin(arg) / cos(arg) - override fun tanh(arg: T): T = sinh(arg) / cosh(arg) - - override fun unaryOperation(operation: String, arg: T): T = when (operation) { + public override fun unaryOperation(operation: String, arg: T): T = when (operation) { TrigonometricOperations.COS_OPERATION -> cos(arg) TrigonometricOperations.SIN_OPERATION -> sin(arg) TrigonometricOperations.TAN_OPERATION -> tan(arg) @@ -37,19 +35,18 @@ public interface ExtendedFieldOperations : } } - /** * Advanced Number-like field that implements basic operations. */ public interface ExtendedField : ExtendedFieldOperations, Field { - override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2 - override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2 - override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg)) - override fun asinh(arg: T): T = ln(sqrt(arg * arg + one) + arg) - override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one))) - override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2 + public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2 + public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2 + public override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg)) + public override fun asinh(arg: T): T = ln(sqrt(arg * arg + one) + arg) + 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 - override fun rightSideNumberOperation(operation: String, left: T, right: Number): T = when (operation) { + public override fun rightSideNumberOperation(operation: String, left: T, right: Number): T = when (operation) { PowerOperations.POW_OPERATION -> power(left, right) else -> super.rightSideNumberOperation(operation, left, right) } @@ -63,12 +60,11 @@ public interface ExtendedField : ExtendedFieldOperations, Field { * TODO inline does not work due to compiler bug. Waiting for fix for KT-27586 */ public inline class Real(public val value: Double) : FieldElement { - override val context: RealField + public override val context: RealField get() = RealField - override fun unwrap(): Double = value - - override fun Double.wrap(): Real = Real(value) + public override fun unwrap(): Double = value + public override fun Double.wrap(): Real = Real(value) public companion object } @@ -78,49 +74,49 @@ public inline class Real(public val value: Double) : FieldElement, Norm { - override val zero: Double + public override val zero: Double get() = 0.0 - override val one: Double + public override val one: Double get() = 1.0 - override fun binaryOperation(operation: String, left: Double, right: Double): Double = when (operation) { + public override fun binaryOperation(operation: String, left: Double, right: Double): Double = when (operation) { PowerOperations.POW_OPERATION -> left pow right else -> super.binaryOperation(operation, left, right) } - override inline fun add(a: Double, b: Double): Double = a + b - override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble() + public override inline fun add(a: Double, b: Double): Double = a + b + public override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble() - override inline fun multiply(a: Double, b: Double): Double = a * b + public override inline fun multiply(a: Double, b: Double): Double = a * b - override inline fun divide(a: Double, b: Double): Double = a / b + public override inline fun divide(a: Double, b: Double): Double = a / b - override inline fun sin(arg: Double): Double = kotlin.math.sin(arg) - override inline fun cos(arg: Double): Double = kotlin.math.cos(arg) - override inline fun tan(arg: Double): Double = kotlin.math.tan(arg) - override inline fun acos(arg: Double): Double = kotlin.math.acos(arg) - override inline fun asin(arg: Double): Double = kotlin.math.asin(arg) - override inline fun atan(arg: Double): Double = kotlin.math.atan(arg) + public override inline fun sin(arg: Double): Double = kotlin.math.sin(arg) + public override inline fun cos(arg: Double): Double = kotlin.math.cos(arg) + public override inline fun tan(arg: Double): Double = kotlin.math.tan(arg) + public override inline fun acos(arg: Double): Double = kotlin.math.acos(arg) + public override inline fun asin(arg: Double): Double = kotlin.math.asin(arg) + public override inline fun atan(arg: Double): Double = kotlin.math.atan(arg) - override inline fun sinh(arg: Double): Double = kotlin.math.sinh(arg) - override inline fun cosh(arg: Double): Double = kotlin.math.cosh(arg) - override inline fun tanh(arg: Double): Double = kotlin.math.tanh(arg) - override inline fun asinh(arg: Double): Double = kotlin.math.asinh(arg) - override inline fun acosh(arg: Double): Double = kotlin.math.acosh(arg) - override inline fun atanh(arg: Double): Double = kotlin.math.atanh(arg) + public override inline fun sinh(arg: Double): Double = kotlin.math.sinh(arg) + public override inline fun cosh(arg: Double): Double = kotlin.math.cosh(arg) + public override inline fun tanh(arg: Double): Double = kotlin.math.tanh(arg) + public override inline fun asinh(arg: Double): Double = kotlin.math.asinh(arg) + public override inline fun acosh(arg: Double): Double = kotlin.math.acosh(arg) + public override inline fun atanh(arg: Double): Double = kotlin.math.atanh(arg) - override inline fun power(arg: Double, pow: Number): Double = arg.kpow(pow.toDouble()) - override inline fun exp(arg: Double): Double = kotlin.math.exp(arg) - override inline fun ln(arg: Double): Double = kotlin.math.ln(arg) + public override inline fun power(arg: Double, pow: Number): Double = arg.kpow(pow.toDouble()) + public override inline fun exp(arg: Double): Double = kotlin.math.exp(arg) + public override inline fun ln(arg: Double): Double = kotlin.math.ln(arg) - override inline fun norm(arg: Double): Double = abs(arg) + public override inline fun norm(arg: Double): Double = abs(arg) - override inline fun Double.unaryMinus(): Double = -this - override inline fun Double.plus(b: Double): Double = this + b - override inline fun Double.minus(b: Double): Double = this - b - override inline fun Double.times(b: Double): Double = this * b - override inline fun Double.div(b: Double): Double = this / b + public override inline fun Double.unaryMinus(): Double = -this + public override inline fun Double.plus(b: Double): Double = this + b + public override inline fun Double.minus(b: Double): Double = this - b + public override inline fun Double.times(b: Double): Double = this * b + public override inline fun Double.div(b: Double): Double = this / b } /** @@ -128,49 +124,49 @@ public object RealField : ExtendedField, Norm { */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object FloatField : ExtendedField, Norm { - override val zero: Float + public override val zero: Float get() = 0.0f - override val one: Float + public override val one: Float get() = 1.0f - override fun binaryOperation(operation: String, left: Float, right: Float): Float = when (operation) { + public override fun binaryOperation(operation: String, left: Float, right: Float): Float = when (operation) { PowerOperations.POW_OPERATION -> left pow right else -> super.binaryOperation(operation, left, right) } - override inline fun add(a: Float, b: Float): Float = a + b - override inline fun multiply(a: Float, k: Number): Float = a * k.toFloat() + public override inline fun add(a: Float, b: Float): Float = a + b + public override inline fun multiply(a: Float, k: Number): Float = a * k.toFloat() - override inline fun multiply(a: Float, b: Float): Float = a * b + public override inline fun multiply(a: Float, b: Float): Float = a * b - override inline fun divide(a: Float, b: Float): Float = a / b + public override inline fun divide(a: Float, b: Float): Float = a / b - override inline fun sin(arg: Float): Float = kotlin.math.sin(arg) - override inline fun cos(arg: Float): Float = kotlin.math.cos(arg) - override inline fun tan(arg: Float): Float = kotlin.math.tan(arg) - override inline fun acos(arg: Float): Float = kotlin.math.acos(arg) - override inline fun asin(arg: Float): Float = kotlin.math.asin(arg) - override inline fun atan(arg: Float): Float = kotlin.math.atan(arg) + public override inline fun sin(arg: Float): Float = kotlin.math.sin(arg) + public override inline fun cos(arg: Float): Float = kotlin.math.cos(arg) + public override inline fun tan(arg: Float): Float = kotlin.math.tan(arg) + public override inline fun acos(arg: Float): Float = kotlin.math.acos(arg) + public override inline fun asin(arg: Float): Float = kotlin.math.asin(arg) + public override inline fun atan(arg: Float): Float = kotlin.math.atan(arg) - override inline fun sinh(arg: Float): Float = kotlin.math.sinh(arg) - override inline fun cosh(arg: Float): Float = kotlin.math.cosh(arg) - override inline fun tanh(arg: Float): Float = kotlin.math.tanh(arg) - override inline fun asinh(arg: Float): Float = kotlin.math.asinh(arg) - override inline fun acosh(arg: Float): Float = kotlin.math.acosh(arg) - override inline fun atanh(arg: Float): Float = kotlin.math.atanh(arg) + public override inline fun sinh(arg: Float): Float = kotlin.math.sinh(arg) + public override inline fun cosh(arg: Float): Float = kotlin.math.cosh(arg) + public override inline fun tanh(arg: Float): Float = kotlin.math.tanh(arg) + public override inline fun asinh(arg: Float): Float = kotlin.math.asinh(arg) + public override inline fun acosh(arg: Float): Float = kotlin.math.acosh(arg) + public override inline fun atanh(arg: Float): Float = kotlin.math.atanh(arg) - override inline fun power(arg: Float, pow: Number): Float = arg.kpow(pow.toFloat()) - override inline fun exp(arg: Float): Float = kotlin.math.exp(arg) - override inline fun ln(arg: Float): Float = kotlin.math.ln(arg) + public override inline fun power(arg: Float, pow: Number): Float = arg.kpow(pow.toFloat()) + public override inline fun exp(arg: Float): Float = kotlin.math.exp(arg) + public override inline fun ln(arg: Float): Float = kotlin.math.ln(arg) - override inline fun norm(arg: Float): Float = abs(arg) + public override inline fun norm(arg: Float): Float = abs(arg) - override inline fun Float.unaryMinus(): Float = -this - override inline fun Float.plus(b: Float): Float = this + b - override inline fun Float.minus(b: Float): Float = this - b - override inline fun Float.times(b: Float): Float = this * b - override inline fun Float.div(b: Float): Float = this / b + public override inline fun Float.unaryMinus(): Float = -this + public override inline fun Float.plus(b: Float): Float = this + b + public override inline fun Float.minus(b: Float): Float = this - b + public override inline fun Float.times(b: Float): Float = this * b + public override inline fun Float.div(b: Float): Float = this / b } /** @@ -178,23 +174,23 @@ public object FloatField : ExtendedField, Norm { */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object IntRing : Ring, Norm { - override val zero: Int + public override val zero: Int get() = 0 - override val one: Int + public override val one: Int get() = 1 - override inline fun add(a: Int, b: Int): Int = a + b - override inline fun multiply(a: Int, k: Number): Int = k.toInt() * a + public override inline fun add(a: Int, b: Int): Int = a + b + public override inline fun multiply(a: Int, k: Number): Int = k.toInt() * a - override inline fun multiply(a: Int, b: Int): Int = a * b + public override inline fun multiply(a: Int, b: Int): Int = a * b - override inline fun norm(arg: Int): Int = abs(arg) + public override inline fun norm(arg: Int): Int = abs(arg) - override inline fun Int.unaryMinus(): Int = -this - override inline fun Int.plus(b: Int): Int = this + b - override inline fun Int.minus(b: Int): Int = this - b - override inline fun Int.times(b: Int): Int = this * b + public override inline fun Int.unaryMinus(): Int = -this + public override inline fun Int.plus(b: Int): Int = this + b + public override inline fun Int.minus(b: Int): Int = this - b + public override inline fun Int.times(b: Int): Int = this * b } /** @@ -202,23 +198,23 @@ public object IntRing : Ring, Norm { */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object ShortRing : Ring, Norm { - override val zero: Short + public override val zero: Short get() = 0 - override val one: Short + public override val one: Short get() = 1 - override inline fun add(a: Short, b: Short): Short = (a + b).toShort() - override inline fun multiply(a: Short, k: Number): Short = (a * k.toShort()).toShort() + public override inline fun add(a: Short, b: Short): Short = (a + b).toShort() + public override inline fun multiply(a: Short, k: Number): Short = (a * k.toShort()).toShort() - override inline fun multiply(a: Short, b: Short): Short = (a * b).toShort() + public override inline fun multiply(a: Short, b: Short): Short = (a * b).toShort() - override fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort() + public override fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort() - override inline fun Short.unaryMinus(): Short = (-this).toShort() - override inline fun Short.plus(b: Short): Short = (this + b).toShort() - override inline fun Short.minus(b: Short): Short = (this - b).toShort() - override inline fun Short.times(b: Short): Short = (this * b).toShort() + public override inline fun Short.unaryMinus(): Short = (-this).toShort() + public override inline fun Short.plus(b: Short): Short = (this + b).toShort() + public override inline fun Short.minus(b: Short): Short = (this - b).toShort() + public override inline fun Short.times(b: Short): Short = (this * b).toShort() } /** @@ -226,23 +222,23 @@ public object ShortRing : Ring, Norm { */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object ByteRing : Ring, Norm { - override val zero: Byte + public override val zero: Byte get() = 0 - override val one: Byte + public override val one: Byte get() = 1 - override inline fun add(a: Byte, b: Byte): Byte = (a + b).toByte() - override inline fun multiply(a: Byte, k: Number): Byte = (a * k.toByte()).toByte() + public override inline fun add(a: Byte, b: Byte): Byte = (a + b).toByte() + public override inline fun multiply(a: Byte, k: Number): Byte = (a * k.toByte()).toByte() - override inline fun multiply(a: Byte, b: Byte): Byte = (a * b).toByte() + public override inline fun multiply(a: Byte, b: Byte): Byte = (a * b).toByte() - override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte() + public override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte() - override inline fun Byte.unaryMinus(): Byte = (-this).toByte() - override inline fun Byte.plus(b: Byte): Byte = (this + b).toByte() - override inline fun Byte.minus(b: Byte): Byte = (this - b).toByte() - override inline fun Byte.times(b: Byte): Byte = (this * b).toByte() + public override inline fun Byte.unaryMinus(): Byte = (-this).toByte() + public override inline fun Byte.plus(b: Byte): Byte = (this + b).toByte() + public override inline fun Byte.minus(b: Byte): Byte = (this - b).toByte() + public override inline fun Byte.times(b: Byte): Byte = (this * b).toByte() } /** @@ -250,21 +246,21 @@ public object ByteRing : Ring, Norm { */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object LongRing : Ring, Norm { - override val zero: Long + public override val zero: Long get() = 0 - override val one: Long + public override val one: Long get() = 1 - override inline fun add(a: Long, b: Long): Long = a + b - override inline fun multiply(a: Long, k: Number): Long = a * k.toLong() + public override inline fun add(a: Long, b: Long): Long = a + b + public override inline fun multiply(a: Long, k: Number): Long = a * k.toLong() - override inline fun multiply(a: Long, b: Long): Long = a * b + public override inline fun multiply(a: Long, b: Long): Long = a * b - override fun norm(arg: Long): Long = abs(arg) + public override fun norm(arg: Long): Long = abs(arg) - override inline fun Long.unaryMinus(): Long = (-this) - override inline fun Long.plus(b: Long): Long = (this + b) - override inline fun Long.minus(b: Long): Long = (this - b) - override inline fun Long.times(b: Long): Long = (this * b) + public override inline fun Long.unaryMinus(): Long = (-this) + public override inline fun Long.plus(b: Long): Long = (this + b) + public override inline fun Long.minus(b: Long): Long = (this - b) + public override inline fun Long.times(b: Long): Long = (this * b) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt index 5950532e1..a258c7a2f 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt @@ -4,27 +4,27 @@ import scientifik.kmath.operations.Field import scientifik.kmath.operations.FieldElement public class BoxingNDField>( - override val shape: IntArray, - override val elementContext: F, + public override val shape: IntArray, + public override val elementContext: F, public val bufferFactory: BufferFactory ) : BufferedNDField { - override val zero: BufferedNDFieldElement by lazy { produce { zero } } - override val one: BufferedNDFieldElement by lazy { produce { one } } - override val strides: Strides = DefaultStrides(shape) + public override val zero: BufferedNDFieldElement by lazy { produce { zero } } + public override val one: BufferedNDFieldElement by lazy { produce { one } } + public override val strides: Strides = DefaultStrides(shape) public fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) - override fun check(vararg elements: NDBuffer) { + public override fun check(vararg elements: NDBuffer) { check(elements.all { it.strides == strides }) { "Element strides are not the same as context strides" } } - override fun produce(initializer: F.(IntArray) -> T): BufferedNDFieldElement = + public override fun produce(initializer: F.(IntArray) -> T): BufferedNDFieldElement = BufferedNDFieldElement( this, buildBuffer(strides.linearSize) { offset -> elementContext.initializer(strides.index(offset)) }) - override fun map(arg: NDBuffer, transform: F.(T) -> T): BufferedNDFieldElement { + public override fun map(arg: NDBuffer, transform: F.(T) -> T): BufferedNDFieldElement { check(arg) return BufferedNDFieldElement( @@ -36,7 +36,7 @@ public class BoxingNDField>( } - override fun mapIndexed( + public override fun mapIndexed( arg: NDBuffer, transform: F.(index: IntArray, T) -> T ): BufferedNDFieldElement { @@ -55,7 +55,7 @@ public class BoxingNDField>( // return BufferedNDFieldElement(this, buffer) } - override fun combine( + public override fun combine( a: NDBuffer, b: NDBuffer, transform: F.(T, T) -> T @@ -66,7 +66,7 @@ public class BoxingNDField>( buildBuffer(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) }) } - override fun NDBuffer.toElement(): FieldElement, *, out BufferedNDField> = + public override fun NDBuffer.toElement(): FieldElement, *, out BufferedNDField> = BufferedNDFieldElement(this@BoxingNDField, buffer) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt index 0fe975e42..f6c3421cd 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt @@ -21,7 +21,6 @@ public inline class LongBuffer(public val array: LongArray) : MutableBuffer = LongBuffer(array.copyOf()) - } /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt index db79c6b78..363ce0275 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt @@ -8,7 +8,7 @@ import kotlin.math.* * [ExtendedFieldOperations] over [RealBuffer]. */ public object RealBufferFieldOperations : ExtendedFieldOperations> { - override fun add(a: Buffer, b: Buffer): RealBuffer { + public override fun add(a: Buffer, b: Buffer): RealBuffer { require(b.size == a.size) { "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " } @@ -20,7 +20,7 @@ public object RealBufferFieldOperations : ExtendedFieldOperations } else RealBuffer(DoubleArray(a.size) { a[it] + b[it] }) } - override fun multiply(a: Buffer, k: Number): RealBuffer { + public override fun multiply(a: Buffer, k: Number): RealBuffer { val kValue = k.toDouble() return if (a is RealBuffer) { @@ -29,7 +29,7 @@ public object RealBufferFieldOperations : ExtendedFieldOperations } else RealBuffer(DoubleArray(a.size) { a[it] * kValue }) } - override fun multiply(a: Buffer, b: Buffer): RealBuffer { + public override fun multiply(a: Buffer, b: Buffer): RealBuffer { require(b.size == a.size) { "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " } @@ -42,7 +42,7 @@ public object RealBufferFieldOperations : ExtendedFieldOperations RealBuffer(DoubleArray(a.size) { a[it] * b[it] }) } - override fun divide(a: Buffer, b: Buffer): RealBuffer { + public override fun divide(a: Buffer, b: Buffer): RealBuffer { require(b.size == a.size) { "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " } @@ -54,87 +54,87 @@ public object RealBufferFieldOperations : ExtendedFieldOperations } else RealBuffer(DoubleArray(a.size) { a[it] / b[it] }) } - override fun sin(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun sin(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { sin(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { sin(arg[it]) }) - override fun cos(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun cos(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { cos(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { cos(arg[it]) }) - override fun tan(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun tan(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { tan(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { tan(arg[it]) }) - override fun asin(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun asin(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { asin(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { asin(arg[it]) }) - override fun acos(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun acos(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { acos(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { acos(arg[it]) }) - override fun atan(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun atan(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { atan(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { atan(arg[it]) }) - override fun sinh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun sinh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { sinh(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { sinh(arg[it]) }) - override fun cosh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun cosh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { cosh(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { cosh(arg[it]) }) - override fun tanh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun tanh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { tanh(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { tanh(arg[it]) }) - override fun asinh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun asinh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { asinh(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { asinh(arg[it]) }) - override fun acosh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun acosh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { acosh(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { acosh(arg[it]) }) - override fun atanh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun atanh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { atanh(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { atanh(arg[it]) }) - override fun power(arg: Buffer, pow: Number): RealBuffer = if (arg is RealBuffer) { + public override fun power(arg: Buffer, pow: Number): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { array[it].pow(pow.toDouble()) }) } else RealBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) }) - override fun exp(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun exp(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { exp(array[it]) }) } else RealBuffer(DoubleArray(arg.size) { exp(arg[it]) }) - override fun ln(arg: Buffer): RealBuffer = if (arg is RealBuffer) { + public override fun ln(arg: Buffer): RealBuffer = if (arg is RealBuffer) { val array = arg.array RealBuffer(DoubleArray(arg.size) { ln(array[it]) }) } else @@ -147,100 +147,100 @@ public object RealBufferFieldOperations : ExtendedFieldOperations * @property size the size of buffers to operate on. */ public class RealBufferField(public val size: Int) : ExtendedField> { - override val zero: Buffer by lazy { RealBuffer(size) { 0.0 } } - override val one: Buffer by lazy { RealBuffer(size) { 1.0 } } + public override val zero: Buffer by lazy { RealBuffer(size) { 0.0 } } + public override val one: Buffer by lazy { RealBuffer(size) { 1.0 } } - override fun add(a: Buffer, b: Buffer): RealBuffer { + public override fun add(a: Buffer, b: Buffer): RealBuffer { require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } return RealBufferFieldOperations.add(a, b) } - override fun multiply(a: Buffer, k: Number): RealBuffer { + public override fun multiply(a: Buffer, k: Number): RealBuffer { require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } return RealBufferFieldOperations.multiply(a, k) } - override fun multiply(a: Buffer, b: Buffer): RealBuffer { + public override fun multiply(a: Buffer, b: Buffer): RealBuffer { require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } return RealBufferFieldOperations.multiply(a, b) } - override fun divide(a: Buffer, b: Buffer): RealBuffer { + public override fun divide(a: Buffer, b: Buffer): RealBuffer { require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } return RealBufferFieldOperations.divide(a, b) } - override fun sin(arg: Buffer): RealBuffer { + public override fun sin(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.sin(arg) } - override fun cos(arg: Buffer): RealBuffer { + public override fun cos(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.cos(arg) } - override fun tan(arg: Buffer): RealBuffer { + public override fun tan(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.tan(arg) } - override fun asin(arg: Buffer): RealBuffer { + public override fun asin(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.asin(arg) } - override fun acos(arg: Buffer): RealBuffer { + public override fun acos(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.acos(arg) } - override fun atan(arg: Buffer): RealBuffer { + public override fun atan(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.atan(arg) } - override fun sinh(arg: Buffer): RealBuffer { + public override fun sinh(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.sinh(arg) } - override fun cosh(arg: Buffer): RealBuffer { + public override fun cosh(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.cosh(arg) } - override fun tanh(arg: Buffer): RealBuffer { + public override fun tanh(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.tanh(arg) } - override fun asinh(arg: Buffer): RealBuffer { + public override fun asinh(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.asinh(arg) } - override fun acosh(arg: Buffer): RealBuffer { + public override fun acosh(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.acosh(arg) } - override fun atanh(arg: Buffer): RealBuffer { + public override fun atanh(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.atanh(arg) } - override fun power(arg: Buffer, pow: Number): RealBuffer { + public override fun power(arg: Buffer, pow: Number): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.power(arg, pow) } - override fun exp(arg: Buffer): RealBuffer { + public override fun exp(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.exp(arg) } - override fun ln(arg: Buffer): RealBuffer { + public override fun ln(arg: Buffer): RealBuffer { require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } return RealBufferFieldOperations.ln(arg) } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt index d1a725556..de26da460 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt @@ -1,25 +1,21 @@ package scientifik.kmath.structures -import kotlin.contracts.contract - /** * Specialized [MutableBuffer] implementation over [ShortArray]. * * @property array the underlying array. */ public inline class ShortBuffer(public val array: ShortArray) : MutableBuffer { - override val size: Int get() = array.size + public override val size: Int get() = array.size - override operator fun get(index: Int): Short = array[index] + public override operator fun get(index: Int): Short = array[index] - override operator fun set(index: Int, value: Short) { + public override operator fun set(index: Int, value: Short) { array[index] = value } - override operator fun iterator(): ShortIterator = array.iterator() - - override fun copy(): MutableBuffer = - ShortBuffer(array.copyOf()) + public override operator fun iterator(): ShortIterator = array.iterator() + public override fun copy(): MutableBuffer = ShortBuffer(array.copyOf()) } /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt index 22d0c4750..72602695f 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt @@ -4,25 +4,24 @@ package scientifik.kmath.structures * A structure that is guaranteed to be one-dimensional */ public interface Structure1D : NDStructure, Buffer { - override val dimension: Int get() = 1 + public override val dimension: Int get() = 1 - override operator fun get(index: IntArray): T { + public override operator fun get(index: IntArray): T { require(index.size == 1) { "Index dimension mismatch. Expected 1 but found ${index.size}" } return get(index[0]) } - override operator fun iterator(): Iterator = (0 until size).asSequence().map(::get).iterator() + public override operator fun iterator(): Iterator = (0 until size).asSequence().map(::get).iterator() } /** * A 1D wrapper for nd-structure */ -private inline class Structure1DWrapper(val structure: NDStructure) : Structure1D { +private inline class Structure1DWrapper(public val structure: NDStructure) : Structure1D { override val shape: IntArray get() = structure.shape override val size: Int get() = structure.shape[0] override operator fun get(index: Int): T = structure[index] - override fun elements(): Sequence> = structure.elements() } @@ -32,7 +31,6 @@ private inline class Structure1DWrapper(val structure: NDStructure) : Stru */ private inline 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> = diff --git a/kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt b/kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt index e5ec374c9..7310dcc68 100644 --- a/kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt +++ b/kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt @@ -8,19 +8,19 @@ import java.math.MathContext * A field over [BigInteger]. */ public object JBigIntegerField : Field { - override val zero: BigInteger + public override val zero: BigInteger get() = BigInteger.ZERO - override val one: BigInteger + public override val one: BigInteger get() = BigInteger.ONE - override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong()) - override fun divide(a: BigInteger, b: BigInteger): BigInteger = a.div(b) - override fun add(a: BigInteger, b: BigInteger): BigInteger = a.add(b) - override operator fun BigInteger.minus(b: BigInteger): BigInteger = subtract(b) - override fun multiply(a: BigInteger, k: Number): BigInteger = a.multiply(k.toInt().toBigInteger()) - override fun multiply(a: BigInteger, b: BigInteger): BigInteger = a.multiply(b) - override operator fun BigInteger.unaryMinus(): BigInteger = negate() + public override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong()) + public override fun divide(a: BigInteger, b: BigInteger): BigInteger = a.div(b) + public override fun add(a: BigInteger, b: BigInteger): BigInteger = a.add(b) + public override operator fun BigInteger.minus(b: BigInteger): BigInteger = subtract(b) + public override fun multiply(a: BigInteger, k: Number): BigInteger = a.multiply(k.toInt().toBigInteger()) + public override fun multiply(a: BigInteger, b: BigInteger): BigInteger = a.multiply(b) + public override operator fun BigInteger.unaryMinus(): BigInteger = negate() } /** @@ -31,24 +31,24 @@ public object JBigIntegerField : Field { public abstract class JBigDecimalFieldBase internal constructor(public val mathContext: MathContext = MathContext.DECIMAL64) : Field, PowerOperations { - override val zero: BigDecimal + public override val zero: BigDecimal get() = BigDecimal.ZERO - override val one: BigDecimal + public override val one: BigDecimal get() = BigDecimal.ONE - override fun add(a: BigDecimal, b: BigDecimal): BigDecimal = a.add(b) - override operator fun BigDecimal.minus(b: BigDecimal): BigDecimal = subtract(b) - override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble()) + public override fun add(a: BigDecimal, b: BigDecimal): BigDecimal = a.add(b) + public override operator fun BigDecimal.minus(b: BigDecimal): BigDecimal = subtract(b) + public override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble()) - override fun multiply(a: BigDecimal, k: Number): BigDecimal = + public override fun multiply(a: BigDecimal, k: Number): BigDecimal = a.multiply(k.toDouble().toBigDecimal(mathContext), mathContext) - override fun multiply(a: BigDecimal, b: BigDecimal): BigDecimal = a.multiply(b, mathContext) - override fun divide(a: BigDecimal, b: BigDecimal): BigDecimal = a.divide(b, mathContext) - override fun power(arg: BigDecimal, pow: Number): BigDecimal = arg.pow(pow.toInt(), mathContext) - override fun sqrt(arg: BigDecimal): BigDecimal = arg.sqrt(mathContext) - override operator fun BigDecimal.unaryMinus(): BigDecimal = negate(mathContext) + public override fun multiply(a: BigDecimal, b: BigDecimal): BigDecimal = a.multiply(b, mathContext) + public override fun divide(a: BigDecimal, b: BigDecimal): BigDecimal = a.divide(b, mathContext) + public override fun power(arg: BigDecimal, pow: Number): BigDecimal = arg.pow(pow.toInt(), mathContext) + public override fun sqrt(arg: BigDecimal): BigDecimal = arg.sqrt(mathContext) + public override operator fun BigDecimal.unaryMinus(): BigDecimal = negate(mathContext) } /** diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt index e9b499d71..25a95273d 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt @@ -3,10 +3,10 @@ package scientifik.kmath.chains /** * Performance optimized chain for integer values */ -abstract class BlockingIntChain : Chain { - abstract fun nextInt(): Int +public abstract class BlockingIntChain : Chain { + public abstract fun nextInt(): Int override suspend fun next(): Int = nextInt() - fun nextBlock(size: Int): IntArray = IntArray(size) { nextInt() } + public fun nextBlock(size: Int): IntArray = IntArray(size) { nextInt() } } diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt index ab819d327..867fee19f 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt @@ -3,10 +3,10 @@ package scientifik.kmath.chains /** * Performance optimized chain for real values */ -abstract class BlockingRealChain : Chain { - abstract fun nextDouble(): Double +public abstract class BlockingRealChain : Chain { + public abstract fun nextDouble(): Double override suspend fun next(): Double = nextDouble() - fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { nextDouble() } + public fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { nextDouble() } } diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/flowExtra.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/flowExtra.kt index 5db660c39..389e0b6db 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/flowExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/flowExtra.kt @@ -3,20 +3,19 @@ package scientifik.kmath.chains import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.runningReduce import kotlinx.coroutines.flow.scan -import kotlinx.coroutines.flow.scanReduce import scientifik.kmath.operations.Space import scientifik.kmath.operations.SpaceOperations import scientifik.kmath.operations.invoke @ExperimentalCoroutinesApi -fun Flow.cumulativeSum(space: SpaceOperations): Flow = space { - scanReduce { sum: T, element: T -> sum + element } -} +public fun Flow.cumulativeSum(space: SpaceOperations): Flow = + space { runningReduce { sum, element -> sum + element } } @ExperimentalCoroutinesApi -fun Flow.mean(space: Space): Flow = space { - class Accumulator(var sum: T, var num: Int) +public fun Flow.mean(space: Space): Flow = space { + data class Accumulator(var sum: T, var num: Int) scan(Accumulator(zero, 0)) { sum, element -> sum.apply { diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt index 9b7e82da5..ae1860974 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt @@ -11,18 +11,18 @@ import scientifik.kmath.structures.asBuffer /** * Create a [Flow] from buffer */ -fun Buffer.asFlow(): Flow = iterator().asFlow() +public fun Buffer.asFlow(): Flow = iterator().asFlow() /** * Flat map a [Flow] of [Buffer] into continuous [Flow] of elements */ @FlowPreview -fun Flow>.spread(): Flow = flatMapConcat { it.asFlow() } +public fun Flow>.spread(): Flow = flatMapConcat { it.asFlow() } /** * Collect incoming flow into fixed size chunks */ -fun Flow.chunked(bufferSize: Int, bufferFactory: BufferFactory): Flow> = flow { +public fun Flow.chunked(bufferSize: Int, bufferFactory: BufferFactory): Flow> = flow { require(bufferSize > 0) { "Resulting chunk size must be more than zero" } val list = ArrayList(bufferSize) var counter = 0 @@ -30,6 +30,7 @@ fun Flow.chunked(bufferSize: Int, bufferFactory: BufferFactory): Flow< this@chunked.collect { element -> list.add(element) counter++ + if (counter == bufferSize) { val buffer = bufferFactory(bufferSize) { list[it] } emit(buffer) @@ -37,15 +38,14 @@ fun Flow.chunked(bufferSize: Int, bufferFactory: BufferFactory): Flow< counter = 0 } } - if (counter > 0) { - emit(bufferFactory(counter) { list[it] }) - } + + if (counter > 0) emit(bufferFactory(counter) { list[it] }) } /** * Specialized flow chunker for real buffer */ -fun Flow.chunked(bufferSize: Int): Flow = flow { +public fun Flow.chunked(bufferSize: Int): Flow = flow { require(bufferSize > 0) { "Resulting chunk size must be more than zero" } if (this@chunked is BlockingRealChain) { @@ -66,9 +66,8 @@ fun Flow.chunked(bufferSize: Int): Flow = flow { counter = 0 } } - if (counter > 0) { - emit(RealBuffer(counter) { array[it] }) - } + + if (counter > 0) emit(RealBuffer(counter) { array[it] }) } } @@ -76,9 +75,10 @@ fun Flow.chunked(bufferSize: Int): Flow = flow { * Map a flow to a moving window buffer. The window step is one. * In order to get different steps, one could use skip operation. */ -fun Flow.windowed(window: Int): Flow> = flow { +public fun Flow.windowed(window: Int): Flow> = flow { require(window > 1) { "Window size must be more than one" } val ringBuffer = RingBuffer.boxing(window) + this@windowed.collect { element -> ringBuffer.push(element) emit(ringBuffer.snapshot()) diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt index f1c0bfc6a..b30100d43 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt @@ -10,28 +10,28 @@ import scientifik.kmath.structures.VirtualBuffer * Thread-safe ring buffer */ @Suppress("UNCHECKED_CAST") -class RingBuffer( +public class RingBuffer( private val buffer: MutableBuffer, private var startIndex: Int = 0, size: Int = 0 ) : Buffer { private val mutex: Mutex = Mutex() - override var size: Int = size + public override var size: Int = size private set - override operator fun get(index: Int): T { + public override operator fun get(index: Int): T { require(index >= 0) { "Index must be positive" } require(index < size) { "Index $index is out of circular buffer size $size" } return buffer[startIndex.forward(index)] as T } - fun isFull(): Boolean = size == buffer.size + public fun isFull(): Boolean = size == buffer.size /** * Iterator could provide wrong results if buffer is changed in initialization (iteration is safe) */ - override operator fun iterator(): Iterator = object : AbstractIterator() { + public override operator fun iterator(): Iterator = object : AbstractIterator() { private var count = size private var index = startIndex val copy = buffer.copy() @@ -48,23 +48,17 @@ class RingBuffer( /** * A safe snapshot operation */ - suspend fun snapshot(): Buffer { + public suspend fun snapshot(): Buffer { mutex.withLock { val copy = buffer.copy() - return VirtualBuffer(size) { i -> - copy[startIndex.forward(i)] as T - } + return VirtualBuffer(size) { i -> copy[startIndex.forward(i)] as T } } } - suspend fun push(element: T) { + public suspend fun push(element: T) { mutex.withLock { buffer[startIndex.forward(size)] = element - if (isFull()) { - startIndex++ - } else { - size++ - } + if (isFull()) startIndex++ else size++ } } @@ -72,8 +66,8 @@ class RingBuffer( @Suppress("NOTHING_TO_INLINE") private inline fun Int.forward(n: Int): Int = (this + n) % (buffer.size) - companion object { - inline fun build(size: Int, empty: T): RingBuffer { + public companion object { + public inline fun build(size: Int, empty: T): RingBuffer { val buffer = MutableBuffer.auto(size) { empty } as MutableBuffer return RingBuffer(buffer) } @@ -81,7 +75,7 @@ class RingBuffer( /** * Slow yet universal buffer */ - fun boxing(size: Int): RingBuffer { + public fun boxing(size: Int): RingBuffer { val buffer: MutableBuffer = MutableBuffer.boxing(size) { null } return RingBuffer(buffer) } diff --git a/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt index 8ebbf47c0..120069d83 100644 --- a/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt @@ -118,39 +118,39 @@ public inline class DMatrixContext>(public val context: Ge other: DMatrix ): DMatrix = context { this@dot dot other }.coerce() - inline infix fun DMatrix.dot(vector: DPoint): DPoint = + public inline infix fun DMatrix.dot(vector: DPoint): DPoint = DPoint.coerceUnsafe(context { this@dot dot vector }) - inline operator fun DMatrix.times(value: T): DMatrix = + public inline operator fun DMatrix.times(value: T): DMatrix = context { this@times.times(value) }.coerce() - inline operator fun T.times(m: DMatrix): DMatrix = + public inline operator fun T.times(m: DMatrix): DMatrix = m * this - inline operator fun DMatrix.plus(other: DMatrix): DMatrix = + public inline operator fun DMatrix.plus(other: DMatrix): DMatrix = context { this@plus + other }.coerce() - inline operator fun DMatrix.minus(other: DMatrix): DMatrix = + public inline operator fun DMatrix.minus(other: DMatrix): DMatrix = context { this@minus + other }.coerce() - inline operator fun DMatrix.unaryMinus(): DMatrix = + public inline operator fun DMatrix.unaryMinus(): DMatrix = context { this@unaryMinus.unaryMinus() }.coerce() - inline fun DMatrix.transpose(): DMatrix = + public inline fun DMatrix.transpose(): DMatrix = context { (this@transpose as Matrix).transpose() }.coerce() /** * A square unit matrix */ - inline fun one(): DMatrix = produce { i, j -> + public inline fun one(): DMatrix = produce { i, j -> if (i == j) context.elementContext.one else context.elementContext.zero } - inline fun zero(): DMatrix = produce { _, _ -> + public inline fun zero(): DMatrix = produce { _, _ -> context.elementContext.zero } - companion object { - val real: DMatrixContext = DMatrixContext(MatrixContext.real) + public companion object { + public val real: DMatrixContext = DMatrixContext(MatrixContext.real) } } diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt index 811b54d7c..8c6d5fae4 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt @@ -12,39 +12,38 @@ import scientifik.kmath.structures.asBuffer import scientifik.kmath.structures.asIterable import kotlin.math.sqrt -typealias RealPoint = Point +public typealias RealPoint = Point -fun DoubleArray.asVector(): RealVector = RealVector(this.asBuffer()) -fun List.asVector(): RealVector = RealVector(this.asBuffer()) +public fun DoubleArray.asVector(): RealVector = RealVector(this.asBuffer()) +public fun List.asVector(): RealVector = RealVector(this.asBuffer()) -object VectorL2Norm : Norm, Double> { +public object VectorL2Norm : Norm, Double> { override fun norm(arg: Point): Double = sqrt(arg.asIterable().sumByDouble { it.toDouble() }) } -inline class RealVector(private val point: Point) : +public inline class RealVector(private val point: Point) : SpaceElement>, RealPoint { + public override val size: Int get() = point.size + public override val context: VectorSpace get() = space(point.size) - override val context: VectorSpace get() = space(point.size) + public override fun unwrap(): RealPoint = point - override fun unwrap(): RealPoint = point + public override fun RealPoint.wrap(): RealVector = RealVector(this) - override fun RealPoint.wrap(): RealVector = RealVector(this) - - override val size: Int get() = point.size override operator fun get(index: Int): Double = point[index] override operator fun iterator(): Iterator = point.iterator() - companion object { + public companion object { private val spaceCache: MutableMap> = hashMapOf() - inline operator fun invoke(dim: Int, initializer: (Int) -> Double): RealVector = + public inline operator fun invoke(dim: Int, initializer: (Int) -> Double): RealVector = RealVector(RealBuffer(dim, initializer)) - operator fun invoke(vararg values: Double): RealVector = values.asVector() + public operator fun invoke(vararg values: Double): RealVector = values.asVector() - fun space(dim: Int): BufferVectorSpace = spaceCache.getOrPut(dim) { + public fun space(dim: Int): BufferVectorSpace = spaceCache.getOrPut(dim) { BufferVectorSpace(dim, RealField) { size, init -> Buffer.real(size, init) } } } diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realBuffer.kt b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realBuffer.kt index 82c0e86b2..480481d97 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realBuffer.kt +++ b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realBuffer.kt @@ -5,4 +5,4 @@ import scientifik.kmath.structures.RealBuffer /** * Simplified [RealBuffer] to array comparison */ -fun RealBuffer.contentEquals(vararg doubles: Double) = array.contentEquals(doubles) \ No newline at end of file +public fun RealBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles) diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt index 5cecafd2e..f406c0aad 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt @@ -138,11 +138,11 @@ public fun Matrix.sumByColumn(): RealBuffer = RealBuffer(colNum) { j -> } public fun Matrix.minByColumn(): RealBuffer = RealBuffer(colNum) { j -> - columns[j].asIterable().min() ?: error("Cannot produce min on empty column") + columns[j].asIterable().minOrNull() ?: error("Cannot produce min on empty column") } public fun Matrix.maxByColumn(): RealBuffer = RealBuffer(colNum) { j -> - columns[j].asIterable().max() ?: error("Cannot produce min on empty column") + columns[j].asIterable().maxOrNull() ?: error("Cannot produce min on empty column") } public fun Matrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j -> @@ -154,6 +154,6 @@ public fun Matrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j */ public fun Matrix.sum(): Double = elements().map { (_, value) -> value }.sum() -public fun Matrix.min(): Double? = elements().map { (_, value) -> value }.min() -public fun Matrix.max(): Double? = elements().map { (_, value) -> value }.max() +public fun Matrix.min(): Double? = elements().map { (_, value) -> value }.minOrNull() +public fun Matrix.max(): Double? = elements().map { (_, value) -> value }.maxOrNull() public fun Matrix.average(): Double = elements().map { (_, value) -> value }.average() diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt index 25a9a9421..77196a121 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt @@ -36,8 +36,10 @@ public fun > Polynomial.value(ring: C, arg: T): T = ring /** * Represent a polynomial as a context-dependent function */ -public fun > Polynomial.asMathFunction(): MathFunction = - MathFunction { arg -> value(this, arg) } +public fun > Polynomial.asMathFunction(): MathFunction = + object : MathFunction { + override fun C.invoke(arg: T): T = value(this, arg) + } /** * Represent the polynomial as a regular context-less function diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt index ce6156c0b..7b26fd221 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt @@ -3,13 +3,14 @@ package scientifik.kmath.functions import scientifik.kmath.operations.Algebra import scientifik.kmath.operations.RealField +// TODO make fun interface when KT-41770 is fixed /** * A regular function that could be called only inside specific algebra context * @param T source type * @param C source algebra constraint * @param R result type */ -public fun interface MathFunction, R> { +public /*fun*/ interface MathFunction, R> { public operator fun C.invoke(arg: T): R } diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt index eec61159d..e5dd8906b 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt @@ -15,15 +15,11 @@ public class SplineInterpolator>( public override val algebra: Field, public val bufferFactory: MutableBufferFactory ) : PolynomialInterpolator { - //TODO possibly optimize zeroed buffers public override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { - if (points.size < 3) { - error("Can't use spline interpolator with less than 3 points") - } + require(points.size >= 3) { "Can't use spline interpolator with less than 3 points" } insureSorted(points) - // Number of intervals. The number of data points is n + 1. val n = points.size - 1 // Differences between knot points @@ -34,6 +30,7 @@ public class SplineInterpolator>( for (i in 1 until n) { val g = 2.0 * (points.x[i + 1] - points.x[i - 1]) - h[i - 1] * mu[i - 1] mu[i] = h[i] / g + z[i] = (3.0 * (points.y[i + 1] * h[i - 1] - points.x[i] * (points.x[i + 1] - points.x[i - 1]) + points.y[i - 1] * h[i]) / (h[i - 1] * h[i]) - h[i - 1] * z[i - 1]) / g @@ -54,7 +51,5 @@ public class SplineInterpolator>( putLeft(points.x[j], polynomial) } } - } - } diff --git a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Counters.kt b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Counters.kt index 9c7de3303..ede6db5cf 100644 --- a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Counters.kt +++ b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Counters.kt @@ -5,16 +5,16 @@ package scientifik.kmath.histogram * TODO replace with atomics */ -expect class LongCounter() { - fun decrement() - fun increment() - fun reset() - fun sum(): Long - fun add(l: Long) +public expect class LongCounter() { + public fun decrement() + public fun increment() + public fun reset() + public fun sum(): Long + public fun add(l: Long) } -expect class DoubleCounter() { - fun reset() - fun sum(): Double - fun add(d: Double) -} \ No newline at end of file +public expect class DoubleCounter() { + public fun reset() + public fun sum(): Double + public fun add(d: Double) +} diff --git a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt index 9ff2aacf5..0acef2fb7 100644 --- a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt @@ -11,49 +11,47 @@ import kotlin.contracts.contract /** * The bin in the histogram. The histogram is by definition always done in the real space */ -interface Bin : Domain { +public interface Bin : Domain { /** * The value of this bin */ - val value: Number - val center: Point + public val value: Number + public val center: Point } -interface Histogram> : Iterable { - +public interface Histogram> : Iterable { /** * Find existing bin, corresponding to given coordinates */ - operator fun get(point: Point): B? + public operator fun get(point: Point): B? /** * Dimension of the histogram */ - val dimension: Int + public val dimension: Int } -interface MutableHistogram> : Histogram { +public interface MutableHistogram> : Histogram { /** * Increment appropriate bin */ - fun putWithWeight(point: Point, weight: Double) + public fun putWithWeight(point: Point, weight: Double) - fun put(point: Point): Unit = putWithWeight(point, 1.0) + public fun put(point: Point): Unit = putWithWeight(point, 1.0) } -fun MutableHistogram.put(vararg point: T): Unit = put(ArrayBuffer(point)) +public fun MutableHistogram.put(vararg point: T): Unit = put(ArrayBuffer(point)) -fun MutableHistogram.put(vararg point: Number): Unit = +public fun MutableHistogram.put(vararg point: Number): Unit = put(RealBuffer(point.map { it.toDouble() }.toDoubleArray())) -fun MutableHistogram.put(vararg point: Double): Unit = put(RealBuffer(point)) - -fun MutableHistogram.fill(sequence: Iterable>): Unit = sequence.forEach { put(it) } +public fun MutableHistogram.put(vararg point: Double): Unit = put(RealBuffer(point)) +public fun MutableHistogram.fill(sequence: Iterable>): Unit = sequence.forEach { put(it) } /** * Pass a sequence builder into histogram */ -fun MutableHistogram.fill(block: suspend SequenceScope>.() -> Unit): Unit = +public fun MutableHistogram.fill(block: suspend SequenceScope>.() -> Unit): Unit = fill(sequence(block).asIterable()) diff --git a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/RealHistogram.kt b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/RealHistogram.kt index f05ae1694..64ddc5515 100644 --- a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/RealHistogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/RealHistogram.kt @@ -7,9 +7,12 @@ import scientifik.kmath.real.asVector import scientifik.kmath.structures.* import kotlin.math.floor - -data class BinDef>(val space: SpaceOperations>, val center: Point, val sizes: Point) { - fun contains(vector: Point): Boolean { +public data class BinDef>( + public val space: SpaceOperations>, + public val center: Point, + public val sizes: Point +) { + public fun contains(vector: Point): Boolean { require(vector.size == center.size) { "Dimension mismatch for input vector. Expected ${center.size}, but found ${vector.size}" } val upper = space { center + sizes / 2.0 } val lower = space { center - sizes / 2.0 } @@ -18,21 +21,20 @@ data class BinDef>(val space: SpaceOperations>, val c } -class MultivariateBin>(val def: BinDef, override val value: Number) : Bin { - override operator fun contains(point: Point): Boolean = def.contains(point) - - override val dimension: Int +public class MultivariateBin>(public val def: BinDef, public override val value: Number) : Bin { + public override val dimension: Int get() = def.center.size - override val center: Point + public override val center: Point get() = def.center + public override operator fun contains(point: Point): Boolean = def.contains(point) } /** * Uniform multivariate histogram with fixed borders. Based on NDStructure implementation with complexity of m for bin search, where m is the number of dimensions. */ -class RealHistogram( +public class RealHistogram( private val lower: Buffer, private val upper: Buffer, private val binNums: IntArray = IntArray(lower.size) { 20 } @@ -40,7 +42,7 @@ class RealHistogram( private val strides = DefaultStrides(IntArray(binNums.size) { binNums[it] + 2 }) private val values: NDStructure = NDStructure.auto(strides) { LongCounter() } private val weights: NDStructure = NDStructure.auto(strides) { DoubleCounter() } - override val dimension: Int get() = lower.size + public override val dimension: Int get() = lower.size private val binSize = RealBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] } init { @@ -64,7 +66,7 @@ class RealHistogram( private fun getValue(index: IntArray): Long = values[index].sum() - fun getValue(point: Buffer): Long = getValue(getIndex(point)) + public fun getValue(point: Buffer): Long = getValue(getIndex(point)) private fun getDef(index: IntArray): BinDef { val center = index.mapIndexed { axis, i -> @@ -78,9 +80,9 @@ class RealHistogram( return BinDef(RealBufferFieldOperations, center, binSize) } - fun getDef(point: Buffer): BinDef = getDef(getIndex(point)) + public fun getDef(point: Buffer): BinDef = getDef(getIndex(point)) - override operator fun get(point: Buffer): MultivariateBin? { + public override operator fun get(point: Buffer): MultivariateBin? { val index = getIndex(point) return MultivariateBin(getDef(index), getValue(index)) } @@ -90,27 +92,27 @@ class RealHistogram( // values[index].increment() // } - override fun putWithWeight(point: Buffer, weight: Double) { + public override fun putWithWeight(point: Buffer, weight: Double) { val index = getIndex(point) values[index].increment() weights[index].add(weight) } - override operator fun iterator(): Iterator> = weights.elements().map { (index, value) -> - MultivariateBin(getDef(index), value.sum()) - }.iterator() + public override operator fun iterator(): Iterator> = + weights.elements().map { (index, value) -> MultivariateBin(getDef(index), value.sum()) } + .iterator() /** * Convert this histogram into NDStructure containing bin values but not bin descriptions */ - fun values(): NDStructure = NDStructure.auto(values.shape) { values[it].sum() } + public fun values(): NDStructure = NDStructure.auto(values.shape) { values[it].sum() } /** * Sum of weights */ - fun weights(): NDStructure = NDStructure.auto(weights.shape) { weights[it].sum() } + public fun weights(): NDStructure = NDStructure.auto(weights.shape) { weights[it].sum() } - companion object { + public companion object { /** * Use it like * ``` @@ -120,9 +122,9 @@ class RealHistogram( *) *``` */ - fun fromRanges(vararg ranges: ClosedFloatingPointRange): RealHistogram = RealHistogram( - ranges.map { it.start }.asVector(), - ranges.map { it.endInclusive }.asVector() + public fun fromRanges(vararg ranges: ClosedFloatingPointRange): RealHistogram = RealHistogram( + ranges.map(ClosedFloatingPointRange::start).asVector(), + ranges.map(ClosedFloatingPointRange::endInclusive).asVector() ) /** @@ -134,10 +136,21 @@ class RealHistogram( *) *``` */ - fun fromRanges(vararg ranges: Pair, Int>): RealHistogram = RealHistogram( - ListBuffer(ranges.map { it.first.start }), - ListBuffer(ranges.map { it.first.endInclusive }), - ranges.map { it.second }.toIntArray() - ) + public fun fromRanges(vararg ranges: Pair, Int>): RealHistogram = + RealHistogram( + ListBuffer( + ranges + .map(Pair, Int>::first) + .map(ClosedFloatingPointRange::start) + ), + + ListBuffer( + ranges + .map(Pair, Int>::first) + .map(ClosedFloatingPointRange::endInclusive) + ), + + ranges.map(Pair, Int>::second).toIntArray() + ) } } diff --git a/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt index 5edecb5a5..4400da7c9 100644 --- a/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt @@ -10,7 +10,7 @@ import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue -class MultivariateHistogramTest { +internal class MultivariateHistogramTest { @Test fun testSinglePutHistogram() { val histogram = RealHistogram.fromRanges( diff --git a/kmath-histograms/src/jsMain/kotlin/scientifik/kmath/histogram/Counters.kt b/kmath-histograms/src/jsMain/kotlin/scientifik/kmath/histogram/Counters.kt index 3765220b9..8e2e946f4 100644 --- a/kmath-histograms/src/jsMain/kotlin/scientifik/kmath/histogram/Counters.kt +++ b/kmath-histograms/src/jsMain/kotlin/scientifik/kmath/histogram/Counters.kt @@ -1,33 +1,37 @@ package scientifik.kmath.histogram -actual class LongCounter { - private var sum: Long = 0 - actual fun decrement() { +public actual class LongCounter { + private var sum: Long = 0L + + public actual fun decrement() { sum-- } - actual fun increment() { + public actual fun increment() { sum++ } - actual fun reset() { + public actual fun reset() { sum = 0 } - actual fun sum(): Long = sum - actual fun add(l: Long) { + public actual fun sum(): Long = sum + + public actual fun add(l: Long) { sum += l } } -actual class DoubleCounter { +public actual class DoubleCounter { private var sum: Double = 0.0 - actual fun reset() { + + public actual fun reset() { sum = 0.0 } - actual fun sum(): Double = sum - actual fun add(d: Double) { + public actual fun sum(): Double = sum + + public actual fun add(d: Double) { sum += d } -} \ No newline at end of file +} diff --git a/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/Counters.kt b/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/Counters.kt index bb3667f7d..dcf3d5491 100644 --- a/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/Counters.kt +++ b/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/Counters.kt @@ -3,5 +3,5 @@ package scientifik.kmath.histogram import java.util.concurrent.atomic.DoubleAdder import java.util.concurrent.atomic.LongAdder -actual typealias LongCounter = LongAdder -actual typealias DoubleCounter = DoubleAdder \ No newline at end of file +public actual typealias LongCounter = LongAdder +public actual typealias DoubleCounter = DoubleAdder diff --git a/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt index e30a45f5a..24c30bf4c 100644 --- a/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt @@ -8,25 +8,26 @@ import kotlin.math.floor //TODO move to common -class UnivariateBin(val position: Double, val size: Double, val counter: LongCounter = LongCounter()) : Bin { +public class UnivariateBin( + public val position: Double, + public val size: Double, + public val counter: LongCounter = LongCounter() +) : Bin { //TODO add weighting - override val value: Number get() = counter.sum() + public override val value: Number get() = counter.sum() - override val center: RealVector get() = doubleArrayOf(position).asVector() + public override val center: RealVector get() = doubleArrayOf(position).asVector() + public override val dimension: Int get() = 1 - operator fun contains(value: Double): Boolean = value in (position - size / 2)..(position + size / 2) - - override fun contains(point: Buffer): Boolean = contains(point[0]) - - internal operator fun inc() = this.also { counter.increment() } - - override val dimension: Int get() = 1 + public operator fun contains(value: Double): Boolean = value in (position - size / 2)..(position + size / 2) + public override fun contains(point: Buffer): Boolean = contains(point[0]) + internal operator fun inc(): UnivariateBin = this.also { counter.increment() } } /** * Univariate histogram with log(n) bin search speed */ -class UnivariateHistogram private constructor(private val factory: (Double) -> UnivariateBin) : +public class UnivariateHistogram private constructor(private val factory: (Double) -> UnivariateBin) : MutableHistogram { private val bins: TreeMap = TreeMap() @@ -46,16 +47,16 @@ class UnivariateHistogram private constructor(private val factory: (Double) -> U synchronized(this) { bins.put(it.position, it) } } - override operator fun get(point: Buffer): UnivariateBin? = get(point[0]) + public override operator fun get(point: Buffer): UnivariateBin? = get(point[0]) - override val dimension: Int get() = 1 + public override val dimension: Int get() = 1 - override operator fun iterator(): Iterator = bins.values.iterator() + public override operator fun iterator(): Iterator = bins.values.iterator() /** * Thread safe put operation */ - fun put(value: Double) { + public fun put(value: Double) { (get(value) ?: createBin(value)).inc() } @@ -64,13 +65,13 @@ class UnivariateHistogram private constructor(private val factory: (Double) -> U put(point[0]) } - companion object { - fun uniform(binSize: Double, start: Double = 0.0): UnivariateHistogram = UnivariateHistogram { value -> + public companion object { + public fun uniform(binSize: Double, start: Double = 0.0): UnivariateHistogram = UnivariateHistogram { value -> val center = start + binSize * floor((value - start) / binSize + 0.5) UnivariateBin(center, binSize) } - fun custom(borders: DoubleArray): UnivariateHistogram { + public fun custom(borders: DoubleArray): UnivariateHistogram { val sorted = borders.sortedArray() return UnivariateHistogram { value -> @@ -79,10 +80,12 @@ class UnivariateHistogram private constructor(private val factory: (Double) -> U Double.NEGATIVE_INFINITY, Double.MAX_VALUE ) + value > sorted.last() -> UnivariateBin( Double.POSITIVE_INFINITY, Double.MAX_VALUE ) + else -> { val index = (0 until sorted.size).first { value > sorted[it] } val left = sorted[index] @@ -95,4 +98,4 @@ class UnivariateHistogram private constructor(private val factory: (Double) -> U } } -fun UnivariateHistogram.fill(sequence: Iterable) = sequence.forEach { put(it) } +public fun UnivariateHistogram.fill(sequence: Iterable): Unit = sequence.forEach(::put) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt index 3b874adaa..e1f0e8d6e 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt @@ -5,19 +5,19 @@ import scientifik.kmath.chains.collect import scientifik.kmath.structures.Buffer import scientifik.kmath.structures.BufferFactory -interface Sampler { - fun sample(generator: RandomGenerator): Chain +public interface Sampler { + public fun sample(generator: RandomGenerator): Chain } /** * A distribution of typed objects */ -interface Distribution : Sampler { +public interface Distribution : Sampler { /** * A probability value for given argument [arg]. * For continuous distributions returns PDF */ - fun probability(arg: T): Double + public fun probability(arg: T): Double /** * Create a chain of samples from this distribution. @@ -28,20 +28,20 @@ interface Distribution : Sampler { /** * An empty companion. Distribution factories should be written as its extensions */ - companion object + public companion object } -interface UnivariateDistribution> : Distribution { +public interface UnivariateDistribution> : Distribution { /** * Cumulative distribution for ordered parameter (CDF) */ - fun cumulative(arg: T): Double + public fun cumulative(arg: T): Double } /** * Compute probability integral in an interval */ -fun > UnivariateDistribution.integral(from: T, to: T): Double { +public fun > UnivariateDistribution.integral(from: T, to: T): Double { require(to > from) return cumulative(to) - cumulative(from) } @@ -49,7 +49,7 @@ fun > UnivariateDistribution.integral(from: T, to: T): Doub /** * Sample a bunch of values */ -fun Sampler.sampleBuffer( +public fun Sampler.sampleBuffer( generator: RandomGenerator, size: Int, bufferFactory: BufferFactory = Buffer.Companion::boxing @@ -57,6 +57,7 @@ fun Sampler.sampleBuffer( require(size > 1) //creating temporary storage once val tmp = ArrayList(size) + return sample(generator).collect { chain -> //clear list from previous run tmp.clear() @@ -72,5 +73,5 @@ fun Sampler.sampleBuffer( /** * Generate a bunch of samples from real distributions */ -fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int) = - sampleBuffer(generator, size, Buffer.Companion::real) \ No newline at end of file +public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int) = + sampleBuffer(generator, size, Buffer.Companion::real) diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt index ddb50ef42..b3a37ada1 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt +++ b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt @@ -12,33 +12,29 @@ import kotlin.math.pow import kotlin.math.sqrt public abstract class ContinuousSamplerDistribution : Distribution { - private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingRealChain() { private val sampler = buildCMSampler(generator) - override fun nextDouble(): Double = sampler.sample() - - override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) + public override fun nextDouble(): Double = sampler.sample() + public override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) } protected abstract fun buildCMSampler(generator: RandomGenerator): ContinuousSampler - override fun sample(generator: RandomGenerator): BlockingRealChain = ContinuousSamplerChain(generator) + public override fun sample(generator: RandomGenerator): BlockingRealChain = ContinuousSamplerChain(generator) } public abstract class DiscreteSamplerDistribution : Distribution { - private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingIntChain() { private val sampler = buildSampler(generator) - override fun nextInt(): Int = sampler.sample() - - override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) + public override fun nextInt(): Int = sampler.sample() + public override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) } protected abstract fun buildSampler(generator: RandomGenerator): DiscreteSampler - override fun sample(generator: RandomGenerator): BlockingIntChain = ContinuousSamplerChain(generator) + public override fun sample(generator: RandomGenerator): BlockingIntChain = ContinuousSamplerChain(generator) } public enum class NormalSamplerMethod { @@ -58,7 +54,7 @@ public fun Distribution.Companion.normal( method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat ): Distribution = object : ContinuousSamplerDistribution() { override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { - val provider: UniformRandomProvider = generator.asUniformRandomProvider() + val provider = generator.asUniformRandomProvider() return normalSampler(method, provider) } @@ -76,34 +72,27 @@ public fun Distribution.Companion.normal( private val norm = sigma * sqrt(PI * 2) override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { - val provider: UniformRandomProvider = generator.asUniformRandomProvider() + val provider = generator.asUniformRandomProvider() val normalizedSampler = normalSampler(method, provider) return GaussianSampler(normalizedSampler, mean, sigma) } - override fun probability(arg: Double): Double { - return exp(-(arg - mean).pow(2) / 2 / sigma2) / norm - } + override fun probability(arg: Double): Double = exp(-(arg - mean).pow(2) / 2 / sigma2) / norm } -public fun Distribution.Companion.poisson( - lambda: Double -): DiscreteSamplerDistribution = object : DiscreteSamplerDistribution() { +public fun Distribution.Companion.poisson(lambda: Double): DiscreteSamplerDistribution = + object : DiscreteSamplerDistribution() { + private val computedProb: MutableMap = hashMapOf(0 to exp(-lambda)) - override fun buildSampler(generator: RandomGenerator): DiscreteSampler { - return PoissonSampler.of(generator.asUniformRandomProvider(), lambda) - } + override fun buildSampler(generator: RandomGenerator): DiscreteSampler = + PoissonSampler.of(generator.asUniformRandomProvider(), lambda) - private val computedProb: HashMap = hashMapOf(0 to exp(-lambda)) + override fun probability(arg: Int): Double { + require(arg >= 0) { "The argument must be >= 0" } - override fun probability(arg: Int): Double { - require(arg >= 0) { "The argument must be >= 0" } - return if (arg > 40) { - exp(-(arg - lambda).pow(2) / 2 / lambda) / sqrt(2 * PI * lambda) - } else { - computedProb.getOrPut(arg) { - probability(arg - 1) * lambda / arg - } + return if (arg > 40) + exp(-(arg - lambda).pow(2) / 2 / lambda) / sqrt(2 * PI * lambda) + else + computedProb.getOrPut(arg) { probability(arg - 1) * lambda / arg } } } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index a09e4e144..53e3ece3c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -27,7 +27,6 @@ include( ":kmath-memory", ":kmath-core", ":kmath-functions", -// ":kmath-io", ":kmath-coroutines", ":kmath-histograms", ":kmath-commons", @@ -38,6 +37,6 @@ include( ":kmath-dimensions", ":kmath-for-real", ":kmath-geometry", - ":kmath-ast", +// ":kmath-ast", ":examples" ) From 8ae9a071ef362f630ead28b30fce80680238955b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 9 Sep 2020 21:12:18 +0700 Subject: [PATCH 028/199] Add more explicit public modifiers --- .../commons/expressions/DiffExpression.kt | 78 +++++++++---------- .../kmath/commons/linear/CMMatrix.kt | 68 ++++++++-------- .../kmath/commons/linear/CMSolver.kt | 33 ++++---- .../random/CMRandomGeneratorWrapper.kt | 24 +++--- .../commons/transform/Transformations.kt | 27 +++---- .../kmath/commons/expressions/AutoDiffTest.kt | 10 ++- .../scientifik/kmath/operations/BigInt.kt | 30 +++---- .../kotlin/scientifik/kmath/chains/Chain.kt | 15 ++-- .../scientifik/kmath/streaming/BufferFlow.kt | 7 +- .../scientifik/kmath/chains/ChainExt.kt | 5 +- .../kmath/structures/LazyNDStructure.kt | 4 +- .../kmath/streaming/BufferFlowTest.kt | 2 +- .../kmath/streaming/RingBufferTest.kt | 2 +- .../dimensions/DMatrixContextTest.kt | 4 +- .../kotlin/scientifik/kmath/dimensions/dim.kt | 24 +++--- .../kotlin/scientifik/kmath/dimensions/dim.kt | 20 +++-- .../scientifik/kmath/real/RealVector.kt | 14 ++-- .../scientific.kmath.real/RealMatrixTest.kt | 2 +- .../scientifik/kmath/linear/VectorTest.kt | 2 +- .../kmath/geometry/Euclidean2DSpace.kt | 47 +++++------ .../kmath/geometry/Euclidean3DSpace.kt | 41 +++++----- .../kmath/geometry/GeometrySpace.kt | 8 +- .../kotlin/scientifik/kmath/geometry/Line.kt | 6 +- .../kmath/geometry/ReferenceFrame.kt | 3 +- .../scientifik.kmath.linear/KomaMatrix.kt | 53 ++++++------- kmath-prob/build.gradle.kts | 4 + .../kmath/prob/CommonsDistributionsTest.kt | 5 +- .../scientifik/kmath/prob/StatisticTest.kt | 9 ++- .../kmath/viktor/ViktorNDStructure.kt | 70 +++++++++-------- 29 files changed, 298 insertions(+), 319 deletions(-) diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt index a6f905471..d556eb762 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt +++ b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt @@ -15,8 +15,8 @@ public class DerivativeStructureField( public val order: Int, public val parameters: Map ) : ExtendedField { - override val zero: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size) } - override val one: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size, 1.0) } + public override val zero: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size) } + public override val one: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size, 1.0) } private val variables: Map = parameters.mapValues { (key, value) -> DerivativeStructure(parameters.size, order, parameters.keys.indexOf(key), value) @@ -40,46 +40,43 @@ public class DerivativeStructureField( } public fun DerivativeStructure.deriv(vararg orders: Pair): Double = deriv(mapOf(*orders)) + public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b) - override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b) - - override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) { + public override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) { is Double -> a.multiply(k) is Int -> a.multiply(k) else -> a.multiply(k.toDouble()) } - override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b) + public override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b) + public override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b) + public override fun sin(arg: DerivativeStructure): DerivativeStructure = arg.sin() + public override fun cos(arg: DerivativeStructure): DerivativeStructure = arg.cos() + public override fun tan(arg: DerivativeStructure): DerivativeStructure = arg.tan() + public override fun asin(arg: DerivativeStructure): DerivativeStructure = arg.asin() + public override fun acos(arg: DerivativeStructure): DerivativeStructure = arg.acos() + public override fun atan(arg: DerivativeStructure): DerivativeStructure = arg.atan() + public override fun sinh(arg: DerivativeStructure): DerivativeStructure = arg.sinh() + public override fun cosh(arg: DerivativeStructure): DerivativeStructure = arg.cosh() + public override fun tanh(arg: DerivativeStructure): DerivativeStructure = arg.tanh() + public override fun asinh(arg: DerivativeStructure): DerivativeStructure = arg.asinh() + public override fun acosh(arg: DerivativeStructure): DerivativeStructure = arg.acosh() + public override fun atanh(arg: DerivativeStructure): DerivativeStructure = arg.atanh() - override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b) - - override fun sin(arg: DerivativeStructure): DerivativeStructure = arg.sin() - override fun cos(arg: DerivativeStructure): DerivativeStructure = arg.cos() - override fun tan(arg: DerivativeStructure): DerivativeStructure = arg.tan() - override fun asin(arg: DerivativeStructure): DerivativeStructure = arg.asin() - override fun acos(arg: DerivativeStructure): DerivativeStructure = arg.acos() - override fun atan(arg: DerivativeStructure): DerivativeStructure = arg.atan() - override fun sinh(arg: DerivativeStructure): DerivativeStructure = arg.sinh() - override fun cosh(arg: DerivativeStructure): DerivativeStructure = arg.cosh() - override fun tanh(arg: DerivativeStructure): DerivativeStructure = arg.tanh() - override fun asinh(arg: DerivativeStructure): DerivativeStructure = arg.asinh() - override fun acosh(arg: DerivativeStructure): DerivativeStructure = arg.acosh() - override fun atanh(arg: DerivativeStructure): DerivativeStructure = arg.atanh() - - override fun power(arg: DerivativeStructure, pow: Number): DerivativeStructure = when (pow) { + public override fun power(arg: DerivativeStructure, pow: Number): DerivativeStructure = when (pow) { is Double -> arg.pow(pow) is Int -> arg.pow(pow) else -> arg.pow(pow.toDouble()) } public fun power(arg: DerivativeStructure, pow: DerivativeStructure): DerivativeStructure = arg.pow(pow) - override fun exp(arg: DerivativeStructure): DerivativeStructure = arg.exp() - override fun ln(arg: DerivativeStructure): DerivativeStructure = arg.log() + public override fun exp(arg: DerivativeStructure): DerivativeStructure = arg.exp() + public override fun ln(arg: DerivativeStructure): DerivativeStructure = arg.log() - override operator fun DerivativeStructure.plus(b: Number): DerivativeStructure = add(b.toDouble()) - override operator fun DerivativeStructure.minus(b: Number): DerivativeStructure = subtract(b.toDouble()) - override operator fun Number.plus(b: DerivativeStructure): DerivativeStructure = b + this - override operator fun Number.minus(b: DerivativeStructure): DerivativeStructure = b - this + public override operator fun DerivativeStructure.plus(b: Number): DerivativeStructure = add(b.toDouble()) + public override operator fun DerivativeStructure.minus(b: Number): DerivativeStructure = subtract(b.toDouble()) + public override operator fun Number.plus(b: DerivativeStructure): DerivativeStructure = b + this + public override operator fun Number.minus(b: DerivativeStructure): DerivativeStructure = b - this } /** @@ -87,10 +84,10 @@ public class DerivativeStructureField( */ public class DiffExpression(public val function: DerivativeStructureField.() -> DerivativeStructure) : Expression { - override operator fun invoke(arguments: Map): Double = DerivativeStructureField( + public override operator fun invoke(arguments: Map): Double = DerivativeStructureField( 0, arguments - ).run(function).value + ).function().value /** * Get the derivative expression with given orders @@ -110,25 +107,22 @@ public fun DiffExpression.derivative(name: String): Expression = derivat * A context for [DiffExpression] (not to be confused with [DerivativeStructure]) */ public object DiffExpressionAlgebra : ExpressionAlgebra, Field { - override fun variable(name: String, default: Double?): DiffExpression = + public override val zero: DiffExpression = DiffExpression { 0.0.const() } + public override val one: DiffExpression = DiffExpression { 1.0.const() } + + public override fun variable(name: String, default: Double?): DiffExpression = DiffExpression { variable(name, default?.const()) } - override fun const(value: Double): DiffExpression = - DiffExpression { value.const() } + public override fun const(value: Double): DiffExpression = DiffExpression { value.const() } - override fun add(a: DiffExpression, b: DiffExpression): DiffExpression = + public override fun add(a: DiffExpression, b: DiffExpression): DiffExpression = DiffExpression { a.function(this) + b.function(this) } - override val zero: DiffExpression = DiffExpression { 0.0.const() } + public override fun multiply(a: DiffExpression, k: Number): DiffExpression = DiffExpression { a.function(this) * k } - override fun multiply(a: DiffExpression, k: Number): DiffExpression = - DiffExpression { a.function(this) * k } - - override val one: DiffExpression = DiffExpression { 1.0.const() } - - override fun multiply(a: DiffExpression, b: DiffExpression): DiffExpression = + public override fun multiply(a: DiffExpression, b: DiffExpression): DiffExpression = DiffExpression { a.function(this) * b.function(this) } - override fun divide(a: DiffExpression, b: DiffExpression): DiffExpression = + public override fun divide(a: DiffExpression, b: DiffExpression): DiffExpression = DiffExpression { a.function(this) / b.function(this) } } diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMMatrix.kt index f0bbdbe65..72288a85e 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMMatrix.kt @@ -5,32 +5,32 @@ import scientifik.kmath.linear.* import scientifik.kmath.structures.Matrix import scientifik.kmath.structures.NDStructure -class CMMatrix(val origin: RealMatrix, features: Set? = null) : +public class CMMatrix(public val origin: RealMatrix, features: Set? = null) : FeaturedMatrix { - override val rowNum: Int get() = origin.rowDimension - override val colNum: Int get() = origin.columnDimension + public override val rowNum: Int get() = origin.rowDimension + public override val colNum: Int get() = origin.columnDimension - override val features: Set = features ?: sequence { + public override val features: Set = features ?: sequence { if (origin is DiagonalMatrix) yield(DiagonalFeature) }.toHashSet() - override fun suggestFeature(vararg features: MatrixFeature): CMMatrix = + public override fun suggestFeature(vararg features: MatrixFeature): CMMatrix = CMMatrix(origin, this.features + features) - override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j) + public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j) - override fun equals(other: Any?): Boolean { + public override fun equals(other: Any?): Boolean { return NDStructure.equals(this, other as? NDStructure<*> ?: return false) } - override fun hashCode(): Int { + public override fun hashCode(): Int { var result = origin.hashCode() result = 31 * result + features.hashCode() return result } } -fun Matrix.toCM(): CMMatrix = if (this is CMMatrix) { +public fun Matrix.toCM(): CMMatrix = if (this is CMMatrix) { this } else { //TODO add feature analysis @@ -38,56 +38,56 @@ fun Matrix.toCM(): CMMatrix = if (this is CMMatrix) { CMMatrix(Array2DRowRealMatrix(array)) } -fun RealMatrix.asMatrix(): CMMatrix = CMMatrix(this) +public fun RealMatrix.asMatrix(): CMMatrix = CMMatrix(this) -class CMVector(val origin: RealVector) : Point { - override val size: Int get() = origin.dimension +public class CMVector(public val origin: RealVector) : Point { + public override val size: Int get() = origin.dimension - override operator fun get(index: Int): Double = origin.getEntry(index) + public override operator fun get(index: Int): Double = origin.getEntry(index) - override operator fun iterator(): Iterator = origin.toArray().iterator() + public override operator fun iterator(): Iterator = origin.toArray().iterator() } -fun Point.toCM(): CMVector = if (this is CMVector) this else { +public fun Point.toCM(): CMVector = if (this is CMVector) this else { val array = DoubleArray(size) { this[it] } CMVector(ArrayRealVector(array)) } -fun RealVector.toPoint(): CMVector = CMVector(this) +public fun RealVector.toPoint(): CMVector = CMVector(this) -object CMMatrixContext : MatrixContext { - override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): CMMatrix { +public object CMMatrixContext : MatrixContext { + public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): CMMatrix { val array = Array(rows) { i -> DoubleArray(columns) { j -> initializer(i, j) } } return CMMatrix(Array2DRowRealMatrix(array)) } - override fun Matrix.dot(other: Matrix): CMMatrix = - CMMatrix(this.toCM().origin.multiply(other.toCM().origin)) + public override fun Matrix.dot(other: Matrix): CMMatrix = + CMMatrix(toCM().origin.multiply(other.toCM().origin)) - override fun Matrix.dot(vector: Point): CMVector = - CMVector(this.toCM().origin.preMultiply(vector.toCM().origin)) + public override fun Matrix.dot(vector: Point): CMVector = + CMVector(toCM().origin.preMultiply(vector.toCM().origin)) - override operator fun Matrix.unaryMinus(): CMMatrix = + public override operator fun Matrix.unaryMinus(): CMMatrix = produce(rowNum, colNum) { i, j -> -get(i, j) } - override fun add(a: Matrix, b: Matrix): CMMatrix = + public override fun add(a: Matrix, b: Matrix): CMMatrix = CMMatrix(a.toCM().origin.multiply(b.toCM().origin)) - override operator fun Matrix.minus(b: Matrix): CMMatrix = - CMMatrix(this.toCM().origin.subtract(b.toCM().origin)) + public override operator fun Matrix.minus(b: Matrix): CMMatrix = + CMMatrix(toCM().origin.subtract(b.toCM().origin)) - override fun multiply(a: Matrix, k: Number): CMMatrix = + public override fun multiply(a: Matrix, k: Number): CMMatrix = CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble())) - override operator fun Matrix.times(value: Double): Matrix = + public override operator fun Matrix.times(value: Double): Matrix = produce(rowNum, colNum) { i, j -> get(i, j) * value } } -operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = - CMMatrix(this.origin.add(other.origin)) +public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = + CMMatrix(origin.add(other.origin)) -operator fun CMMatrix.minus(other: CMMatrix): CMMatrix = - CMMatrix(this.origin.subtract(other.origin)) +public operator fun CMMatrix.minus(other: CMMatrix): CMMatrix = + CMMatrix(origin.subtract(other.origin)) -infix fun CMMatrix.dot(other: CMMatrix): CMMatrix = - CMMatrix(this.origin.multiply(other.origin)) +public infix fun CMMatrix.dot(other: CMMatrix): CMMatrix = + CMMatrix(origin.multiply(other.origin)) diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMSolver.kt b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMSolver.kt index 77b688e31..1e79aff21 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMSolver.kt +++ b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMSolver.kt @@ -4,7 +4,7 @@ import org.apache.commons.math3.linear.* import scientifik.kmath.linear.Point import scientifik.kmath.structures.Matrix -enum class CMDecomposition { +public enum class CMDecomposition { LUP, QR, RRQR, @@ -12,29 +12,30 @@ enum class CMDecomposition { CHOLESKY } +public fun CMMatrixContext.solver( + a: Matrix, + decomposition: CMDecomposition = CMDecomposition.LUP +): DecompositionSolver = when (decomposition) { + CMDecomposition.LUP -> LUDecomposition(a.toCM().origin).solver + CMDecomposition.RRQR -> RRQRDecomposition(a.toCM().origin).solver + CMDecomposition.QR -> QRDecomposition(a.toCM().origin).solver + CMDecomposition.EIGEN -> EigenDecomposition(a.toCM().origin).solver + CMDecomposition.CHOLESKY -> CholeskyDecomposition(a.toCM().origin).solver +} -fun CMMatrixContext.solver(a: Matrix, decomposition: CMDecomposition = CMDecomposition.LUP) = - when (decomposition) { - CMDecomposition.LUP -> LUDecomposition(a.toCM().origin).solver - CMDecomposition.RRQR -> RRQRDecomposition(a.toCM().origin).solver - CMDecomposition.QR -> QRDecomposition(a.toCM().origin).solver - CMDecomposition.EIGEN -> EigenDecomposition(a.toCM().origin).solver - CMDecomposition.CHOLESKY -> CholeskyDecomposition(a.toCM().origin).solver - } - -fun CMMatrixContext.solve( +public fun CMMatrixContext.solve( a: Matrix, b: Matrix, decomposition: CMDecomposition = CMDecomposition.LUP -) = solver(a, decomposition).solve(b.toCM().origin).asMatrix() +): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).asMatrix() -fun CMMatrixContext.solve( +public fun CMMatrixContext.solve( a: Matrix, b: Point, decomposition: CMDecomposition = CMDecomposition.LUP -) = solver(a, decomposition).solve(b.toCM().origin).toPoint() +): CMVector = solver(a, decomposition).solve(b.toCM().origin).toPoint() -fun CMMatrixContext.inverse( +public fun CMMatrixContext.inverse( a: Matrix, decomposition: CMDecomposition = CMDecomposition.LUP -) = solver(a, decomposition).inverse.asMatrix() +): CMMatrix = solver(a, decomposition).inverse.asMatrix() diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/random/CMRandomGeneratorWrapper.kt index cb2b5dd9c..3e60d7cdd 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/random/CMRandomGeneratorWrapper.kt +++ b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/random/CMRandomGeneratorWrapper.kt @@ -2,32 +2,32 @@ package scientifik.kmath.commons.random import scientifik.kmath.prob.RandomGenerator -class CMRandomGeneratorWrapper(val factory: (IntArray) -> RandomGenerator) : +public class CMRandomGeneratorWrapper(public val factory: (IntArray) -> RandomGenerator) : org.apache.commons.math3.random.RandomGenerator { private var generator: RandomGenerator = factory(intArrayOf()) - override fun nextBoolean(): Boolean = generator.nextBoolean() - override fun nextFloat(): Float = generator.nextDouble().toFloat() + public override fun nextBoolean(): Boolean = generator.nextBoolean() + public override fun nextFloat(): Float = generator.nextDouble().toFloat() - override fun setSeed(seed: Int) { + public override fun setSeed(seed: Int) { generator = factory(intArrayOf(seed)) } - override fun setSeed(seed: IntArray) { + public override fun setSeed(seed: IntArray) { generator = factory(seed) } - override fun setSeed(seed: Long) { + public override fun setSeed(seed: Long) { setSeed(seed.toInt()) } - override fun nextBytes(bytes: ByteArray) { + public override fun nextBytes(bytes: ByteArray) { generator.fillBytes(bytes) } - override fun nextInt(): Int = generator.nextInt() - override fun nextInt(n: Int): Int = generator.nextInt(n) - override fun nextGaussian(): Double = TODO() - override fun nextDouble(): Double = generator.nextDouble() - override fun nextLong(): Long = generator.nextLong() + public override fun nextInt(): Int = generator.nextInt() + public override fun nextInt(n: Int): Int = generator.nextInt(n) + public override fun nextGaussian(): Double = TODO() + public override fun nextDouble(): Double = generator.nextDouble() + public override fun nextLong(): Long = generator.nextLong() } diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/transform/Transformations.kt index eb1b5b69a..4af0d2b72 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/transform/Transformations.kt +++ b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/transform/Transformations.kt @@ -13,8 +13,7 @@ import scientifik.kmath.structures.* /** * Streaming and buffer transformations */ -object Transformations { - +public object Transformations { private fun Buffer.toArray(): Array = Array(size) { org.apache.commons.math3.complex.Complex(get(it).re, get(it).im) } @@ -32,35 +31,35 @@ object Transformations { Complex(value.real, value.imaginary) } - fun fourier( + public fun fourier( normalization: DftNormalization = DftNormalization.STANDARD, direction: TransformType = TransformType.FORWARD ): SuspendBufferTransform = { FastFourierTransformer(normalization).transform(it.toArray(), direction).asBuffer() } - fun realFourier( + public fun realFourier( normalization: DftNormalization = DftNormalization.STANDARD, direction: TransformType = TransformType.FORWARD ): SuspendBufferTransform = { FastFourierTransformer(normalization).transform(it.asArray(), direction).asBuffer() } - fun sine( + public fun sine( normalization: DstNormalization = DstNormalization.STANDARD_DST_I, direction: TransformType = TransformType.FORWARD ): SuspendBufferTransform = { FastSineTransformer(normalization).transform(it.asArray(), direction).asBuffer() } - fun cosine( + public fun cosine( normalization: DctNormalization = DctNormalization.STANDARD_DCT_I, direction: TransformType = TransformType.FORWARD ): SuspendBufferTransform = { FastCosineTransformer(normalization).transform(it.asArray(), direction).asBuffer() } - fun hadamard( + public fun hadamard( direction: TransformType = TransformType.FORWARD ): SuspendBufferTransform = { FastHadamardTransformer().transform(it.asArray(), direction).asBuffer() @@ -71,7 +70,7 @@ object Transformations { * Process given [Flow] with commons-math fft transformation */ @FlowPreview -fun Flow>.FFT( +public fun Flow>.FFT( normalization: DftNormalization = DftNormalization.STANDARD, direction: TransformType = TransformType.FORWARD ): Flow> { @@ -81,7 +80,7 @@ fun Flow>.FFT( @FlowPreview @JvmName("realFFT") -fun Flow>.FFT( +public fun Flow>.FFT( normalization: DftNormalization = DftNormalization.STANDARD, direction: TransformType = TransformType.FORWARD ): Flow> { @@ -90,20 +89,18 @@ fun Flow>.FFT( } /** - * Process a continous flow of real numbers in FFT splitting it in chunks of [bufferSize]. + * Process a continuous flow of real numbers in FFT splitting it in chunks of [bufferSize]. */ @FlowPreview @JvmName("realFFT") -fun Flow.FFT( +public fun Flow.FFT( bufferSize: Int = Int.MAX_VALUE, normalization: DftNormalization = DftNormalization.STANDARD, direction: TransformType = TransformType.FORWARD -): Flow { - return chunked(bufferSize).FFT(normalization,direction).spread() -} +): Flow = chunked(bufferSize).FFT(normalization, direction).spread() /** * Map a complex flow into real flow by taking real part of each number */ @FlowPreview -fun Flow.real(): Flow = map{it.re} \ No newline at end of file +public fun Flow.real(): Flow = map { it.re } diff --git a/kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt b/kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt index bbdcff2fc..3d8a1d5f0 100644 --- a/kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt +++ b/kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt @@ -6,12 +6,16 @@ import kotlin.contracts.contract import kotlin.test.Test import kotlin.test.assertEquals -inline fun diff(order: Int, vararg parameters: Pair, block: DerivativeStructureField.() -> R): R { +internal inline fun diff( + order: Int, + vararg parameters: Pair, + block: DerivativeStructureField.() -> R +): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return DerivativeStructureField(order, mapOf(*parameters)).run(block) } -class AutoDiffTest { +internal class AutoDiffTest { @Test fun derivativeStructureFieldTest() { val res = diff(3, "x" to 1.0, "y" to 1.0) { @@ -33,4 +37,4 @@ class AutoDiffTest { assertEquals(10.0, f("x" to 1.0, "y" to 2.0)) assertEquals(6.0, f.derivative("x")("x" to 1.0, "y" to 2.0)) } -} \ No newline at end of file +} diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt index cbee88e38..fbb60026e 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt @@ -41,10 +41,10 @@ public class BigInt internal constructor( private val magnitude: Magnitude ) : Comparable { public override fun compareTo(other: BigInt): Int = when { - (this.sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0 - this.sign < other.sign -> -1 - this.sign > other.sign -> 1 - else -> this.sign * compareMagnitudes(this.magnitude, other.magnitude) + (sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0 + sign < other.sign -> -1 + sign > other.sign -> 1 + else -> sign * compareMagnitudes(magnitude, other.magnitude) } public override fun equals(other: Any?): Boolean = @@ -123,7 +123,7 @@ public class BigInt internal constructor( return Pair(BigInt((this.sign * other.sign).toByte(), q.magnitude), r) } - public operator fun div(other: BigInt): BigInt = this.division(other).first + public operator fun div(other: BigInt): BigInt = division(other).first public infix fun shl(i: Int): BigInt { if (this == ZERO) return ZERO @@ -132,16 +132,16 @@ public class BigInt internal constructor( val relShift = i % BASE_SIZE val shiftLeft = { x: UInt -> if (relShift >= 32) 0U else x shl relShift } val shiftRight = { x: UInt -> if (BASE_SIZE - relShift >= 32) 0U else x shr (BASE_SIZE - relShift) } - val newMagnitude = Magnitude(this.magnitude.size + fullShifts) + val newMagnitude = Magnitude(magnitude.size + fullShifts) - for (j in this.magnitude.indices) { + for (j in magnitude.indices) { newMagnitude[j + fullShifts - 1] = shiftLeft(this.magnitude[j]) if (j != 0) newMagnitude[j + fullShifts - 1] = newMagnitude[j + fullShifts - 1] or shiftRight(this.magnitude[j - 1]) } - newMagnitude[this.magnitude.size + fullShifts - 1] = shiftRight(this.magnitude.last()) + newMagnitude[magnitude.size + fullShifts - 1] = shiftRight(magnitude.last()) return BigInt(this.sign, stripLeadingZeros(newMagnitude)) } @@ -153,13 +153,13 @@ public class BigInt internal constructor( val shiftRight = { x: UInt -> if (relShift >= 32) 0U else x shr relShift } val shiftLeft = { x: UInt -> if (BASE_SIZE - relShift >= 32) 0U else x shl (BASE_SIZE - relShift) } if (this.magnitude.size - fullShifts <= 0) return ZERO - val newMagnitude: Magnitude = Magnitude(this.magnitude.size - fullShifts) + val newMagnitude: Magnitude = Magnitude(magnitude.size - fullShifts) - for (j in fullShifts until this.magnitude.size) { - newMagnitude[j - fullShifts] = shiftRight(this.magnitude[j]) + for (j in fullShifts until magnitude.size) { + newMagnitude[j - fullShifts] = shiftRight(magnitude[j]) - if (j != this.magnitude.size - 1) - newMagnitude[j - fullShifts] = newMagnitude[j - fullShifts] or shiftLeft(this.magnitude[j + 1]) + if (j != magnitude.size - 1) + newMagnitude[j - fullShifts] = newMagnitude[j - fullShifts] or shiftLeft(magnitude[j + 1]) } return BigInt(this.sign, stripLeadingZeros(newMagnitude)) @@ -168,11 +168,11 @@ public class BigInt internal constructor( public infix fun or(other: BigInt): BigInt { if (this == ZERO) return other if (other == ZERO) return this - val resSize = max(this.magnitude.size, other.magnitude.size) + val resSize = max(magnitude.size, other.magnitude.size) val newMagnitude: Magnitude = Magnitude(resSize) for (i in 0 until resSize) { - if (i < this.magnitude.size) newMagnitude[i] = newMagnitude[i] or this.magnitude[i] + if (i < magnitude.size) newMagnitude[i] = newMagnitude[i] or magnitude[i] if (i < other.magnitude.size) newMagnitude[i] = newMagnitude[i] or other.magnitude[i] } diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt index e899f8ece..bf79c1601 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt @@ -149,13 +149,16 @@ public fun Chain.collect(mapper: suspend (Chain) -> R): Chain = override fun fork(): Chain = this@collect.fork().collect(mapper) } -public fun Chain.collectWithState(state: S, stateFork: (S) -> S, mapper: suspend S.(Chain) -> R): Chain = - object : Chain { - override suspend fun next(): R = state.mapper(this@collectWithState) +public fun Chain.collectWithState( + state: S, + stateFork: (S) -> S, + mapper: suspend S.(Chain) -> R +): Chain = object : Chain { + override suspend fun next(): R = state.mapper(this@collectWithState) - override fun fork(): Chain = - this@collectWithState.fork().collectWithState(stateFork(state), stateFork, mapper) - } + override fun fork(): Chain = + this@collectWithState.fork().collectWithState(stateFork(state), stateFork, mapper) +} /** * Zip two chains together using given transformation diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt index ae1860974..991642787 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt @@ -49,10 +49,8 @@ public fun Flow.chunked(bufferSize: Int): Flow = flow { require(bufferSize > 0) { "Resulting chunk size must be more than zero" } if (this@chunked is BlockingRealChain) { - //performance optimization for blocking primitive chain - while (true) { - emit(nextBlock(bufferSize).asBuffer()) - } + // performance optimization for blocking primitive chain + while (true) emit(nextBlock(bufferSize).asBuffer()) } else { val array = DoubleArray(bufferSize) var counter = 0 @@ -60,6 +58,7 @@ public fun Flow.chunked(bufferSize: Int): Flow = flow { this@chunked.collect { element -> array[counter] = element counter++ + if (counter == bufferSize) { val buffer = RealBuffer(array) emit(buffer) diff --git a/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/chains/ChainExt.kt b/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/chains/ChainExt.kt index 5686b0ac0..c0df59645 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/chains/ChainExt.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/chains/ChainExt.kt @@ -5,13 +5,12 @@ import kotlinx.coroutines.runBlocking /** * Represent a chain as regular iterator (uses blocking calls) */ -operator fun Chain.iterator(): Iterator = object : Iterator { +public operator fun Chain.iterator(): Iterator = object : Iterator { override fun hasNext(): Boolean = true - override fun next(): R = runBlocking { next() } } /** * Represent a chain as a sequence */ -fun Chain.asSequence(): Sequence = Sequence { this@asSequence.iterator() } \ No newline at end of file +public fun Chain.asSequence(): Sequence = Sequence { this@asSequence.iterator() } diff --git a/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt b/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt index a607d2d85..82950159b 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt @@ -37,10 +37,10 @@ public class LazyNDStructure( } public fun NDStructure.deferred(index: IntArray): Deferred = - if (this is LazyNDStructure) this.deferred(index) else CompletableDeferred(get(index)) + if (this is LazyNDStructure) deferred(index) else CompletableDeferred(get(index)) public suspend fun NDStructure.await(index: IntArray): T = - if (this is LazyNDStructure) this.await(index) else get(index) + if (this is LazyNDStructure) await(index) else get(index) /** * PENDING would benefit from KEEP-176 diff --git a/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/BufferFlowTest.kt b/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/BufferFlowTest.kt index 427349072..d17e4d86b 100644 --- a/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/BufferFlowTest.kt +++ b/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/BufferFlowTest.kt @@ -14,7 +14,7 @@ import kotlin.test.Test @ExperimentalCoroutinesApi @InternalCoroutinesApi @FlowPreview -class BufferFlowTest { +internal class BufferFlowTest { val dispatcher: CoroutineDispatcher = Executors.newFixedThreadPool(4).asCoroutineDispatcher() @Test diff --git a/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/RingBufferTest.kt b/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/RingBufferTest.kt index c84ef89ef..630749861 100644 --- a/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/RingBufferTest.kt +++ b/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/RingBufferTest.kt @@ -6,7 +6,7 @@ import scientifik.kmath.structures.asSequence import kotlin.test.Test import kotlin.test.assertEquals -class RingBufferTest { +internal class RingBufferTest { @Test fun push() { val buffer = RingBuffer.build(20, Double.NaN) diff --git a/kmath-dimensions/src/commonTest/kotlin/scientifik/dimensions/DMatrixContextTest.kt b/kmath-dimensions/src/commonTest/kotlin/scientifik/dimensions/DMatrixContextTest.kt index 8dabdeeac..dc7acdcc2 100644 --- a/kmath-dimensions/src/commonTest/kotlin/scientifik/dimensions/DMatrixContextTest.kt +++ b/kmath-dimensions/src/commonTest/kotlin/scientifik/dimensions/DMatrixContextTest.kt @@ -5,7 +5,7 @@ import scientifik.kmath.dimensions.D3 import scientifik.kmath.dimensions.DMatrixContext import kotlin.test.Test -class DMatrixContextTest { +internal class DMatrixContextTest { @Test fun testDimensionSafeMatrix() { val res = with(DMatrixContext.real) { @@ -26,4 +26,4 @@ class DMatrixContextTest { m1.transpose() + m2 } } -} \ No newline at end of file +} diff --git a/kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt b/kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt index e5cc451d1..139f77e92 100644 --- a/kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt +++ b/kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt @@ -2,21 +2,17 @@ package scientifik.kmath.dimensions import kotlin.reflect.KClass -private val dimensionMap = hashMapOf( - 1u to D1, - 2u to D2, - 3u to D3 -) +private val dimensionMap: MutableMap = hashMapOf(1u to D1, 2u to D2, 3u to D3) @Suppress("UNCHECKED_CAST") -public actual fun Dimension.Companion.resolve(type: KClass): D { - return dimensionMap.entries.find { it.value::class == type }?.value as? D ?: error("Can't resolve dimension $type") -} +public actual fun Dimension.Companion.resolve(type: KClass): D = dimensionMap + .entries + .map(MutableMap.MutableEntry::value) + .find { it::class == type } as? D + ?: error("Can't resolve dimension $type") -public actual fun Dimension.Companion.of(dim: UInt): Dimension { - return dimensionMap.getOrPut(dim) { - object : Dimension { - override val dim: UInt get() = dim - } +public actual fun Dimension.Companion.of(dim: UInt): Dimension = dimensionMap.getOrPut(dim) { + object : Dimension { + override val dim: UInt get() = dim } -} \ No newline at end of file +} diff --git a/kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt b/kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt index 42310cb3a..714133ecb 100644 --- a/kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt +++ b/kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt @@ -2,17 +2,15 @@ package scientifik.kmath.dimensions import kotlin.reflect.KClass -public actual fun Dimension.Companion.resolve(type: KClass): D{ - return type.objectInstance ?: error("No object instance for dimension class") -} +public actual fun Dimension.Companion.resolve(type: KClass): D = + type.objectInstance ?: error("No object instance for dimension class") -public actual fun Dimension.Companion.of(dim: UInt): Dimension{ - return when(dim){ - 1u -> D1 - 2u -> D2 - 3u -> D3 - else -> object : Dimension { - override val dim: UInt get() = dim - } +public actual fun Dimension.Companion.of(dim: UInt): Dimension = when (dim) { + 1u -> D1 + 2u -> D2 + 3u -> D3 + + else -> object : Dimension { + override val dim: UInt get() = dim } } \ No newline at end of file diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt index 8c6d5fae4..474a701ca 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt @@ -14,11 +14,11 @@ import kotlin.math.sqrt public typealias RealPoint = Point -public fun DoubleArray.asVector(): RealVector = RealVector(this.asBuffer()) -public fun List.asVector(): RealVector = RealVector(this.asBuffer()) +public fun DoubleArray.asVector(): RealVector = RealVector(asBuffer()) +public fun List.asVector(): RealVector = RealVector(asBuffer()) public object VectorL2Norm : Norm, Double> { - override fun norm(arg: Point): Double = sqrt(arg.asIterable().sumByDouble { it.toDouble() }) + override fun norm(arg: Point): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble)) } public inline class RealVector(private val point: Point) : @@ -27,13 +27,9 @@ public inline class RealVector(private val point: Point) : public override val context: VectorSpace get() = space(point.size) public override fun unwrap(): RealPoint = point - public override fun RealPoint.wrap(): RealVector = RealVector(this) - - - override operator fun get(index: Int): Double = point[index] - - override operator fun iterator(): Iterator = point.iterator() + public override operator fun get(index: Int): Double = point[index] + public override operator fun iterator(): Iterator = point.iterator() public companion object { private val spaceCache: MutableMap> = hashMapOf() diff --git a/kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt index 8918fb300..baf1db8b5 100644 --- a/kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt @@ -8,7 +8,7 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue -class RealMatrixTest { +internal class RealMatrixTest { @Test fun testSum() { val m = realMatrix(10, 10) { i, j -> (i + j).toDouble() } diff --git a/kmath-for-real/src/commonTest/kotlin/scientifik/kmath/linear/VectorTest.kt b/kmath-for-real/src/commonTest/kotlin/scientifik/kmath/linear/VectorTest.kt index ef7f40afe..e24037953 100644 --- a/kmath-for-real/src/commonTest/kotlin/scientifik/kmath/linear/VectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/scientifik/kmath/linear/VectorTest.kt @@ -5,7 +5,7 @@ import scientifik.kmath.real.RealVector import kotlin.test.Test import kotlin.test.assertEquals -class VectorTest { +internal class VectorTest { @Test fun testSum() { val vector1 = RealVector(5) { it.toDouble() } diff --git a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean2DSpace.kt index f0dc49882..a5318b709 100644 --- a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean2DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean2DSpace.kt @@ -5,28 +5,28 @@ import scientifik.kmath.operations.SpaceElement import scientifik.kmath.operations.invoke import kotlin.math.sqrt +public interface Vector2D : Point, Vector, SpaceElement { + public val x: Double + public val y: Double + public override val context: Euclidean2DSpace get() = Euclidean2DSpace + public override val size: Int get() = 2 -interface Vector2D : Point, Vector, SpaceElement { - val x: Double - val y: Double - override val context: Euclidean2DSpace get() = Euclidean2DSpace - override val size: Int get() = 2 - - override operator fun get(index: Int): Double = when (index) { + public override operator fun get(index: Int): Double = when (index) { 1 -> x 2 -> y else -> error("Accessing outside of point bounds") } - override operator fun iterator(): Iterator = listOf(x, y).iterator() - override fun unwrap(): Vector2D = this - override fun Vector2D.wrap(): Vector2D = this + public override operator fun iterator(): Iterator = listOf(x, y).iterator() + public override fun unwrap(): Vector2D = this + public override fun Vector2D.wrap(): Vector2D = this } -val Vector2D.r: Double get() = Euclidean2DSpace { sqrt(norm()) } +public val Vector2D.r: Double + get() = Euclidean2DSpace { sqrt(norm()) } @Suppress("FunctionName") -fun Vector2D(x: Double, y: Double): Vector2D = Vector2DImpl(x, y) +public fun Vector2D(x: Double, y: Double): Vector2D = Vector2DImpl(x, y) private data class Vector2DImpl( override val x: Double, @@ -36,19 +36,12 @@ private data class Vector2DImpl( /** * 2D Euclidean space */ -object Euclidean2DSpace : GeometrySpace { - fun Vector2D.norm(): Double = sqrt(x * x + y * y) +public object Euclidean2DSpace : GeometrySpace { + public override val zero: Vector2D by lazy { Vector2D(0.0, 0.0) } - override fun Vector2D.distanceTo(other: Vector2D): Double = (this - other).norm() - - override fun add(a: Vector2D, b: Vector2D): Vector2D = - Vector2D(a.x + b.x, a.y + b.y) - - override fun multiply(a: Vector2D, k: Number): Vector2D = - Vector2D(a.x * k.toDouble(), a.y * k.toDouble()) - - override val zero: Vector2D = Vector2D(0.0, 0.0) - - override fun Vector2D.dot(other: Vector2D): Double = - x * other.x + y * other.y -} \ No newline at end of file + public fun Vector2D.norm(): Double = sqrt(x * x + y * y) + public override fun Vector2D.distanceTo(other: Vector2D): Double = (this - other).norm() + public override fun add(a: Vector2D, b: Vector2D): Vector2D = Vector2D(a.x + b.x, a.y + b.y) + public override fun multiply(a: Vector2D, k: Number): Vector2D = Vector2D(a.x * k.toDouble(), a.y * k.toDouble()) + public override fun Vector2D.dot(other: Vector2D): Double = x * other.x + y * other.y +} diff --git a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean3DSpace.kt index 3748e58c7..f695c0f64 100644 --- a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean3DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean3DSpace.kt @@ -5,32 +5,29 @@ import scientifik.kmath.operations.SpaceElement import scientifik.kmath.operations.invoke import kotlin.math.sqrt +public interface Vector3D : Point, Vector, SpaceElement { + 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 -interface Vector3D : Point, Vector, SpaceElement { - val x: Double - val y: Double - val z: Double - override val context: Euclidean3DSpace get() = Euclidean3DSpace - override val size: Int get() = 3 - - override operator fun get(index: Int): Double = when (index) { + public override operator fun get(index: Int): Double = when (index) { 1 -> x 2 -> y 3 -> z else -> error("Accessing outside of point bounds") } - override operator fun iterator(): Iterator = listOf(x, y, z).iterator() - - override fun unwrap(): Vector3D = this - - override fun Vector3D.wrap(): Vector3D = this + public override operator fun iterator(): Iterator = listOf(x, y, z).iterator() + public override fun unwrap(): Vector3D = this + public override fun Vector3D.wrap(): Vector3D = this } @Suppress("FunctionName") -fun Vector3D(x: Double, y: Double, z: Double): Vector3D = Vector3DImpl(x, y, z) +public fun Vector3D(x: Double, y: Double, z: Double): Vector3D = Vector3DImpl(x, y, z) -val Vector3D.r: Double get() = Euclidean3DSpace { sqrt(norm()) } +public val Vector3D.r: Double get() = Euclidean3DSpace { sqrt(norm()) } private data class Vector3DImpl( override val x: Double, @@ -38,19 +35,19 @@ private data class Vector3DImpl( override val z: Double ) : Vector3D -object Euclidean3DSpace : GeometrySpace { - override val zero: Vector3D = Vector3D(0.0, 0.0, 0.0) +public object Euclidean3DSpace : GeometrySpace { + public override val zero: Vector3D by lazy { Vector3D(0.0, 0.0, 0.0) } - fun Vector3D.norm(): Double = sqrt(x * x + y * y + z * z) + public fun Vector3D.norm(): Double = sqrt(x * x + y * y + z * z) - override fun Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm() + public override fun Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm() - override fun add(a: Vector3D, b: Vector3D): Vector3D = + public override fun add(a: Vector3D, b: Vector3D): Vector3D = Vector3D(a.x + b.x, a.y + b.y, a.z + b.z) - override fun multiply(a: Vector3D, k: Number): Vector3D = + public override fun multiply(a: Vector3D, k: Number): Vector3D = Vector3D(a.x * k.toDouble(), a.y * k.toDouble(), a.z * k.toDouble()) - override fun Vector3D.dot(other: Vector3D): Double = + public override fun Vector3D.dot(other: Vector3D): Double = x * other.x + y * other.y + z * other.z } diff --git a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/GeometrySpace.kt index b65a8dd3a..6798a6291 100644 --- a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/GeometrySpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/GeometrySpace.kt @@ -2,16 +2,16 @@ package scientifik.kmath.geometry import scientifik.kmath.operations.Space -interface Vector +public interface Vector -interface GeometrySpace: Space { +public interface GeometrySpace: Space { /** * L2 distance */ - fun V.distanceTo(other: V): Double + public fun V.distanceTo(other: V): Double /** * Scalar product */ - infix fun V.dot(other: V): Double + public infix fun V.dot(other: V): Double } \ No newline at end of file diff --git a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Line.kt b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Line.kt index d802a103f..a529f7f1b 100644 --- a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Line.kt +++ b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Line.kt @@ -1,6 +1,6 @@ package scientifik.kmath.geometry -data class Line(val base: V, val direction: V) +public data class Line(val base: V, val direction: V) -typealias Line2D = Line -typealias Line3D = Line +public typealias Line2D = Line +public typealias Line3D = Line diff --git a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/ReferenceFrame.kt b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/ReferenceFrame.kt index 420e38ce2..49bf3793c 100644 --- a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/ReferenceFrame.kt +++ b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/ReferenceFrame.kt @@ -1,4 +1,3 @@ package scientifik.kmath.geometry -interface ReferenceFrame { -} \ No newline at end of file +public interface ReferenceFrame diff --git a/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt b/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt index bd8fa782a..139b8cc8d 100644 --- a/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt +++ b/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt @@ -7,67 +7,64 @@ import scientifik.kmath.operations.invoke import scientifik.kmath.structures.Matrix import scientifik.kmath.structures.NDStructure -class KomaMatrixContext( +public class KomaMatrixContext( private val factory: MatrixFactory>, private val space: Space ) : MatrixContext { - - override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): KomaMatrix = + public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): KomaMatrix = KomaMatrix(factory.zeros(rows, columns).fill(initializer)) - fun Matrix.toKoma(): KomaMatrix = if (this is KomaMatrix) { + public fun Matrix.toKoma(): KomaMatrix = if (this is KomaMatrix) this - } else { + else produce(rowNum, colNum) { i, j -> get(i, j) } - } - fun Point.toKoma(): KomaVector = if (this is KomaVector) { + public fun Point.toKoma(): KomaVector = if (this is KomaVector) this - } else { + else KomaVector(factory.zeros(size, 1).fill { i, _ -> get(i) }) - } - - override fun Matrix.dot(other: Matrix): KomaMatrix = + public override fun Matrix.dot(other: Matrix): KomaMatrix = KomaMatrix(toKoma().origin * other.toKoma().origin) - override fun Matrix.dot(vector: Point): KomaVector = + public override fun Matrix.dot(vector: Point): KomaVector = KomaVector(toKoma().origin * vector.toKoma().origin) - override operator fun Matrix.unaryMinus(): KomaMatrix = + public override operator fun Matrix.unaryMinus(): KomaMatrix = KomaMatrix(toKoma().origin.unaryMinus()) - override fun add(a: Matrix, b: Matrix): KomaMatrix = + public override fun add(a: Matrix, b: Matrix): KomaMatrix = KomaMatrix(a.toKoma().origin + b.toKoma().origin) - override operator fun Matrix.minus(b: Matrix): KomaMatrix = + public override operator fun Matrix.minus(b: Matrix): KomaMatrix = KomaMatrix(toKoma().origin - b.toKoma().origin) - override fun multiply(a: Matrix, k: Number): Matrix = + public override fun multiply(a: Matrix, k: Number): Matrix = produce(a.rowNum, a.colNum) { i, j -> space { a[i, j] * k } } - override operator fun Matrix.times(value: T): KomaMatrix = + public override operator fun Matrix.times(value: T): KomaMatrix = KomaMatrix(toKoma().origin * value) - companion object + public companion object } -fun KomaMatrixContext.solve(a: Matrix, b: Matrix) = +public fun KomaMatrixContext.solve(a: Matrix, b: Matrix): KomaMatrix = KomaMatrix(a.toKoma().origin.solve(b.toKoma().origin)) -fun KomaMatrixContext.solve(a: Matrix, b: Point) = +public fun KomaMatrixContext.solve(a: Matrix, b: Point): KomaVector = KomaVector(a.toKoma().origin.solve(b.toKoma().origin)) -fun KomaMatrixContext.inverse(a: Matrix) = +public fun KomaMatrixContext.inverse(a: Matrix): KomaMatrix = KomaMatrix(a.toKoma().origin.inv()) -class KomaMatrix(val origin: koma.matrix.Matrix, features: Set? = null) : FeaturedMatrix { - override val rowNum: Int get() = origin.numRows() - override val colNum: Int get() = origin.numCols() +public class KomaMatrix(public val origin: koma.matrix.Matrix, features: Set? = null) : + FeaturedMatrix { + public override val rowNum: Int get() = origin.numRows() + public override val colNum: Int get() = origin.numCols() - override val shape: IntArray get() = intArrayOf(origin.numRows(), origin.numCols()) + public override val shape: IntArray get() = intArrayOf(origin.numRows(), origin.numCols()) - override val features: Set = features ?: hashSetOf( + public override val features: Set = features ?: hashSetOf( object : DeterminantFeature { override val determinant: T get() = origin.det() }, @@ -94,11 +91,9 @@ class KomaMatrix(val origin: koma.matrix.Matrix, features: Set internal constructor(val origin: koma.matrix.Matrix) : Point { +public class KomaVector internal constructor(public val origin: koma.matrix.Matrix) : Point { override val size: Int get() = origin.numRows() init { diff --git a/kmath-prob/build.gradle.kts b/kmath-prob/build.gradle.kts index 4c9663e5f..795a8760e 100644 --- a/kmath-prob/build.gradle.kts +++ b/kmath-prob/build.gradle.kts @@ -13,4 +13,8 @@ kotlin.sourceSets { api("org.apache.commons:commons-rng-simple:1.3") } } + + jvmTest { + languageSettings.useExperimentalAnnotation("kotlinx.coroutines.FlowPreview") + } } diff --git a/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/CommonsDistributionsTest.kt b/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/CommonsDistributionsTest.kt index 7638c695e..0680083ce 100644 --- a/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/CommonsDistributionsTest.kt +++ b/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/CommonsDistributionsTest.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test -class CommonsDistributionsTest { +internal class CommonsDistributionsTest { @Test fun testNormalDistributionSuspend() { val distribution = Distribution.normal(7.0, 2.0) @@ -24,5 +24,4 @@ class CommonsDistributionsTest { val sample = distribution.sample(generator).nextBlock(1000) Assertions.assertEquals(7.0, sample.average(), 0.1) } - -} \ No newline at end of file +} diff --git a/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/StatisticTest.kt b/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/StatisticTest.kt index 2613f71d5..30789a004 100644 --- a/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/StatisticTest.kt +++ b/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/StatisticTest.kt @@ -7,12 +7,14 @@ import kotlinx.coroutines.runBlocking import scientifik.kmath.streaming.chunked import kotlin.test.Test -class StatisticTest { +internal class StatisticTest { //create a random number generator. val generator = RandomGenerator.default(1) + //Create a stateless chain from generator. val data = generator.chain { nextDouble() } - //Convert a chaint to Flow and break it into chunks. + + //Convert a chain to Flow and break it into chunks. val chunked = data.chunked(1000) @Test @@ -22,7 +24,8 @@ class StatisticTest { .flow(chunked) //create a flow with results .drop(99) // Skip first 99 values and use one with total data .first() //get 1e5 data samples average + println(average) } } -} \ No newline at end of file +} diff --git a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt b/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt index 84e927721..64f2da4c1 100644 --- a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt +++ b/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt @@ -5,82 +5,84 @@ import scientifik.kmath.operations.RealField import scientifik.kmath.structures.DefaultStrides import scientifik.kmath.structures.MutableNDStructure import scientifik.kmath.structures.NDField +import scientifik.kmath.structures.Strides @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -inline class ViktorNDStructure(val f64Buffer: F64Array) : MutableNDStructure { +public inline class ViktorNDStructure(public val f64Buffer: F64Array) : MutableNDStructure { + public override val shape: IntArray get() = f64Buffer.shape - override val shape: IntArray get() = f64Buffer.shape + public override inline fun get(index: IntArray): Double = f64Buffer.get(*index) - override inline fun get(index: IntArray): Double = f64Buffer.get(*index) - - override inline fun set(index: IntArray, value: Double) { + public override inline fun set(index: IntArray, value: Double) { f64Buffer.set(*index, value = value) } - override fun elements(): Sequence> { - return DefaultStrides(shape).indices().map { it to get(it) } - } + public override fun elements(): Sequence> = + DefaultStrides(shape).indices().map { it to get(it) } } -fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this) +public fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this) @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -class ViktorNDField(override val shape: IntArray) : NDField { - override val zero: ViktorNDStructure +public class ViktorNDField(public override val shape: IntArray) : NDField { + public override val zero: ViktorNDStructure get() = F64Array.full(init = 0.0, shape = *shape).asStructure() - override val one: ViktorNDStructure + + public override val one: ViktorNDStructure get() = F64Array.full(init = 1.0, shape = *shape).asStructure() - val strides = DefaultStrides(shape) + public val strides: Strides = DefaultStrides(shape) - override val elementContext: RealField get() = RealField + public override val elementContext: RealField get() = RealField - override fun produce(initializer: RealField.(IntArray) -> Double): ViktorNDStructure = F64Array(*shape).apply { - this@ViktorNDField.strides.indices().forEach { index -> - set(value = RealField.initializer(index), indices = *index) - } - }.asStructure() - - override fun map(arg: ViktorNDStructure, transform: RealField.(Double) -> Double): ViktorNDStructure = + public override fun produce(initializer: RealField.(IntArray) -> Double): ViktorNDStructure = F64Array(*shape).apply { this@ViktorNDField.strides.indices().forEach { index -> - set(value = RealField.transform(arg[index]), indices = *index) + set(value = RealField.initializer(index), indices = index) } }.asStructure() - override fun mapIndexed( + public override fun map(arg: ViktorNDStructure, transform: RealField.(Double) -> Double): ViktorNDStructure = + F64Array(*shape).apply { + this@ViktorNDField.strides.indices().forEach { index -> + set(value = RealField.transform(arg[index]), indices = index) + } + }.asStructure() + + public override fun mapIndexed( arg: ViktorNDStructure, transform: RealField.(index: IntArray, Double) -> Double ): ViktorNDStructure = F64Array(*shape).apply { this@ViktorNDField.strides.indices().forEach { index -> - set(value = RealField.transform(index, arg[index]), indices = *index) + set(value = RealField.transform(index, arg[index]), indices = index) } }.asStructure() - override fun combine( + public override fun combine( a: ViktorNDStructure, b: ViktorNDStructure, transform: RealField.(Double, Double) -> Double ): ViktorNDStructure = F64Array(*shape).apply { this@ViktorNDField.strides.indices().forEach { index -> - set(value = RealField.transform(a[index], b[index]), indices = *index) + set(value = RealField.transform(a[index], b[index]), indices = index) } }.asStructure() - override fun add(a: ViktorNDStructure, b: ViktorNDStructure): ViktorNDStructure { - return (a.f64Buffer + b.f64Buffer).asStructure() - } + public override fun add(a: ViktorNDStructure, b: ViktorNDStructure): ViktorNDStructure = + (a.f64Buffer + b.f64Buffer).asStructure() - override fun multiply(a: ViktorNDStructure, k: Number): ViktorNDStructure = + public override fun multiply(a: ViktorNDStructure, k: Number): ViktorNDStructure = (a.f64Buffer * k.toDouble()).asStructure() - override inline fun ViktorNDStructure.plus(b: ViktorNDStructure): ViktorNDStructure = + public override inline fun ViktorNDStructure.plus(b: ViktorNDStructure): ViktorNDStructure = (f64Buffer + b.f64Buffer).asStructure() - override inline fun ViktorNDStructure.minus(b: ViktorNDStructure): ViktorNDStructure = + public override inline fun ViktorNDStructure.minus(b: ViktorNDStructure): ViktorNDStructure = (f64Buffer - b.f64Buffer).asStructure() - override inline fun ViktorNDStructure.times(k: Number): ViktorNDStructure = (f64Buffer * k.toDouble()).asStructure() + public override inline fun ViktorNDStructure.times(k: Number): ViktorNDStructure = + (f64Buffer * k.toDouble()).asStructure() - override inline fun ViktorNDStructure.plus(arg: Double): ViktorNDStructure = (f64Buffer.plus(arg)).asStructure() + public override inline fun ViktorNDStructure.plus(arg: Double): ViktorNDStructure = + (f64Buffer.plus(arg)).asStructure() } \ No newline at end of file From fc5ec8fed74b0a4f27d212a9e78e61d6cd9794bb Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 9 Sep 2020 22:31:54 +0700 Subject: [PATCH 029/199] Drop koma support, add more explicit visibility modifiers --- README.md | 3 - doc/features.md | 3 - examples/build.gradle.kts | 3 - .../kmath/structures/ArrayBenchmark.kt | 29 ++-- .../ast/ExpressionsInterpretersBenchmark.kt | 140 +++++++++--------- .../kmath/linear/LinearAlgebraBenchmark.kt | 55 ------- .../kmath/linear/MultiplicationBenchmark.kt | 49 ------ kmath-commons/build.gradle.kts | 2 +- .../kotlin/scientifik/kmath/chains/Chain.kt | 25 ++-- .../scientifik/kmath/functions/functions.kt | 2 +- .../scientifik/kmath/histogram/Histogram.kt | 1 - .../kmath/histogram/UnivariateHistogram.kt | 4 +- kmath-koma/build.gradle.kts | 30 ---- .../scientifik.kmath.linear/KomaMatrix.kt | 105 ------------- .../scientifik/kmath/prob/Distribution.kt | 2 +- .../kmath/prob/FactorizedDistribution.kt | 30 ++-- .../scientifik/kmath/prob/RandomChain.kt | 7 +- .../scientifik/kmath/prob/RandomGenerator.kt | 55 +++---- .../scientifik/kmath/prob/SamplerAlgebra.kt | 17 +-- .../kotlin/scientifik/kmath/prob/Statistic.kt | 44 +++--- .../kmath/prob/UniformDistribution.kt | 34 ++--- .../scientifik/kmath/prob/distributions.kt | 12 +- settings.gradle.kts | 4 +- 23 files changed, 182 insertions(+), 474 deletions(-) delete mode 100644 examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt delete mode 100644 examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt delete mode 100644 kmath-koma/build.gradle.kts delete mode 100644 kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt diff --git a/README.md b/README.md index 24a7d7a4a..08d1e988a 100644 --- a/README.md +++ b/README.md @@ -54,9 +54,6 @@ can be used for a wide variety of purposes from high performance calculations to library in Kotlin code and maybe rewrite some parts to better suit the Kotlin programming paradigm, however there is no fixed roadmap for that. Feel free to submit a feature request if you want something to be done first. -* **Koma wrapper** [Koma](https://github.com/kyonifer/koma) is a well established numerics library in Kotlin, specifically linear algebra. -The plan is to have wrappers for koma implementations for compatibility with kmath API. - ## Planned features * **Messaging** A mathematical notation to support multi-language and multi-node communication for mathematical tasks. diff --git a/doc/features.md b/doc/features.md index e6a820c1e..0f2c4203f 100644 --- a/doc/features.md +++ b/doc/features.md @@ -12,6 +12,3 @@ api and multiple library back-ends. * [Expressions](./expressions.md) * Commons math integration - -* Koma integration - diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 2c51574e5..40da41d2b 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -10,7 +10,6 @@ plugins { allOpen.annotation("org.openjdk.jmh.annotations.State") repositories { - maven("http://dl.bintray.com/kyonifer/maven") maven("https://dl.bintray.com/mipt-npm/scientifik") maven("https://dl.bintray.com/mipt-npm/dev") maven("https://dl.bintray.com/kotlin/kotlin-dev/") @@ -25,10 +24,8 @@ dependencies { implementation(project(":kmath-coroutines")) implementation(project(":kmath-commons")) implementation(project(":kmath-prob")) - implementation(project(":kmath-koma")) implementation(project(":kmath-viktor")) implementation(project(":kmath-dimensions")) - implementation("com.kyonifer:koma-core-ejml:0.12") implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6") implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20") "benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath diff --git a/examples/src/benchmarks/kotlin/scientifik/kmath/structures/ArrayBenchmark.kt b/examples/src/benchmarks/kotlin/scientifik/kmath/structures/ArrayBenchmark.kt index d605e1b9c..2ccb27871 100644 --- a/examples/src/benchmarks/kotlin/scientifik/kmath/structures/ArrayBenchmark.kt +++ b/examples/src/benchmarks/kotlin/scientifik/kmath/structures/ArrayBenchmark.kt @@ -5,44 +5,33 @@ import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State import java.nio.IntBuffer - @State(Scope.Benchmark) class ArrayBenchmark { - @Benchmark fun benchmarkArrayRead() { var res = 0 - for (i in 1..size) { - res += array[size - i] - } + for (i in 1..size) res += array[size - i] } @Benchmark fun benchmarkBufferRead() { var res = 0 - for (i in 1..size) { - res += arrayBuffer.get(size - i) - } + for (i in 1..size) res += arrayBuffer.get(size - i) } @Benchmark fun nativeBufferRead() { var res = 0 - for (i in 1..size) { - res += nativeBuffer.get(size - i) - } + for (i in 1..size) res += nativeBuffer.get(size - i) } companion object { - val size = 1000 - - val array = IntArray(size) { it } - val arrayBuffer = IntBuffer.wrap(array) - val nativeBuffer = IntBuffer.allocate(size).also { - for (i in 0 until size) { - it.put(i, i) - } + const val size: Int = 1000 + val array: IntArray = IntArray(size) { it } + val arrayBuffer: IntBuffer = IntBuffer.wrap(array) + val nativeBuffer: IntBuffer = IntBuffer.allocate(size).also { + for (i in 0 until size) it.put(i, i) } } -} \ No newline at end of file +} diff --git a/examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt index 17a70a4aa..80e70d149 100644 --- a/examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt @@ -1,70 +1,70 @@ -package scientifik.kmath.ast - -import scientifik.kmath.asm.compile -import scientifik.kmath.expressions.Expression -import scientifik.kmath.expressions.expressionInField -import scientifik.kmath.expressions.invoke -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.RealField -import kotlin.random.Random -import kotlin.system.measureTimeMillis - -class ExpressionsInterpretersBenchmark { - private val algebra: Field = RealField - fun functionalExpression() { - val expr = algebra.expressionInField { - variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0) - } - - invokeAndSum(expr) - } - - fun mstExpression() { - val expr = algebra.mstInField { - symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) - } - - invokeAndSum(expr) - } - - fun asmExpression() { - val expr = algebra.mstInField { - symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) - }.compile() - - invokeAndSum(expr) - } - - private fun invokeAndSum(expr: Expression) { - val random = Random(0) - var sum = 0.0 - - repeat(1000000) { - sum += expr("x" to random.nextDouble()) - } - - println(sum) - } -} - -fun main() { - val benchmark = ExpressionsInterpretersBenchmark() - - val fe = measureTimeMillis { - benchmark.functionalExpression() - } - - println("fe=$fe") - - val mst = measureTimeMillis { - benchmark.mstExpression() - } - - println("mst=$mst") - - val asm = measureTimeMillis { - benchmark.asmExpression() - } - - println("asm=$asm") -} +//package scientifik.kmath.ast +// +//import scientifik.kmath.asm.compile +//import scientifik.kmath.expressions.Expression +//import scientifik.kmath.expressions.expressionInField +//import scientifik.kmath.expressions.invoke +//import scientifik.kmath.operations.Field +//import scientifik.kmath.operations.RealField +//import kotlin.random.Random +//import kotlin.system.measureTimeMillis +// +//class ExpressionsInterpretersBenchmark { +// private val algebra: Field = RealField +// fun functionalExpression() { +// val expr = algebra.expressionInField { +// variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0) +// } +// +// invokeAndSum(expr) +// } +// +// fun mstExpression() { +// val expr = algebra.mstInField { +// symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) +// } +// +// invokeAndSum(expr) +// } +// +// fun asmExpression() { +// val expr = algebra.mstInField { +// symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) +// }.compile() +// +// invokeAndSum(expr) +// } +// +// private fun invokeAndSum(expr: Expression) { +// val random = Random(0) +// var sum = 0.0 +// +// repeat(1000000) { +// sum += expr("x" to random.nextDouble()) +// } +// +// println(sum) +// } +//} +// +//fun main() { +// val benchmark = ExpressionsInterpretersBenchmark() +// +// val fe = measureTimeMillis { +// benchmark.functionalExpression() +// } +// +// println("fe=$fe") +// +// val mst = measureTimeMillis { +// benchmark.mstExpression() +// } +// +// println("mst=$mst") +// +// val asm = measureTimeMillis { +// benchmark.asmExpression() +// } +// +// println("asm=$asm") +//} diff --git a/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt deleted file mode 100644 index 6cc5411b8..000000000 --- a/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt +++ /dev/null @@ -1,55 +0,0 @@ -package scientifik.kmath.linear - -import koma.matrix.ejml.EJMLMatrixFactory -import scientifik.kmath.commons.linear.CMMatrixContext -import scientifik.kmath.commons.linear.inverse -import scientifik.kmath.commons.linear.toCM -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.invoke -import scientifik.kmath.structures.Matrix -import kotlin.contracts.ExperimentalContracts -import kotlin.random.Random -import kotlin.system.measureTimeMillis - -@ExperimentalContracts -fun main() { - val random = Random(1224) - val dim = 100 - //creating invertible matrix - val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } - val l = Matrix.real(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 } - val matrix = l dot u - - val n = 5000 // iterations - - MatrixContext.real { - repeat(50) { val res = inverse(matrix) } - val inverseTime = measureTimeMillis { repeat(n) { val res = inverse(matrix) } } - println("[kmath] Inversion of $n matrices $dim x $dim finished in $inverseTime millis") - } - - //commons-math - - val commonsTime = measureTimeMillis { - CMMatrixContext { - val cm = matrix.toCM() //avoid overhead on conversion - repeat(n) { val res = inverse(cm) } - } - } - - - println("[commons-math] Inversion of $n matrices $dim x $dim finished in $commonsTime millis") - - //koma-ejml - - val komaTime = measureTimeMillis { - (KomaMatrixContext(EJMLMatrixFactory(), RealField)) { - val km = matrix.toKoma() //avoid overhead on conversion - repeat(n) { - val res = inverse(km) - } - } - } - - println("[koma-ejml] Inversion of $n matrices $dim x $dim finished in $komaTime millis") -} \ No newline at end of file diff --git a/examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt deleted file mode 100644 index 3ae550682..000000000 --- a/examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt +++ /dev/null @@ -1,49 +0,0 @@ -package scientifik.kmath.linear - -import koma.matrix.ejml.EJMLMatrixFactory -import scientifik.kmath.commons.linear.CMMatrixContext -import scientifik.kmath.commons.linear.toCM -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.invoke -import scientifik.kmath.structures.Matrix -import kotlin.random.Random -import kotlin.system.measureTimeMillis - -fun main() { - val random = Random(12224) - val dim = 1000 - //creating invertible matrix - 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 } - -// //warmup -// matrix1 dot matrix2 - - CMMatrixContext { - val cmMatrix1 = matrix1.toCM() - val cmMatrix2 = matrix2.toCM() - - val cmTime = measureTimeMillis { - cmMatrix1 dot cmMatrix2 - } - - println("CM implementation time: $cmTime") - } - - (KomaMatrixContext(EJMLMatrixFactory(), RealField)) { - val komaMatrix1 = matrix1.toKoma() - val komaMatrix2 = matrix2.toKoma() - - val komaTime = measureTimeMillis { - komaMatrix1 dot komaMatrix2 - } - - println("Koma-ejml implementation time: $komaTime") - } - - val genericTime = measureTimeMillis { - val res = matrix1 dot matrix2 - } - - println("Generic implementation time: $genericTime") -} \ No newline at end of file diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 45eee7765..b64b855a4 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -5,6 +5,6 @@ dependencies { api(project(":kmath-core")) api(project(":kmath-coroutines")) api(project(":kmath-prob")) - api(project(":kmath-functions")) +// api(project(":kmath-functions")) api("org.apache.commons:commons-math3:3.6.1") } diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt index bf79c1601..e27290fbb 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt @@ -43,7 +43,6 @@ public interface Chain : Flow { public companion object } - public fun Iterator.asChain(): Chain = SimpleChain { next() } public fun Sequence.asChain(): Chain = iterator().asChain() @@ -51,22 +50,20 @@ public fun Sequence.asChain(): Chain = iterator().asChain() * A simple chain of independent tokens */ public class SimpleChain(private val gen: suspend () -> R) : Chain { - override suspend fun next(): R = gen() - override fun fork(): Chain = this + public override suspend fun next(): R = gen() + public override fun fork(): Chain = this } /** * A stateless Markov chain */ public class MarkovChain(private val seed: suspend () -> R, private val gen: suspend (R) -> R) : Chain { - - private val mutex = Mutex() - + private val mutex: Mutex = Mutex() private var value: R? = null public fun value(): R? = value - override suspend fun next(): R { + public override suspend fun next(): R { mutex.withLock { val newValue = gen(value ?: seed()) value = newValue @@ -74,9 +71,7 @@ public class MarkovChain(private val seed: suspend () -> R, private } } - override fun fork(): Chain { - return MarkovChain(seed = { value ?: seed() }, gen = gen) - } + public override fun fork(): Chain = MarkovChain(seed = { value ?: seed() }, gen = gen) } /** @@ -91,12 +86,11 @@ public class StatefulChain( private val gen: suspend S.(R) -> R ) : Chain { private val mutex: Mutex = Mutex() - private var value: R? = null public fun value(): R? = value - override suspend fun next(): R { + public override suspend fun next(): R { mutex.withLock { val newValue = state.gen(value ?: state.seed()) value = newValue @@ -104,16 +98,15 @@ public class StatefulChain( } } - override fun fork(): Chain = StatefulChain(forkState(state), seed, forkState, gen) + public override fun fork(): Chain = StatefulChain(forkState(state), seed, forkState, gen) } /** * A chain that repeats the same value */ public class ConstantChain(public val value: T) : Chain { - override suspend fun next(): T = value - - override fun fork(): Chain = this + public override suspend fun next(): T = value + public override fun fork(): Chain = this } /** diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt index 7b26fd221..2b6073e07 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt @@ -24,7 +24,7 @@ public interface SuspendableMathFunction, R> { public suspend operator fun C.invoke(arg: T): R } -public suspend fun SuspendableMathFunction.invoke(arg: Double) = RealField.invoke(arg) +public suspend fun SuspendableMathFunction.invoke(arg: Double): R = RealField.invoke(arg) /** * A parametric function with parameter diff --git a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt index 0acef2fb7..530dee4f2 100644 --- a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt @@ -29,7 +29,6 @@ public interface Histogram> : Iterable { * Dimension of the histogram */ public val dimension: Int - } public interface MutableHistogram> : Histogram { diff --git a/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt index 24c30bf4c..add01d82c 100644 --- a/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt @@ -44,7 +44,7 @@ public class UnivariateHistogram private constructor(private val factory: (Doubl } private fun createBin(value: Double): UnivariateBin = factory(value).also { - synchronized(this) { bins.put(it.position, it) } + synchronized(this) { bins[it.position] = it } } public override operator fun get(point: Buffer): UnivariateBin? = get(point[0]) @@ -87,7 +87,7 @@ public class UnivariateHistogram private constructor(private val factory: (Doubl ) else -> { - val index = (0 until sorted.size).first { value > sorted[it] } + val index = sorted.indices.first { value > sorted[it] } val left = sorted[index] val right = sorted[index + 1] UnivariateBin((left + right) / 2, (right - left)) diff --git a/kmath-koma/build.gradle.kts b/kmath-koma/build.gradle.kts deleted file mode 100644 index 606113e75..000000000 --- a/kmath-koma/build.gradle.kts +++ /dev/null @@ -1,30 +0,0 @@ -plugins { id("ru.mipt.npm.mpp") } - -repositories.maven("http://dl.bintray.com/kyonifer/maven") - -kotlin.sourceSets { - commonMain { - dependencies { - api(project(":kmath-core")) - api("com.kyonifer:koma-core-api-common:0.12") - } - } - - jvmMain { - dependencies { - api("com.kyonifer:koma-core-api-jvm:0.12") - } - } - - jvmTest { - dependencies { - implementation("com.kyonifer:koma-core-ejml:0.12") - } - } - - jsMain { - dependencies { - api("com.kyonifer:koma-core-api-js:0.12") - } - } -} diff --git a/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt b/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt deleted file mode 100644 index 139b8cc8d..000000000 --- a/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt +++ /dev/null @@ -1,105 +0,0 @@ -package scientifik.kmath.linear - -import koma.extensions.fill -import koma.matrix.MatrixFactory -import scientifik.kmath.operations.Space -import scientifik.kmath.operations.invoke -import scientifik.kmath.structures.Matrix -import scientifik.kmath.structures.NDStructure - -public class KomaMatrixContext( - private val factory: MatrixFactory>, - private val space: Space -) : MatrixContext { - public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): KomaMatrix = - KomaMatrix(factory.zeros(rows, columns).fill(initializer)) - - public fun Matrix.toKoma(): KomaMatrix = if (this is KomaMatrix) - this - else - produce(rowNum, colNum) { i, j -> get(i, j) } - - public fun Point.toKoma(): KomaVector = if (this is KomaVector) - this - else - KomaVector(factory.zeros(size, 1).fill { i, _ -> get(i) }) - - public override fun Matrix.dot(other: Matrix): KomaMatrix = - KomaMatrix(toKoma().origin * other.toKoma().origin) - - public override fun Matrix.dot(vector: Point): KomaVector = - KomaVector(toKoma().origin * vector.toKoma().origin) - - public override operator fun Matrix.unaryMinus(): KomaMatrix = - KomaMatrix(toKoma().origin.unaryMinus()) - - public override fun add(a: Matrix, b: Matrix): KomaMatrix = - KomaMatrix(a.toKoma().origin + b.toKoma().origin) - - public override operator fun Matrix.minus(b: Matrix): KomaMatrix = - KomaMatrix(toKoma().origin - b.toKoma().origin) - - public override fun multiply(a: Matrix, k: Number): Matrix = - produce(a.rowNum, a.colNum) { i, j -> space { a[i, j] * k } } - - public override operator fun Matrix.times(value: T): KomaMatrix = - KomaMatrix(toKoma().origin * value) - - public companion object -} - -public fun KomaMatrixContext.solve(a: Matrix, b: Matrix): KomaMatrix = - KomaMatrix(a.toKoma().origin.solve(b.toKoma().origin)) - -public fun KomaMatrixContext.solve(a: Matrix, b: Point): KomaVector = - KomaVector(a.toKoma().origin.solve(b.toKoma().origin)) - -public fun KomaMatrixContext.inverse(a: Matrix): KomaMatrix = - KomaMatrix(a.toKoma().origin.inv()) - -public class KomaMatrix(public val origin: koma.matrix.Matrix, features: Set? = null) : - FeaturedMatrix { - public override val rowNum: Int get() = origin.numRows() - public override val colNum: Int get() = origin.numCols() - - public override val shape: IntArray get() = intArrayOf(origin.numRows(), origin.numCols()) - - public override val features: Set = features ?: hashSetOf( - object : DeterminantFeature { - override val determinant: T get() = origin.det() - }, - - object : LUPDecompositionFeature { - private val lup by lazy { origin.LU() } - override val l: FeaturedMatrix get() = KomaMatrix(lup.second) - override val u: FeaturedMatrix get() = KomaMatrix(lup.third) - override val p: FeaturedMatrix get() = KomaMatrix(lup.first) - } - ) - - override fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix = - KomaMatrix(this.origin, this.features + features) - - override operator fun get(i: Int, j: Int): T = origin.getGeneric(i, j) - - override fun equals(other: Any?): Boolean { - return NDStructure.equals(this, other as? NDStructure<*> ?: return false) - } - - override fun hashCode(): Int { - var result = origin.hashCode() - result = 31 * result + features.hashCode() - return result - } -} - -public class KomaVector internal constructor(public val origin: koma.matrix.Matrix) : Point { - override val size: Int get() = origin.numRows() - - init { - require(origin.numCols() == 1) { error("Only single column matrices are allowed") } - } - - override operator fun get(index: Int): T = origin.getGeneric(index) - override operator fun iterator(): Iterator = origin.toIterable().iterator() -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt index e1f0e8d6e..3c4d0420f 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt @@ -73,5 +73,5 @@ public fun Sampler.sampleBuffer( /** * Generate a bunch of samples from real distributions */ -public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int) = +public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int): Chain> = sampleBuffer(generator, size, Buffer.Companion::real) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt index ea526c058..05b62deb8 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt @@ -6,42 +6,38 @@ import scientifik.kmath.chains.SimpleChain /** * A multivariate distribution which takes a map of parameters */ -interface NamedDistribution : Distribution> +public interface NamedDistribution : Distribution> /** * A multivariate distribution that has independent distributions for separate axis */ -class FactorizedDistribution(val distributions: Collection>) : NamedDistribution { - - override fun probability(arg: Map): Double { - return distributions.fold(1.0) { acc, distr -> acc * distr.probability(arg) } - } +public class FactorizedDistribution(public val distributions: Collection>) : + NamedDistribution { + override fun probability(arg: Map): Double = + distributions.fold(1.0) { acc, distr -> acc * distr.probability(arg) } override fun sample(generator: RandomGenerator): Chain> { val chains = distributions.map { it.sample(generator) } - return SimpleChain> { - chains.fold(emptyMap()) { acc, chain -> acc + chain.next() } - } + return SimpleChain { chains.fold(emptyMap()) { acc, chain -> acc + chain.next() } } } } -class NamedDistributionWrapper(val name: String, val distribution: Distribution) : NamedDistribution { +public class NamedDistributionWrapper(public val name: String, public val distribution: Distribution) : + NamedDistribution { override fun probability(arg: Map): Double = distribution.probability( arg[name] ?: error("Argument with name $name not found in input parameters") ) override fun sample(generator: RandomGenerator): Chain> { val chain = distribution.sample(generator) - return SimpleChain { - mapOf(name to chain.next()) - } + return SimpleChain { mapOf(name to chain.next()) } } } -class DistributionBuilder{ +public class DistributionBuilder { private val distributions = ArrayList>() - infix fun String.to(distribution: Distribution){ - distributions.add(NamedDistributionWrapper(this,distribution)) + public infix fun String.to(distribution: Distribution) { + distributions.add(NamedDistributionWrapper(this, distribution)) } -} \ No newline at end of file +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt index 49163c701..4fc7fe241 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt @@ -5,10 +5,13 @@ import scientifik.kmath.chains.Chain /** * A possibly stateful chain producing random values. */ -class RandomChain(val generator: RandomGenerator, private val gen: suspend RandomGenerator.() -> R) : Chain { +public class RandomChain( + public val generator: RandomGenerator, + private val gen: suspend RandomGenerator.() -> R +) : Chain { override suspend fun next(): R = generator.gen() override fun fork(): Chain = RandomChain(generator.fork(), gen) } -fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) +public fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt index 2a225fe47..ecf9beeb1 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt @@ -5,17 +5,15 @@ import kotlin.random.Random /** * A basic generator */ -interface RandomGenerator { - fun nextBoolean(): Boolean - - fun nextDouble(): Double - fun nextInt(): Int - fun nextInt(until: Int): Int - fun nextLong(): Long - fun nextLong(until: Long): Long - - fun fillBytes(array: ByteArray, fromIndex: Int = 0, toIndex: Int = array.size) - fun nextBytes(size: Int): ByteArray = ByteArray(size).also { fillBytes(it) } +public interface RandomGenerator { + public fun nextBoolean(): Boolean + public fun nextDouble(): Double + public fun nextInt(): Int + public fun nextInt(until: Int): Int + public fun nextLong(): Long + public fun nextLong(until: Long): Long + public fun fillBytes(array: ByteArray, fromIndex: Int = 0, toIndex: Int = array.size) + public fun nextBytes(size: Int): ByteArray = ByteArray(size).also { fillBytes(it) } /** * Create a new generator which is independent from current generator (operations on new generator do not affect this one @@ -24,32 +22,27 @@ interface RandomGenerator { * * The thread safety of this operation is not guaranteed since it could affect the state of the generator. */ - fun fork(): RandomGenerator + public fun fork(): RandomGenerator - companion object { - val default by lazy { DefaultGenerator() } + public companion object { + public val default: DefaultGenerator by lazy { DefaultGenerator() } - fun default(seed: Long) = DefaultGenerator(Random(seed)) + public fun default(seed: Long): DefaultGenerator = DefaultGenerator(Random(seed)) } } -inline class DefaultGenerator(val random: Random = Random) : RandomGenerator { - override fun nextBoolean(): Boolean = random.nextBoolean() +public inline class DefaultGenerator(public val random: Random = Random) : RandomGenerator { + public override fun nextBoolean(): Boolean = random.nextBoolean() + public override fun nextDouble(): Double = random.nextDouble() + public override fun nextInt(): Int = random.nextInt() + public override fun nextInt(until: Int): Int = random.nextInt(until) + public override fun nextLong(): Long = random.nextLong() + public override fun nextLong(until: Long): Long = random.nextLong(until) - override fun nextDouble(): Double = random.nextDouble() - - override fun nextInt(): Int = random.nextInt() - override fun nextInt(until: Int): Int = random.nextInt(until) - - override fun nextLong(): Long = random.nextLong() - - override fun nextLong(until: Long): Long = random.nextLong(until) - - override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) { + public override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) { random.nextBytes(array, fromIndex, toIndex) } - override fun nextBytes(size: Int): ByteArray = random.nextBytes(size) - - override fun fork(): RandomGenerator = RandomGenerator.default(random.nextLong()) -} \ No newline at end of file + public override fun nextBytes(size: Int): ByteArray = random.nextBytes(size) + public override fun fork(): RandomGenerator = RandomGenerator.default(random.nextLong()) +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/SamplerAlgebra.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/SamplerAlgebra.kt index 02f98439e..184665928 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/SamplerAlgebra.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/SamplerAlgebra.kt @@ -7,26 +7,25 @@ import scientifik.kmath.chains.zip import scientifik.kmath.operations.Space import scientifik.kmath.operations.invoke -class BasicSampler(val chainBuilder: (RandomGenerator) -> Chain) : Sampler { - override fun sample(generator: RandomGenerator): Chain = chainBuilder(generator) +public class BasicSampler(public val chainBuilder: (RandomGenerator) -> Chain) : Sampler { + public override fun sample(generator: RandomGenerator): Chain = chainBuilder(generator) } -class ConstantSampler(val value: T) : Sampler { - override fun sample(generator: RandomGenerator): Chain = ConstantChain(value) +public class ConstantSampler(public val value: T) : Sampler { + public override fun sample(generator: RandomGenerator): Chain = ConstantChain(value) } /** * A space for samplers. Allows to perform simple operations on distributions */ -class SamplerSpace(val space: Space) : Space> { +public class SamplerSpace(public val space: Space) : Space> { + public override val zero: Sampler = ConstantSampler(space.zero) - override val zero: Sampler = ConstantSampler(space.zero) - - override fun add(a: Sampler, b: Sampler): Sampler = BasicSampler { generator -> + public override fun add(a: Sampler, b: Sampler): Sampler = BasicSampler { generator -> a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> space { aValue + bValue } } } - override fun multiply(a: Sampler, k: Number): Sampler = BasicSampler { generator -> + public override fun multiply(a: Sampler, k: Number): Sampler = BasicSampler { generator -> a.sample(generator).map { space { it * k.toDouble() } } } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Statistic.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Statistic.kt index c82d262bf..7811b88f6 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Statistic.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Statistic.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.scanReduce +import kotlinx.coroutines.flow.runningReduce import scientifik.kmath.coroutines.mapParallel import scientifik.kmath.operations.* import scientifik.kmath.structures.Buffer @@ -16,8 +16,8 @@ import scientifik.kmath.structures.asSequence /** * A function, that transforms a buffer of random quantities to some resulting value */ -interface Statistic { - suspend operator fun invoke(data: Buffer): R +public interface Statistic { + public suspend operator fun invoke(data: Buffer): R } /** @@ -26,17 +26,17 @@ interface Statistic { * @param I - intermediate block type * @param R - result type */ -interface ComposableStatistic : Statistic { +public interface ComposableStatistic : Statistic { //compute statistic on a single block - suspend fun computeIntermediate(data: Buffer): I + public suspend fun computeIntermediate(data: Buffer): I //Compose two blocks - suspend fun composeIntermediate(first: I, second: I): I + public suspend fun composeIntermediate(first: I, second: I): I //Transform block to result - suspend fun toResult(intermediate: I): R + public suspend fun toResult(intermediate: I): R - override suspend fun invoke(data: Buffer): R = toResult(computeIntermediate(data)) + public override suspend fun invoke(data: Buffer): R = toResult(computeIntermediate(data)) } @FlowPreview @@ -46,7 +46,7 @@ private fun ComposableStatistic.flowIntermediate( dispatcher: CoroutineDispatcher = Dispatchers.Default ): Flow = flow .mapParallel(dispatcher) { computeIntermediate(it) } - .scanReduce(::composeIntermediate) + .runningReduce(::composeIntermediate) /** @@ -57,7 +57,7 @@ private fun ComposableStatistic.flowIntermediate( */ @FlowPreview @ExperimentalCoroutinesApi -fun ComposableStatistic.flow( +public fun ComposableStatistic.flow( flow: Flow>, dispatcher: CoroutineDispatcher = Dispatchers.Default ): Flow = flowIntermediate(flow, dispatcher).map(::toResult) @@ -65,32 +65,32 @@ fun ComposableStatistic.flow( /** * Arithmetic mean */ -class Mean(val space: Space) : ComposableStatistic, T> { - override suspend fun computeIntermediate(data: Buffer): Pair = +public class Mean(public val space: Space) : ComposableStatistic, T> { + public override suspend fun computeIntermediate(data: Buffer): Pair = space { sum(data.asIterable()) } to data.size - override suspend fun composeIntermediate(first: Pair, second: Pair): Pair = + public override suspend fun composeIntermediate(first: Pair, second: Pair): Pair = space { first.first + second.first } to (first.second + second.second) - override suspend fun toResult(intermediate: Pair): T = + public override suspend fun toResult(intermediate: Pair): T = space { intermediate.first / intermediate.second } - companion object { + public companion object { //TODO replace with optimized version which respects overflow - val real: Mean = Mean(RealField) - val int: Mean = Mean(IntRing) - val long: Mean = Mean(LongRing) + public val real: Mean = Mean(RealField) + public val int: Mean = Mean(IntRing) + public val long: Mean = Mean(LongRing) } } /** * Non-composable median */ -class Median(private val comparator: Comparator) : Statistic { - override suspend fun invoke(data: Buffer): T = +public class Median(private val comparator: Comparator) : Statistic { + public override suspend fun invoke(data: Buffer): T = data.asSequence().sortedWith(comparator).toList()[data.size / 2] //TODO check if this is correct - companion object { - val real: Median = Median(Comparator { a: Double, b: Double -> a.compareTo(b) }) + public companion object { + public val real: Median = Median { a: Double, b: Double -> a.compareTo(b) } } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/UniformDistribution.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/UniformDistribution.kt index 9d96bff59..10445219d 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/UniformDistribution.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/UniformDistribution.kt @@ -3,32 +3,20 @@ package scientifik.kmath.prob import scientifik.kmath.chains.Chain import scientifik.kmath.chains.SimpleChain -class UniformDistribution(val range: ClosedFloatingPointRange) : UnivariateDistribution { +public class UniformDistribution(public val range: ClosedFloatingPointRange) : UnivariateDistribution { + private val length: Double = range.endInclusive - range.start - private val length = range.endInclusive - range.start + override fun probability(arg: Double): Double = if (arg in range) 1.0 / length else 0.0 - override fun probability(arg: Double): Double { - return if (arg in range) { - return 1.0 / length - } else { - 0.0 - } - } + override fun sample(generator: RandomGenerator): Chain = + SimpleChain { range.start + generator.nextDouble() * length } - override fun sample(generator: RandomGenerator): Chain { - return SimpleChain { - range.start + generator.nextDouble() * length - } - } - - override fun cumulative(arg: Double): Double { - return when { - arg < range.start -> 0.0 - arg >= range.endInclusive -> 1.0 - else -> (arg - range.start) / length - } + override fun cumulative(arg: Double): Double = when { + arg < range.start -> 0.0 + arg >= range.endInclusive -> 1.0 + else -> (arg - range.start) / length } } -fun Distribution.Companion.uniform(range: ClosedFloatingPointRange): UniformDistribution = - UniformDistribution(range) \ No newline at end of file +public fun Distribution.Companion.uniform(range: ClosedFloatingPointRange): UniformDistribution = + UniformDistribution(range) diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt index b3a37ada1..923317ed2 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt +++ b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt @@ -15,8 +15,8 @@ public abstract class ContinuousSamplerDistribution : Distribution { private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingRealChain() { private val sampler = buildCMSampler(generator) - public override fun nextDouble(): Double = sampler.sample() - public override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) + override fun nextDouble(): Double = sampler.sample() + override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) } protected abstract fun buildCMSampler(generator: RandomGenerator): ContinuousSampler @@ -28,8 +28,8 @@ public abstract class DiscreteSamplerDistribution : Distribution { private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingIntChain() { private val sampler = buildSampler(generator) - public override fun nextInt(): Int = sampler.sample() - public override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) + override fun nextInt(): Int = sampler.sample() + override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) } protected abstract fun buildSampler(generator: RandomGenerator): DiscreteSampler @@ -58,9 +58,7 @@ public fun Distribution.Companion.normal( return normalSampler(method, provider) } - override fun probability(arg: Double): Double { - return exp(-arg.pow(2) / 2) / sqrt(PI * 2) - } + override fun probability(arg: Double): Double = exp(-arg.pow(2) / 2) / sqrt(PI * 2) } public fun Distribution.Companion.normal( diff --git a/settings.gradle.kts b/settings.gradle.kts index 53e3ece3c..2e40b2abc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,14 +26,12 @@ rootProject.name = "kmath" include( ":kmath-memory", ":kmath-core", - ":kmath-functions", +// ":kmath-functions", ":kmath-coroutines", ":kmath-histograms", ":kmath-commons", ":kmath-viktor", - ":kmath-koma", ":kmath-prob", - ":kmath-io", ":kmath-dimensions", ":kmath-for-real", ":kmath-geometry", From d1184802bd811d379cf68be9041268194aaa90e1 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 9 Sep 2020 23:42:43 +0700 Subject: [PATCH 030/199] Drop koma module, implement kmath-ejml module copying it, but for EJML SimpleMatrix --- README.md | 3 - doc/features.md | 3 - examples/build.gradle.kts | 3 +- .../kmath/linear/LinearAlgebraBenchmark.kt | 25 ++-- .../kmath/linear/MultiplicationBenchmark.kt | 29 ++--- kmath-ejml/build.gradle.kts | 6 + .../scientifik/kmath/ejml/EjmlMatrix.kt | 69 +++++++++++ .../kmath/ejml/EjmlMatrixContext.kt | 75 ++++++++++++ .../scientifik/kmath/ejml/EjmlVector.kt | 30 +++++ kmath-koma/build.gradle.kts | 31 ----- .../scientifik.kmath.linear/KomaMatrix.kt | 110 ------------------ settings.gradle.kts | 4 +- 12 files changed, 203 insertions(+), 185 deletions(-) create mode 100644 kmath-ejml/build.gradle.kts create mode 100644 kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt create mode 100644 kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt create mode 100644 kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt delete mode 100644 kmath-koma/build.gradle.kts delete mode 100644 kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt diff --git a/README.md b/README.md index 24a7d7a4a..6bfbc717a 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,6 @@ can be used for a wide variety of purposes from high performance calculations to * **Commons-math wrapper** It is planned to gradually wrap most parts of [Apache commons-math](http://commons.apache.org/proper/commons-math/) library in Kotlin code and maybe rewrite some parts to better suit the Kotlin programming paradigm, however there is no fixed roadmap for that. Feel free to submit a feature request if you want something to be done first. - -* **Koma wrapper** [Koma](https://github.com/kyonifer/koma) is a well established numerics library in Kotlin, specifically linear algebra. -The plan is to have wrappers for koma implementations for compatibility with kmath API. ## Planned features diff --git a/doc/features.md b/doc/features.md index e6a820c1e..0f2c4203f 100644 --- a/doc/features.md +++ b/doc/features.md @@ -12,6 +12,3 @@ api and multiple library back-ends. * [Expressions](./expressions.md) * Commons math integration - -* Koma integration - diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index f5a4d5831..519c72615 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -29,10 +29,9 @@ dependencies { implementation(project(":kmath-coroutines")) implementation(project(":kmath-commons")) implementation(project(":kmath-prob")) - implementation(project(":kmath-koma")) implementation(project(":kmath-viktor")) implementation(project(":kmath-dimensions")) - implementation("com.kyonifer:koma-core-ejml:0.12") + implementation(project(":kmath-ejml")) implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6") implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-8") "benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath diff --git a/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt index 6cc5411b8..9b6d3e585 100644 --- a/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt +++ b/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt @@ -1,9 +1,10 @@ package scientifik.kmath.linear -import koma.matrix.ejml.EJMLMatrixFactory import scientifik.kmath.commons.linear.CMMatrixContext import scientifik.kmath.commons.linear.inverse import scientifik.kmath.commons.linear.toCM +import scientifik.kmath.ejml.EjmlMatrixContext +import scientifik.kmath.ejml.inverse import scientifik.kmath.operations.RealField import scientifik.kmath.operations.invoke import scientifik.kmath.structures.Matrix @@ -23,8 +24,8 @@ fun main() { val n = 5000 // iterations MatrixContext.real { - repeat(50) { val res = inverse(matrix) } - val inverseTime = measureTimeMillis { repeat(n) { val res = inverse(matrix) } } + repeat(50) { inverse(matrix) } + val inverseTime = measureTimeMillis { repeat(n) { inverse(matrix) } } println("[kmath] Inversion of $n matrices $dim x $dim finished in $inverseTime millis") } @@ -33,23 +34,19 @@ fun main() { val commonsTime = measureTimeMillis { CMMatrixContext { val cm = matrix.toCM() //avoid overhead on conversion - repeat(n) { val res = inverse(cm) } + repeat(n) { inverse(cm) } } } println("[commons-math] Inversion of $n matrices $dim x $dim finished in $commonsTime millis") - //koma-ejml - - val komaTime = measureTimeMillis { - (KomaMatrixContext(EJMLMatrixFactory(), RealField)) { - val km = matrix.toKoma() //avoid overhead on conversion - repeat(n) { - val res = inverse(km) - } + val ejmlTime = measureTimeMillis { + (EjmlMatrixContext(RealField)) { + val km = matrix.toEjml() //avoid overhead on conversion + repeat(n) { inverse(km) } } } - println("[koma-ejml] Inversion of $n matrices $dim x $dim finished in $komaTime millis") -} \ No newline at end of file + println("[ejml] Inversion of $n matrices $dim x $dim finished in $ejmlTime millis") +} diff --git a/examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt index 3ae550682..6e3f786ea 100644 --- a/examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt +++ b/examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt @@ -1,8 +1,8 @@ package scientifik.kmath.linear -import koma.matrix.ejml.EJMLMatrixFactory import scientifik.kmath.commons.linear.CMMatrixContext import scientifik.kmath.commons.linear.toCM +import scientifik.kmath.ejml.EjmlMatrixContext import scientifik.kmath.operations.RealField import scientifik.kmath.operations.invoke import scientifik.kmath.structures.Matrix @@ -22,28 +22,17 @@ fun main() { CMMatrixContext { val cmMatrix1 = matrix1.toCM() val cmMatrix2 = matrix2.toCM() - - val cmTime = measureTimeMillis { - cmMatrix1 dot cmMatrix2 - } - + val cmTime = measureTimeMillis { cmMatrix1 dot cmMatrix2 } println("CM implementation time: $cmTime") } - (KomaMatrixContext(EJMLMatrixFactory(), RealField)) { - val komaMatrix1 = matrix1.toKoma() - val komaMatrix2 = matrix2.toKoma() - - val komaTime = measureTimeMillis { - komaMatrix1 dot komaMatrix2 - } - - println("Koma-ejml implementation time: $komaTime") - } - - val genericTime = measureTimeMillis { - val res = matrix1 dot matrix2 + (EjmlMatrixContext(RealField)) { + val ejmlMatrix1 = matrix1.toEjml() + val ejmlMatrix2 = matrix2.toEjml() + val ejmlTime = measureTimeMillis { ejmlMatrix1 dot ejmlMatrix2 } + println("EJML implementation time: $ejmlTime") } + val genericTime = measureTimeMillis { val res = matrix1 dot matrix2 } println("Generic implementation time: $genericTime") -} \ No newline at end of file +} diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts new file mode 100644 index 000000000..cfc52af5d --- /dev/null +++ b/kmath-ejml/build.gradle.kts @@ -0,0 +1,6 @@ +plugins { id("scientifik.jvm") } + +dependencies { + implementation("org.ejml:ejml-simple:0.39") + implementation(project(":kmath-core")) +} diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt new file mode 100644 index 000000000..a53856af0 --- /dev/null +++ b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt @@ -0,0 +1,69 @@ +package scientifik.kmath.ejml + +import org.ejml.dense.row.factory.DecompositionFactory_DDRM +import org.ejml.simple.SimpleMatrix +import scientifik.kmath.linear.DeterminantFeature +import scientifik.kmath.linear.FeaturedMatrix +import scientifik.kmath.linear.LUPDecompositionFeature +import scientifik.kmath.linear.MatrixFeature +import scientifik.kmath.structures.NDStructure + +/** + * Represents featured matrix over EJML [SimpleMatrix]. + * + * @property origin the underlying [SimpleMatrix]. + */ +class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) : FeaturedMatrix { + override val rowNum: Int + get() = origin.numRows() + + override val colNum: Int + get() = origin.numCols() + + override val shape: IntArray + get() = intArrayOf(origin.numRows(), origin.numCols()) + + override val features: Set = features ?: hashSetOf( + object : DeterminantFeature { + override val determinant: Double + get() = origin.determinant() + }, + + object : LUPDecompositionFeature { + private val lup by lazy { + val ludecompositionF64 = DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()) + .also { it.decompose(origin.ddrm.copy()) } + + Triple( + EjmlMatrix(SimpleMatrix(ludecompositionF64.getRowPivot(null))), + EjmlMatrix(SimpleMatrix(ludecompositionF64.getLower(null))), + EjmlMatrix(SimpleMatrix(ludecompositionF64.getUpper(null))) + ) + } + + override val l: FeaturedMatrix + get() = lup.second + + override val u: FeaturedMatrix + get() = lup.third + + override val p: FeaturedMatrix + get() = lup.first + } + ) + + override fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix = + EjmlMatrix(origin, this.features + features) + + override operator fun get(i: Int, j: Int): Double = origin[i, j] + + override fun equals(other: Any?): Boolean { + return NDStructure.equals(this, other as? NDStructure<*> ?: return false) + } + + override fun hashCode(): Int { + var result = origin.hashCode() + result = 31 * result + features.hashCode() + return result + } +} diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt new file mode 100644 index 000000000..142f1bee3 --- /dev/null +++ b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt @@ -0,0 +1,75 @@ +package scientifik.kmath.ejml + +import org.ejml.simple.SimpleMatrix +import scientifik.kmath.linear.MatrixContext +import scientifik.kmath.linear.Point +import scientifik.kmath.operations.Space +import scientifik.kmath.operations.invoke +import scientifik.kmath.structures.Matrix + +/** + * Represents context of basic operations operating with [EjmlMatrix]. + */ +class EjmlMatrixContext(private val space: Space) : MatrixContext { + override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): EjmlMatrix = + EjmlMatrix(SimpleMatrix(rows, columns).also { + (0 until it.numRows()).forEach { row -> + (0 until it.numCols()).forEach { col -> it[row, col] = initializer(row, col) } + } + }) + + fun Matrix.toEjml(): EjmlMatrix = + if (this is EjmlMatrix) this else produce(rowNum, colNum) { i, j -> get(i, j) } + + fun Point.toEjml(): EjmlVector = + if (this is EjmlVector) this else EjmlVector(SimpleMatrix(size, 1).also { + (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) } + }) + + override fun Matrix.dot(other: Matrix): EjmlMatrix = + EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) + + override fun Matrix.dot(vector: Point): EjmlVector = + EjmlVector(toEjml().origin.mult(vector.toEjml().origin)) + + override fun add(a: Matrix, b: Matrix): EjmlMatrix = + EjmlMatrix(a.toEjml().origin + b.toEjml().origin) + + override operator fun Matrix.minus(b: Matrix): EjmlMatrix = + EjmlMatrix(toEjml().origin - b.toEjml().origin) + + override fun multiply(a: Matrix, k: Number): Matrix = + produce(a.rowNum, a.colNum) { i, j -> space { a[i, j] * k } } + + override operator fun Matrix.times(value: Double): EjmlMatrix = EjmlMatrix(toEjml().origin.scale(value)) + + companion object +} + +/** + * Solves for X in the following equation: x = a^-1*b, where 'a' is base matrix and 'b' is an n by p matrix. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for 'x' that is n by p. + */ +fun EjmlMatrixContext.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, where 'a' is base matrix and 'b' is an n by p matrix. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for 'x' that is n by p. + */ +fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = + EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) + +/** + * Returns the inverse of given matrix: b = a^(-1). + * + * @param a the matrix. + * @return the inverse of this matrix. + */ +fun EjmlMatrixContext.inverse(a: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.invert()) diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt new file mode 100644 index 000000000..ab9d4e87c --- /dev/null +++ b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt @@ -0,0 +1,30 @@ +package scientifik.kmath.ejml + +import org.ejml.simple.SimpleMatrix +import scientifik.kmath.linear.Point + +/** + * Represents point over EJML [SimpleMatrix]. + * + * @property origin the underlying [SimpleMatrix]. + */ +class EjmlVector internal constructor(val origin: SimpleMatrix) : Point { + override val size: Int get() = origin.numRows() + + init { + require(origin.numCols() == 1) { error("Only single column matrices are allowed") } + } + + override operator fun get(index: Int): Double = origin[index] + + override operator fun iterator(): Iterator = object : Iterator { + private var cursor: Int = 0 + + override fun next(): Double { + cursor += 1 + return origin[cursor - 1] + } + + override fun hasNext(): Boolean = cursor < origin.numCols() * origin.numRows() + } +} diff --git a/kmath-koma/build.gradle.kts b/kmath-koma/build.gradle.kts deleted file mode 100644 index 26955bca7..000000000 --- a/kmath-koma/build.gradle.kts +++ /dev/null @@ -1,31 +0,0 @@ -plugins { - id("scientifik.mpp") -} - -repositories { - maven("http://dl.bintray.com/kyonifer/maven") -} - -kotlin.sourceSets { - commonMain { - dependencies { - api(project(":kmath-core")) - api("com.kyonifer:koma-core-api-common:0.12") - } - } - jvmMain { - dependencies { - api("com.kyonifer:koma-core-api-jvm:0.12") - } - } - jvmTest { - dependencies { - implementation("com.kyonifer:koma-core-ejml:0.12") - } - } - jsMain { - dependencies { - api("com.kyonifer:koma-core-api-js:0.12") - } - } -} diff --git a/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt b/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt deleted file mode 100644 index bd8fa782a..000000000 --- a/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt +++ /dev/null @@ -1,110 +0,0 @@ -package scientifik.kmath.linear - -import koma.extensions.fill -import koma.matrix.MatrixFactory -import scientifik.kmath.operations.Space -import scientifik.kmath.operations.invoke -import scientifik.kmath.structures.Matrix -import scientifik.kmath.structures.NDStructure - -class KomaMatrixContext( - private val factory: MatrixFactory>, - private val space: Space -) : MatrixContext { - - override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): KomaMatrix = - KomaMatrix(factory.zeros(rows, columns).fill(initializer)) - - fun Matrix.toKoma(): KomaMatrix = if (this is KomaMatrix) { - this - } else { - produce(rowNum, colNum) { i, j -> get(i, j) } - } - - fun Point.toKoma(): KomaVector = if (this is KomaVector) { - this - } else { - KomaVector(factory.zeros(size, 1).fill { i, _ -> get(i) }) - } - - - override fun Matrix.dot(other: Matrix): KomaMatrix = - KomaMatrix(toKoma().origin * other.toKoma().origin) - - override fun Matrix.dot(vector: Point): KomaVector = - KomaVector(toKoma().origin * vector.toKoma().origin) - - override operator fun Matrix.unaryMinus(): KomaMatrix = - KomaMatrix(toKoma().origin.unaryMinus()) - - override fun add(a: Matrix, b: Matrix): KomaMatrix = - KomaMatrix(a.toKoma().origin + b.toKoma().origin) - - override operator fun Matrix.minus(b: Matrix): KomaMatrix = - KomaMatrix(toKoma().origin - b.toKoma().origin) - - override fun multiply(a: Matrix, k: Number): Matrix = - produce(a.rowNum, a.colNum) { i, j -> space { a[i, j] * k } } - - override operator fun Matrix.times(value: T): KomaMatrix = - KomaMatrix(toKoma().origin * value) - - companion object -} - -fun KomaMatrixContext.solve(a: Matrix, b: Matrix) = - KomaMatrix(a.toKoma().origin.solve(b.toKoma().origin)) - -fun KomaMatrixContext.solve(a: Matrix, b: Point) = - KomaVector(a.toKoma().origin.solve(b.toKoma().origin)) - -fun KomaMatrixContext.inverse(a: Matrix) = - KomaMatrix(a.toKoma().origin.inv()) - -class KomaMatrix(val origin: koma.matrix.Matrix, features: Set? = null) : FeaturedMatrix { - override val rowNum: Int get() = origin.numRows() - override val colNum: Int get() = origin.numCols() - - override val shape: IntArray get() = intArrayOf(origin.numRows(), origin.numCols()) - - override val features: Set = features ?: hashSetOf( - object : DeterminantFeature { - override val determinant: T get() = origin.det() - }, - - object : LUPDecompositionFeature { - private val lup by lazy { origin.LU() } - override val l: FeaturedMatrix get() = KomaMatrix(lup.second) - override val u: FeaturedMatrix get() = KomaMatrix(lup.third) - override val p: FeaturedMatrix get() = KomaMatrix(lup.first) - } - ) - - override fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix = - KomaMatrix(this.origin, this.features + features) - - override operator fun get(i: Int, j: Int): T = origin.getGeneric(i, j) - - override fun equals(other: Any?): Boolean { - return NDStructure.equals(this, other as? NDStructure<*> ?: return false) - } - - override fun hashCode(): Int { - var result = origin.hashCode() - result = 31 * result + features.hashCode() - return result - } - - -} - -class KomaVector internal constructor(val origin: koma.matrix.Matrix) : Point { - override val size: Int get() = origin.numRows() - - init { - require(origin.numCols() == 1) { error("Only single column matrices are allowed") } - } - - override operator fun get(index: Int): T = origin.getGeneric(index) - override operator fun iterator(): Iterator = origin.toIterable().iterator() -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 487e1d87f..7c5c00212 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -40,12 +40,12 @@ include( ":kmath-histograms", ":kmath-commons", ":kmath-viktor", - ":kmath-koma", ":kmath-prob", ":kmath-io", ":kmath-dimensions", ":kmath-for-real", ":kmath-geometry", ":kmath-ast", - ":examples" + ":examples", + ":kmath-ejml" ) From 413d129ffc7638fc7ab91c564f009aa69127e70c Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 9 Sep 2020 23:46:10 +0700 Subject: [PATCH 031/199] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3944c673e..e787a5d2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Blocking chains in `kmath-coroutines` - Full hyperbolic functions support and default implementations within `ExtendedField` - Norm support for `Complex` +- `kmath-ejml` to supply EJML SimpleMatrix wrapper. ### Changed - `readAsMemory` now has `throws IOException` in JVM signature. @@ -36,3 +37,6 @@ - Multiplication in integer rings in `kmath-core` (https://github.com/mipt-npm/kmath/pull/101) - Commons RNG compatibility (https://github.com/mipt-npm/kmath/issues/93) - Multiplication of BigInt by scalar + +### Removed +- `kmath-koma` module. From edd3022aaccb49aed040547ada66c92dd2eeb0eb Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 10 Sep 2020 05:53:44 +0700 Subject: [PATCH 032/199] Add dynamic operations and add documentations --- .../scientifik/kmath/linear/MatrixContext.kt | 33 +++++++ .../kmath/ejml/EjmlMatrixContext.kt | 91 +++++++++++-------- 2 files changed, 87 insertions(+), 37 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt index 763bb1615..b7e79f1bc 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt @@ -18,12 +18,45 @@ interface MatrixContext : SpaceOperations> { */ fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): Matrix + override fun binaryOperation(operation: String, left: Matrix, right: Matrix): Matrix = when (operation) { + "dot" -> left dot right + else -> super.binaryOperation(operation, left, right) + } + + /** + * Computes the dot product of this matrix and another one. + * + * @receiver the multiplicand. + * @param other the multiplier. + * @return the dot product. + */ infix fun Matrix.dot(other: Matrix): Matrix + /** + * Computes the dot product of this matrix and a vector. + * + * @receiver the multiplicand. + * @param vector the multiplier. + * @return the dot product. + */ infix fun Matrix.dot(vector: Point): Point + /** + * Multiplies a matrix by its element. + * + * @receiver the multiplicand. + * @param value the multiplier. + * @receiver the product. + */ operator fun Matrix.times(value: T): Matrix + /** + * Multiplies an element by a matrix of it. + * + * @receiver the multiplicand. + * @param value the multiplier. + * @receiver the product. + */ operator fun T.times(m: Matrix): Matrix = m * this companion object { diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt index 142f1bee3..ee44cd686 100644 --- a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt @@ -11,6 +11,59 @@ import scientifik.kmath.structures.Matrix * Represents context of basic operations operating with [EjmlMatrix]. */ class EjmlMatrixContext(private val space: Space) : MatrixContext { + /** + * Solves for X in the following equation: x = a^-1*b, where 'a' is base matrix and 'b' is an n by p matrix. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for 'x' that is n by p. + */ + fun 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, where 'a' is base matrix and 'b' is an n by p matrix. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for 'x' that is n by p. + */ + fun solve(a: Matrix, b: Point): EjmlVector = + EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) + + /** + * Returns the inverse of given matrix: b = a^(-1). + * + * @param a the matrix. + * @return the inverse of this matrix. + */ + fun inverse(a: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.invert()) + + /** + * Converts this matrix to EJML one. + */ + fun Matrix.toEjml(): EjmlMatrix = + if (this is EjmlMatrix) this else produce(rowNum, colNum) { i, j -> get(i, j) } + + /** + * Converts this vector to EJML one. + */ + fun Point.toEjml(): EjmlVector = + if (this is EjmlVector) this else EjmlVector(SimpleMatrix(size, 1).also { + (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) } + }) + + override fun unaryOperation(operation: String, arg: Matrix): Matrix = when (operation) { + "inverse" -> inverse(arg) + else -> super.unaryOperation(operation, arg) + } + + override fun binaryOperation(operation: String, left: Matrix, right: Matrix): Matrix = + when (operation) { + "solve" -> solve(left, right) + else -> super.binaryOperation(operation, left, right) + } + override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): EjmlMatrix = EjmlMatrix(SimpleMatrix(rows, columns).also { (0 until it.numRows()).forEach { row -> @@ -18,14 +71,6 @@ class EjmlMatrixContext(private val space: Space) : MatrixContext.toEjml(): EjmlMatrix = - if (this is EjmlMatrix) this else produce(rowNum, colNum) { i, j -> get(i, j) } - - fun Point.toEjml(): EjmlVector = - if (this is EjmlVector) this else EjmlVector(SimpleMatrix(size, 1).also { - (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) } - }) - override fun Matrix.dot(other: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) @@ -38,38 +83,10 @@ class EjmlMatrixContext(private val space: Space) : MatrixContext.minus(b: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin - b.toEjml().origin) - override fun multiply(a: Matrix, k: Number): Matrix = + override fun multiply(a: Matrix, k: Number): EjmlMatrix = produce(a.rowNum, a.colNum) { i, j -> space { a[i, j] * k } } override operator fun Matrix.times(value: Double): EjmlMatrix = EjmlMatrix(toEjml().origin.scale(value)) companion object } - -/** - * Solves for X in the following equation: x = a^-1*b, where 'a' is base matrix and 'b' is an n by p matrix. - * - * @param a the base matrix. - * @param b n by p matrix. - * @return the solution for 'x' that is n by p. - */ -fun EjmlMatrixContext.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, where 'a' is base matrix and 'b' is an n by p matrix. - * - * @param a the base matrix. - * @param b n by p vector. - * @return the solution for 'x' that is n by p. - */ -fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = - EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) - -/** - * Returns the inverse of given matrix: b = a^(-1). - * - * @param a the matrix. - * @return the inverse of this matrix. - */ -fun EjmlMatrixContext.inverse(a: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.invert()) From 2b15d69f11513045a15a6405ff0148f0a0f2ce0f Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 10 Sep 2020 15:22:01 +0700 Subject: [PATCH 033/199] Enable functions module and unmark Polynomial inline --- .../scientifik/kmath/functions/Polynomial.kt | 8 +-- .../kmath/prob/RandomSourceGenerator.kt | 55 ++++++++----------- .../kmath/viktor/ViktorNDStructure.kt | 4 +- settings.gradle.kts | 2 +- 4 files changed, 30 insertions(+), 39 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt index 77196a121..6eadf4301 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt @@ -8,16 +8,16 @@ import kotlin.contracts.contract import kotlin.math.max import kotlin.math.pow +// TODO make `inline`, when KT-41771 gets fixed /** * Polynomial coefficients without fixation on specific context they are applied to * @param coefficients constant is the leftmost coefficient */ -public inline class Polynomial(public val coefficients: List) { +public /*inline*/ class Polynomial(public val coefficients: List) { public constructor(vararg coefficients: T) : this(coefficients.toList()) } -public fun Polynomial.value(): Double = - coefficients.reduceIndexed { index: Int, acc: Double, d: Double -> acc + d.pow(index) } +public fun Polynomial.value(): Double = coefficients.reduceIndexed { index, acc, d -> acc + d.pow(index) } public fun > Polynomial.value(ring: C, arg: T): T = ring { if (coefficients.isEmpty()) return@ring zero @@ -26,7 +26,7 @@ public fun > Polynomial.value(ring: C, arg: T): T = ring for (index in 1 until coefficients.size) { res += coefficients[index] * powerArg - //recalculating power on each step to avoid power costs on long polynomials + // recalculating power on each step to avoid power costs on long polynomials powerArg *= arg } diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt index f5a73a08b..eda36415a 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt +++ b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt @@ -3,65 +3,56 @@ package scientifik.kmath.prob import org.apache.commons.rng.UniformRandomProvider import org.apache.commons.rng.simple.RandomSource -class RandomSourceGenerator(val source: RandomSource, seed: Long?) : RandomGenerator { +public class RandomSourceGenerator(public val source: RandomSource, seed: Long?) : RandomGenerator { internal val random: UniformRandomProvider = seed?.let { RandomSource.create(source, seed) } ?: RandomSource.create(source) - override fun nextBoolean(): Boolean = random.nextBoolean() + public override fun nextBoolean(): Boolean = random.nextBoolean() + public override fun nextDouble(): Double = random.nextDouble() + public override fun nextInt(): Int = random.nextInt() + public override fun nextInt(until: Int): Int = random.nextInt(until) + public override fun nextLong(): Long = random.nextLong() + public override fun nextLong(until: Long): Long = random.nextLong(until) - override fun nextDouble(): Double = random.nextDouble() - - override fun nextInt(): Int = random.nextInt() - override fun nextInt(until: Int): Int = random.nextInt(until) - - override fun nextLong(): Long = random.nextLong() - override fun nextLong(until: Long): Long = random.nextLong(until) - - override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) { + public override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) { require(toIndex > fromIndex) random.nextBytes(array, fromIndex, toIndex - fromIndex) } - override fun fork(): RandomGenerator = RandomSourceGenerator(source, nextLong()) + public override fun fork(): RandomGenerator = RandomSourceGenerator(source, nextLong()) } -inline class RandomGeneratorProvider(val generator: RandomGenerator) : UniformRandomProvider { - override fun nextBoolean(): Boolean = generator.nextBoolean() +public inline class RandomGeneratorProvider(public val generator: RandomGenerator) : UniformRandomProvider { + public override fun nextBoolean(): Boolean = generator.nextBoolean() + public override fun nextFloat(): Float = generator.nextDouble().toFloat() - override fun nextFloat(): Float = generator.nextDouble().toFloat() - - override fun nextBytes(bytes: ByteArray) { + public override fun nextBytes(bytes: ByteArray) { generator.fillBytes(bytes) } - override fun nextBytes(bytes: ByteArray, start: Int, len: Int) { + public override fun nextBytes(bytes: ByteArray, start: Int, len: Int) { generator.fillBytes(bytes, start, start + len) } - override fun nextInt(): Int = generator.nextInt() - - override fun nextInt(n: Int): Int = generator.nextInt(n) - - override fun nextDouble(): Double = generator.nextDouble() - - override fun nextLong(): Long = generator.nextLong() - - override fun nextLong(n: Long): Long = generator.nextLong(n) + public override fun nextInt(): Int = generator.nextInt() + public override fun nextInt(n: Int): Int = generator.nextInt(n) + public override fun nextDouble(): Double = generator.nextDouble() + public override fun nextLong(): Long = generator.nextLong() + public override fun nextLong(n: Long): Long = generator.nextLong(n) } /** * Represent this [RandomGenerator] as commons-rng [UniformRandomProvider] preserving and mirroring its current state. * Getting new value from one of those changes the state of another. */ -fun RandomGenerator.asUniformRandomProvider(): UniformRandomProvider = if (this is RandomSourceGenerator) { +public fun RandomGenerator.asUniformRandomProvider(): UniformRandomProvider = if (this is RandomSourceGenerator) random -} else { +else RandomGeneratorProvider(this) -} -fun RandomGenerator.Companion.fromSource(source: RandomSource, seed: Long? = null): RandomSourceGenerator = +public fun RandomGenerator.Companion.fromSource(source: RandomSource, seed: Long? = null): RandomSourceGenerator = RandomSourceGenerator(source, seed) -fun RandomGenerator.Companion.mersenneTwister(seed: Long? = null): RandomSourceGenerator = +public fun RandomGenerator.Companion.mersenneTwister(seed: Long? = null): RandomSourceGenerator = fromSource(RandomSource.MT, seed) diff --git a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt b/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt index 64f2da4c1..cbd5357af 100644 --- a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt +++ b/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt @@ -26,10 +26,10 @@ public fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this) @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public class ViktorNDField(public override val shape: IntArray) : NDField { public override val zero: ViktorNDStructure - get() = F64Array.full(init = 0.0, shape = *shape).asStructure() + get() = F64Array.full(init = 0.0, shape = shape).asStructure() public override val one: ViktorNDStructure - get() = F64Array.full(init = 1.0, shape = *shape).asStructure() + get() = F64Array.full(init = 1.0, shape = shape).asStructure() public val strides: Strides = DefaultStrides(shape) diff --git a/settings.gradle.kts b/settings.gradle.kts index 2e40b2abc..594c727cb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,7 +26,7 @@ rootProject.name = "kmath" include( ":kmath-memory", ":kmath-core", -// ":kmath-functions", + ":kmath-functions", ":kmath-coroutines", ":kmath-histograms", ":kmath-commons", From 8b171ac3a353e0831e18045ccb7732272ac74f11 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 12 Sep 2020 09:22:26 +0700 Subject: [PATCH 034/199] Update changelog --- CHANGELOG.md | 2 +- .../scientifik/kmath/operations/BigInt.kt | 24 +++++++++---------- .../scientifik/kmath/functions/Polynomial.kt | 6 ++--- .../scientifik/kmath/viktor/ViktorBuffer.kt | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3944c673e..cf42a33e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ - `power(T, Int)` extension function has preconditions and supports `Field` - Memory objects have more preconditions (overflow checking) - `tg` function is renamed to `tan` (https://github.com/mipt-npm/kmath/pull/114) -- Gradle version: 6.3 -> 6.6 +- Gradle version: 6.3 -> 6.6.1 - Moved probability distributions to commons-rng and to `kmath-prob` ### Fixed diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt index fbb60026e..d54557a1f 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt @@ -255,9 +255,9 @@ public class BigInt internal constructor( } private fun addMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude { - val resultLength: Int = max(mag1.size, mag2.size) + 1 + val resultLength = max(mag1.size, mag2.size) + 1 val result = Magnitude(resultLength) - var carry: TBase = 0UL + var carry = 0uL for (i in 0 until resultLength - 1) { val res = when { @@ -265,20 +265,22 @@ public class BigInt internal constructor( i >= mag2.size -> mag1[i].toULong() + carry else -> mag1[i].toULong() + mag2[i].toULong() + carry } + result[i] = (res and BASE).toUInt() carry = (res shr BASE_SIZE) } + result[resultLength - 1] = carry.toUInt() return stripLeadingZeros(result) } private fun subtractMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude { - val resultLength: Int = mag1.size + val resultLength = mag1.size val result = Magnitude(resultLength) var carry = 0L for (i in 0 until resultLength) { - var res: Long = + var res = if (i < mag2.size) mag1[i].toLong() - mag2[i].toLong() - carry else mag1[i].toLong() - carry @@ -292,9 +294,9 @@ public class BigInt internal constructor( } private fun multiplyMagnitudeByUInt(mag: Magnitude, x: UInt): Magnitude { - val resultLength: Int = mag.size + 1 + val resultLength = mag.size + 1 val result = Magnitude(resultLength) - var carry: ULong = 0UL + var carry = 0uL for (i in mag.indices) { val cur: ULong = carry + mag[i].toULong() * x.toULong() @@ -307,11 +309,11 @@ public class BigInt internal constructor( } private fun multiplyMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude { - val resultLength: Int = mag1.size + mag2.size + val resultLength = mag1.size + mag2.size val result = Magnitude(resultLength) for (i in mag1.indices) { - var carry: ULong = 0UL + var carry = 0uL for (j in mag2.indices) { val cur: ULong = result[i + j].toULong() + mag1[i].toULong() * mag2[j].toULong() + carry @@ -338,9 +340,7 @@ public class BigInt internal constructor( return stripLeadingZeros(result) } - } - } private fun stripLeadingZeros(mag: Magnitude): Magnitude { @@ -366,7 +366,8 @@ public fun Int.toBigInt(): BigInt = BigInt(sign.toByte(), uintArrayOf(kotlin.mat * Convert this [Long] to [BigInt] */ public fun Long.toBigInt(): BigInt = BigInt( - sign.toByte(), stripLeadingZeros( + sign.toByte(), + stripLeadingZeros( uintArrayOf( (kotlin.math.abs(this).toULong() and BASE).toUInt(), ((kotlin.math.abs(this).toULong() shr BASE_SIZE) and BASE).toUInt() @@ -384,7 +385,6 @@ public fun UInt.toBigInt(): BigInt = BigInt(1, uintArrayOf(this)) */ public fun ULong.toBigInt(): BigInt = BigInt( 1, - stripLeadingZeros( uintArrayOf( (this and BASE).toUInt(), diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt index 6eadf4301..3d97936f9 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt @@ -13,9 +13,9 @@ import kotlin.math.pow * Polynomial coefficients without fixation on specific context they are applied to * @param coefficients constant is the leftmost coefficient */ -public /*inline*/ class Polynomial(public val coefficients: List) { - public constructor(vararg coefficients: T) : this(coefficients.toList()) -} +public inline class Polynomial(public val coefficients: List) + +public fun Polynomial(vararg coefficients: T): Polynomial = Polynomial(coefficients.toList()) public fun Polynomial.value(): Double = coefficients.reduceIndexed { index, acc, d -> acc + d.pow(index) } diff --git a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt b/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt index be5bf5740..97ab9e6d7 100644 --- a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt +++ b/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt @@ -10,7 +10,7 @@ public inline class ViktorBuffer(public val flatArray: F64FlatArray) : MutableBu public override inline fun get(index: Int): Double = flatArray[index] - override inline fun set(index: Int, value: Double) { + public override inline fun set(index: Int, value: Double) { flatArray[index] = value } From d088fdf77cd061a63f2fb8338a8e28014f7aadf3 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 12 Sep 2020 09:23:47 +0700 Subject: [PATCH 035/199] Move matrix solving and inverting to extensions because of consistency --- .../kmath/ejml/EjmlMatrixContext.kt | 67 ++++++++----------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt index ee44cd686..1b59a89ca 100644 --- a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt @@ -11,34 +11,6 @@ import scientifik.kmath.structures.Matrix * Represents context of basic operations operating with [EjmlMatrix]. */ class EjmlMatrixContext(private val space: Space) : MatrixContext { - /** - * Solves for X in the following equation: x = a^-1*b, where 'a' is base matrix and 'b' is an n by p matrix. - * - * @param a the base matrix. - * @param b n by p matrix. - * @return the solution for 'x' that is n by p. - */ - fun 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, where 'a' is base matrix and 'b' is an n by p matrix. - * - * @param a the base matrix. - * @param b n by p vector. - * @return the solution for 'x' that is n by p. - */ - fun solve(a: Matrix, b: Point): EjmlVector = - EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) - - /** - * Returns the inverse of given matrix: b = a^(-1). - * - * @param a the matrix. - * @return the inverse of this matrix. - */ - fun inverse(a: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.invert()) - /** * Converts this matrix to EJML one. */ @@ -53,17 +25,6 @@ class EjmlMatrixContext(private val space: Space) : MatrixContext it[row, 0] = get(row) } }) - override fun unaryOperation(operation: String, arg: Matrix): Matrix = when (operation) { - "inverse" -> inverse(arg) - else -> super.unaryOperation(operation, arg) - } - - override fun binaryOperation(operation: String, left: Matrix, right: Matrix): Matrix = - when (operation) { - "solve" -> solve(left, right) - else -> super.binaryOperation(operation, left, right) - } - override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): EjmlMatrix = EjmlMatrix(SimpleMatrix(rows, columns).also { (0 until it.numRows()).forEach { row -> @@ -90,3 +51,31 @@ class EjmlMatrixContext(private val space: Space) : MatrixContext, b: Matrix): EjmlMatrix = + EjmlMatrix(a.toEjml().origin.solve(b.toEjml().origin)) + +/** + * Solves for X in the following equation: x = a^(-1)*b, where 'a' is base matrix and 'b' is an n by p matrix. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for 'x' that is n by p. + */ +fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = + EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) + +/** + * Returns the inverse of given matrix: b = a^(-1). + * + * @param a the matrix. + * @return the inverse of this matrix. + */ +fun EjmlMatrixContext.inverse(a: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.invert()) From 1c495759cd23d7e4f3ea826715d179c9713d6447 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 14 Sep 2020 19:53:31 +0700 Subject: [PATCH 036/199] Replace ?: with set merging --- .../src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt index a53856af0..90f6e64cd 100644 --- a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt @@ -23,7 +23,7 @@ class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) override val shape: IntArray get() = intArrayOf(origin.numRows(), origin.numCols()) - override val features: Set = features ?: hashSetOf( + override val features: Set = hashSetOf( object : DeterminantFeature { override val determinant: Double get() = origin.determinant() @@ -50,7 +50,7 @@ class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) override val p: FeaturedMatrix get() = lup.first } - ) + ).addAll(features) override fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix = EjmlMatrix(origin, this.features + features) From a046f5c060fc8f046c80ddf96a187e057a023d2b Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 14 Sep 2020 20:02:53 +0700 Subject: [PATCH 037/199] Update features --- .../src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt index 90f6e64cd..09b9c4fcd 100644 --- a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt @@ -24,12 +24,10 @@ class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) get() = intArrayOf(origin.numRows(), origin.numCols()) override val features: Set = hashSetOf( - object : DeterminantFeature { + object : LUPDecompositionFeature, DeterminantFeature { override val determinant: Double get() = origin.determinant() - }, - object : LUPDecompositionFeature { private val lup by lazy { val ludecompositionF64 = DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()) .also { it.decompose(origin.ddrm.copy()) } @@ -50,7 +48,7 @@ class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) override val p: FeaturedMatrix get() = lup.first } - ).addAll(features) + ).addAll(features.orEmpty()) override fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix = EjmlMatrix(origin, this.features + features) From 91d692381c6705f2fdd8b947f5ee3e0e7238d3b9 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 14 Sep 2020 20:15:11 +0700 Subject: [PATCH 038/199] Update comparison and fix type error --- .../src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt index 09b9c4fcd..4bf0a505f 100644 --- a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt @@ -23,7 +23,7 @@ class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) override val shape: IntArray get() = intArrayOf(origin.numRows(), origin.numCols()) - override val features: Set = hashSetOf( + override val features: Set = setOf( object : LUPDecompositionFeature, DeterminantFeature { override val determinant: Double get() = origin.determinant() @@ -48,7 +48,7 @@ class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) override val p: FeaturedMatrix get() = lup.first } - ).addAll(features.orEmpty()) + ) union features.orEmpty() override fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix = EjmlMatrix(origin, this.features + features) @@ -56,6 +56,7 @@ class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) override operator fun get(i: Int, j: Int): Double = origin[i, j] override fun equals(other: Any?): Boolean { + if (other is EjmlMatrix) return origin.isIdentical(other.origin, 0.0) return NDStructure.equals(this, other as? NDStructure<*> ?: return false) } From 2f2315f6cdeaadc59aab96014fc3f68e85898b65 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 14 Sep 2020 20:18:43 +0700 Subject: [PATCH 039/199] Override toString --- kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt index 4bf0a505f..a4923b5e3 100644 --- a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt @@ -65,4 +65,6 @@ class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) result = 31 * result + features.hashCode() return result } + + override fun toString(): String = "EjmlMatrix(origin=$origin, features=$features)" } From 09b82a891063630e170faf84fb15cf22490baf0f Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 14 Sep 2020 20:20:07 +0700 Subject: [PATCH 040/199] Override toString and contentEquals --- .../src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt index ab9d4e87c..dd7969e83 100644 --- a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt @@ -2,6 +2,7 @@ package scientifik.kmath.ejml import org.ejml.simple.SimpleMatrix import scientifik.kmath.linear.Point +import scientifik.kmath.structures.Buffer /** * Represents point over EJML [SimpleMatrix]. @@ -27,4 +28,11 @@ class EjmlVector internal constructor(val origin: SimpleMatrix) : Point override fun hasNext(): Boolean = cursor < origin.numCols() * origin.numRows() } + + override fun contentEquals(other: Buffer<*>): Boolean { + if (other is EjmlVector) return origin.isIdentical(other.origin, 0.0) + return super.contentEquals(other) + } + + override fun toString(): String = "EjmlVector(origin=$origin)" } From 148c0c8bc58362db79f8c835b8cc51a472afd26b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 15 Sep 2020 17:47:49 +0700 Subject: [PATCH 041/199] Update changelog --- CHANGELOG.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aaf69038..ba271bb01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,14 @@ ## [Unreleased] ### Added +- `kmath-ejml` to supply EJML SimpleMatrix wrapper. ### Changed ### Deprecated ### Removed +- `kmath-koma` module. ### Fixed @@ -30,7 +32,6 @@ - Blocking chains in `kmath-coroutines` - Full hyperbolic functions support and default implementations within `ExtendedField` - Norm support for `Complex` -- `kmath-ejml` to supply EJML SimpleMatrix wrapper. ### Changed - `readAsMemory` now has `throws IOException` in JVM signature. @@ -49,6 +50,3 @@ - Multiplication in integer rings in `kmath-core` (https://github.com/mipt-npm/kmath/pull/101) - Commons RNG compatibility (https://github.com/mipt-npm/kmath/issues/93) - Multiplication of BigInt by scalar - -### Removed -- `kmath-koma` module. From d54e7c3e97e02090ef5abae2cfe1aca32c6d8e0a Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 15 Sep 2020 17:48:43 +0700 Subject: [PATCH 042/199] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 015f0deeb..bf0316c9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] ### Added +- ND4J support module submitting `NDStructure` and `NDAlgebra` over `INDArray`. ### Changed @@ -30,7 +31,6 @@ - Blocking chains in `kmath-coroutines` - Full hyperbolic functions support and default implementations within `ExtendedField` - Norm support for `Complex` -- ND4J support module submitting `NDStructure` and `NDAlgebra` over `INDArray`. ### Changed - `readAsMemory` now has `throws IOException` in JVM signature. From 5eaeb82a0f13336d098375ad68b88184f06f859b Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 20 Sep 2020 16:36:48 +0700 Subject: [PATCH 043/199] Make one-liners not one-liners, add newlines at EOFs, optimize imports and Kotlin extension configurations --- build.gradle.kts | 17 ++++++++--------- .../kmath/linear/LinearAlgebraBenchmark.kt | 2 -- .../scientifik/kmath/structures/NDField.kt | 1 - kmath-ast/build.gradle.kts | 6 +++--- .../scientifik/kmath/ast/MstExpression.kt | 1 - .../kmath/asm/internal/codegenUtils.kt | 1 - kmath-commons/build.gradle.kts | 7 ++++--- kmath-core/build.gradle.kts | 8 +++----- .../scientifik/kmath/expressions/Builders.kt | 1 - .../scientifik/kmath/linear/FeaturedMatrix.kt | 1 - .../kotlin/scientifik/kmath/misc/AutoDiff.kt | 1 - .../kotlin/scientifik/kmath/misc/cumulative.kt | 1 - .../scientifik/kmath/operations/BigInt.kt | 1 - .../scientifik/kmath/operations/Complex.kt | 1 - .../scientifik/kmath/structures/Buffers.kt | 1 - .../kmath/structures/ComplexNDField.kt | 1 - .../kmath/structures/FlaggedBuffer.kt | 1 - .../scientifik/kmath/structures/FloatBuffer.kt | 1 - .../scientifik/kmath/structures/IntBuffer.kt | 7 +------ .../scientifik/kmath/structures/LongBuffer.kt | 1 - .../scientifik/kmath/structures/NDStructure.kt | 1 - .../scientifik/kmath/structures/RealBuffer.kt | 1 - .../scientifik/kmath/structures/ShortBuffer.kt | 1 - .../scientifik/kmath/linear/RealLUSolverTest.kt | 2 -- kmath-coroutines/build.gradle.kts | 1 - kmath-dimensions/build.gradle.kts | 6 +++--- kmath-for-real/build.gradle.kts | 13 ++++++++----- .../kotlin/scientifik/kmath/real/realMatrix.kt | 1 - kmath-functions/build.gradle.kts | 13 ++++++++----- .../scientifik/kmath/functions/Polynomial.kt | 1 - .../scientifik/kmath/histogram/Histogram.kt | 3 --- kmath-memory/build.gradle.kts | 2 +- .../scientifik/memory/ByteBufferMemory.kt | 1 - kmath-prob/build.gradle.kts | 2 +- kmath-viktor/build.gradle.kts | 2 +- 35 files changed, 41 insertions(+), 70 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b24ecd15b..96434d01f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,10 +1,12 @@ +import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension +import scientifik.ScientifikPublishPlugin + plugins { id("scientifik.publish") apply false id("org.jetbrains.changelog") version "0.4.0" } val kmathVersion by extra("0.1.4") - val bintrayRepo by extra("scientifik") val githubProject by extra("kmath") @@ -19,18 +21,15 @@ allprojects { version = kmathVersion afterEvaluate { - extensions.findByType()?.run { - targets.all { - sourceSets.all { - languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") - } + extensions.findByType()?.run { + sourceSets.all { + languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } } } } subprojects { - if (name.startsWith("kmath")) { - apply(plugin = "scientifik.publish") - } + if (name.startsWith("kmath")) + apply() } \ No newline at end of file diff --git a/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt index 6cc5411b8..0386ffcbc 100644 --- a/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt +++ b/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt @@ -7,11 +7,9 @@ import scientifik.kmath.commons.linear.toCM import scientifik.kmath.operations.RealField import scientifik.kmath.operations.invoke import scientifik.kmath.structures.Matrix -import kotlin.contracts.ExperimentalContracts import kotlin.random.Random import kotlin.system.measureTimeMillis -@ExperimentalContracts fun main() { val random = Random(1224) val dim = 100 diff --git a/examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt b/examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt index 1bc0ed7c8..54ffcb67c 100644 --- a/examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt @@ -3,7 +3,6 @@ package scientifik.kmath.structures import kotlinx.coroutines.GlobalScope import scientifik.kmath.operations.RealField import scientifik.kmath.operations.invoke -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.system.measureTimeMillis diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 86b10bdc7..ace121a09 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,8 +1,8 @@ -plugins { id("scientifik.mpp") } +plugins { + id("scientifik.mpp") +} kotlin.sourceSets { - all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } - commonMain { dependencies { api(project(":kmath-core")) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt index 3cee33956..293152cdd 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt @@ -2,7 +2,6 @@ package scientifik.kmath.ast import scientifik.kmath.expressions.* import scientifik.kmath.operations.* -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt index 6f51fe855..021c8ae02 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt @@ -7,7 +7,6 @@ import scientifik.kmath.ast.MST import scientifik.kmath.expressions.Expression import scientifik.kmath.operations.Algebra import java.lang.reflect.Method -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.reflect.KClass diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 63c832b7c..a77d8ab47 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -1,4 +1,7 @@ -plugins { id("scientifik.jvm") } +plugins { + id("scientifik.jvm") +} + description = "Commons math binding for kmath" dependencies { @@ -8,5 +11,3 @@ dependencies { api(project(":kmath-functions")) api("org.apache.commons:commons-math3:3.6.1") } - -kotlin.sourceSets.all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 18c0cc771..5a5a8be6d 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -2,10 +2,8 @@ plugins { id("scientifik.mpp") } -kotlin.sourceSets { - commonMain { - dependencies { - api(project(":kmath-memory")) - } +kotlin.sourceSets.commonMain { + dependencies { + api(project(":kmath-memory")) } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt index 8d0b82a89..8090db75e 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Builders.kt @@ -4,7 +4,6 @@ import scientifik.kmath.operations.ExtendedField import scientifik.kmath.operations.Field import scientifik.kmath.operations.Ring import scientifik.kmath.operations.Space -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt index 9b60bf719..7237739fb 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt @@ -4,7 +4,6 @@ import scientifik.kmath.operations.Ring import scientifik.kmath.structures.Matrix import scientifik.kmath.structures.Structure2D import scientifik.kmath.structures.asBuffer -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.math.sqrt diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt index be222783e..808312877 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt @@ -6,7 +6,6 @@ import scientifik.kmath.operations.Field import scientifik.kmath.operations.invoke import scientifik.kmath.operations.sum import scientifik.kmath.structures.asBuffer -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt index e11adc135..6ac03f463 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt @@ -2,7 +2,6 @@ package scientifik.kmath.misc import scientifik.kmath.operations.Space import scientifik.kmath.operations.invoke -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.jvm.JvmName diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt index 0eed7132e..f03275ed9 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt @@ -3,7 +3,6 @@ package scientifik.kmath.operations import scientifik.kmath.operations.BigInt.Companion.BASE import scientifik.kmath.operations.BigInt.Companion.BASE_SIZE import scientifik.kmath.structures.* -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.math.log2 import kotlin.math.max diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt index dcfd97d1a..49200b5f9 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt @@ -6,7 +6,6 @@ import scientifik.kmath.structures.MutableBuffer import scientifik.memory.MemoryReader import scientifik.memory.MemorySpec import scientifik.memory.MemoryWriter -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.math.* diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt index 4afaa63ab..1ea8ca3d5 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt @@ -2,7 +2,6 @@ package scientifik.kmath.structures import scientifik.kmath.operations.Complex import scientifik.kmath.operations.complex -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.reflect.KClass diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt index 2c6e3a5c7..5364115d4 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt @@ -4,7 +4,6 @@ import scientifik.kmath.operations.Complex import scientifik.kmath.operations.ComplexField import scientifik.kmath.operations.FieldElement import scientifik.kmath.operations.complex -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt index 9c32aa31b..5146c0668 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt @@ -1,6 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.experimental.and diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt index 9e974c644..3beb110cf 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt @@ -1,6 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt index 95651c547..f88ed7d66 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt @@ -1,7 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind import kotlin.contracts.contract /** @@ -31,10 +29,7 @@ inline class IntBuffer(val array: IntArray) : MutableBuffer { * The function [init] is called for each array element sequentially starting from the first one. * It should return the value for an buffer element given its index. */ -inline fun IntBuffer(size: Int, init: (Int) -> Int): IntBuffer { - contract { callsInPlace(init) } - return IntBuffer(IntArray(size) { init(it) }) -} +inline fun IntBuffer(size: Int, init: (Int) -> Int): IntBuffer = IntBuffer(IntArray(size) { init(it) }) /** * Returns a new [IntBuffer] of given elements. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt index a44109f8a..3a1d679c2 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt @@ -1,6 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt index f4eb93b9e..01a692a65 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt @@ -1,6 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.jvm.JvmName import kotlin.reflect.KClass diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt index cba8e9689..3c92fb0ce 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt @@ -1,6 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt index 9aa674177..1feba1e6b 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt @@ -1,6 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract /** diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt index 34bd8a0e3..9de9fb575 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt @@ -1,11 +1,9 @@ package scientifik.kmath.linear import scientifik.kmath.structures.Matrix -import kotlin.contracts.ExperimentalContracts import kotlin.test.Test import kotlin.test.assertEquals -@ExperimentalContracts class RealLUSolverTest { @Test diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 4469a9ef6..bbbddeba3 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -6,7 +6,6 @@ plugins { kotlin.sourceSets { all { with(languageSettings) { - useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") useExperimentalAnnotation("kotlinx.coroutines.InternalCoroutinesApi") useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi") useExperimentalAnnotation("kotlinx.coroutines.FlowPreview") diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index dda6cd2f0..597ce8799 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -11,9 +11,9 @@ kotlin.sourceSets { } } - jvmMain{ - dependencies{ + jvmMain { + dependencies { api(kotlin("reflect")) } } -} \ No newline at end of file +} diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 46d2682f7..675457ac5 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -1,6 +1,9 @@ -plugins { id("scientifik.mpp") } - -kotlin.sourceSets { - all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } - commonMain { dependencies { api(project(":kmath-core")) } } +plugins { + id("scientifik.mpp") +} + +kotlin.sourceSets.commonMain { + dependencies { + api(project(":kmath-core")) + } } diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt index 3752fc3ca..b5569cca6 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt @@ -9,7 +9,6 @@ import scientifik.kmath.structures.Buffer import scientifik.kmath.structures.Matrix import scientifik.kmath.structures.RealBuffer import scientifik.kmath.structures.asIterable -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.math.pow diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 46d2682f7..675457ac5 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -1,6 +1,9 @@ -plugins { id("scientifik.mpp") } - -kotlin.sourceSets { - all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") } - commonMain { dependencies { api(project(":kmath-core")) } } +plugins { + id("scientifik.mpp") +} + +kotlin.sourceSets.commonMain { + dependencies { + api(project(":kmath-core")) + } } diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt index c4470ad27..fcfa9f1aa 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt @@ -3,7 +3,6 @@ package scientifik.kmath.functions import scientifik.kmath.operations.Ring import scientifik.kmath.operations.Space import scientifik.kmath.operations.invoke -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.math.max diff --git a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt index 9ff2aacf5..32b6444cc 100644 --- a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt @@ -4,9 +4,6 @@ import scientifik.kmath.domains.Domain import scientifik.kmath.linear.Point import scientifik.kmath.structures.ArrayBuffer import scientifik.kmath.structures.RealBuffer -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract /** * The bin in the histogram. The histogram is by definition always done in the real space diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 75b4f174e..1f34a4f17 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1,3 +1,3 @@ plugins { id("scientifik.mpp") -} \ No newline at end of file +} diff --git a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt index f4967bf5c..ac8609094 100644 --- a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt @@ -6,7 +6,6 @@ import java.nio.channels.FileChannel import java.nio.file.Files import java.nio.file.Path import java.nio.file.StandardOpenOption -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-prob/build.gradle.kts b/kmath-prob/build.gradle.kts index a69d61b73..6cdd301c2 100644 --- a/kmath-prob/build.gradle.kts +++ b/kmath-prob/build.gradle.kts @@ -14,4 +14,4 @@ kotlin.sourceSets { api("org.apache.commons:commons-rng-simple:1.3") } } -} \ No newline at end of file +} diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 52ee7c497..5ad0620e9 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -7,4 +7,4 @@ description = "Binding for https://github.com/JetBrains-Research/viktor" dependencies { api(project(":kmath-core")) api("org.jetbrains.bio:viktor:1.0.1") -} \ No newline at end of file +} From 1e67ffb5ef329daaa6350efdbcd52df5ffdc4685 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 20 Sep 2020 16:40:07 +0700 Subject: [PATCH 044/199] Make one-liner not a one-liner --- kmath-ejml/build.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index cfc52af5d..58d8972b8 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -1,4 +1,6 @@ -plugins { id("scientifik.jvm") } +plugins { + id("scientifik.jvm") +} dependencies { implementation("org.ejml:ejml-simple:0.39") From 4e5c7ab366e41fe5ec8f392b4bf36d0ba9be6769 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 20 Sep 2020 16:45:26 +0700 Subject: [PATCH 045/199] Make one-liner not a one-liner --- kmath-nd4j/build.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 59354a8f9..110a2ac30 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,4 +1,6 @@ -plugins { id("scientifik.jvm") } +plugins { + id("scientifik.jvm") +} dependencies { api(project(":kmath-core")) From 4cebca51ef6a3c09a0e921f4a171e7a58bf8c560 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 20 Sep 2020 19:01:27 +0700 Subject: [PATCH 046/199] Add @author annotations, minor KDoc updates --- .../kotlin/scientifik/kmath/ast/MST.kt | 3 ++ .../kotlin/scientifik/kmath/ast/MstAlgebra.kt | 10 +++++ .../scientifik/kmath/ast/MstExpression.kt | 19 ++++++++ .../kotlin/scientifik/kmath/ast/parser.kt | 4 ++ .../kotlin/scientifik/kmath/asm/asm.kt | 15 +++++-- .../kmath/asm/internal/AsmBuilder.kt | 1 + .../scientifik/kmath/asm/internal/MstType.kt | 3 ++ .../kmath/asm/internal/codegenUtils.kt | 43 +++++++++++++++---- .../kmath/asm/internal/mapIntrinsics.kt | 5 +++ .../kmath/operations/AlgebraExtensions.kt | 5 +++ .../kmath/structures/FloatBuffer.kt | 1 + 11 files changed, 97 insertions(+), 12 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt index 0e8151c04..22b2efcda 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt @@ -6,6 +6,8 @@ import scientifik.kmath.operations.RealField /** * A Mathematical Syntax Tree node for mathematical expressions. + * + * @author Alexander Nozik */ sealed class MST { /** @@ -52,6 +54,7 @@ sealed class MST { * @receiver the algebra that provides operations. * @param node the node to evaluate. * @return the value of expression. + * @author Alexander Nozik */ fun Algebra.evaluate(node: MST): T = when (node) { is MST.Numeric -> (this as? NumericAlgebra)?.number(node.value) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt index 23deae24b..ac8765198 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt @@ -4,6 +4,8 @@ import scientifik.kmath.operations.* /** * [Algebra] over [MST] nodes. + * + * @author Alexander Nozik */ object MstAlgebra : NumericAlgebra { override fun number(value: Number): MST = MST.Numeric(value) @@ -19,6 +21,8 @@ object MstAlgebra : NumericAlgebra { /** * [Space] over [MST] nodes. + * + * @author Alexander Nozik */ object MstSpace : Space, NumericAlgebra { override val zero: MST = number(0.0) @@ -36,6 +40,8 @@ object MstSpace : Space, NumericAlgebra { /** * [Ring] over [MST] nodes. + * + * @author Alexander Nozik */ object MstRing : Ring, NumericAlgebra { override val zero: MST = number(0.0) @@ -57,6 +63,8 @@ object MstRing : Ring, NumericAlgebra { /** * [Field] over [MST] nodes. + * + * @author Alexander Nozik */ object MstField : Field { override val zero: MST = number(0.0) @@ -77,6 +85,8 @@ object MstField : Field { /** * [ExtendedField] over [MST] nodes. + * + * @author Iaroslav Postovalov */ object MstExtendedField : ExtendedField { override val zero: MST = number(0.0) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt index 293152cdd..71779ac96 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt @@ -11,6 +11,7 @@ import kotlin.contracts.contract * * @property algebra the algebra that provides operations. * @property mst the [MST] node. + * @author Alexander Nozik */ class MstExpression(val algebra: Algebra, val mst: MST) : Expression { private inner class InnerAlgebra(val arguments: Map) : NumericAlgebra { @@ -31,6 +32,8 @@ class MstExpression(val algebra: Algebra, val mst: MST) : Expression { /** * Builds [MstExpression] over [Algebra]. + * + * @author Alexander Nozik */ inline fun , E : Algebra> A.mst( mstAlgebra: E, @@ -39,6 +42,8 @@ inline fun , E : Algebra> A.mst( /** * Builds [MstExpression] over [Space]. + * + * @author Alexander Nozik */ inline fun Space.mstInSpace(block: MstSpace.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -47,6 +52,8 @@ inline fun Space.mstInSpace(block: MstSpace.() -> MST): Mst /** * Builds [MstExpression] over [Ring]. + * + * @author Alexander Nozik */ inline fun Ring.mstInRing(block: MstRing.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -55,6 +62,8 @@ inline fun Ring.mstInRing(block: MstRing.() -> MST): MstExp /** * Builds [MstExpression] over [Field]. + * + * @author Alexander Nozik */ inline fun Field.mstInField(block: MstField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -63,6 +72,8 @@ inline fun Field.mstInField(block: MstField.() -> MST): Mst /** * Builds [MstExpression] over [ExtendedField]. + * + * @author Iaroslav Postovalov */ inline fun Field.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -71,6 +82,8 @@ inline fun Field.mstInExtendedField(block: MstExtendedField /** * Builds [MstExpression] over [FunctionalExpressionSpace]. + * + * @author Alexander Nozik */ inline fun > FunctionalExpressionSpace.mstInSpace(block: MstSpace.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -79,6 +92,8 @@ inline fun > FunctionalExpressionSpace.mstIn /** * Builds [MstExpression] over [FunctionalExpressionRing]. + * + * @author Alexander Nozik */ inline fun > FunctionalExpressionRing.mstInRing(block: MstRing.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -87,6 +102,8 @@ inline fun > FunctionalExpressionRing.mstInRi /** * Builds [MstExpression] over [FunctionalExpressionField]. + * + * @author Alexander Nozik */ inline fun > FunctionalExpressionField.mstInField(block: MstField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -95,6 +112,8 @@ inline fun > FunctionalExpressionField.mstIn /** * Builds [MstExpression] over [FunctionalExpressionExtendedField]. + * + * @author Iaroslav Postovalov */ inline fun > FunctionalExpressionExtendedField.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt index cba335a8d..d83b12486 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt @@ -17,6 +17,8 @@ import scientifik.kmath.operations.SpaceOperations /** * TODO move to core + * + * @author Alexander Nozik and Iaroslav Postovalov */ object ArithmeticsEvaluator : Grammar() { // TODO replace with "...".toRegex() when better-parse 0.4.1 is released @@ -85,6 +87,7 @@ object ArithmeticsEvaluator : Grammar() { * * @receiver the string to parse. * @return the [MST] node. + * @author Alexander Nozik */ fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryParseToEnd(this) @@ -93,5 +96,6 @@ fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryParseToEnd * * @receiver the string to parse. * @return the [MST] node. + * @author Alexander Nozik */ fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this) diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt index ee0ea15ff..a5da51564 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt @@ -11,7 +11,12 @@ import scientifik.kmath.operations.Algebra import kotlin.reflect.KClass /** - * Compile given MST to an Expression using AST compiler + * Compiles given MST to an Expression using AST compiler. + * + * @param type the target type. + * @param algebra the target algebra. + * @return the compiled expression. + * @author Alexander Nozik */ fun MST.compileWith(type: KClass, algebra: Algebra): Expression { fun AsmBuilder.visit(node: MST) { @@ -54,11 +59,15 @@ fun MST.compileWith(type: KClass, algebra: Algebra): Expression< } /** - * Compile an [MST] to ASM using given algebra + * Compiles an [MST] to ASM using given algebra. + * + * @author Alexander Nozik. */ inline fun Algebra.expression(mst: MST): Expression = mst.compileWith(T::class, this) /** - * Optimize performance of an [MstExpression] using ASM codegen + * Optimizes performance of an [MstExpression] using ASM codegen. + * + * @author Alexander Nozik. */ inline fun MstExpression.compile(): Expression = mst.compileWith(T::class, algebra) diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt index f8c159baf..1cf49a251 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt @@ -20,6 +20,7 @@ import kotlin.reflect.KClass * @property algebra the algebra the applied AsmExpressions use. * @property className the unique class name of new loaded class. * @property invokeLabel0Visitor the function to apply to this object when generating invoke method, label 0. + * @author Iaroslav Postovalov */ internal class AsmBuilder internal constructor( private val classOfT: KClass<*>, diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt index bf73d304b..81e6791c1 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt @@ -2,6 +2,9 @@ package scientifik.kmath.asm.internal import scientifik.kmath.ast.MST +/** + * Represents types known in [MST], numbers and general values. + */ internal enum class MstType { GENERAL, NUMBER; diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt index 021c8ae02..ab29d3614 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt @@ -6,6 +6,9 @@ import org.objectweb.asm.commons.InstructionAdapter import scientifik.kmath.ast.MST import scientifik.kmath.expressions.Expression import scientifik.kmath.operations.Algebra +import scientifik.kmath.operations.FieldOperations +import scientifik.kmath.operations.RingOperations +import scientifik.kmath.operations.SpaceOperations import java.lang.reflect.Method import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -13,20 +16,27 @@ import kotlin.reflect.KClass private val methodNameAdapters: Map, String> by lazy { hashMapOf( - "+" to 2 to "add", - "*" to 2 to "multiply", - "/" to 2 to "divide", - "+" to 1 to "unaryPlus", - "-" to 1 to "unaryMinus", - "-" to 2 to "minus" + SpaceOperations.PLUS_OPERATION to 2 to "add", + RingOperations.TIMES_OPERATION to 2 to "multiply", + FieldOperations.DIV_OPERATION to 2 to "divide", + SpaceOperations.PLUS_OPERATION to 1 to "unaryPlus", + SpaceOperations.MINUS_OPERATION to 1 to "unaryMinus", + SpaceOperations.MINUS_OPERATION to 2 to "minus" ) } +/** + * Returns ASM [Type] for given [KClass]. + * + * @author Iaroslav Postovalov + */ internal val KClass<*>.asm: Type get() = Type.getType(java) /** * Returns singleton array with this value if the [predicate] is true, returns empty array otherwise. + * + * @author Iaroslav Postovalov */ internal inline fun T.wrapToArrayIf(predicate: (T) -> Boolean): Array { contract { callsInPlace(predicate, InvocationKind.EXACTLY_ONCE) } @@ -35,11 +45,15 @@ internal inline fun T.wrapToArrayIf(predicate: (T) -> Boolean): Arra /** * Creates an [InstructionAdapter] from this [MethodVisitor]. + * + * @author Iaroslav Postovalov */ private fun MethodVisitor.instructionAdapter(): InstructionAdapter = InstructionAdapter(this) /** * Creates an [InstructionAdapter] from this [MethodVisitor] and applies [block] to it. + * + * @author Iaroslav Postovalov */ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.() -> Unit): InstructionAdapter { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -48,6 +62,8 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.( /** * Constructs a [Label], then applies it to this visitor. + * + * @author Iaroslav Postovalov */ internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) } @@ -56,6 +72,8 @@ internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) } * * This methods helps to avoid collisions of class name to prevent loading several classes with the same name. If there * is a colliding class, change [collision] parameter or leave it `0` to check existing classes recursively. + * + * @author Iaroslav Postovalov */ internal tailrec fun buildName(mst: MST, collision: Int = 0): String { val name = "scientifik.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision" @@ -75,6 +93,11 @@ internal inline fun ClassWriter(flags: Int, block: ClassWriter.() -> Unit): Clas return ClassWriter(flags).apply(block) } +/** + * Invokes [visitField] and applies [block] to the [FieldVisitor]. + * + * @author Iaroslav Postovalov + */ internal inline fun ClassWriter.visitField( access: Int, name: String, @@ -104,7 +127,7 @@ private fun AsmBuilder.findSpecific(context: Algebra, name: String, pa * Checks if the target [context] for code generation contains a method with needed [name] and arity, also builds * type expectation stack for needed arity. * - * @return `true` if contains, else `false`. + * @author Iaroslav Postovalov */ private fun AsmBuilder.buildExpectationStack( context: Algebra, @@ -136,7 +159,7 @@ private fun AsmBuilder.mapTypes(method: Method, parameterTypes: Array AsmBuilder.tryInvokeSpecific( context: Algebra, @@ -160,7 +183,9 @@ private fun AsmBuilder.tryInvokeSpecific( } /** - * Builds specialized algebra call with option to fallback to generic algebra operation accepting String. + * Builds specialized [context] call with option to fallback to generic algebra operation accepting [String]. + * + * @author Iaroslav Postovalov */ internal inline fun AsmBuilder.buildAlgebraOperationCall( context: Algebra, diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt index 80e83c1bf..997dbbfe5 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt @@ -2,6 +2,11 @@ package scientifik.kmath.asm.internal +/** + * Gets value with given [key] or throws [IllegalStateException] whenever it is not present. + * + * @author Iaroslav Postovalov + */ @JvmOverloads internal fun Map.getOrFail(key: K, default: V? = null): V = this[key] ?: default ?: error("Parameter not found: $key") diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt index 00b16dc98..fabfbdb49 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt @@ -24,6 +24,7 @@ fun Space.sum(data: Sequence): T = data.fold(zero) { left, right -> ad * @receiver the algebra that provides addition and division. * @param data the iterable to find average. * @return the average value. + * @author Iaroslav Postovalov */ fun Space.average(data: Iterable): T = sum(data) / data.count() @@ -33,6 +34,7 @@ fun Space.average(data: Iterable): T = sum(data) / data.count() * @receiver the algebra that provides addition and division. * @param data the sequence to find average. * @return the average value. + * @author Iaroslav Postovalov */ fun Space.average(data: Sequence): T = sum(data) / data.count() @@ -60,6 +62,7 @@ fun Sequence.sumWith(space: Space): T = space.sum(this) * @receiver the iterable to find average. * @param space the algebra that provides addition and division. * @return the average value. + * @author Iaroslav Postovalov */ fun Iterable.averageWith(space: Space): T = space.average(this) @@ -69,6 +72,7 @@ fun Iterable.averageWith(space: Space): T = space.average(this) * @receiver the sequence to find average. * @param space the algebra that provides addition and division. * @return the average value. + * @author Iaroslav Postovalov */ fun Sequence.averageWith(space: Space): T = space.average(this) @@ -98,6 +102,7 @@ fun Ring.power(arg: T, power: Int): T { * @param arg the base. * @param power the exponent. * @return the base raised to the power. + * @author Iaroslav Postovalov */ fun Field.power(arg: T, power: Int): T { require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt index 3beb110cf..d1b99685c 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt @@ -6,6 +6,7 @@ import kotlin.contracts.contract * Specialized [MutableBuffer] implementation over [FloatArray]. * * @property array the underlying array. + * @author Iaroslav Postovalov */ inline class FloatBuffer(val array: FloatArray) : MutableBuffer { override val size: Int get() = array.size From f815e97873824540abf6c23223bcf21f313279c5 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 20 Sep 2020 19:06:01 +0700 Subject: [PATCH 047/199] Update AutoDiff.kt to match new trigonometric functions --- .../kotlin/scientifik/kmath/misc/AutoDiff.kt | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt index 808312877..3ff5fb557 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt @@ -65,7 +65,6 @@ inline fun > F.deriv(body: AutoDiffField.() -> Varia } } - abstract class AutoDiffField> : Field> { abstract val context: F @@ -152,7 +151,6 @@ internal class AutoDiffContext>(override val context: F) : // Basic math (+, -, *, /) - override fun add(a: Variable, b: Variable): Variable = derive(variable { a.value + b.value }) { z -> a.d += z.d b.d += z.d @@ -173,38 +171,66 @@ internal class AutoDiffContext>(override val context: F) : } } -// Extensions for differentiation of various basic mathematical functions - -// x ^ 2 fun > AutoDiffField.sqr(x: Variable): Variable = derive(variable { x.value * x.value }) { z -> x.d += z.d * 2 * x.value } -// x ^ 1/2 fun > AutoDiffField.sqrt(x: Variable): Variable = derive(variable { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value } -// x ^ y (const) fun > AutoDiffField.pow(x: Variable, y: Double): Variable = derive(variable { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) } -fun > AutoDiffField.pow(x: Variable, y: Int): Variable = pow(x, y.toDouble()) +fun > AutoDiffField.pow(x: Variable, y: Int): Variable = + pow(x, y.toDouble()) -// exp(x) fun > AutoDiffField.exp(x: Variable): Variable = derive(variable { exp(x.value) }) { z -> x.d += z.d * z.value } -// ln(x) fun > AutoDiffField.ln(x: Variable): Variable = derive(variable { ln(x.value) }) { z -> x.d += z.d / x.value } -// x ^ y (any) fun > AutoDiffField.pow(x: Variable, y: Variable): Variable = exp(y * ln(x)) -// sin(x) fun > AutoDiffField.sin(x: Variable): Variable = derive(variable { sin(x.value) }) { z -> x.d += z.d * cos(x.value) } -// cos(x) fun > AutoDiffField.cos(x: Variable): Variable = derive(variable { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) } + +fun > AutoDiffField.tan(x: Variable): Variable = + derive(variable { tan(x.value) }) { z -> + val c = cos(x.value) + x.d += z.d / (c * c) + } + +fun > AutoDiffField.asin(x: Variable): Variable = + derive(variable { asin(x.value) }) { z -> x.d += z.d / sqrt(one - x.value * x.value) } + +fun > AutoDiffField.acos(x: Variable): Variable = + derive(variable { acos(x.value) }) { z -> x.d -= z.d / sqrt(one - x.value * x.value) } + +fun > AutoDiffField.atan(x: Variable): Variable = + derive(variable { atan(x.value) }) { z -> x.d += z.d / (one + x.value * x.value) } + +fun > AutoDiffField.sinh(x: Variable): Variable = + derive(variable { sin(x.value) }) { z -> x.d += z.d * cosh(x.value) } + +fun > AutoDiffField.cosh(x: Variable): Variable = + derive(variable { cos(x.value) }) { z -> x.d -= z.d * sinh(x.value) } + +fun > AutoDiffField.tanh(x: Variable): Variable = + derive(variable { tan(x.value) }) { z -> + val c = cosh(x.value) + x.d += z.d / (c * c) + } + +fun > AutoDiffField.asinh(x: Variable): Variable = + derive(variable { asin(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) } + +fun > AutoDiffField.acosh(x: Variable): Variable = + derive(variable { acos(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) } + +fun > AutoDiffField.atanh(x: Variable): Variable = + derive(variable { atan(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) } + From b89a05347cd4d06a4e1aa6f035a39b2c368e2b98 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 20 Sep 2020 19:26:44 +0700 Subject: [PATCH 048/199] Hotfix some problems with MstAlgebra.kt --- .../kotlin/scientifik/kmath/ast/MstAlgebra.kt | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt index 23deae24b..29b76f7ca 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt @@ -38,7 +38,9 @@ object MstSpace : Space, NumericAlgebra { * [Ring] over [MST] nodes. */ object MstRing : Ring, NumericAlgebra { - override val zero: MST = number(0.0) + override val zero: MST + get() = MstSpace.zero + override val one: MST = number(1.0) override fun number(value: Number): MST = MstSpace.number(value) @@ -59,8 +61,11 @@ object MstRing : Ring, NumericAlgebra { * [Field] over [MST] nodes. */ object MstField : Field { - override val zero: MST = number(0.0) - override val one: MST = number(1.0) + override val zero: MST + get() = MstRing.zero + + override val one: MST + get() = MstRing.one override fun symbol(value: String): MST = MstRing.symbol(value) override fun number(value: Number): MST = MstRing.number(value) @@ -79,14 +84,25 @@ object MstField : Field { * [ExtendedField] over [MST] nodes. */ object MstExtendedField : ExtendedField { - override val zero: MST = number(0.0) - override val one: MST = number(1.0) + override val zero: MST + get() = MstField.zero + override val one: MST + get() = MstField.one + + override fun symbol(value: String): MST = MstField.symbol(value) override fun sin(arg: MST): MST = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) override fun cos(arg: MST): MST = unaryOperation(TrigonometricOperations.COS_OPERATION, arg) + override fun tan(arg: MST): MST = unaryOperation(TrigonometricOperations.TAN_OPERATION, arg) override fun asin(arg: MST): MST = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg) override fun acos(arg: MST): MST = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg) override fun atan(arg: MST): MST = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg) + override fun sinh(arg: MST): MST = unaryOperation(HyperbolicOperations.SINH_OPERATION, arg) + override fun cosh(arg: MST): MST = unaryOperation(HyperbolicOperations.COSH_OPERATION, arg) + override fun tanh(arg: MST): MST = unaryOperation(HyperbolicOperations.TANH_OPERATION, arg) + override fun asinh(arg: MST): MST = unaryOperation(HyperbolicOperations.ASINH_OPERATION, arg) + override fun acosh(arg: MST): MST = unaryOperation(HyperbolicOperations.ACOSH_OPERATION, arg) + override fun atanh(arg: MST): MST = unaryOperation(HyperbolicOperations.ATANH_OPERATION, arg) override fun add(a: MST, b: MST): MST = MstField.add(a, b) override fun multiply(a: MST, k: Number): MST = MstField.multiply(a, k) override fun multiply(a: MST, b: MST): MST = MstField.multiply(a, b) From 1b426d79b42b9d2e2a78021400b519a0cb281710 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 20 Sep 2020 19:31:17 +0700 Subject: [PATCH 049/199] Fix sign in (d/dx)*cosh(x)=sinh(x) --- .../src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt index 3ff5fb557..8bc3f2936 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt @@ -217,7 +217,7 @@ fun > AutoDiffField.sinh(x: Variable): Va derive(variable { sin(x.value) }) { z -> x.d += z.d * cosh(x.value) } fun > AutoDiffField.cosh(x: Variable): Variable = - derive(variable { cos(x.value) }) { z -> x.d -= z.d * sinh(x.value) } + derive(variable { cos(x.value) }) { z -> x.d += z.d * sinh(x.value) } fun > AutoDiffField.tanh(x: Variable): Variable = derive(variable { tan(x.value) }) { z -> From a03c650f65019ce4ba7148540d1d8b6e51396d2a Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 20 Sep 2020 20:59:21 +0700 Subject: [PATCH 050/199] Add tests and update changelog --- CHANGELOG.md | 4 +- .../kotlin/scientifik/kmath/misc/AutoDiff.kt | 6 +- .../scientifik/kmath/misc/AutoDiffTest.kt | 138 ++++++++++++++---- 3 files changed, 114 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bcc57810..ef675b692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## [Unreleased] ### Added - +- Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140). ### Changed ### Deprecated @@ -10,7 +10,7 @@ ### Removed ### Fixed - +- `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) ### Security ## [0.1.4] diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt index 8bc3f2936..d701dbfc8 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt @@ -226,11 +226,11 @@ fun > AutoDiffField.tanh(x: Variable): Va } fun > AutoDiffField.asinh(x: Variable): Variable = - derive(variable { asin(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) } + derive(variable { asinh(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) } fun > AutoDiffField.acosh(x: Variable): Variable = - derive(variable { acos(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) } + derive(variable { acosh(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) } fun > AutoDiffField.atanh(x: Variable): Variable = - derive(variable { atan(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) } + derive(variable { atanh(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) } diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt index c08a63ccb..aba6c06ca 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt @@ -3,19 +3,19 @@ package scientifik.kmath.misc import scientifik.kmath.operations.RealField import scientifik.kmath.structures.asBuffer import kotlin.math.PI +import kotlin.math.pow +import kotlin.math.sqrt import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue class AutoDiffTest { - fun Variable(int: Int): Variable = Variable(int.toDouble()) - - fun deriv(body: AutoDiffField.() -> Variable): DerivationResult = + inline fun deriv(body: AutoDiffField.() -> Variable): DerivationResult = RealField.deriv(body) @Test fun testPlusX2() { - val x = Variable(3) // diff w.r.t this x at 3 + val x = Variable(3.0) // diff w.r.t this x at 3 val y = deriv { x + x } assertEquals(6.0, y.value) // y = x + x = 6 assertEquals(2.0, y.deriv(x)) // dy/dx = 2 @@ -24,8 +24,8 @@ class AutoDiffTest { @Test fun testPlus() { // two variables - val x = Variable(2) - val y = Variable(3) + val x = Variable(2.0) + val y = Variable(3.0) val z = deriv { x + y } assertEquals(5.0, z.value) // z = x + y = 5 assertEquals(1.0, z.deriv(x)) // dz/dx = 1 @@ -35,8 +35,8 @@ class AutoDiffTest { @Test fun testMinus() { // two variables - val x = Variable(7) - val y = Variable(3) + val x = Variable(7.0) + val y = Variable(3.0) val z = deriv { x - y } assertEquals(4.0, z.value) // z = x - y = 4 assertEquals(1.0, z.deriv(x)) // dz/dx = 1 @@ -45,7 +45,7 @@ class AutoDiffTest { @Test fun testMulX2() { - val x = Variable(3) // diff w.r.t this x at 3 + val x = Variable(3.0) // diff w.r.t this x at 3 val y = deriv { x * x } assertEquals(9.0, y.value) // y = x * x = 9 assertEquals(6.0, y.deriv(x)) // dy/dx = 2 * x = 7 @@ -53,7 +53,7 @@ class AutoDiffTest { @Test fun testSqr() { - val x = Variable(3) + val x = Variable(3.0) val y = deriv { sqr(x) } assertEquals(9.0, y.value) // y = x ^ 2 = 9 assertEquals(6.0, y.deriv(x)) // dy/dx = 2 * x = 7 @@ -61,7 +61,7 @@ class AutoDiffTest { @Test fun testSqrSqr() { - val x = Variable(2) + val x = Variable(2.0) val y = deriv { sqr(sqr(x)) } assertEquals(16.0, y.value) // y = x ^ 4 = 16 assertEquals(32.0, y.deriv(x)) // dy/dx = 4 * x^3 = 32 @@ -69,7 +69,7 @@ class AutoDiffTest { @Test fun testX3() { - val x = Variable(2) // diff w.r.t this x at 2 + val x = Variable(2.0) // diff w.r.t this x at 2 val y = deriv { x * x * x } assertEquals(8.0, y.value) // y = x * x * x = 8 assertEquals(12.0, y.deriv(x)) // dy/dx = 3 * x * x = 12 @@ -77,8 +77,8 @@ class AutoDiffTest { @Test fun testDiv() { - val x = Variable(5) - val y = Variable(2) + val x = Variable(5.0) + val y = Variable(2.0) val z = deriv { x / y } assertEquals(2.5, z.value) // z = x / y = 2.5 assertEquals(0.5, z.deriv(x)) // dz/dx = 1 / y = 0.5 @@ -87,7 +87,7 @@ class AutoDiffTest { @Test fun testPow3() { - val x = Variable(2) // diff w.r.t this x at 2 + val x = Variable(2.0) // diff w.r.t this x at 2 val y = deriv { pow(x, 3) } assertEquals(8.0, y.value) // y = x ^ 3 = 8 assertEquals(12.0, y.deriv(x)) // dy/dx = 3 * x ^ 2 = 12 @@ -95,8 +95,8 @@ class AutoDiffTest { @Test fun testPowFull() { - val x = Variable(2) - val y = Variable(3) + val x = Variable(2.0) + val y = Variable(3.0) val z = deriv { pow(x, y) } assertApprox(8.0, z.value) // z = x ^ y = 8 assertApprox(12.0, z.deriv(x)) // dz/dx = y * x ^ (y - 1) = 12 @@ -105,7 +105,7 @@ class AutoDiffTest { @Test fun testFromPaper() { - val x = Variable(3) + val x = Variable(3.0) val y = deriv { 2 * x + x * x * x } assertEquals(33.0, y.value) // y = 2 * x + x * x * x = 33 assertEquals(29.0, y.deriv(x)) // dy/dx = 2 + 3 * x * x = 29 @@ -113,9 +113,9 @@ class AutoDiffTest { @Test fun testInnerVariable() { - val x = Variable(1) + val x = Variable(1.0) val y = deriv { - Variable(1) * x + Variable(1.0) * x } assertEquals(1.0, y.value) // y = x ^ n = 1 assertEquals(1.0, y.deriv(x)) // dy/dx = n * x ^ (n - 1) = n - 1 @@ -124,9 +124,9 @@ class AutoDiffTest { @Test fun testLongChain() { val n = 10_000 - val x = Variable(1) + val x = Variable(1.0) val y = deriv { - var res = Variable(1) + var res = Variable(1.0) for (i in 1..n) res *= x res } @@ -136,7 +136,7 @@ class AutoDiffTest { @Test fun testExample() { - val x = Variable(2) + val x = Variable(2.0) val y = deriv { sqr(x) + 5 * x + 3 } assertEquals(17.0, y.value) // the value of result (y) assertEquals(9.0, y.deriv(x)) // dy/dx @@ -144,7 +144,7 @@ class AutoDiffTest { @Test fun testSqrt() { - val x = Variable(16) + val x = Variable(16.0) val y = deriv { sqrt(x) } assertEquals(4.0, y.value) // y = x ^ 1/2 = 4 assertEquals(1.0 / 8, y.deriv(x)) // dy/dx = 1/2 / x ^ 1/4 = 1/8 @@ -152,18 +152,98 @@ class AutoDiffTest { @Test fun testSin() { - val x = Variable(PI / 6) + val x = Variable(PI / 6.0) val y = deriv { sin(x) } - assertApprox(0.5, y.value) // y = sin(PI/6) = 0.5 - assertApprox(kotlin.math.sqrt(3.0) / 2, y.deriv(x)) // dy/dx = cos(PI/6) = sqrt(3)/2 + assertApprox(0.5, y.value) // y = sin(PI/6) = 0.5 + assertApprox(sqrt(3.0) / 2, y.deriv(x)) // dy/dx = cos(pi/6) = sqrt(3)/2 } @Test fun testCos() { val x = Variable(PI / 6) val y = deriv { cos(x) } - assertApprox(kotlin.math.sqrt(3.0) / 2, y.value) // y = cos(PI/6) = sqrt(3)/2 - assertApprox(-0.5, y.deriv(x)) // dy/dx = -sin(PI/6) = -0.5 + assertApprox(sqrt(3.0) / 2, y.value) //y = cos(pi/6) = sqrt(3)/2 + assertApprox(-0.5, y.deriv(x)) // dy/dx = -sin(pi/6) = -0.5 + } + + @Test + fun testTan() { + val x = Variable(PI / 6) + val y = deriv { tan(x) } + assertApprox(1.0 / sqrt(3.0), y.value) // y = tan(pi/6) = 1/sqrt(3) + assertApprox(4.0 / 3.0, y.deriv(x)) // dy/dx = sec(pi/6)^2 = 4/3 + } + + @Test + fun testAsin() { + val x = Variable(PI / 6) + val y = deriv { asin(x) } + assertApprox(kotlin.math.asin(PI / 6.0), y.value) // y = asin(pi/6) + assertApprox(6.0 / sqrt(36 - PI * PI), y.deriv(x)) // dy/dx = 6/sqrt(36-pi^2) + } + + @Test + fun testAcos() { + val x = Variable(PI / 6) + val y = deriv { acos(x) } + assertApprox(kotlin.math.acos(PI / 6.0), y.value) // y = acos(pi/6) + assertApprox(-6.0 / sqrt(36.0 - PI * PI), y.deriv(x)) // dy/dx = -6/sqrt(36-pi^2) + } + + @Test + fun testAtan() { + val x = Variable(PI / 6) + val y = deriv { atan(x) } + assertApprox(kotlin.math.atan(PI / 6.0), y.value) // y = atan(pi/6) + assertApprox(36.0 / (36.0 + PI * PI), y.deriv(x)) // dy/dx = 36/(36+pi^2) + } + + @Test + fun testSinh() { + val x = Variable(0.0) + val y = deriv { sinh(x) } + assertApprox(kotlin.math.sinh(0.0), y.value) // y = sinh(pi/6) + assertApprox(kotlin.math.cosh(0.0), y.deriv(x)) // dy/dx = cosh(pi/6) + } + + @Test + fun testCosh() { + val x = Variable(0.0) + val y = deriv { cosh(x) } + assertApprox(1.0, y.value) //y = cosh(pi/6) + assertApprox(0.0, y.deriv(x)) // dy/dx = sinh(pi/6) + } + + @Test + fun testTanh() { + val x = Variable(PI / 6) + val y = deriv { tanh(x) } + assertApprox(1.0 / sqrt(3.0), y.value) // y = tan(pi/6) = 1/sqrt(3) + assertApprox(1.0 / kotlin.math.cosh(PI / 6.0).pow(2), y.deriv(x)) // dy/dx = sec(PI/6)^2 + } + + @Test + fun testAsinh() { + val x = Variable(PI / 6) + val y = deriv { asinh(x) } + assertApprox(kotlin.math.asinh(PI / 6.0), y.value) // y = asinh(pi/6) + assertApprox(6.0 / sqrt(36 + PI * PI), y.deriv(x)) // dy/dx = 6/sqrt(pi^2+36) + } + + @Test + fun testAcosh() { + val x = Variable(PI / 6) + val y = deriv { acosh(x) } + assertApprox(kotlin.math.acosh(PI / 6.0), y.value) // y = acosh(pi/6) + assertApprox(-6.0 / sqrt(36.0 - PI * PI), y.deriv(x)) // dy/dx = -6/sqrt(36-pi^2) + } + + @Test + fun testAtanh() { + val x = Variable(PI / 6.0) + val y = deriv { atanh(x) } + assertApprox(kotlin.math.atanh(PI / 6.0), y.value) // y = atanh(pi/6) + assertApprox(-36.0 / (PI * PI - 36.0), y.deriv(x)) // dy/dx = -36/(pi^2-36) } @Test From 6374d7a36099c84a03a958646651da58d2de6d1c Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 20 Sep 2020 21:05:37 +0700 Subject: [PATCH 051/199] Update tests --- .../kotlin/scientifik/kmath/misc/AutoDiffTest.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt index aba6c06ca..91d32cf8e 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt @@ -202,24 +202,24 @@ class AutoDiffTest { fun testSinh() { val x = Variable(0.0) val y = deriv { sinh(x) } - assertApprox(kotlin.math.sinh(0.0), y.value) // y = sinh(pi/6) - assertApprox(kotlin.math.cosh(0.0), y.deriv(x)) // dy/dx = cosh(pi/6) + assertApprox(kotlin.math.sinh(0.0), y.value) // y = sinh(0) + assertApprox(kotlin.math.cosh(0.0), y.deriv(x)) // dy/dx = cosh(0) } @Test fun testCosh() { val x = Variable(0.0) val y = deriv { cosh(x) } - assertApprox(1.0, y.value) //y = cosh(pi/6) - assertApprox(0.0, y.deriv(x)) // dy/dx = sinh(pi/6) + assertApprox(1.0, y.value) //y = cosh(0) + assertApprox(0.0, y.deriv(x)) // dy/dx = sinh(0) } @Test fun testTanh() { val x = Variable(PI / 6) val y = deriv { tanh(x) } - assertApprox(1.0 / sqrt(3.0), y.value) // y = tan(pi/6) = 1/sqrt(3) - assertApprox(1.0 / kotlin.math.cosh(PI / 6.0).pow(2), y.deriv(x)) // dy/dx = sec(PI/6)^2 + assertApprox(1.0 / sqrt(3.0), y.value) // y = tanh(pi/6) + assertApprox(1.0 / kotlin.math.cosh(PI / 6.0).pow(2), y.deriv(x)) // dy/dx = sech(pi/6)^2 } @Test From da742d6c69513ed35c946d287767f34a0b807992 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 20 Sep 2020 22:25:50 +0300 Subject: [PATCH 052/199] Fix things after merge --- build.gradle.kts | 15 +++---------- kmath-ast/build.gradle.kts | 2 +- .../kotlin/scientifik/kmath/ast/parser.kt | 13 ++++++------ .../kotlin/scientifik/kmath/misc/AutoDiff.kt | 21 +++++++++---------- settings.gradle.kts | 6 +++--- 5 files changed, 23 insertions(+), 34 deletions(-) rename kmath-ast/src/{commonMain => jvmMain}/kotlin/scientifik/kmath/ast/parser.kt (89%) diff --git a/build.gradle.kts b/build.gradle.kts index 384db5385..838a05771 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,11 +1,10 @@ -plugins { id("ru.mipt.npm.publish") apply false } plugins { - id("scientifik.publish") apply false + id("ru.mipt.npm.base") id("org.jetbrains.changelog") version "0.4.0" } -val kmathVersion by extra("0.1.4") -val bintrayRepo by extra("scientifik") +val kmathVersion by extra("0.2.0-dev-1") +val bintrayRepo by extra("kscience") val githubProject by extra("kmath") allprojects { @@ -17,14 +16,6 @@ allprojects { group = "kscience.kmath" version = kmathVersion - - afterEvaluate { - extensions.findByType()?.run { - sourceSets.all { - languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") - } - } - } } subprojects { if (name.startsWith("kmath")) apply(plugin = "ru.mipt.npm.publish") } diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 3e0a441b7..df876df10 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -6,7 +6,6 @@ kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-core")) - implementation("com.github.h0tk3y.betterParse:better-parse:0.4.0") } } @@ -14,6 +13,7 @@ kotlin.sourceSets { dependencies { implementation("org.ow2.asm:asm:8.0.1") implementation("org.ow2.asm:asm-commons:8.0.1") + implementation("com.github.h0tk3y.betterParse:better-parse:0.4.0") implementation(kotlin("reflect")) } } diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/parser.kt similarity index 89% rename from kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt rename to kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/parser.kt index e48b2817f..8ccbf4606 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/parser.kt @@ -16,8 +16,7 @@ import scientifik.kmath.operations.RingOperations import scientifik.kmath.operations.SpaceOperations /** - * TODO move to core - * + * TODO move to common after IR version is released * @author Alexander Nozik and Iaroslav Postovalov */ public object ArithmeticsEvaluator : Grammar() { @@ -37,14 +36,14 @@ public object ArithmeticsEvaluator : Grammar() { private val number: Parser by num use { MST.Numeric(text.toDouble()) } private val singular: Parser by id use { MST.Symbolic(text) } - private val unaryFunction: Parser by (id and -lpar and parser(::subSumChain) and -rpar) + private val unaryFunction: Parser by (id and -lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar) .map { (id, term) -> MST.Unary(id.text, term) } private val binaryFunction: Parser by id .and(-lpar) - .and(parser(::subSumChain)) + .and(parser(ArithmeticsEvaluator::subSumChain)) .and(-comma) - .and(parser(::subSumChain)) + .and(parser(ArithmeticsEvaluator::subSumChain)) .and(-rpar) .map { (id, left, right) -> MST.Binary(id.text, left, right) } @@ -52,8 +51,8 @@ public object ArithmeticsEvaluator : Grammar() { .or(binaryFunction) .or(unaryFunction) .or(singular) - .or(-minus and parser(::term) map { MST.Unary(SpaceOperations.MINUS_OPERATION, it) }) - .or(-lpar and parser(::subSumChain) and -rpar) + .or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(SpaceOperations.MINUS_OPERATION, it) }) + .or(-lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar) private val powChain: Parser by leftAssociative(term = term, operator = pow) { a, _, b -> MST.Binary(PowerOperations.POW_OPERATION, a, b) diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt index 1c4cc63b6..b09bcff9f 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt @@ -65,7 +65,6 @@ public inline fun > F.deriv(body: AutoDiffField.() - } } - public abstract class AutoDiffField> : Field> { public abstract val context: F @@ -209,39 +208,39 @@ public fun > AutoDiffField.sin(x: Variable> AutoDiffField.cos(x: Variable): Variable = derive(variable { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) } -fun > AutoDiffField.tan(x: Variable): Variable = +public fun > AutoDiffField.tan(x: Variable): Variable = derive(variable { tan(x.value) }) { z -> val c = cos(x.value) x.d += z.d / (c * c) } -fun > AutoDiffField.asin(x: Variable): Variable = +public fun > AutoDiffField.asin(x: Variable): Variable = derive(variable { asin(x.value) }) { z -> x.d += z.d / sqrt(one - x.value * x.value) } -fun > AutoDiffField.acos(x: Variable): Variable = +public fun > AutoDiffField.acos(x: Variable): Variable = derive(variable { acos(x.value) }) { z -> x.d -= z.d / sqrt(one - x.value * x.value) } -fun > AutoDiffField.atan(x: Variable): Variable = +public fun > AutoDiffField.atan(x: Variable): Variable = derive(variable { atan(x.value) }) { z -> x.d += z.d / (one + x.value * x.value) } -fun > AutoDiffField.sinh(x: Variable): Variable = +public fun > AutoDiffField.sinh(x: Variable): Variable = derive(variable { sin(x.value) }) { z -> x.d += z.d * cosh(x.value) } -fun > AutoDiffField.cosh(x: Variable): Variable = +public fun > AutoDiffField.cosh(x: Variable): Variable = derive(variable { cos(x.value) }) { z -> x.d += z.d * sinh(x.value) } -fun > AutoDiffField.tanh(x: Variable): Variable = +public fun > AutoDiffField.tanh(x: Variable): Variable = derive(variable { tan(x.value) }) { z -> val c = cosh(x.value) x.d += z.d / (c * c) } -fun > AutoDiffField.asinh(x: Variable): Variable = +public fun > AutoDiffField.asinh(x: Variable): Variable = derive(variable { asinh(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) } -fun > AutoDiffField.acosh(x: Variable): Variable = +public fun > AutoDiffField.acosh(x: Variable): Variable = derive(variable { acosh(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) } -fun > AutoDiffField.atanh(x: Variable): Variable = +public fun > AutoDiffField.atanh(x: Variable): Variable = derive(variable { atanh(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) } diff --git a/settings.gradle.kts b/settings.gradle.kts index b78ed4647..666a05e45 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,12 +1,13 @@ pluginManagement { - val toolsVersion = "0.6.0-dev-5" + val toolsVersion = "0.6.0" plugins { id("kotlinx.benchmark") version "0.2.0-dev-20" + id("ru.mipt.npm.base") version toolsVersion id("ru.mipt.npm.mpp") version toolsVersion id("ru.mipt.npm.jvm") version toolsVersion id("ru.mipt.npm.publish") version toolsVersion - kotlin("plugin.allopen") version "1.4.20-dev-3898-14" + kotlin("plugin.allopen") } repositories { @@ -17,7 +18,6 @@ pluginManagement { maven("https://dl.bintray.com/mipt-npm/scientifik") maven("https://dl.bintray.com/mipt-npm/dev") maven("https://dl.bintray.com/kotlin/kotlinx") - } maven("https://dl.bintray.com/kotlin/kotlin-dev/") } } From 28190f980012018392dcfd98c3010164e5716142 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 20 Sep 2020 22:39:27 +0300 Subject: [PATCH 053/199] scientifik -> kscience --- README.md | 8 ++-- doc/algebra.md | 8 ++-- examples/build.gradle.kts | 2 +- .../kmath/structures/ArrayBenchmark.kt | 39 +++++++++++++++++++ .../kmath/structures/BufferBenchmark.kt | 6 +-- .../kmath/structures/NDFieldBenchmark.kt | 6 +-- .../kmath/structures/ViktorBenchmark.kt | 8 ++-- .../kmath/utils/utils.kt | 2 +- .../kmath/structures/ArrayBenchmark.kt | 37 ------------------ .../ast/ExpressionsInterpretersBenchmark.kt | 14 +++---- .../commons/prob/DistributionBenchmark.kt | 6 +-- .../kmath/commons/prob/DistributionDemo.kt | 12 +++--- .../kmath/operations/BigIntDemo.kt | 2 +- .../kmath/operations/ComplexDemo.kt | 8 ++-- .../kmath/structures/ComplexND.kt | 10 ++--- .../kmath/structures/NDField.kt | 6 +-- .../structures/StructureReadBenchmark.kt | 2 +- .../structures/StructureWriteBenchmark.kt | 2 +- .../kmath/structures/typeSafeDimensions.kt | 12 +++--- kmath-ast/README.md | 18 ++++----- .../{scientifik => kscience}/kmath/ast/MST.kt | 8 ++-- .../kmath/ast/MstAlgebra.kt | 4 +- .../kmath/ast/MstExpression.kt | 6 +-- .../{scientifik => kscience}/kmath/asm/asm.kt | 18 ++++----- .../kmath/asm/internal/AsmBuilder.kt | 14 +++---- .../kmath/asm/internal/MstType.kt | 4 +- .../kmath/asm/internal/codegenUtils.kt | 16 ++++---- .../kmath/asm/internal/mapIntrinsics.kt | 2 +- .../kmath/ast/parser.kt | 10 ++--- .../scietifik/kmath/asm/TestAsmAlgebras.kt | 14 +++---- .../scietifik/kmath/asm/TestAsmExpressions.kt | 10 ++--- .../kmath/asm/TestAsmSpecialization.kt | 8 ++-- .../scietifik/kmath/asm/TestAsmVariables.kt | 6 +-- .../kotlin/scietifik/kmath/ast/AsmTest.kt | 14 +++---- .../kmath/ast/ParserPrecedenceTest.kt | 8 ++-- .../kotlin/scietifik/kmath/ast/ParserTest.kt | 16 ++++---- .../commons/expressions/DiffExpression.kt | 12 +++--- .../kmath/commons/linear/CMMatrix.kt | 8 ++-- .../kmath/commons/linear/CMSolver.kt | 6 +-- .../random/CMRandomGeneratorWrapper.kt | 4 +- .../commons/transform/Transformations.kt | 10 ++--- .../kmath/commons/expressions/AutoDiffTest.kt | 4 +- kmath-core/README.md | 12 +++--- .../kmath/domains/Domain.kt | 4 +- .../kmath/domains/HyperSquareDomain.kt | 8 ++-- .../kmath/domains/RealDomain.kt | 4 +- .../kmath/domains/UnconstrainedDomain.kt | 4 +- .../kmath/domains/UnivariateDomain.kt | 6 +-- .../kmath/expressions/Expression.kt | 4 +- .../FunctionalExpressionAlgebra.kt | 4 +- .../kmath/expressions/expressionBuilders.kt | 10 ++--- .../kmath/linear/BufferMatrix.kt | 8 ++-- .../kmath/linear/FeaturedMatrix.kt | 11 +++--- .../kmath/linear/LUPDecomposition.kt | 17 ++++---- .../kmath/linear/LinearAlgebra.kt | 8 ++-- .../kmath/linear/MatrixBuilder.kt | 10 ++--- .../kmath/linear/MatrixContext.kt | 18 ++++----- .../kmath/linear/MatrixFeatures.kt | 2 +- .../kmath/linear/VectorSpace.kt | 12 +++--- .../kmath/linear/VirtualMatrix.kt | 4 +- .../kmath/misc/AutoDiff.kt | 14 +++---- .../kmath/misc/Grids.kt | 2 +- .../kmath/misc/cumulative.kt | 7 ++-- .../kmath/operations/Algebra.kt | 4 +- .../kmath/operations/AlgebraElements.kt | 2 +- .../kmath/operations/AlgebraExtensions.kt | 2 +- .../kmath/operations/BigInt.kt | 9 ++--- .../kmath/operations/Complex.kt | 15 ++++--- .../kmath/operations/NumberAlgebra.kt | 2 +- .../kmath/operations/OptionalOperations.kt | 2 +- .../kmath/structures/BoxingNDField.kt | 6 +-- .../kmath/structures/BoxingNDRing.kt | 6 +-- .../kmath/structures/BufferAccessor2D.kt | 2 +- .../kmath/structures/BufferedNDAlgebra.kt | 4 +- .../kmath/structures/BufferedNDElement.kt | 4 +- .../kmath/structures/Buffers.kt | 7 ++-- .../kmath/structures/ComplexNDField.kt | 10 ++--- .../kmath/structures/ExtendedNDField.kt | 4 +- .../kmath/structures/FlaggedBuffer.kt | 3 +- .../kmath/structures/FloatBuffer.kt | 4 +- .../kmath/structures/IntBuffer.kt | 4 +- .../kmath/structures/LongBuffer.kt | 4 +- .../kmath/structures/MemoryBuffer.kt | 4 +- .../kmath/structures/NDAlgebra.kt | 10 ++--- .../kmath/structures/NDElement.kt | 11 +++--- .../kmath/structures/NDStructure.kt | 3 +- .../kmath/structures/RealBuffer.kt | 4 +- .../kmath/structures/RealBufferField.kt | 6 +-- .../kmath/structures/RealNDField.kt | 6 +-- .../kmath/structures/ShortBuffer.kt | 4 +- .../kmath/structures/ShortNDRing.kt | 6 +-- .../kmath/structures/Structure1D.kt | 2 +- .../kmath/structures/Structure2D.kt | 2 +- .../kmath/expressions/ExpressionFieldTest.kt | 10 ++--- .../kmath/linear/MatrixTest.kt | 8 ++-- .../kmath/linear/RealLUSolverTest.kt | 4 +- .../kmath/linear/VectorSpaceTest.kt | 0 .../kmath/misc/AutoDiffTest.kt | 6 +-- .../kmath/misc/CumulativeKtTest.kt | 2 +- .../kmath/operations/BigIntAlgebraTest.kt | 4 +- .../kmath/operations/BigIntConstructorTest.kt | 2 +- .../kmath/operations/BigIntConversionsTest.kt | 2 +- .../kmath/operations/BigIntOperationsTest.kt | 2 +- .../kmath/operations/ComplexFieldTest.kt | 4 +- .../kmath/operations/ComplexTest.kt | 2 +- .../kmath/operations/RealFieldTest.kt | 4 +- .../operations/internal/AlgebraicVerifier.kt | 4 +- .../operations/internal/FieldVerifier.kt | 6 +-- .../kmath/operations/internal/RingVerifier.kt | 6 +-- .../operations/internal/SpaceVerifier.kt | 6 +-- .../kmath/structures/ComplexBufferSpecTest.kt | 6 +-- .../kmath/structures/NDFieldTest.kt | 2 +- .../kmath/structures/NumberNDFieldTest.kt | 8 ++-- .../kmath/operations/BigNumbers.kt | 2 +- .../kmath/chains/BlockingIntChain.kt | 2 +- .../kmath/chains/BlockingRealChain.kt | 2 +- .../kmath/chains/Chain.kt | 2 +- .../kmath/chains/flowExtra.kt | 8 ++-- .../kmath/coroutines/coroutinesExtra.kt | 2 +- .../kmath/streaming/BufferFlow.kt | 12 +++--- .../kmath/streaming/RingBuffer.kt | 8 ++-- .../kmath/chains/ChainExt.kt | 2 +- .../kmath/structures/LazyNDStructure.kt | 4 +- .../kmath/streaming/BufferFlowTest.kt | 8 ++-- .../kmath/streaming/RingBufferTest.kt | 4 +- .../kmath/dimensions/Dimensions.kt | 2 +- .../kmath/dimensions/Wrappers.kt | 20 +++++----- .../dimensions/DMatrixContextTest.kt | 8 ++-- .../kmath/dimensions/dim.kt | 2 +- .../kmath/dimensions/dim.kt | 2 +- .../kmath/real/RealVector.kt | 22 +++++------ .../kmath/real/realBuffer.kt | 4 +- .../kmath/real/realMatrix.kt | 21 +++++----- .../kmath/linear/VectorTest.kt | 6 +-- .../scientific.kmath.real/RealMatrixTest.kt | 8 ++-- .../kmath/functions/Piecewise.kt | 4 +- .../kmath/functions/Polynomial.kt | 8 ++-- .../kmath/functions/functions.kt | 6 +-- .../kmath/interpolation/Interpolator.kt | 12 +++--- .../kmath/interpolation/LinearInterpolator.kt | 12 +++--- .../kmath/interpolation/LoessInterpolator.kt | 8 ++-- .../kmath/interpolation/SplineInterpolator.kt | 14 +++---- .../kmath/interpolation/XYPointSet.kt | 6 +-- .../interpolation/LinearInterpolatorTest.kt | 8 ++-- .../kmath/geometry/Euclidean2DSpace.kt | 8 ++-- .../kmath/geometry/Euclidean3DSpace.kt | 8 ++-- .../kmath/geometry/GeometrySpace.kt | 4 +- .../kmath/geometry/Line.kt | 2 +- .../kscience/kmath/geometry/ReferenceFrame.kt | 3 ++ .../kmath/geometry/ReferenceFrame.kt | 3 -- .../kmath/histogram/Counters.kt | 2 +- .../kmath/histogram/Histogram.kt | 10 ++--- .../kmath/histogram/RealHistogram.kt | 12 +++--- .../histogram/MultivariateHistogramTest.kt | 8 ++-- .../kmath/histogram/Counters.kt | 2 +- .../kmath/histogram/Counters.kt | 2 +- .../kmath/histogram/UnivariateHistogram.kt | 8 ++-- .../kotlin/scientifik/memory/Memory.kt | 2 +- .../kotlin/scientifik/memory/MemorySpec.kt | 2 +- .../scientifik/memory/DataViewMemory.kt | 2 +- .../scientifik/memory/ByteBufferMemory.kt | 2 +- .../kmath/prob/Distribution.kt | 10 ++--- .../kmath/prob/FactorizedDistribution.kt | 6 +-- .../kmath/prob/RandomChain.kt | 4 +- .../kmath/prob/RandomGenerator.kt | 2 +- .../kmath/prob/SamplerAlgebra.kt | 14 +++---- .../kmath/prob/Statistic.kt | 12 +++--- .../kmath/prob/UniformDistribution.kt | 6 +-- .../kmath/prob/RandomSourceGenerator.kt | 2 +- .../kmath/prob/distributions.kt | 9 ++--- .../kmath/prob/CommonsDistributionsTest.kt | 2 +- .../kmath/prob/SamplerTest.kt | 2 +- .../kmath/prob/StatisticTest.kt | 4 +- .../kmath/viktor/ViktorBuffer.kt | 4 +- .../kmath/viktor/ViktorNDStructure.kt | 12 +++--- settings.gradle.kts | 2 +- 176 files changed, 599 insertions(+), 620 deletions(-) create mode 100644 examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt rename examples/src/benchmarks/kotlin/{scientifik => kscience}/kmath/structures/BufferBenchmark.kt (83%) rename examples/src/benchmarks/kotlin/{scientifik => kscience}/kmath/structures/NDFieldBenchmark.kt (89%) rename examples/src/benchmarks/kotlin/{scientifik => kscience}/kmath/structures/ViktorBenchmark.kt (89%) rename examples/src/benchmarks/kotlin/{scientifik => kscience}/kmath/utils/utils.kt (91%) delete mode 100644 examples/src/benchmarks/kotlin/scientifik/kmath/structures/ArrayBenchmark.kt rename examples/src/main/kotlin/{scientifik => kscience}/kmath/ast/ExpressionsInterpretersBenchmark.kt (82%) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/commons/prob/DistributionBenchmark.kt (94%) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/commons/prob/DistributionDemo.kt (72%) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/operations/BigIntDemo.kt (72%) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/operations/ComplexDemo.kt (68%) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/structures/ComplexND.kt (85%) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/structures/NDField.kt (93%) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/structures/StructureReadBenchmark.kt (96%) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/structures/StructureWriteBenchmark.kt (96%) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/structures/typeSafeDimensions.kt (71%) rename kmath-ast/src/commonMain/kotlin/{scientifik => kscience}/kmath/ast/MST.kt (94%) rename kmath-ast/src/commonMain/kotlin/{scientifik => kscience}/kmath/ast/MstAlgebra.kt (98%) rename kmath-ast/src/commonMain/kotlin/{scientifik => kscience}/kmath/ast/MstExpression.kt (97%) rename kmath-ast/src/jvmMain/kotlin/{scientifik => kscience}/kmath/asm/asm.kt (83%) rename kmath-ast/src/jvmMain/kotlin/{scientifik => kscience}/kmath/asm/internal/AsmBuilder.kt (98%) rename kmath-ast/src/jvmMain/kotlin/{scientifik => kscience}/kmath/asm/internal/MstType.kt (81%) rename kmath-ast/src/jvmMain/kotlin/{scientifik => kscience}/kmath/asm/internal/codegenUtils.kt (94%) rename kmath-ast/src/jvmMain/kotlin/{scientifik => kscience}/kmath/asm/internal/mapIntrinsics.kt (89%) rename kmath-ast/src/jvmMain/kotlin/{scientifik => kscience}/kmath/ast/parser.kt (93%) rename kmath-commons/src/main/kotlin/{scientifik => kscience}/kmath/commons/expressions/DiffExpression.kt (95%) rename kmath-commons/src/main/kotlin/{scientifik => kscience}/kmath/commons/linear/CMMatrix.kt (95%) rename kmath-commons/src/main/kotlin/{scientifik => kscience}/kmath/commons/linear/CMSolver.kt (91%) rename kmath-commons/src/main/kotlin/{scientifik => kscience}/kmath/commons/random/CMRandomGeneratorWrapper.kt (92%) rename kmath-commons/src/main/kotlin/{scientifik => kscience}/kmath/commons/transform/Transformations.kt (94%) rename kmath-commons/src/test/kotlin/{scientifik => kscience}/kmath/commons/expressions/AutoDiffTest.kt (92%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/domains/Domain.kt (83%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/domains/HyperSquareDomain.kt (92%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/domains/RealDomain.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/domains/UnconstrainedDomain.kt (94%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/domains/UnivariateDomain.kt (92%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/expressions/Expression.kt (92%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/expressions/FunctionalExpressionAlgebra.kt (99%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/expressions/expressionBuilders.kt (86%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/linear/BufferMatrix.kt (96%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/linear/FeaturedMatrix.kt (92%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/linear/LUPDecomposition.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/linear/LinearAlgebra.kt (82%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/linear/MatrixBuilder.kt (87%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/linear/MatrixContext.kt (90%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/linear/MatrixFeatures.kt (97%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/linear/VectorSpace.kt (89%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/linear/VirtualMatrix.kt (96%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/misc/AutoDiff.kt (97%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/misc/Grids.kt (98%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/misc/cumulative.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/operations/Algebra.kt (99%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/operations/AlgebraElements.kt (98%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/operations/AlgebraExtensions.kt (98%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/operations/BigInt.kt (98%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/operations/Complex.kt (94%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/operations/NumberAlgebra.kt (99%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/operations/OptionalOperations.kt (99%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/BoxingNDField.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/BoxingNDRing.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/BufferAccessor2D.kt (97%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/BufferedNDAlgebra.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/BufferedNDElement.kt (97%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/Buffers.kt (98%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/ComplexNDField.kt (96%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/ExtendedNDField.kt (94%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/FlaggedBuffer.kt (96%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/FloatBuffer.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/IntBuffer.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/LongBuffer.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/MemoryBuffer.kt (97%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/NDAlgebra.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/NDElement.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/NDStructure.kt (99%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/RealBuffer.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/RealBufferField.kt (98%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/RealNDField.kt (97%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/ShortBuffer.kt (95%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/ShortNDRing.kt (96%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/Structure1D.kt (98%) rename kmath-core/src/commonMain/kotlin/{scientifik => kscience}/kmath/structures/Structure2D.kt (97%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/expressions/ExpressionFieldTest.kt (87%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/linear/MatrixTest.kt (91%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/linear/RealLUSolverTest.kt (92%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/linear/VectorSpaceTest.kt (100%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/misc/AutoDiffTest.kt (98%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/misc/CumulativeKtTest.kt (90%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/BigIntAlgebraTest.kt (94%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/BigIntConstructorTest.kt (93%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/BigIntConversionsTest.kt (96%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/BigIntOperationsTest.kt (99%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/ComplexFieldTest.kt (96%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/ComplexTest.kt (96%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/RealFieldTest.kt (75%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/internal/AlgebraicVerifier.kt (55%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/internal/FieldVerifier.kt (88%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/internal/RingVerifier.kt (92%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/operations/internal/SpaceVerifier.kt (92%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/structures/ComplexBufferSpecTest.kt (68%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/structures/NDFieldTest.kt (87%) rename kmath-core/src/commonTest/kotlin/{scientifik => kscience}/kmath/structures/NumberNDFieldTest.kt (90%) rename kmath-core/src/jvmMain/kotlin/{scientifik => kscience}/kmath/operations/BigNumbers.kt (98%) rename kmath-coroutines/src/commonMain/kotlin/{scientifik => kscience}/kmath/chains/BlockingIntChain.kt (89%) rename kmath-coroutines/src/commonMain/kotlin/{scientifik => kscience}/kmath/chains/BlockingRealChain.kt (90%) rename kmath-coroutines/src/commonMain/kotlin/{scientifik => kscience}/kmath/chains/Chain.kt (99%) rename kmath-coroutines/src/commonMain/kotlin/{scientifik => kscience}/kmath/chains/flowExtra.kt (80%) rename kmath-coroutines/src/commonMain/kotlin/{scientifik => kscience}/kmath/coroutines/coroutinesExtra.kt (98%) rename kmath-coroutines/src/commonMain/kotlin/{scientifik => kscience}/kmath/streaming/BufferFlow.kt (89%) rename kmath-coroutines/src/commonMain/kotlin/{scientifik => kscience}/kmath/streaming/RingBuffer.kt (92%) rename kmath-coroutines/src/jvmMain/kotlin/{scientifik => kscience}/kmath/chains/ChainExt.kt (93%) rename kmath-coroutines/src/jvmMain/kotlin/{scientifik => kscience}/kmath/structures/LazyNDStructure.kt (96%) rename kmath-coroutines/src/jvmTest/kotlin/{scientifik => kscience}/kmath/streaming/BufferFlowTest.kt (88%) rename kmath-coroutines/src/jvmTest/kotlin/{scientifik => kscience}/kmath/streaming/RingBufferTest.kt (91%) rename kmath-dimensions/src/commonMain/kotlin/{scientifik => kscience}/kmath/dimensions/Dimensions.kt (95%) rename kmath-dimensions/src/commonMain/kotlin/{scientifik => kscience}/kmath/dimensions/Wrappers.kt (93%) rename kmath-dimensions/src/jsMain/kotlin/{scientifik => kscience}/kmath/dimensions/dim.kt (94%) rename kmath-dimensions/src/jvmMain/kotlin/{scientifik => kscience}/kmath/dimensions/dim.kt (91%) rename kmath-for-real/src/commonMain/kotlin/{scientifik => kscience}/kmath/real/RealVector.kt (76%) rename kmath-for-real/src/commonMain/kotlin/{scientifik => kscience}/kmath/real/realBuffer.kt (67%) rename kmath-for-real/src/commonMain/kotlin/{scientifik => kscience}/kmath/real/realMatrix.kt (91%) rename kmath-for-real/src/commonTest/kotlin/{scientifik => kscience}/kmath/linear/VectorTest.kt (88%) rename kmath-functions/src/commonMain/kotlin/{scientifik => kscience}/kmath/functions/Piecewise.kt (93%) rename kmath-functions/src/commonMain/kotlin/{scientifik => kscience}/kmath/functions/Polynomial.kt (93%) rename kmath-functions/src/commonMain/kotlin/{scientifik => kscience}/kmath/functions/functions.kt (88%) rename kmath-functions/src/commonMain/kotlin/{scientifik => kscience}/kmath/interpolation/Interpolator.kt (83%) rename kmath-functions/src/commonMain/kotlin/{scientifik => kscience}/kmath/interpolation/LinearInterpolator.kt (76%) rename kmath-functions/src/commonMain/kotlin/{scientifik => kscience}/kmath/interpolation/LoessInterpolator.kt (98%) rename kmath-functions/src/commonMain/kotlin/{scientifik => kscience}/kmath/interpolation/SplineInterpolator.kt (86%) rename kmath-functions/src/commonMain/kotlin/{scientifik => kscience}/kmath/interpolation/XYPointSet.kt (92%) rename kmath-functions/src/commonTest/kotlin/{scientifik => kscience}/kmath/interpolation/LinearInterpolatorTest.kt (77%) rename kmath-geometry/src/commonMain/kotlin/{scientifik => kscience}/kmath/geometry/Euclidean2DSpace.kt (90%) rename kmath-geometry/src/commonMain/kotlin/{scientifik => kscience}/kmath/geometry/Euclidean3DSpace.kt (91%) rename kmath-geometry/src/commonMain/kotlin/{scientifik => kscience}/kmath/geometry/GeometrySpace.kt (76%) rename kmath-geometry/src/commonMain/kotlin/{scientifik => kscience}/kmath/geometry/Line.kt (81%) create mode 100644 kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/ReferenceFrame.kt delete mode 100644 kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/ReferenceFrame.kt rename kmath-histograms/src/commonMain/kotlin/{scientifik => kscience}/kmath/histogram/Counters.kt (91%) rename kmath-histograms/src/commonMain/kotlin/{scientifik => kscience}/kmath/histogram/Histogram.kt (87%) rename kmath-histograms/src/commonMain/kotlin/{scientifik => kscience}/kmath/histogram/RealHistogram.kt (95%) rename kmath-histograms/src/jsMain/kotlin/{scientifik => kscience}/kmath/histogram/Counters.kt (94%) rename kmath-histograms/src/jvmMain/kotlin/{scientifik => kscience}/kmath/histogram/Counters.kt (84%) rename kmath-histograms/src/jvmMain/kotlin/{scientifik => kscience}/kmath/histogram/UnivariateHistogram.kt (95%) rename kmath-prob/src/commonMain/kotlin/{scientifik => kscience}/kmath/prob/Distribution.kt (90%) rename kmath-prob/src/commonMain/kotlin/{scientifik => kscience}/kmath/prob/FactorizedDistribution.kt (93%) rename kmath-prob/src/commonMain/kotlin/{scientifik => kscience}/kmath/prob/RandomChain.kt (87%) rename kmath-prob/src/commonMain/kotlin/{scientifik => kscience}/kmath/prob/RandomGenerator.kt (98%) rename kmath-prob/src/commonMain/kotlin/{scientifik => kscience}/kmath/prob/SamplerAlgebra.kt (79%) rename kmath-prob/src/commonMain/kotlin/{scientifik => kscience}/kmath/prob/Statistic.kt (92%) rename kmath-prob/src/commonMain/kotlin/{scientifik => kscience}/kmath/prob/UniformDistribution.kt (87%) rename kmath-prob/src/jvmMain/kotlin/{scientifik => kscience}/kmath/prob/RandomSourceGenerator.kt (98%) rename kmath-prob/src/jvmMain/kotlin/{scientifik => kscience}/kmath/prob/distributions.kt (95%) rename kmath-prob/src/jvmTest/kotlin/{scientifik => kscience}/kmath/prob/CommonsDistributionsTest.kt (96%) rename kmath-prob/src/jvmTest/kotlin/{scientifik => kscience}/kmath/prob/SamplerTest.kt (92%) rename kmath-prob/src/jvmTest/kotlin/{scientifik => kscience}/kmath/prob/StatisticTest.kt (91%) rename kmath-viktor/src/main/kotlin/{scientifik => kscience}/kmath/viktor/ViktorBuffer.kt (88%) rename kmath-viktor/src/main/kotlin/{scientifik => kscience}/kmath/viktor/ViktorNDStructure.kt (92%) diff --git a/README.md b/README.md index 08d1e988a..c2e67e815 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) -Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/scientifik/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/scientifik/kmath-core/_latestVersion) +Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion) @@ -80,12 +80,12 @@ Release artifacts are accessible from bintray with following configuration (see ```kotlin repositories{ - maven("https://dl.bintray.com/mipt-npm/scientifik") + maven("https://dl.bintray.com/mipt-npm/kscience") } dependencies{ - api("scientifik:kmath-core:${kmathVersion}") - //api("scientifik:kmath-core-jvm:${kmathVersion}") for jvm-specific version + api("kscience.kmath:kmath-core:${kmathVersion}") + //api("kscience.kmath:kmath-core-jvm:${kmathVersion}") for jvm-specific version } ``` diff --git a/doc/algebra.md b/doc/algebra.md index b1b77a31f..c3227517f 100644 --- a/doc/algebra.md +++ b/doc/algebra.md @@ -5,7 +5,7 @@ operation, say `+`, one needs two objects of a type `T` and an algebra context, say `Space`. Next one needs to run the actual operation in the context: ```kotlin -import scientifik.kmath.operations.* +import kscience.kmath.operations.* val a: T = ... val b: T = ... @@ -47,7 +47,7 @@ but it also holds reference to the `ComplexField` singleton, which allows perfor numbers without explicit involving the context like: ```kotlin -import scientifik.kmath.operations.* +import kscience.kmath.operations.* // Using elements val c1 = Complex(1.0, 1.0) @@ -82,7 +82,7 @@ operations in all performance-critical places. The performance of element operat KMath submits both contexts and elements for builtin algebraic structures: ```kotlin -import scientifik.kmath.operations.* +import kscience.kmath.operations.* val c1 = Complex(1.0, 2.0) val c2 = ComplexField.i @@ -95,7 +95,7 @@ val c3 = ComplexField { c1 + c2 } Also, `ComplexField` features special operations to mix complex and real numbers, for example: ```kotlin -import scientifik.kmath.operations.* +import kscience.kmath.operations.* val c1 = Complex(1.0, 2.0) val c2 = ComplexField { c1 - 1.0 } // Returns: Complex(re=0.0, im=2.0) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 40da41d2b..3d193efce 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -10,7 +10,7 @@ plugins { allOpen.annotation("org.openjdk.jmh.annotations.State") repositories { - maven("https://dl.bintray.com/mipt-npm/scientifik") + maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://dl.bintray.com/mipt-npm/dev") maven("https://dl.bintray.com/kotlin/kotlin-dev/") mavenCentral() diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt new file mode 100644 index 000000000..2673552f5 --- /dev/null +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt @@ -0,0 +1,39 @@ +package kscience.kmath.structures + +import org.openjdk.jmh.annotations.Benchmark +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.State +import java.nio.IntBuffer + +@State(Scope.Benchmark) +class ArrayBenchmark { + @Benchmark + fun benchmarkArrayRead() { + var res = 0 + for (i in 1.._root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size) res += _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.array[_root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size - i] + } + + @Benchmark + fun benchmarkBufferRead() { + var res = 0 + for (i in 1.._root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size) res += _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.arrayBuffer.get( + _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size - i) + } + + @Benchmark + fun nativeBufferRead() { + var res = 0 + for (i in 1.._root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size) res += _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.nativeBuffer.get( + _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size - i) + } + + companion object { + const val size: Int = 1000 + val array: IntArray = IntArray(_root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size) { it } + val arrayBuffer: IntBuffer = IntBuffer.wrap(_root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.array) + + val nativeBuffer: IntBuffer = IntBuffer.allocate(_root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size).also { + for (i in 0 until _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size) it.put(i, i) + } + } +} diff --git a/examples/src/benchmarks/kotlin/scientifik/kmath/structures/BufferBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt similarity index 83% rename from examples/src/benchmarks/kotlin/scientifik/kmath/structures/BufferBenchmark.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt index e40b0c4b7..009d51001 100644 --- a/examples/src/benchmarks/kotlin/scientifik/kmath/structures/BufferBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.structures +package kscience.kmath.structures +import kscience.kmath.operations.Complex +import kscience.kmath.operations.complex import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State -import scientifik.kmath.operations.Complex -import scientifik.kmath.operations.complex @State(Scope.Benchmark) class BufferBenchmark { diff --git a/examples/src/benchmarks/kotlin/scientifik/kmath/structures/NDFieldBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt similarity index 89% rename from examples/src/benchmarks/kotlin/scientifik/kmath/structures/NDFieldBenchmark.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt index 46da6c6d8..64f279c39 100644 --- a/examples/src/benchmarks/kotlin/scientifik/kmath/structures/NDFieldBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.structures +package kscience.kmath.structures +import kscience.kmath.operations.RealField +import kscience.kmath.operations.invoke import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.invoke @State(Scope.Benchmark) class NDFieldBenchmark { diff --git a/examples/src/benchmarks/kotlin/scientifik/kmath/structures/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt similarity index 89% rename from examples/src/benchmarks/kotlin/scientifik/kmath/structures/ViktorBenchmark.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt index 9627743c9..a4b831f7c 100644 --- a/examples/src/benchmarks/kotlin/scientifik/kmath/structures/ViktorBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt @@ -1,12 +1,12 @@ -package scientifik.kmath.structures +package kscience.kmath.structures +import kscience.kmath.operations.RealField +import kscience.kmath.operations.invoke +import kscience.kmath.viktor.ViktorNDField import org.jetbrains.bio.viktor.F64Array import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.invoke -import scientifik.kmath.viktor.ViktorNDField @State(Scope.Benchmark) class ViktorBenchmark { diff --git a/examples/src/benchmarks/kotlin/scientifik/kmath/utils/utils.kt b/examples/src/benchmarks/kotlin/kscience/kmath/utils/utils.kt similarity index 91% rename from examples/src/benchmarks/kotlin/scientifik/kmath/utils/utils.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/utils/utils.kt index 3b0d56291..329b7b17b 100644 --- a/examples/src/benchmarks/kotlin/scientifik/kmath/utils/utils.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/utils/utils.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.utils +package kscience.kmath.utils import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/examples/src/benchmarks/kotlin/scientifik/kmath/structures/ArrayBenchmark.kt b/examples/src/benchmarks/kotlin/scientifik/kmath/structures/ArrayBenchmark.kt deleted file mode 100644 index 2ccb27871..000000000 --- a/examples/src/benchmarks/kotlin/scientifik/kmath/structures/ArrayBenchmark.kt +++ /dev/null @@ -1,37 +0,0 @@ -package scientifik.kmath.structures - -import org.openjdk.jmh.annotations.Benchmark -import org.openjdk.jmh.annotations.Scope -import org.openjdk.jmh.annotations.State -import java.nio.IntBuffer - -@State(Scope.Benchmark) -class ArrayBenchmark { - @Benchmark - fun benchmarkArrayRead() { - var res = 0 - for (i in 1..size) res += array[size - i] - } - - @Benchmark - fun benchmarkBufferRead() { - var res = 0 - for (i in 1..size) res += arrayBuffer.get(size - i) - } - - @Benchmark - fun nativeBufferRead() { - var res = 0 - for (i in 1..size) res += nativeBuffer.get(size - i) - } - - companion object { - const val size: Int = 1000 - val array: IntArray = IntArray(size) { it } - val arrayBuffer: IntBuffer = IntBuffer.wrap(array) - - val nativeBuffer: IntBuffer = IntBuffer.allocate(size).also { - for (i in 0 until size) it.put(i, i) - } - } -} diff --git a/examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt similarity index 82% rename from examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt rename to examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt index 80e70d149..a5768f1f5 100644 --- a/examples/src/main/kotlin/scientifik/kmath/ast/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt @@ -1,11 +1,11 @@ -//package scientifik.kmath.ast +//package kscience.kmath.ast // -//import scientifik.kmath.asm.compile -//import scientifik.kmath.expressions.Expression -//import scientifik.kmath.expressions.expressionInField -//import scientifik.kmath.expressions.invoke -//import scientifik.kmath.operations.Field -//import scientifik.kmath.operations.RealField +//import kscience.kmath.asm.compile +//import kscience.kmath.expressions.Expression +//import kscience.kmath.expressions.expressionInField +//import kscience.kmath.expressions.invoke +//import kscience.kmath.operations.Field +//import kscience.kmath.operations.RealField //import kotlin.random.Random //import kotlin.system.measureTimeMillis // diff --git a/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt similarity index 94% rename from examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionBenchmark.kt rename to examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt index b060cddb6..57a9c55c5 100644 --- a/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt @@ -1,12 +1,12 @@ -package scientifik.kmath.commons.prob +package kscience.kmath.commons.prob import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking +import kscience.kmath.chains.BlockingRealChain +import kscience.kmath.prob.* import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler import org.apache.commons.rng.simple.RandomSource -import scientifik.kmath.chains.BlockingRealChain -import scientifik.kmath.prob.* import java.time.Duration import java.time.Instant diff --git a/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionDemo.kt b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt similarity index 72% rename from examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionDemo.kt rename to examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt index e059415dc..dbb51267b 100644 --- a/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt @@ -1,11 +1,11 @@ -package scientifik.kmath.commons.prob +package kscience.kmath.commons.prob import kotlinx.coroutines.runBlocking -import scientifik.kmath.chains.Chain -import scientifik.kmath.chains.collectWithState -import scientifik.kmath.prob.Distribution -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.normal +import kscience.kmath.chains.Chain +import kscience.kmath.chains.collectWithState +import kscience.kmath.prob.Distribution +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.normal data class AveragingChainState(var num: Int = 0, var value: Double = 0.0) diff --git a/examples/src/main/kotlin/scientifik/kmath/operations/BigIntDemo.kt b/examples/src/main/kotlin/kscience/kmath/operations/BigIntDemo.kt similarity index 72% rename from examples/src/main/kotlin/scientifik/kmath/operations/BigIntDemo.kt rename to examples/src/main/kotlin/kscience/kmath/operations/BigIntDemo.kt index 10b038943..692ea6d8c 100644 --- a/examples/src/main/kotlin/scientifik/kmath/operations/BigIntDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/operations/BigIntDemo.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.operations +package kscience.kmath.operations fun main() { val res = BigIntField { diff --git a/examples/src/main/kotlin/scientifik/kmath/operations/ComplexDemo.kt b/examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt similarity index 68% rename from examples/src/main/kotlin/scientifik/kmath/operations/ComplexDemo.kt rename to examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt index 6dbfebce1..3c97940a8 100644 --- a/examples/src/main/kotlin/scientifik/kmath/operations/ComplexDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.operations +package kscience.kmath.operations -import scientifik.kmath.structures.NDElement -import scientifik.kmath.structures.NDField -import scientifik.kmath.structures.complex +import kscience.kmath.structures.NDElement +import kscience.kmath.structures.NDField +import kscience.kmath.structures.complex fun main() { val element = NDElement.complex(2, 2) { index: IntArray -> diff --git a/examples/src/main/kotlin/scientifik/kmath/structures/ComplexND.kt b/examples/src/main/kotlin/kscience/kmath/structures/ComplexND.kt similarity index 85% rename from examples/src/main/kotlin/scientifik/kmath/structures/ComplexND.kt rename to examples/src/main/kotlin/kscience/kmath/structures/ComplexND.kt index 2329f3fc3..aa4b10ef2 100644 --- a/examples/src/main/kotlin/scientifik/kmath/structures/ComplexND.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/ComplexND.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.linear.transpose -import scientifik.kmath.operations.Complex -import scientifik.kmath.operations.ComplexField -import scientifik.kmath.operations.invoke +import kscience.kmath.linear.transpose +import kscience.kmath.operations.Complex +import kscience.kmath.operations.ComplexField +import kscience.kmath.operations.invoke import kotlin.system.measureTimeMillis fun main() { diff --git a/examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt b/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt similarity index 93% rename from examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt rename to examples/src/main/kotlin/kscience/kmath/structures/NDField.kt index 54ffcb67c..28bfab779 100644 --- a/examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.structures +package kscience.kmath.structures import kotlinx.coroutines.GlobalScope -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.invoke +import kscience.kmath.operations.RealField +import kscience.kmath.operations.invoke import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.system.measureTimeMillis diff --git a/examples/src/main/kotlin/scientifik/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt similarity index 96% rename from examples/src/main/kotlin/scientifik/kmath/structures/StructureReadBenchmark.kt rename to examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt index d5998cd0a..a2bfea2f9 100644 --- a/examples/src/main/kotlin/scientifik/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.structures +package kscience.kmath.structures import kotlin.system.measureTimeMillis diff --git a/examples/src/main/kotlin/scientifik/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/structures/StructureWriteBenchmark.kt similarity index 96% rename from examples/src/main/kotlin/scientifik/kmath/structures/StructureWriteBenchmark.kt rename to examples/src/main/kotlin/kscience/kmath/structures/StructureWriteBenchmark.kt index ffcecbce2..b2975393f 100644 --- a/examples/src/main/kotlin/scientifik/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.structures +package kscience.kmath.structures import kotlin.system.measureTimeMillis diff --git a/examples/src/main/kotlin/scientifik/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt similarity index 71% rename from examples/src/main/kotlin/scientifik/kmath/structures/typeSafeDimensions.kt rename to examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt index 5d323823a..bf83a9f05 100644 --- a/examples/src/main/kotlin/scientifik/kmath/structures/typeSafeDimensions.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.dimensions.D2 -import scientifik.kmath.dimensions.D3 -import scientifik.kmath.dimensions.DMatrixContext -import scientifik.kmath.dimensions.Dimension -import scientifik.kmath.operations.RealField +import kscience.kmath.dimensions.D2 +import kscience.kmath.dimensions.D3 +import kscience.kmath.dimensions.DMatrixContext +import kscience.kmath.dimensions.Dimension +import kscience.kmath.operations.RealField fun DMatrixContext.simple() { val m1 = produce { i, j -> (i + j).toDouble() } diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 2339d0426..043224800 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -8,32 +8,32 @@ This subproject implements the following features: - Evaluating expressions by traversing MST. > #### Artifact: -> This module is distributed in the artifact `scientifik:kmath-ast:0.1.4-dev-8`. +> This module is distributed in the artifact `kscience.kmath:kmath-ast:0.1.4-dev-8`. > > **Gradle:** > > ```gradle > repositories { -> maven { url 'https://dl.bintray.com/mipt-npm/scientifik' } +> maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } > maven { url https://dl.bintray.com/hotkeytlt/maven' } > } > > dependencies { -> implementation 'scientifik:kmath-ast:0.1.4-dev-8' +> implementation 'kscience.kmath:kmath-ast:0.1.4-dev-8' > } > ``` > **Gradle Kotlin DSL:** > > ```kotlin > repositories { -> maven("https://dl.bintray.com/mipt-npm/scientifik") +> maven("https://dl.bintray.com/mipt-npm/kscience") > maven("https://dl.bintray.com/mipt-npm/dev") > maven("https://dl.bintray.com/hotkeytlt/maven") > } > > dependencies { -> implementation("scientifik:kmath-ast:0.1.4-dev-8") +> implementation("kscience.kmath:kmath-ast:0.1.4-dev-8") > } > ``` > @@ -52,12 +52,12 @@ RealField.mstInField { symbol("x") + 2 }.compile() … leads to generation of bytecode, which can be decompiled to the following Java class: ```java -package scientifik.kmath.asm.generated; +package kscience.kmath.asm.generated; import java.util.Map; -import scientifik.kmath.asm.internal.MapIntrinsics; -import scientifik.kmath.expressions.Expression; -import scientifik.kmath.operations.RealField; +import kscience.kmath.asm.internal.MapIntrinsics; +import kscience.kmath.expressions.Expression; +import kscience.kmath.operations.RealField; public final class AsmCompiledExpression_1073786867_0 implements Expression { private final RealField algebra; diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt similarity index 94% rename from kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt rename to kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt index 283a20649..f312323b9 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.ast +package kscience.kmath.ast -import scientifik.kmath.operations.Algebra -import scientifik.kmath.operations.NumericAlgebra -import scientifik.kmath.operations.RealField +import kscience.kmath.operations.Algebra +import kscience.kmath.operations.NumericAlgebra +import kscience.kmath.operations.RealField /** * A Mathematical Syntax Tree node for mathematical expressions. diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt similarity index 98% rename from kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt rename to kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt index 8cee0ea0b..64a820b20 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.ast +package kscience.kmath.ast -import scientifik.kmath.operations.* +import kscience.kmath.operations.* /** * [Algebra] over [MST] nodes. diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt similarity index 97% rename from kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt rename to kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt index d094e2fee..483bc530c 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.ast +package kscience.kmath.ast -import scientifik.kmath.expressions.* -import scientifik.kmath.operations.* +import kscience.kmath.expressions.* +import kscience.kmath.operations.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt similarity index 83% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt rename to kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt index 3ca817b63..edfe7f01d 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt @@ -1,13 +1,13 @@ -package scientifik.kmath.asm +package kscience.kmath.asm -import scientifik.kmath.asm.internal.AsmBuilder -import scientifik.kmath.asm.internal.MstType -import scientifik.kmath.asm.internal.buildAlgebraOperationCall -import scientifik.kmath.asm.internal.buildName -import scientifik.kmath.ast.MST -import scientifik.kmath.ast.MstExpression -import scientifik.kmath.expressions.Expression -import scientifik.kmath.operations.Algebra +import kscience.kmath.asm.internal.AsmBuilder +import kscience.kmath.asm.internal.MstType +import kscience.kmath.asm.internal.buildAlgebraOperationCall +import kscience.kmath.asm.internal.buildName +import kscience.kmath.ast.MST +import kscience.kmath.ast.MstExpression +import kscience.kmath.expressions.Expression +import kscience.kmath.operations.Algebra import kotlin.reflect.KClass /** diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt similarity index 98% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt rename to kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index 1cf49a251..ab2de97aa 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -1,13 +1,13 @@ -package scientifik.kmath.asm.internal +package kscience.kmath.asm.internal +import kscience.kmath.asm.internal.AsmBuilder.ClassLoader +import kscience.kmath.ast.MST +import kscience.kmath.expressions.Expression +import kscience.kmath.operations.Algebra +import kscience.kmath.operations.NumericAlgebra import org.objectweb.asm.* import org.objectweb.asm.Opcodes.* import org.objectweb.asm.commons.InstructionAdapter -import scientifik.kmath.asm.internal.AsmBuilder.ClassLoader -import scientifik.kmath.ast.MST -import scientifik.kmath.expressions.Expression -import scientifik.kmath.operations.Algebra -import scientifik.kmath.operations.NumericAlgebra import java.util.* import java.util.stream.Collectors import kotlin.reflect.KClass @@ -564,6 +564,6 @@ internal class AsmBuilder internal constructor( /** * ASM type for MapIntrinsics. */ - internal val MAP_INTRINSICS_TYPE: Type by lazy { Type.getObjectType("scientifik/kmath/asm/internal/MapIntrinsics") } + internal val MAP_INTRINSICS_TYPE: Type by lazy { Type.getObjectType("kscience/kmath/asm/internal/MapIntrinsics") } } } diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/MstType.kt similarity index 81% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt rename to kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/MstType.kt index 81e6791c1..526c27305 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/MstType.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.asm.internal +package kscience.kmath.asm.internal -import scientifik.kmath.ast.MST +import kscience.kmath.ast.MST /** * Represents types known in [MST], numbers and general values. diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt similarity index 94% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt rename to kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt index ab29d3614..67fce40ac 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt @@ -1,14 +1,14 @@ -package scientifik.kmath.asm.internal +package kscience.kmath.asm.internal +import kscience.kmath.ast.MST +import kscience.kmath.expressions.Expression +import kscience.kmath.operations.Algebra +import kscience.kmath.operations.FieldOperations +import kscience.kmath.operations.RingOperations +import kscience.kmath.operations.SpaceOperations import org.objectweb.asm.* import org.objectweb.asm.Opcodes.INVOKEVIRTUAL import org.objectweb.asm.commons.InstructionAdapter -import scientifik.kmath.ast.MST -import scientifik.kmath.expressions.Expression -import scientifik.kmath.operations.Algebra -import scientifik.kmath.operations.FieldOperations -import scientifik.kmath.operations.RingOperations -import scientifik.kmath.operations.SpaceOperations import java.lang.reflect.Method import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -76,7 +76,7 @@ internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) } * @author Iaroslav Postovalov */ internal tailrec fun buildName(mst: MST, collision: Int = 0): String { - val name = "scientifik.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision" + val name = "kscience.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision" try { Class.forName(name) diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt similarity index 89% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt rename to kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt index 997dbbfe5..708b3c2b4 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt @@ -1,6 +1,6 @@ @file:JvmName("MapIntrinsics") -package scientifik.kmath.asm.internal +package kscience.kmath.asm.internal /** * Gets value with given [key] or throws [IllegalStateException] whenever it is not present. diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt similarity index 93% rename from kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/parser.kt rename to kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt index 8ccbf4606..15e6625db 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/ast/parser.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.ast +package kscience.kmath.ast import com.github.h0tk3y.betterParse.combinators.* import com.github.h0tk3y.betterParse.grammar.Grammar @@ -10,10 +10,10 @@ import com.github.h0tk3y.betterParse.lexer.TokenMatch import com.github.h0tk3y.betterParse.lexer.regexToken import com.github.h0tk3y.betterParse.parser.ParseResult import com.github.h0tk3y.betterParse.parser.Parser -import scientifik.kmath.operations.FieldOperations -import scientifik.kmath.operations.PowerOperations -import scientifik.kmath.operations.RingOperations -import scientifik.kmath.operations.SpaceOperations +import kscience.kmath.operations.FieldOperations +import kscience.kmath.operations.PowerOperations +import kscience.kmath.operations.RingOperations +import kscience.kmath.operations.SpaceOperations /** * TODO move to common after IR version is released diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmAlgebras.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmAlgebras.kt index 3acc6eb28..5d8f90c9b 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmAlgebras.kt +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmAlgebras.kt @@ -1,12 +1,12 @@ package scietifik.kmath.asm -import scientifik.kmath.asm.compile -import scientifik.kmath.ast.mstInField -import scientifik.kmath.ast.mstInRing -import scientifik.kmath.ast.mstInSpace -import scientifik.kmath.expressions.invoke -import scientifik.kmath.operations.ByteRing -import scientifik.kmath.operations.RealField +import kscience.kmath.asm.compile +import kscience.kmath.ast.mstInField +import kscience.kmath.ast.mstInRing +import kscience.kmath.ast.mstInSpace +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.ByteRing +import kscience.kmath.operations.RealField import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmExpressions.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmExpressions.kt index 36c254c38..c2e45b8ff 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmExpressions.kt +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmExpressions.kt @@ -1,10 +1,10 @@ package scietifik.kmath.asm -import scientifik.kmath.asm.compile -import scientifik.kmath.ast.mstInField -import scientifik.kmath.ast.mstInSpace -import scientifik.kmath.expressions.invoke -import scientifik.kmath.operations.RealField +import kscience.kmath.asm.compile +import kscience.kmath.ast.mstInField +import kscience.kmath.ast.mstInSpace +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.RealField import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmSpecialization.kt index a88431e9d..2b27fdc0f 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmSpecialization.kt @@ -1,9 +1,9 @@ package scietifik.kmath.asm -import scientifik.kmath.asm.compile -import scientifik.kmath.ast.mstInField -import scientifik.kmath.expressions.invoke -import scientifik.kmath.operations.RealField +import kscience.kmath.asm.compile +import kscience.kmath.ast.mstInField +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.RealField import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmVariables.kt index aafc75448..3511be97c 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmVariables.kt +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmVariables.kt @@ -1,8 +1,8 @@ package scietifik.kmath.asm -import scientifik.kmath.ast.mstInRing -import scientifik.kmath.expressions.invoke -import scientifik.kmath.operations.ByteRing +import kscience.kmath.ast.mstInRing +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.ByteRing import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt index 75659cc35..bb371bed0 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt @@ -1,12 +1,12 @@ package scietifik.kmath.ast -import scientifik.kmath.asm.compile -import scientifik.kmath.asm.expression -import scientifik.kmath.ast.mstInField -import scientifik.kmath.ast.parseMath -import scientifik.kmath.expressions.invoke -import scientifik.kmath.operations.Complex -import scientifik.kmath.operations.ComplexField +import kscience.kmath.asm.compile +import kscience.kmath.asm.expression +import kscience.kmath.ast.mstInField +import kscience.kmath.ast.parseMath +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.Complex +import kscience.kmath.operations.ComplexField import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt index 9bdbb12c9..21ee47d13 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt @@ -1,9 +1,9 @@ package scietifik.kmath.ast -import scientifik.kmath.ast.evaluate -import scientifik.kmath.ast.parseMath -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.RealField +import kscience.kmath.ast.evaluate +import kscience.kmath.ast.parseMath +import kscience.kmath.operations.Field +import kscience.kmath.operations.RealField import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt index 9179c3428..8a5d6ba48 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt @@ -1,13 +1,13 @@ package scietifik.kmath.ast -import scientifik.kmath.ast.evaluate -import scientifik.kmath.ast.mstInField -import scientifik.kmath.ast.parseMath -import scientifik.kmath.expressions.invoke -import scientifik.kmath.operations.Algebra -import scientifik.kmath.operations.Complex -import scientifik.kmath.operations.ComplexField -import scientifik.kmath.operations.RealField +import kscience.kmath.ast.evaluate +import kscience.kmath.ast.mstInField +import kscience.kmath.ast.parseMath +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.Algebra +import kscience.kmath.operations.Complex +import kscience.kmath.operations.ComplexField +import kscience.kmath.operations.RealField import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt similarity index 95% rename from kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt rename to kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt index d556eb762..3ac908536 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt @@ -1,11 +1,11 @@ -package scientifik.kmath.commons.expressions +package kscience.kmath.commons.expressions +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.ExpressionAlgebra +import kscience.kmath.operations.ExtendedField +import kscience.kmath.operations.Field +import kscience.kmath.operations.invoke import org.apache.commons.math3.analysis.differentiation.DerivativeStructure -import scientifik.kmath.expressions.Expression -import scientifik.kmath.expressions.ExpressionAlgebra -import scientifik.kmath.operations.ExtendedField -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.invoke import kotlin.properties.ReadOnlyProperty /** diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt similarity index 95% rename from kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMMatrix.kt rename to kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt index 72288a85e..377d167bc 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.commons.linear +package kscience.kmath.commons.linear +import kscience.kmath.linear.* +import kscience.kmath.structures.Matrix +import kscience.kmath.structures.NDStructure import org.apache.commons.math3.linear.* -import scientifik.kmath.linear.* -import scientifik.kmath.structures.Matrix -import scientifik.kmath.structures.NDStructure public class CMMatrix(public val origin: RealMatrix, features: Set? = null) : FeaturedMatrix { diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMSolver.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMSolver.kt similarity index 91% rename from kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMSolver.kt rename to kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMSolver.kt index 1e79aff21..210014e1a 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/linear/CMSolver.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMSolver.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.commons.linear +package kscience.kmath.commons.linear +import kscience.kmath.linear.Point +import kscience.kmath.structures.Matrix import org.apache.commons.math3.linear.* -import scientifik.kmath.linear.Point -import scientifik.kmath.structures.Matrix public enum class CMDecomposition { LUP, diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt similarity index 92% rename from kmath-commons/src/main/kotlin/scientifik/kmath/commons/random/CMRandomGeneratorWrapper.kt rename to kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt index 3e60d7cdd..58609deae 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/random/CMRandomGeneratorWrapper.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.commons.random +package kscience.kmath.commons.random -import scientifik.kmath.prob.RandomGenerator +import kscience.kmath.prob.RandomGenerator public class CMRandomGeneratorWrapper(public val factory: (IntArray) -> RandomGenerator) : org.apache.commons.math3.random.RandomGenerator { diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/transform/Transformations.kt similarity index 94% rename from kmath-commons/src/main/kotlin/scientifik/kmath/commons/transform/Transformations.kt rename to kmath-commons/src/main/kotlin/kscience/kmath/commons/transform/Transformations.kt index 4af0d2b72..cd2896be6 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/transform/Transformations.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/transform/Transformations.kt @@ -1,13 +1,13 @@ -package scientifik.kmath.commons.transform +package kscience.kmath.commons.transform import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kscience.kmath.operations.Complex +import kscience.kmath.streaming.chunked +import kscience.kmath.streaming.spread +import kscience.kmath.structures.* import org.apache.commons.math3.transform.* -import scientifik.kmath.operations.Complex -import scientifik.kmath.streaming.chunked -import scientifik.kmath.streaming.spread -import scientifik.kmath.structures.* /** diff --git a/kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/AutoDiffTest.kt similarity index 92% rename from kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt rename to kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/AutoDiffTest.kt index 3d8a1d5f0..f905e6818 100644 --- a/kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/AutoDiffTest.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.commons.expressions +package kscience.kmath.commons.expressions -import scientifik.kmath.expressions.invoke +import kscience.kmath.expressions.invoke import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.test.Test diff --git a/kmath-core/README.md b/kmath-core/README.md index aed33a257..9d05331f9 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -10,31 +10,31 @@ The core features of KMath: - Automatic differentiation. > #### Artifact: -> This module is distributed in the artifact `scientifik:kmath-core:0.1.4-dev-8`. +> This module is distributed in the artifact `kscience.kmath:kmath-core:0.1.4-dev-8`. > > **Gradle:** > > ```gradle > repositories { -> maven { url 'https://dl.bintray.com/mipt-npm/scientifik' } +> maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } > maven { url https://dl.bintray.com/hotkeytlt/maven' } > } > > dependencies { -> implementation 'scientifik:kmath-core:0.1.4-dev-8' +> implementation 'kscience.kmath:kmath-core:0.1.4-dev-8' > } > ``` > **Gradle Kotlin DSL:** > > ```kotlin > repositories { -> maven("https://dl.bintray.com/mipt-npm/scientifik") +> maven("https://dl.bintray.com/mipt-npm/kscience") > maven("https://dl.bintray.com/mipt-npm/dev") > maven("https://dl.bintray.com/hotkeytlt/maven") > } > -> dependencies {`` -> implementation("scientifik:kmath-core:0.1.4-dev-8") +> dependencies { +> implementation("kscience.kmath:kmath-core:0.1.4-dev-8") > } > ``` diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/Domain.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/domains/Domain.kt similarity index 83% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/Domain.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/domains/Domain.kt index c4c823bf2..5c3cff2c5 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/Domain.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/domains/Domain.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.domains +package kscience.kmath.domains -import scientifik.kmath.linear.Point +import kscience.kmath.linear.Point /** * A simple geometric domain. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/domains/HyperSquareDomain.kt similarity index 92% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/domains/HyperSquareDomain.kt index 61d443ff3..b45cf6bf5 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/HyperSquareDomain.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/domains/HyperSquareDomain.kt @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package scientifik.kmath.domains +package kscience.kmath.domains -import scientifik.kmath.linear.Point -import scientifik.kmath.structures.RealBuffer -import scientifik.kmath.structures.indices +import kscience.kmath.linear.Point +import kscience.kmath.structures.RealBuffer +import kscience.kmath.structures.indices /** * diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/RealDomain.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/domains/RealDomain.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/RealDomain.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/domains/RealDomain.kt index b1da63519..369b093bb 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/RealDomain.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/domains/RealDomain.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package scientifik.kmath.domains +package kscience.kmath.domains -import scientifik.kmath.linear.Point +import kscience.kmath.linear.Point /** * n-dimensional volume diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/domains/UnconstrainedDomain.kt similarity index 94% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/domains/UnconstrainedDomain.kt index c637795df..e2efb51ab 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnconstrainedDomain.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/domains/UnconstrainedDomain.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package scientifik.kmath.domains +package kscience.kmath.domains -import scientifik.kmath.linear.Point +import kscience.kmath.linear.Point public class UnconstrainedDomain(public override val dimension: Int) : RealDomain { public override operator fun contains(point: Point): Boolean = true diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/domains/UnivariateDomain.kt similarity index 92% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/domains/UnivariateDomain.kt index 066a8ae25..bf090f2e5 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/domains/UnivariateDomain.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/domains/UnivariateDomain.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.domains +package kscience.kmath.domains -import scientifik.kmath.linear.Point -import scientifik.kmath.structures.asBuffer +import kscience.kmath.linear.Point +import kscience.kmath.structures.asBuffer public inline class UnivariateDomain(public val range: ClosedFloatingPointRange) : RealDomain { public override val dimension: Int diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt similarity index 92% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index a21735f27..5ade9e3ca 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.expressions +package kscience.kmath.expressions -import scientifik.kmath.operations.Algebra +import kscience.kmath.operations.Algebra /** * An elementary function that could be invoked on a map of arguments diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt similarity index 99% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index 3804819e6..49844a2be 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.expressions +package kscience.kmath.expressions -import scientifik.kmath.operations.* +import kscience.kmath.operations.* internal class FunctionalUnaryOperation(val context: Algebra, val name: String, private val expr: Expression) : Expression { diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/expressionBuilders.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt similarity index 86% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/expressionBuilders.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt index 3af24b595..1702a5921 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/expressionBuilders.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.expressions +package kscience.kmath.expressions -import scientifik.kmath.operations.ExtendedField -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.Ring -import scientifik.kmath.operations.Space +import kscience.kmath.operations.ExtendedField +import kscience.kmath.operations.Field +import kscience.kmath.operations.Ring +import kscience.kmath.operations.Space import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt similarity index 96% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt index d053f016c..d51f40890 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.Ring -import scientifik.kmath.structures.* +import kscience.kmath.operations.RealField +import kscience.kmath.operations.Ring +import kscience.kmath.structures.* /** * Basic implementation of Matrix space based on [NDStructure] diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt similarity index 92% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt index d5f8f8e20..65dc8df76 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt @@ -1,10 +1,9 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.operations.Ring -import scientifik.kmath.structures.Matrix -import scientifik.kmath.structures.Structure2D -import scientifik.kmath.structures.asBuffer -import kotlin.contracts.contract +import kscience.kmath.operations.Ring +import kscience.kmath.structures.Matrix +import kscience.kmath.structures.Structure2D +import kscience.kmath.structures.asBuffer import kotlin.math.sqrt /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt index ab23afff0..bb80bcafd 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt @@ -1,13 +1,12 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.Ring -import scientifik.kmath.operations.invoke -import scientifik.kmath.structures.BufferAccessor2D -import scientifik.kmath.structures.Matrix -import scientifik.kmath.structures.Structure2D -import kotlin.contracts.contract +import kscience.kmath.operations.Field +import kscience.kmath.operations.RealField +import kscience.kmath.operations.Ring +import kscience.kmath.operations.invoke +import kscience.kmath.structures.BufferAccessor2D +import kscience.kmath.structures.Matrix +import kscience.kmath.structures.Structure2D import kotlin.reflect.KClass /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LinearAlgebra.kt similarity index 82% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LinearAlgebra.kt index 607d63bb1..034decc2f 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LinearAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LinearAlgebra.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.Matrix -import scientifik.kmath.structures.VirtualBuffer +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.Matrix +import kscience.kmath.structures.VirtualBuffer public typealias Point = Buffer diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixBuilder.kt similarity index 87% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixBuilder.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixBuilder.kt index 5efa53bc2..91c1ec824 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixBuilder.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.BufferFactory -import scientifik.kmath.structures.Structure2D -import scientifik.kmath.structures.asBuffer +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.BufferFactory +import kscience.kmath.structures.Structure2D +import kscience.kmath.structures.asBuffer public class MatrixBuilder(public val rows: Int, public val columns: Int) { public operator fun invoke(vararg elements: T): FeaturedMatrix { diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt similarity index 90% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt index 13d4e68b9..d66530472 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt @@ -1,13 +1,13 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.operations.Ring -import scientifik.kmath.operations.SpaceOperations -import scientifik.kmath.operations.invoke -import scientifik.kmath.operations.sum -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.BufferFactory -import scientifik.kmath.structures.Matrix -import scientifik.kmath.structures.asSequence +import kscience.kmath.operations.Ring +import kscience.kmath.operations.SpaceOperations +import kscience.kmath.operations.invoke +import kscience.kmath.operations.sum +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.BufferFactory +import kscience.kmath.structures.Matrix +import kscience.kmath.structures.asSequence /** * Basic operations on matrices. Operates on [Matrix] diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt similarity index 97% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixFeatures.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt index 3448a2e7c..a82032e50 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixFeatures.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.linear +package kscience.kmath.linear /** * A marker interface representing some matrix feature like diagonal, sparse, zero, etc. Features used to optimize matrix diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VectorSpace.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VectorSpace.kt similarity index 89% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VectorSpace.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VectorSpace.kt index a75523f7c..67056c6b2 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VectorSpace.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VectorSpace.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.Space -import scientifik.kmath.operations.invoke -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.BufferFactory +import kscience.kmath.operations.RealField +import kscience.kmath.operations.Space +import kscience.kmath.operations.invoke +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.BufferFactory /** * A linear space for vectors. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VirtualMatrix.kt similarity index 96% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VirtualMatrix.kt index f6794ce01..e0a1d0026 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VirtualMatrix.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.structures.Matrix +import kscience.kmath.structures.Matrix public class VirtualMatrix( override val rowNum: Int, diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt similarity index 97% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt index b09bcff9f..b4a610eb1 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt @@ -1,11 +1,11 @@ -package scientifik.kmath.misc +package kscience.kmath.misc -import scientifik.kmath.linear.Point -import scientifik.kmath.operations.ExtendedField -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.invoke -import scientifik.kmath.operations.sum -import scientifik.kmath.structures.asBuffer +import kscience.kmath.linear.Point +import kscience.kmath.operations.ExtendedField +import kscience.kmath.operations.Field +import kscience.kmath.operations.invoke +import kscience.kmath.operations.sum +import kscience.kmath.structures.asBuffer import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Grids.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/Grids.kt similarity index 98% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Grids.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/misc/Grids.kt index cf3e93895..4d058c366 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/Grids.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/Grids.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.misc +package kscience.kmath.misc import kotlin.math.abs diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/cumulative.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/misc/cumulative.kt index 1712fef58..72d2f2388 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/cumulative.kt @@ -1,8 +1,7 @@ -package scientifik.kmath.misc +package kscience.kmath.misc -import scientifik.kmath.operations.Space -import scientifik.kmath.operations.invoke -import kotlin.contracts.contract +import kscience.kmath.operations.Space +import kscience.kmath.operations.invoke import kotlin.jvm.JvmName /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt similarity index 99% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index 1ea105f67..12a45615a 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -1,6 +1,4 @@ -package scientifik.kmath.operations - -import kotlin.contracts.contract +package kscience.kmath.operations /** * Stub for DSL the [Algebra] is. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/AlgebraElements.kt similarity index 98% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/operations/AlgebraElements.kt index 4ed1be0ee..94328dcb5 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/AlgebraElements.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.operations +package kscience.kmath.operations /** * The generic mathematics elements which is able to store its context diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/AlgebraExtensions.kt similarity index 98% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/operations/AlgebraExtensions.kt index 1020df7d9..657da6b4e 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/AlgebraExtensions.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.operations +package kscience.kmath.operations /** * Returns the sum of all elements in the iterable in this [Space]. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt similarity index 98% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt index d54557a1f..4590c58fc 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt @@ -1,9 +1,8 @@ -package scientifik.kmath.operations +package kscience.kmath.operations -import scientifik.kmath.operations.BigInt.Companion.BASE -import scientifik.kmath.operations.BigInt.Companion.BASE_SIZE -import scientifik.kmath.structures.* -import kotlin.contracts.contract +import kscience.kmath.operations.BigInt.Companion.BASE +import kscience.kmath.operations.BigInt.Companion.BASE_SIZE +import kscience.kmath.structures.* import kotlin.math.log2 import kotlin.math.max import kotlin.math.min diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt similarity index 94% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt index 05a592e97..c0faf5dc5 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt @@ -1,12 +1,11 @@ -package scientifik.kmath.operations +package kscience.kmath.operations -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.MemoryBuffer -import scientifik.kmath.structures.MutableBuffer -import scientifik.memory.MemoryReader -import scientifik.memory.MemorySpec -import scientifik.memory.MemoryWriter -import kotlin.contracts.contract +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.MemoryBuffer +import kscience.kmath.structures.MutableBuffer +import kscience.memory.MemoryReader +import kscience.memory.MemorySpec +import kscience.memory.MemoryWriter import kotlin.math.* /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt similarity index 99% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt index 150a0d582..a2b33a0c4 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/NumberAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.operations +package kscience.kmath.operations import kotlin.math.abs import kotlin.math.pow as kpow diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/OptionalOperations.kt similarity index 99% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/OptionalOperations.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/operations/OptionalOperations.kt index 101f62293..f31d61ae1 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/OptionalOperations.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/OptionalOperations.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.operations +package kscience.kmath.operations /** * A container for trigonometric operations for specific type. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt index a258c7a2f..c3c859f7a 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.FieldElement +import kscience.kmath.operations.Field +import kscience.kmath.operations.FieldElement public class BoxingNDField>( public override val shape: IntArray, diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDRing.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDRing.kt index de83768a0..461b0387c 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BoxingNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDRing.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.Ring -import scientifik.kmath.operations.RingElement +import kscience.kmath.operations.Ring +import kscience.kmath.operations.RingElement public class BoxingNDRing>( override val shape: IntArray, diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferAccessor2D.kt similarity index 97% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferAccessor2D.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferAccessor2D.kt index 0a02fdc8f..00fc4aef0 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferAccessor2D.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.structures +package kscience.kmath.structures import kotlin.reflect.KClass diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt index 4b1a67805..66b4f19e1 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.* +import kscience.kmath.operations.* public interface BufferedNDAlgebra : NDAlgebra> { public val strides: Strides diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDElement.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDElement.kt similarity index 97% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDElement.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDElement.kt index 4de31d101..d53702566 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/BufferedNDElement.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDElement.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.* +import kscience.kmath.operations.* /** * Base class for an element with context, containing strides diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt similarity index 98% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt index 4326159d3..53587e503 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt @@ -1,8 +1,7 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.Complex -import scientifik.kmath.operations.complex -import kotlin.contracts.contract +import kscience.kmath.operations.Complex +import kscience.kmath.operations.complex import kotlin.reflect.KClass /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ComplexNDField.kt similarity index 96% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ComplexNDField.kt index 87dd11f59..f1f1074e5 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ComplexNDField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ComplexNDField.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.Complex -import scientifik.kmath.operations.ComplexField -import scientifik.kmath.operations.FieldElement -import scientifik.kmath.operations.complex +import kscience.kmath.operations.Complex +import kscience.kmath.operations.ComplexField +import kscience.kmath.operations.FieldElement +import kscience.kmath.operations.complex import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ExtendedNDField.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ExtendedNDField.kt similarity index 94% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ExtendedNDField.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ExtendedNDField.kt index 12731ff86..a9fa2763b 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ExtendedNDField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ExtendedNDField.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.ExtendedField +import kscience.kmath.operations.ExtendedField /** * [ExtendedField] over [NDStructure]. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/FlaggedBuffer.kt similarity index 96% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/FlaggedBuffer.kt index f627ede07..e3fda0e10 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/FlaggedBuffer.kt @@ -1,6 +1,5 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import kotlin.contracts.contract import kotlin.experimental.and /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/FloatBuffer.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/FloatBuffer.kt index 4bf7d6ad2..e96c45572 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/FloatBuffer.kt @@ -1,6 +1,4 @@ -package scientifik.kmath.structures - -import kotlin.contracts.contract +package kscience.kmath.structures /** * Specialized [MutableBuffer] implementation over [FloatArray]. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/IntBuffer.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/IntBuffer.kt index 7daa48201..0fe68803b 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/IntBuffer.kt @@ -1,6 +1,4 @@ -package scientifik.kmath.structures - -import kotlin.contracts.contract +package kscience.kmath.structures /** * Specialized [MutableBuffer] implementation over [IntArray]. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/LongBuffer.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/LongBuffer.kt index f87fdc705..87853c251 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/LongBuffer.kt @@ -1,6 +1,4 @@ -package scientifik.kmath.structures - -import kotlin.contracts.contract +package kscience.kmath.structures /** * Specialized [MutableBuffer] implementation over [LongArray]. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/MemoryBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt similarity index 97% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/MemoryBuffer.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt index 2936932d0..b7e6a8218 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/MemoryBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.memory.* +import kscience.memory.* /** * A non-boxing buffer over [Memory] object. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt index a6212469d..28eaef2f1 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.Complex -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.Ring -import scientifik.kmath.operations.Space +import kscience.kmath.operations.Complex +import kscience.kmath.operations.Field +import kscience.kmath.operations.Ring +import kscience.kmath.operations.Space /** * An exception is thrown when the expected ans actual shape of NDArray differs diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDElement.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDElement.kt index 99a87f374..f2f565064 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDElement.kt @@ -1,10 +1,9 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.Ring -import scientifik.kmath.operations.Space -import kotlin.contracts.contract +import kscience.kmath.operations.Field +import kscience.kmath.operations.RealField +import kscience.kmath.operations.Ring +import kscience.kmath.operations.Space /** * The root for all [NDStructure] based algebra elements. Does not implement algebra element root because of problems with recursive self-types diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt similarity index 99% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt index d3007bb09..4ab49c9bc 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt @@ -1,6 +1,5 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import kotlin.contracts.contract import kotlin.jvm.JvmName import kotlin.reflect.KClass diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBuffer.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBuffer.kt index dbb599c85..2a03e2dd3 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBuffer.kt @@ -1,6 +1,4 @@ -package scientifik.kmath.structures - -import kotlin.contracts.contract +package kscience.kmath.structures /** * Specialized [MutableBuffer] implementation over [DoubleArray]. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBufferField.kt similarity index 98% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBufferField.kt index 363ce0275..f7b2ee31e 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBufferField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBufferField.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.ExtendedField -import scientifik.kmath.operations.ExtendedFieldOperations +import kscience.kmath.operations.ExtendedField +import kscience.kmath.operations.ExtendedFieldOperations import kotlin.math.* /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealNDField.kt similarity index 97% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealNDField.kt index 94855d670..ed28fb9f2 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealNDField.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.FieldElement -import scientifik.kmath.operations.RealField +import kscience.kmath.operations.FieldElement +import kscience.kmath.operations.RealField public typealias RealNDElement = BufferedNDFieldElement diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ShortBuffer.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ShortBuffer.kt index b364630f7..0d9222320 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ShortBuffer.kt @@ -1,6 +1,4 @@ -package scientifik.kmath.structures - -import kotlin.contracts.contract +package kscience.kmath.structures /** * Specialized [MutableBuffer] implementation over [ShortArray]. diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ShortNDRing.kt similarity index 96% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ShortNDRing.kt index 30e87fd6a..3b506a26a 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ShortNDRing.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.RingElement -import scientifik.kmath.operations.ShortRing +import kscience.kmath.operations.RingElement +import kscience.kmath.operations.ShortRing public typealias ShortNDElement = BufferedNDRingElement diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure1D.kt similarity index 98% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure1D.kt index 72602695f..af5cc9e3f 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure1D.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.structures +package kscience.kmath.structures /** * A structure that is guaranteed to be one-dimensional diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt similarity index 97% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt index 7633d8898..25fdf3f3d 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.structures +package kscience.kmath.structures /** * A structure that is guaranteed to be two-dimensional diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/ExpressionFieldTest.kt similarity index 87% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/expressions/ExpressionFieldTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/ExpressionFieldTest.kt index 485de08b4..1d3f520f6 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/ExpressionFieldTest.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.expressions +package kscience.kmath.expressions -import scientifik.kmath.operations.Complex -import scientifik.kmath.operations.ComplexField -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.invoke +import kscience.kmath.operations.Complex +import kscience.kmath.operations.ComplexField +import kscience.kmath.operations.RealField +import kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/MatrixTest.kt similarity index 91% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/MatrixTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/linear/MatrixTest.kt index 52a2f80a6..7cfa25a66 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/MatrixTest.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.structures.Matrix -import scientifik.kmath.structures.NDStructure -import scientifik.kmath.structures.as2D +import kscience.kmath.structures.Matrix +import kscience.kmath.structures.NDStructure +import kscience.kmath.structures.as2D import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/RealLUSolverTest.kt similarity index 92% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/linear/RealLUSolverTest.kt index 9de9fb575..de07d3639 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/RealLUSolverTest.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.structures.Matrix +import kscience.kmath.structures.Matrix import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/VectorSpaceTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/VectorSpaceTest.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/VectorSpaceTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/linear/VectorSpaceTest.kt diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/misc/AutoDiffTest.kt similarity index 98% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/misc/AutoDiffTest.kt index 91d32cf8e..3b1813185 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/misc/AutoDiffTest.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.misc +package kscience.kmath.misc -import scientifik.kmath.operations.RealField -import scientifik.kmath.structures.asBuffer +import kscience.kmath.operations.RealField +import kscience.kmath.structures.asBuffer import kotlin.math.PI import kotlin.math.pow import kotlin.math.sqrt diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/CumulativeKtTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/misc/CumulativeKtTest.kt similarity index 90% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/CumulativeKtTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/misc/CumulativeKtTest.kt index 82ea5318f..1e6d2fd5d 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/CumulativeKtTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/misc/CumulativeKtTest.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.misc +package kscience.kmath.misc import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntAlgebraTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntAlgebraTest.kt similarity index 94% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntAlgebraTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntAlgebraTest.kt index d140f1017..78611e5d2 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntAlgebraTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntAlgebraTest.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.operations +package kscience.kmath.operations -import scientifik.kmath.operations.internal.RingVerifier +import kscience.kmath.operations.internal.RingVerifier import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntConstructorTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntConstructorTest.kt similarity index 93% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntConstructorTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntConstructorTest.kt index 5e3f6d1b0..ba2582bbf 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntConstructorTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntConstructorTest.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.operations +package kscience.kmath.operations import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntConversionsTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntConversionsTest.kt similarity index 96% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntConversionsTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntConversionsTest.kt index 41df1968d..0b433c436 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntConversionsTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntConversionsTest.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.operations +package kscience.kmath.operations import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntOperationsTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntOperationsTest.kt similarity index 99% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntOperationsTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntOperationsTest.kt index b7f4cf43b..a3ed85c7b 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/BigIntOperationsTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/BigIntOperationsTest.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.operations +package kscience.kmath.operations import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/ComplexFieldTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/ComplexFieldTest.kt similarity index 96% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/ComplexFieldTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/ComplexFieldTest.kt index 2c480ebea..c0b4853f4 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/ComplexFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/ComplexFieldTest.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.operations +package kscience.kmath.operations -import scientifik.kmath.operations.internal.FieldVerifier +import kscience.kmath.operations.internal.FieldVerifier import kotlin.math.PI import kotlin.math.abs import kotlin.test.Test diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/ComplexTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/ComplexTest.kt similarity index 96% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/ComplexTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/ComplexTest.kt index e8d698c70..f8b9b7262 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/ComplexTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/ComplexTest.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.operations +package kscience.kmath.operations import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/RealFieldTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/RealFieldTest.kt similarity index 75% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/RealFieldTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/RealFieldTest.kt index a168b4afd..5705733cf 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/RealFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/RealFieldTest.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.operations +package kscience.kmath.operations -import scientifik.kmath.operations.internal.FieldVerifier +import kscience.kmath.operations.internal.FieldVerifier import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/AlgebraicVerifier.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/AlgebraicVerifier.kt similarity index 55% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/AlgebraicVerifier.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/AlgebraicVerifier.kt index cb097d46e..7334c13a3 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/AlgebraicVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/AlgebraicVerifier.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.operations.internal +package kscience.kmath.operations.internal -import scientifik.kmath.operations.Algebra +import kscience.kmath.operations.Algebra internal interface AlgebraicVerifier where A : Algebra { val algebra: A diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/FieldVerifier.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/FieldVerifier.kt similarity index 88% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/FieldVerifier.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/FieldVerifier.kt index 973fd00b1..1ca09ab0c 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/FieldVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/FieldVerifier.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.operations.internal +package kscience.kmath.operations.internal -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.invoke +import kscience.kmath.operations.Field +import kscience.kmath.operations.invoke import kotlin.test.assertEquals import kotlin.test.assertNotEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/RingVerifier.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/RingVerifier.kt similarity index 92% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/RingVerifier.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/RingVerifier.kt index 047a213e9..863169b9b 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/RingVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/RingVerifier.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.operations.internal +package kscience.kmath.operations.internal -import scientifik.kmath.operations.Ring -import scientifik.kmath.operations.invoke +import kscience.kmath.operations.Ring +import kscience.kmath.operations.invoke import kotlin.test.assertEquals internal open class RingVerifier(override val algebra: Ring, a: T, b: T, c: T, x: Number) : diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/SpaceVerifier.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/SpaceVerifier.kt similarity index 92% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/SpaceVerifier.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/SpaceVerifier.kt index bc241c97d..4dc855829 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/operations/internal/SpaceVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/SpaceVerifier.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.operations.internal +package kscience.kmath.operations.internal -import scientifik.kmath.operations.Space -import scientifik.kmath.operations.invoke +import kscience.kmath.operations.Space +import kscience.kmath.operations.invoke import kotlin.test.assertEquals import kotlin.test.assertNotEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/ComplexBufferSpecTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/ComplexBufferSpecTest.kt similarity index 68% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/ComplexBufferSpecTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/structures/ComplexBufferSpecTest.kt index cbbe6f0f4..4837236db 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/ComplexBufferSpecTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/ComplexBufferSpecTest.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.Complex -import scientifik.kmath.operations.complex +import kscience.kmath.operations.Complex +import kscience.kmath.operations.complex import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/NDFieldTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt similarity index 87% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/NDFieldTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt index 7abeefca6..79b56ea4a 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/NDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.structures +package kscience.kmath.structures import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt similarity index 90% rename from kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/NumberNDFieldTest.kt rename to kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt index b7e2594ec..f5e008ef3 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.structures +package kscience.kmath.structures -import scientifik.kmath.operations.Norm -import scientifik.kmath.operations.invoke -import scientifik.kmath.structures.NDElement.Companion.real2D +import kscience.kmath.operations.Norm +import kscience.kmath.operations.invoke +import kscience.kmath.structures.NDElement.Companion.real2D import kotlin.math.abs import kotlin.math.pow import kotlin.test.Test diff --git a/kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt b/kmath-core/src/jvmMain/kotlin/kscience/kmath/operations/BigNumbers.kt similarity index 98% rename from kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt rename to kmath-core/src/jvmMain/kotlin/kscience/kmath/operations/BigNumbers.kt index 7310dcc68..2f0978237 100644 --- a/kmath-core/src/jvmMain/kotlin/scientifik/kmath/operations/BigNumbers.kt +++ b/kmath-core/src/jvmMain/kotlin/kscience/kmath/operations/BigNumbers.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.operations +package kscience.kmath.operations import java.math.BigDecimal import java.math.BigInteger diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingIntChain.kt similarity index 89% rename from kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt rename to kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingIntChain.kt index 25a95273d..6088267a2 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingIntChain.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.chains +package kscience.kmath.chains /** * Performance optimized chain for integer values diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt similarity index 90% rename from kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt rename to kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt index 867fee19f..718b3a18b 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.chains +package kscience.kmath.chains /** * Performance optimized chain for real values diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt similarity index 99% rename from kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt rename to kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt index e27290fbb..8c15e52c7 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package scientifik.kmath.chains +package kscience.kmath.chains import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.FlowCollector diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/flowExtra.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/flowExtra.kt similarity index 80% rename from kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/flowExtra.kt rename to kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/flowExtra.kt index 389e0b6db..6b14057fe 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/flowExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/flowExtra.kt @@ -1,13 +1,13 @@ -package scientifik.kmath.chains +package kscience.kmath.chains import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.runningReduce import kotlinx.coroutines.flow.scan -import scientifik.kmath.operations.Space -import scientifik.kmath.operations.SpaceOperations -import scientifik.kmath.operations.invoke +import kscience.kmath.operations.Space +import kscience.kmath.operations.SpaceOperations +import kscience.kmath.operations.invoke @ExperimentalCoroutinesApi public fun Flow.cumulativeSum(space: SpaceOperations): Flow = diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/coroutines/coroutinesExtra.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/coroutines/coroutinesExtra.kt similarity index 98% rename from kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/coroutines/coroutinesExtra.kt rename to kmath-coroutines/src/commonMain/kotlin/kscience/kmath/coroutines/coroutinesExtra.kt index 86bc2d6e3..351207111 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/coroutines/coroutinesExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/coroutines/coroutinesExtra.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.coroutines +package kscience.kmath.coroutines import kotlinx.coroutines.* import kotlinx.coroutines.channels.produce diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/BufferFlow.kt similarity index 89% rename from kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt rename to kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/BufferFlow.kt index 991642787..328a7807c 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/BufferFlow.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/BufferFlow.kt @@ -1,12 +1,12 @@ -package scientifik.kmath.streaming +package kscience.kmath.streaming import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.* -import scientifik.kmath.chains.BlockingRealChain -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.BufferFactory -import scientifik.kmath.structures.RealBuffer -import scientifik.kmath.structures.asBuffer +import kscience.kmath.chains.BlockingRealChain +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.BufferFactory +import kscience.kmath.structures.RealBuffer +import kscience.kmath.structures.asBuffer /** * Create a [Flow] from buffer diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/RingBuffer.kt similarity index 92% rename from kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt rename to kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/RingBuffer.kt index b30100d43..385bbaae2 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/streaming/RingBuffer.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/RingBuffer.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.streaming +package kscience.kmath.streaming import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.MutableBuffer -import scientifik.kmath.structures.VirtualBuffer +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.MutableBuffer +import kscience.kmath.structures.VirtualBuffer /** * Thread-safe ring buffer diff --git a/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/chains/ChainExt.kt b/kmath-coroutines/src/jvmMain/kotlin/kscience/kmath/chains/ChainExt.kt similarity index 93% rename from kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/chains/ChainExt.kt rename to kmath-coroutines/src/jvmMain/kotlin/kscience/kmath/chains/ChainExt.kt index c0df59645..3dfeddbac 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/chains/ChainExt.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/kscience/kmath/chains/ChainExt.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.chains +package kscience.kmath.chains import kotlinx.coroutines.runBlocking diff --git a/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt b/kmath-coroutines/src/jvmMain/kotlin/kscience/kmath/structures/LazyNDStructure.kt similarity index 96% rename from kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt rename to kmath-coroutines/src/jvmMain/kotlin/kscience/kmath/structures/LazyNDStructure.kt index 82950159b..bb0d19c23 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/scientifik/kmath/structures/LazyNDStructure.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/kscience/kmath/structures/LazyNDStructure.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.structures +package kscience.kmath.structures import kotlinx.coroutines.* -import scientifik.kmath.coroutines.Math +import kscience.kmath.coroutines.Math public class LazyNDStructure( public val scope: CoroutineScope, diff --git a/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/BufferFlowTest.kt b/kmath-coroutines/src/jvmTest/kotlin/kscience/kmath/streaming/BufferFlowTest.kt similarity index 88% rename from kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/BufferFlowTest.kt rename to kmath-coroutines/src/jvmTest/kotlin/kscience/kmath/streaming/BufferFlowTest.kt index d17e4d86b..a9bf38c12 100644 --- a/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/BufferFlowTest.kt +++ b/kmath-coroutines/src/jvmTest/kotlin/kscience/kmath/streaming/BufferFlowTest.kt @@ -1,12 +1,12 @@ -package scientifik.kmath.streaming +package kscience.kmath.streaming import kotlinx.coroutines.* import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.collect +import kscience.kmath.coroutines.async +import kscience.kmath.coroutines.collect +import kscience.kmath.coroutines.mapParallel import org.junit.jupiter.api.Timeout -import scientifik.kmath.coroutines.async -import scientifik.kmath.coroutines.collect -import scientifik.kmath.coroutines.mapParallel import java.util.concurrent.Executors import kotlin.test.Test diff --git a/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/RingBufferTest.kt b/kmath-coroutines/src/jvmTest/kotlin/kscience/kmath/streaming/RingBufferTest.kt similarity index 91% rename from kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/RingBufferTest.kt rename to kmath-coroutines/src/jvmTest/kotlin/kscience/kmath/streaming/RingBufferTest.kt index 630749861..5bb0c1d40 100644 --- a/kmath-coroutines/src/jvmTest/kotlin/scientifik/kmath/streaming/RingBufferTest.kt +++ b/kmath-coroutines/src/jvmTest/kotlin/kscience/kmath/streaming/RingBufferTest.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.streaming +package kscience.kmath.streaming import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlocking -import scientifik.kmath.structures.asSequence +import kscience.kmath.structures.asSequence import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Dimensions.kt b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Dimensions.kt similarity index 95% rename from kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Dimensions.kt rename to kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Dimensions.kt index e96367443..f49e1e0f0 100644 --- a/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Dimensions.kt +++ b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Dimensions.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.dimensions +package kscience.kmath.dimensions import kotlin.reflect.KClass diff --git a/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt similarity index 93% rename from kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt rename to kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt index 120069d83..4111cb78d 100644 --- a/kmath-dimensions/src/commonMain/kotlin/scientifik/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt @@ -1,14 +1,14 @@ -package scientifik.kmath.dimensions +package kscience.kmath.dimensions -import scientifik.kmath.linear.GenericMatrixContext -import scientifik.kmath.linear.MatrixContext -import scientifik.kmath.linear.Point -import scientifik.kmath.linear.transpose -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.Ring -import scientifik.kmath.operations.invoke -import scientifik.kmath.structures.Matrix -import scientifik.kmath.structures.Structure2D +import kscience.kmath.linear.GenericMatrixContext +import kscience.kmath.linear.MatrixContext +import kscience.kmath.linear.Point +import kscience.kmath.linear.transpose +import kscience.kmath.operations.RealField +import kscience.kmath.operations.Ring +import kscience.kmath.operations.invoke +import kscience.kmath.structures.Matrix +import kscience.kmath.structures.Structure2D /** * A matrix with compile-time controlled dimension diff --git a/kmath-dimensions/src/commonTest/kotlin/scientifik/dimensions/DMatrixContextTest.kt b/kmath-dimensions/src/commonTest/kotlin/scientifik/dimensions/DMatrixContextTest.kt index dc7acdcc2..f44b16753 100644 --- a/kmath-dimensions/src/commonTest/kotlin/scientifik/dimensions/DMatrixContextTest.kt +++ b/kmath-dimensions/src/commonTest/kotlin/scientifik/dimensions/DMatrixContextTest.kt @@ -1,8 +1,8 @@ -package scientifik.dimensions +package kscience.dimensions -import scientifik.kmath.dimensions.D2 -import scientifik.kmath.dimensions.D3 -import scientifik.kmath.dimensions.DMatrixContext +import kscience.kmath.dimensions.D2 +import kscience.kmath.dimensions.D3 +import kscience.kmath.dimensions.DMatrixContext import kotlin.test.Test internal class DMatrixContextTest { diff --git a/kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt b/kmath-dimensions/src/jsMain/kotlin/kscience/kmath/dimensions/dim.kt similarity index 94% rename from kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt rename to kmath-dimensions/src/jsMain/kotlin/kscience/kmath/dimensions/dim.kt index 139f77e92..4230da156 100644 --- a/kmath-dimensions/src/jsMain/kotlin/scientifik/kmath/dimensions/dim.kt +++ b/kmath-dimensions/src/jsMain/kotlin/kscience/kmath/dimensions/dim.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.dimensions +package kscience.kmath.dimensions import kotlin.reflect.KClass diff --git a/kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt b/kmath-dimensions/src/jvmMain/kotlin/kscience/kmath/dimensions/dim.kt similarity index 91% rename from kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt rename to kmath-dimensions/src/jvmMain/kotlin/kscience/kmath/dimensions/dim.kt index 714133ecb..dec3979ef 100644 --- a/kmath-dimensions/src/jvmMain/kotlin/scientifik/kmath/dimensions/dim.kt +++ b/kmath-dimensions/src/jvmMain/kotlin/kscience/kmath/dimensions/dim.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.dimensions +package kscience.kmath.dimensions import kotlin.reflect.KClass diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt similarity index 76% rename from kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt rename to kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt index 474a701ca..ba5f8444b 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt @@ -1,15 +1,15 @@ -package scientifik.kmath.real +package kscience.kmath.real -import scientifik.kmath.linear.BufferVectorSpace -import scientifik.kmath.linear.Point -import scientifik.kmath.linear.VectorSpace -import scientifik.kmath.operations.Norm -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.SpaceElement -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.RealBuffer -import scientifik.kmath.structures.asBuffer -import scientifik.kmath.structures.asIterable +import kscience.kmath.linear.BufferVectorSpace +import kscience.kmath.linear.Point +import kscience.kmath.linear.VectorSpace +import kscience.kmath.operations.Norm +import kscience.kmath.operations.RealField +import kscience.kmath.operations.SpaceElement +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.RealBuffer +import kscience.kmath.structures.asBuffer +import kscience.kmath.structures.asIterable import kotlin.math.sqrt public typealias RealPoint = Point diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realBuffer.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realBuffer.kt similarity index 67% rename from kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realBuffer.kt rename to kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realBuffer.kt index 480481d97..0a2119b0d 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realBuffer.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realBuffer.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.real +package kscience.kmath.real -import scientifik.kmath.structures.RealBuffer +import kscience.kmath.structures.RealBuffer /** * Simplified [RealBuffer] to array comparison diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realMatrix.kt similarity index 91% rename from kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt rename to kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realMatrix.kt index 1bc5f0a5b..1860b5870 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realMatrix.kt @@ -1,15 +1,14 @@ -package scientifik.kmath.real +package kscience.kmath.real -import scientifik.kmath.linear.MatrixContext -import scientifik.kmath.linear.RealMatrixContext.elementContext -import scientifik.kmath.linear.VirtualMatrix -import scientifik.kmath.operations.invoke -import scientifik.kmath.operations.sum -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.Matrix -import scientifik.kmath.structures.RealBuffer -import scientifik.kmath.structures.asIterable -import kotlin.contracts.contract +import kscience.kmath.linear.MatrixContext +import kscience.kmath.linear.RealMatrixContext.elementContext +import kscience.kmath.linear.VirtualMatrix +import kscience.kmath.operations.invoke +import kscience.kmath.operations.sum +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.Matrix +import kscience.kmath.structures.RealBuffer +import kscience.kmath.structures.asIterable import kotlin.math.pow /* diff --git a/kmath-for-real/src/commonTest/kotlin/scientifik/kmath/linear/VectorTest.kt b/kmath-for-real/src/commonTest/kotlin/kscience/kmath/linear/VectorTest.kt similarity index 88% rename from kmath-for-real/src/commonTest/kotlin/scientifik/kmath/linear/VectorTest.kt rename to kmath-for-real/src/commonTest/kotlin/kscience/kmath/linear/VectorTest.kt index e24037953..17ff4ef20 100644 --- a/kmath-for-real/src/commonTest/kotlin/scientifik/kmath/linear/VectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kscience/kmath/linear/VectorTest.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.linear +package kscience.kmath.linear -import scientifik.kmath.operations.invoke -import scientifik.kmath.real.RealVector +import kscience.kmath.operations.invoke +import kscience.kmath.real.RealVector import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt index baf1db8b5..859938481 100644 --- a/kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt @@ -1,9 +1,9 @@ package scientific.kmath.real -import scientifik.kmath.linear.VirtualMatrix -import scientifik.kmath.linear.build -import scientifik.kmath.real.* -import scientifik.kmath.structures.Matrix +import kscience.kmath.linear.VirtualMatrix +import kscience.kmath.linear.build +import kscience.kmath.real.* +import kscience.kmath.structures.Matrix import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt similarity index 93% rename from kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt rename to kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt index 52030f0fd..a8c020c05 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.functions +package kscience.kmath.functions -import scientifik.kmath.operations.Ring +import kscience.kmath.operations.Ring public fun interface Piecewise { public fun findPiece(arg: T): R? diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt similarity index 93% rename from kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt rename to kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt index 3d97936f9..c513a6889 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.functions +package kscience.kmath.functions -import scientifik.kmath.operations.Ring -import scientifik.kmath.operations.Space -import scientifik.kmath.operations.invoke +import kscience.kmath.operations.Ring +import kscience.kmath.operations.Space +import kscience.kmath.operations.invoke import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.math.max diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/functions.kt similarity index 88% rename from kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt rename to kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/functions.kt index 2b6073e07..d780c16f3 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/functions/functions.kt +++ b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/functions.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.functions +package kscience.kmath.functions -import scientifik.kmath.operations.Algebra -import scientifik.kmath.operations.RealField +import kscience.kmath.operations.Algebra +import kscience.kmath.operations.RealField // TODO make fun interface when KT-41770 is fixed /** diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/Interpolator.kt similarity index 83% rename from kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt rename to kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/Interpolator.kt index a53cafece..0620b4aa8 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/Interpolator.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.interpolation +package kscience.kmath.interpolation -import scientifik.kmath.functions.PiecewisePolynomial -import scientifik.kmath.functions.value -import scientifik.kmath.operations.Ring -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.asBuffer +import kscience.kmath.functions.PiecewisePolynomial +import kscience.kmath.functions.value +import kscience.kmath.operations.Ring +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.asBuffer public fun interface Interpolator { public fun interpolate(points: XYPointSet): (X) -> Y diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt similarity index 76% rename from kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt rename to kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt index 4fac86693..377aa1fbe 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.interpolation +package kscience.kmath.interpolation -import scientifik.kmath.functions.OrderedPiecewisePolynomial -import scientifik.kmath.functions.PiecewisePolynomial -import scientifik.kmath.functions.Polynomial -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.invoke +import kscience.kmath.functions.OrderedPiecewisePolynomial +import kscience.kmath.functions.PiecewisePolynomial +import kscience.kmath.functions.Polynomial +import kscience.kmath.operations.Field +import kscience.kmath.operations.invoke /** * Reference JVM implementation: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/analysis/interpolation/LinearInterpolator.java diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LoessInterpolator.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/LoessInterpolator.kt similarity index 98% rename from kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LoessInterpolator.kt rename to kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/LoessInterpolator.kt index 6707bd8bc..6931857b1 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/LoessInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/LoessInterpolator.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.interpolation +package kscience.kmath.interpolation // -//import scientifik.kmath.functions.PiecewisePolynomial -//import scientifik.kmath.operations.Ring -//import scientifik.kmath.structures.Buffer +//import kscience.kmath.functions.PiecewisePolynomial +//import kscience.kmath.operations.Ring +//import kscience.kmath.structures.Buffer //import kotlin.math.abs //import kotlin.math.sqrt // diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt similarity index 86% rename from kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt rename to kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt index e5dd8906b..6cda45f72 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt @@ -1,11 +1,11 @@ -package scientifik.kmath.interpolation +package kscience.kmath.interpolation -import scientifik.kmath.functions.OrderedPiecewisePolynomial -import scientifik.kmath.functions.PiecewisePolynomial -import scientifik.kmath.functions.Polynomial -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.invoke -import scientifik.kmath.structures.MutableBufferFactory +import kscience.kmath.functions.OrderedPiecewisePolynomial +import kscience.kmath.functions.PiecewisePolynomial +import kscience.kmath.functions.Polynomial +import kscience.kmath.operations.Field +import kscience.kmath.operations.invoke +import kscience.kmath.structures.MutableBufferFactory /** * Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type specific ones. diff --git a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/XYPointSet.kt similarity index 92% rename from kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt rename to kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/XYPointSet.kt index 3c45223d9..2abb7742c 100644 --- a/kmath-functions/src/commonMain/kotlin/scientifik/kmath/interpolation/XYPointSet.kt +++ b/kmath-functions/src/commonMain/kotlin/kscience/kmath/interpolation/XYPointSet.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.interpolation +package kscience.kmath.interpolation -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.Structure2D +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.Structure2D public interface XYPointSet { public val size: Int diff --git a/kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/kscience/kmath/interpolation/LinearInterpolatorTest.kt similarity index 77% rename from kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt rename to kmath-functions/src/commonTest/kotlin/kscience/kmath/interpolation/LinearInterpolatorTest.kt index 3d39de4c9..303615676 100644 --- a/kmath-functions/src/commonTest/kotlin/scientifik/kmath/interpolation/LinearInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/kscience/kmath/interpolation/LinearInterpolatorTest.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.interpolation +package kscience.kmath.interpolation -import scientifik.kmath.functions.PiecewisePolynomial -import scientifik.kmath.functions.asFunction -import scientifik.kmath.operations.RealField +import kscience.kmath.functions.PiecewisePolynomial +import kscience.kmath.functions.asFunction +import kscience.kmath.operations.RealField import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/Euclidean2DSpace.kt similarity index 90% rename from kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean2DSpace.kt rename to kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/Euclidean2DSpace.kt index a5318b709..c2a883a64 100644 --- a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean2DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/Euclidean2DSpace.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.geometry +package kscience.kmath.geometry -import scientifik.kmath.linear.Point -import scientifik.kmath.operations.SpaceElement -import scientifik.kmath.operations.invoke +import kscience.kmath.linear.Point +import kscience.kmath.operations.SpaceElement +import kscience.kmath.operations.invoke import kotlin.math.sqrt public interface Vector2D : Point, Vector, SpaceElement { diff --git a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/Euclidean3DSpace.kt similarity index 91% rename from kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean3DSpace.kt rename to kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/Euclidean3DSpace.kt index f695c0f64..e0052d791 100644 --- a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Euclidean3DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/Euclidean3DSpace.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.geometry +package kscience.kmath.geometry -import scientifik.kmath.linear.Point -import scientifik.kmath.operations.SpaceElement -import scientifik.kmath.operations.invoke +import kscience.kmath.linear.Point +import kscience.kmath.operations.SpaceElement +import kscience.kmath.operations.invoke import kotlin.math.sqrt public interface Vector3D : Point, Vector, SpaceElement { diff --git a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/GeometrySpace.kt similarity index 76% rename from kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/GeometrySpace.kt rename to kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/GeometrySpace.kt index 6798a6291..64badacf5 100644 --- a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/GeometrySpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/GeometrySpace.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.geometry +package kscience.kmath.geometry -import scientifik.kmath.operations.Space +import kscience.kmath.operations.Space public interface Vector diff --git a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Line.kt b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/Line.kt similarity index 81% rename from kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Line.kt rename to kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/Line.kt index a529f7f1b..ec2ce31ca 100644 --- a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/Line.kt +++ b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/Line.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.geometry +package kscience.kmath.geometry public data class Line(val base: V, val direction: V) diff --git a/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/ReferenceFrame.kt b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/ReferenceFrame.kt new file mode 100644 index 000000000..f9de7b51f --- /dev/null +++ b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/ReferenceFrame.kt @@ -0,0 +1,3 @@ +package kscience.kmath.geometry + +public interface ReferenceFrame diff --git a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/ReferenceFrame.kt b/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/ReferenceFrame.kt deleted file mode 100644 index 49bf3793c..000000000 --- a/kmath-geometry/src/commonMain/kotlin/scientifik/kmath/geometry/ReferenceFrame.kt +++ /dev/null @@ -1,3 +0,0 @@ -package scientifik.kmath.geometry - -public interface ReferenceFrame diff --git a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Counters.kt b/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/Counters.kt similarity index 91% rename from kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Counters.kt rename to kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/Counters.kt index ede6db5cf..7a263a9fc 100644 --- a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Counters.kt +++ b/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/Counters.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.histogram +package kscience.kmath.histogram /* * Common representation for atomic counters diff --git a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/Histogram.kt similarity index 87% rename from kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt rename to kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/Histogram.kt index 4ecd62809..98300dada 100644 --- a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/Histogram.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.histogram +package kscience.kmath.histogram -import scientifik.kmath.domains.Domain -import scientifik.kmath.linear.Point -import scientifik.kmath.structures.ArrayBuffer -import scientifik.kmath.structures.RealBuffer +import kscience.kmath.domains.Domain +import kscience.kmath.linear.Point +import kscience.kmath.structures.ArrayBuffer +import kscience.kmath.structures.RealBuffer /** * The bin in the histogram. The histogram is by definition always done in the real space diff --git a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/RealHistogram.kt b/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/RealHistogram.kt similarity index 95% rename from kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/RealHistogram.kt rename to kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/RealHistogram.kt index 64ddc5515..c58952ab4 100644 --- a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/RealHistogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/RealHistogram.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.histogram +package kscience.kmath.histogram -import scientifik.kmath.linear.Point -import scientifik.kmath.operations.SpaceOperations -import scientifik.kmath.operations.invoke -import scientifik.kmath.real.asVector -import scientifik.kmath.structures.* +import kscience.kmath.linear.Point +import kscience.kmath.operations.SpaceOperations +import kscience.kmath.operations.invoke +import kscience.kmath.real.asVector +import kscience.kmath.structures.* import kotlin.math.floor public data class BinDef>( diff --git a/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt index 4400da7c9..87292f17e 100644 --- a/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt @@ -1,9 +1,9 @@ package scietifik.kmath.histogram -import scientifik.kmath.histogram.RealHistogram -import scientifik.kmath.histogram.fill -import scientifik.kmath.histogram.put -import scientifik.kmath.real.RealVector +import kscience.kmath.histogram.RealHistogram +import kscience.kmath.histogram.fill +import kscience.kmath.histogram.put +import kscience.kmath.real.RealVector import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-histograms/src/jsMain/kotlin/scientifik/kmath/histogram/Counters.kt b/kmath-histograms/src/jsMain/kotlin/kscience/kmath/histogram/Counters.kt similarity index 94% rename from kmath-histograms/src/jsMain/kotlin/scientifik/kmath/histogram/Counters.kt rename to kmath-histograms/src/jsMain/kotlin/kscience/kmath/histogram/Counters.kt index 8e2e946f4..d0fa1f4c2 100644 --- a/kmath-histograms/src/jsMain/kotlin/scientifik/kmath/histogram/Counters.kt +++ b/kmath-histograms/src/jsMain/kotlin/kscience/kmath/histogram/Counters.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.histogram +package kscience.kmath.histogram public actual class LongCounter { private var sum: Long = 0L diff --git a/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/Counters.kt b/kmath-histograms/src/jvmMain/kotlin/kscience/kmath/histogram/Counters.kt similarity index 84% rename from kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/Counters.kt rename to kmath-histograms/src/jvmMain/kotlin/kscience/kmath/histogram/Counters.kt index dcf3d5491..efbd185ef 100644 --- a/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/Counters.kt +++ b/kmath-histograms/src/jvmMain/kotlin/kscience/kmath/histogram/Counters.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.histogram +package kscience.kmath.histogram import java.util.concurrent.atomic.DoubleAdder import java.util.concurrent.atomic.LongAdder diff --git a/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/kscience/kmath/histogram/UnivariateHistogram.kt similarity index 95% rename from kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt rename to kmath-histograms/src/jvmMain/kotlin/kscience/kmath/histogram/UnivariateHistogram.kt index add01d82c..5fada1302 100644 --- a/kmath-histograms/src/jvmMain/kotlin/scientifik/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/kscience/kmath/histogram/UnivariateHistogram.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.histogram +package kscience.kmath.histogram -import scientifik.kmath.real.RealVector -import scientifik.kmath.real.asVector -import scientifik.kmath.structures.Buffer +import kscience.kmath.real.RealVector +import kscience.kmath.real.asVector +import kscience.kmath.structures.Buffer import java.util.* import kotlin.math.floor diff --git a/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt b/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt index 9b6eb0435..8de9a7a0c 100644 --- a/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt +++ b/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt @@ -1,4 +1,4 @@ -package scientifik.memory +package kscience.memory import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt b/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt index 5bb163bc1..d2cbb32fd 100644 --- a/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt +++ b/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt @@ -1,4 +1,4 @@ -package scientifik.memory +package kscience.memory /** * A specification to read or write custom objects with fixed size in bytes. diff --git a/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt b/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt index 452ef1fea..d6b8841e4 100644 --- a/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt +++ b/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt @@ -1,4 +1,4 @@ -package scientifik.memory +package kscience.memory import org.khronos.webgl.ArrayBuffer import org.khronos.webgl.DataView diff --git a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt index 0e7c49c74..c912b28ff 100644 --- a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt @@ -1,4 +1,4 @@ -package scientifik.memory +package kscience.memory import java.io.IOException import java.nio.ByteBuffer diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt similarity index 90% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt rename to kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt index 3c4d0420f..d55a52f56 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.prob +package kscience.kmath.prob -import scientifik.kmath.chains.Chain -import scientifik.kmath.chains.collect -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.BufferFactory +import kscience.kmath.chains.Chain +import kscience.kmath.chains.collect +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.BufferFactory public interface Sampler { public fun sample(generator: RandomGenerator): Chain diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt similarity index 93% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt rename to kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt index 05b62deb8..4d713fc4e 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.prob +package kscience.kmath.prob -import scientifik.kmath.chains.Chain -import scientifik.kmath.chains.SimpleChain +import kscience.kmath.chains.Chain +import kscience.kmath.chains.SimpleChain /** * A multivariate distribution which takes a map of parameters diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomChain.kt similarity index 87% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt rename to kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomChain.kt index 4fc7fe241..b4a80f6c5 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomChain.kt @@ -1,6 +1,6 @@ -package scientifik.kmath.prob +package kscience.kmath.prob -import scientifik.kmath.chains.Chain +import kscience.kmath.chains.Chain /** * A possibly stateful chain producing random values. diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt similarity index 98% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt rename to kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt index ecf9beeb1..0d95d6f97 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.prob +package kscience.kmath.prob import kotlin.random.Random diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/SamplerAlgebra.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/SamplerAlgebra.kt similarity index 79% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/SamplerAlgebra.kt rename to kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/SamplerAlgebra.kt index 184665928..e363ba30b 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/SamplerAlgebra.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/SamplerAlgebra.kt @@ -1,11 +1,11 @@ -package scientifik.kmath.prob +package kscience.kmath.prob -import scientifik.kmath.chains.Chain -import scientifik.kmath.chains.ConstantChain -import scientifik.kmath.chains.map -import scientifik.kmath.chains.zip -import scientifik.kmath.operations.Space -import scientifik.kmath.operations.invoke +import kscience.kmath.chains.Chain +import kscience.kmath.chains.ConstantChain +import kscience.kmath.chains.map +import kscience.kmath.chains.zip +import kscience.kmath.operations.Space +import kscience.kmath.operations.invoke public class BasicSampler(public val chainBuilder: (RandomGenerator) -> Chain) : Sampler { public override fun sample(generator: RandomGenerator): Chain = chainBuilder(generator) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Statistic.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Statistic.kt similarity index 92% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Statistic.kt rename to kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Statistic.kt index 7811b88f6..6720a3d7f 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Statistic.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Statistic.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.prob +package kscience.kmath.prob import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers @@ -7,11 +7,11 @@ import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.runningReduce -import scientifik.kmath.coroutines.mapParallel -import scientifik.kmath.operations.* -import scientifik.kmath.structures.Buffer -import scientifik.kmath.structures.asIterable -import scientifik.kmath.structures.asSequence +import kscience.kmath.coroutines.mapParallel +import kscience.kmath.operations.* +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.asIterable +import kscience.kmath.structures.asSequence /** * A function, that transforms a buffer of random quantities to some resulting value diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/UniformDistribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/UniformDistribution.kt similarity index 87% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/UniformDistribution.kt rename to kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/UniformDistribution.kt index 10445219d..8df2c01e1 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/UniformDistribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/UniformDistribution.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.prob +package kscience.kmath.prob -import scientifik.kmath.chains.Chain -import scientifik.kmath.chains.SimpleChain +import kscience.kmath.chains.Chain +import kscience.kmath.chains.SimpleChain public class UniformDistribution(public val range: ClosedFloatingPointRange) : UnivariateDistribution { private val length: Double = range.endInclusive - range.start diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt similarity index 98% rename from kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt rename to kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt index eda36415a..18be6f019 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt +++ b/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.prob +package kscience.kmath.prob import org.apache.commons.rng.UniformRandomProvider import org.apache.commons.rng.simple.RandomSource diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt b/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/distributions.kt similarity index 95% rename from kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt rename to kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/distributions.kt index 923317ed2..ff20572cc 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt +++ b/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/distributions.kt @@ -1,11 +1,10 @@ -package scientifik.kmath.prob +package kscience.kmath.prob +import kscience.kmath.chains.BlockingIntChain +import kscience.kmath.chains.BlockingRealChain +import kscience.kmath.chains.Chain import org.apache.commons.rng.UniformRandomProvider import org.apache.commons.rng.sampling.distribution.* -import scientifik.kmath.chains.BlockingIntChain -import scientifik.kmath.chains.BlockingRealChain -import scientifik.kmath.chains.Chain -import java.util.* import kotlin.math.PI import kotlin.math.exp import kotlin.math.pow diff --git a/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/CommonsDistributionsTest.kt b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/CommonsDistributionsTest.kt similarity index 96% rename from kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/CommonsDistributionsTest.kt rename to kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/CommonsDistributionsTest.kt index 0680083ce..12a00684b 100644 --- a/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/CommonsDistributionsTest.kt +++ b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/CommonsDistributionsTest.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.prob +package kscience.kmath.prob import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList diff --git a/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/SamplerTest.kt b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt similarity index 92% rename from kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/SamplerTest.kt rename to kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt index 1152f3057..3d8a4f531 100644 --- a/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/SamplerTest.kt +++ b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.prob +package kscience.kmath.prob import kotlinx.coroutines.runBlocking import kotlin.test.Test diff --git a/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/StatisticTest.kt b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/StatisticTest.kt similarity index 91% rename from kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/StatisticTest.kt rename to kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/StatisticTest.kt index 30789a004..22ca472a8 100644 --- a/kmath-prob/src/jvmTest/kotlin/scientifik/kmath/prob/StatisticTest.kt +++ b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/StatisticTest.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.prob +package kscience.kmath.prob import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking -import scientifik.kmath.streaming.chunked +import kscience.kmath.streaming.chunked import kotlin.test.Test internal class StatisticTest { diff --git a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt b/kmath-viktor/src/main/kotlin/kscience/kmath/viktor/ViktorBuffer.kt similarity index 88% rename from kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt rename to kmath-viktor/src/main/kotlin/kscience/kmath/viktor/ViktorBuffer.kt index 97ab9e6d7..5c9611758 100644 --- a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorBuffer.kt +++ b/kmath-viktor/src/main/kotlin/kscience/kmath/viktor/ViktorBuffer.kt @@ -1,7 +1,7 @@ -package scientifik.kmath.viktor +package kscience.kmath.viktor +import kscience.kmath.structures.MutableBuffer import org.jetbrains.bio.viktor.F64FlatArray -import scientifik.kmath.structures.MutableBuffer @Suppress("NOTHING_TO_INLINE", "OVERRIDE_BY_INLINE") public inline class ViktorBuffer(public val flatArray: F64FlatArray) : MutableBuffer { diff --git a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt b/kmath-viktor/src/main/kotlin/kscience/kmath/viktor/ViktorNDStructure.kt similarity index 92% rename from kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt rename to kmath-viktor/src/main/kotlin/kscience/kmath/viktor/ViktorNDStructure.kt index cbd5357af..2471362cb 100644 --- a/kmath-viktor/src/main/kotlin/scientifik/kmath/viktor/ViktorNDStructure.kt +++ b/kmath-viktor/src/main/kotlin/kscience/kmath/viktor/ViktorNDStructure.kt @@ -1,11 +1,11 @@ -package scientifik.kmath.viktor +package kscience.kmath.viktor +import kscience.kmath.operations.RealField +import kscience.kmath.structures.DefaultStrides +import kscience.kmath.structures.MutableNDStructure +import kscience.kmath.structures.NDField +import kscience.kmath.structures.Strides import org.jetbrains.bio.viktor.F64Array -import scientifik.kmath.operations.RealField -import scientifik.kmath.structures.DefaultStrides -import scientifik.kmath.structures.MutableNDStructure -import scientifik.kmath.structures.NDField -import scientifik.kmath.structures.Strides @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public inline class ViktorNDStructure(public val f64Buffer: F64Array) : MutableNDStructure { diff --git a/settings.gradle.kts b/settings.gradle.kts index 666a05e45..c0d729c32 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,7 +15,7 @@ pluginManagement { jcenter() gradlePluginPortal() maven("https://dl.bintray.com/kotlin/kotlin-eap") - maven("https://dl.bintray.com/mipt-npm/scientifik") + maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://dl.bintray.com/mipt-npm/dev") maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/kotlin/kotlin-dev/") From 735eb937dfddb4220557bc1d46fe096b91d7fdc8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 20 Sep 2020 22:40:29 +0300 Subject: [PATCH 054/199] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 386e1277e..550aad22b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added - Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140). ### Changed +- Package changed from `scientifik` to `kscience.kmath`. ### Deprecated From eb8b7196dc33279116b2a93b88b73071ad912b9a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 20 Sep 2020 22:41:33 +0300 Subject: [PATCH 055/199] Update CHANGELOG.md --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 550aad22b..60aee156f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,15 +4,18 @@ ### Added - Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140). ### Changed -- Package changed from `scientifik` to `kscience.kmath`. +- Package changed from `scientifik` to `kscience.kmath`. ### Deprecated ### Removed +- Koma module ### Fixed - `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) + ### Security + ## [0.1.4] ### Added From 68845b7a03a5fe75d73e1d9aa5ffb825cb6efb9e Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 18:49:02 +0700 Subject: [PATCH 056/199] Update CHANGELOG.md --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60aee156f..bd9d0c2aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,20 @@ ## [Unreleased] ### Added +- `fun` annotation for SAM interfaces in library +- Explicit `public` visibility for all public APIs - Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140). + ### Changed - Package changed from `scientifik` to `kscience.kmath`. +- Gradle version: 6.6 -> 6.6.1 +- Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`) +- `Polynomial` secondary constructor made function. ### Deprecated ### Removed -- Koma module +- `kmath-koma` module because it doesn't support Kotlin 1.4. ### Fixed - `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) @@ -43,7 +49,7 @@ - `power(T, Int)` extension function has preconditions and supports `Field` - Memory objects have more preconditions (overflow checking) - `tg` function is renamed to `tan` (https://github.com/mipt-npm/kmath/pull/114) -- Gradle version: 6.3 -> 6.6.1 +- Gradle version: 6.3 -> 6.6 - Moved probability distributions to commons-rng and to `kmath-prob` ### Fixed From 267b6086a9fb65b70300137aa322ac38c98d054d Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 18:59:02 +0700 Subject: [PATCH 057/199] Change package and specify public visibilities, fix old plugin ID --- kmath-ejml/build.gradle.kts | 2 +- .../kmath/ejml/EjmlMatrix.kt | 32 +++++++++---------- .../kmath/ejml/EjmlMatrixContext.kt | 26 +++++++-------- .../kmath/ejml/EjmlVector.kt | 6 ++-- 4 files changed, 33 insertions(+), 33 deletions(-) rename kmath-ejml/src/main/kotlin/{scientifik => kscience}/kmath/ejml/EjmlMatrix.kt (64%) rename kmath-ejml/src/main/kotlin/{scientifik => kscience}/kmath/ejml/EjmlMatrixContext.kt (76%) rename kmath-ejml/src/main/kotlin/{scientifik => kscience}/kmath/ejml/EjmlVector.kt (90%) diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index 58d8972b8..fa4aa3e39 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("scientifik.jvm") + id("ru.mipt.npm.jvm") } dependencies { diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt similarity index 64% rename from kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt rename to kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt index a4923b5e3..60e3aec8e 100644 --- a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt @@ -1,29 +1,29 @@ -package scientifik.kmath.ejml +package kscience.kmath.ejml import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix -import scientifik.kmath.linear.DeterminantFeature -import scientifik.kmath.linear.FeaturedMatrix -import scientifik.kmath.linear.LUPDecompositionFeature -import scientifik.kmath.linear.MatrixFeature -import scientifik.kmath.structures.NDStructure +import kscience.kmath.linear.DeterminantFeature +import kscience.kmath.linear.FeaturedMatrix +import kscience.kmath.linear.LUPDecompositionFeature +import kscience.kmath.linear.MatrixFeature +import kscience.kmath.structures.NDStructure /** * Represents featured matrix over EJML [SimpleMatrix]. * * @property origin the underlying [SimpleMatrix]. */ -class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) : FeaturedMatrix { - override val rowNum: Int +public class EjmlMatrix(public val origin: SimpleMatrix, features: Set? = null) : FeaturedMatrix { + public override val rowNum: Int get() = origin.numRows() - override val colNum: Int + public override val colNum: Int get() = origin.numCols() - override val shape: IntArray + public override val shape: IntArray get() = intArrayOf(origin.numRows(), origin.numCols()) - override val features: Set = setOf( + public override val features: Set = setOf( object : LUPDecompositionFeature, DeterminantFeature { override val determinant: Double get() = origin.determinant() @@ -50,21 +50,21 @@ class EjmlMatrix(val origin: SimpleMatrix, features: Set? = null) } ) union features.orEmpty() - override fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix = + public override fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix = EjmlMatrix(origin, this.features + features) - override operator fun get(i: Int, j: Int): Double = origin[i, j] + public override operator fun get(i: Int, j: Int): Double = origin[i, j] - override fun equals(other: Any?): Boolean { + public override fun equals(other: Any?): Boolean { if (other is EjmlMatrix) return origin.isIdentical(other.origin, 0.0) return NDStructure.equals(this, other as? NDStructure<*> ?: return false) } - override fun hashCode(): Int { + public override fun hashCode(): Int { var result = origin.hashCode() result = 31 * result + features.hashCode() return result } - override fun toString(): String = "EjmlMatrix(origin=$origin, features=$features)" + public override fun toString(): String = "EjmlMatrix(origin=$origin, features=$features)" } diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt similarity index 76% rename from kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt rename to kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt index 1b59a89ca..b2d99ac3d 100644 --- a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt @@ -1,26 +1,26 @@ -package scientifik.kmath.ejml +package kscience.kmath.ejml import org.ejml.simple.SimpleMatrix -import scientifik.kmath.linear.MatrixContext -import scientifik.kmath.linear.Point -import scientifik.kmath.operations.Space -import scientifik.kmath.operations.invoke -import scientifik.kmath.structures.Matrix +import kscience.kmath.linear.MatrixContext +import kscience.kmath.linear.Point +import kscience.kmath.operations.Space +import kscience.kmath.operations.invoke +import kscience.kmath.structures.Matrix /** * Represents context of basic operations operating with [EjmlMatrix]. */ -class EjmlMatrixContext(private val space: Space) : MatrixContext { +public class EjmlMatrixContext(private val space: Space) : MatrixContext { /** * Converts this matrix to EJML one. */ - fun Matrix.toEjml(): EjmlMatrix = + public fun Matrix.toEjml(): EjmlMatrix = if (this is EjmlMatrix) this else produce(rowNum, colNum) { i, j -> get(i, j) } /** * Converts this vector to EJML one. */ - fun Point.toEjml(): EjmlVector = + public fun Point.toEjml(): EjmlVector = if (this is EjmlVector) this else EjmlVector(SimpleMatrix(size, 1).also { (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) } }) @@ -49,7 +49,7 @@ class EjmlMatrixContext(private val space: Space) : MatrixContext.times(value: Double): EjmlMatrix = EjmlMatrix(toEjml().origin.scale(value)) - companion object + public companion object } /** @@ -59,7 +59,7 @@ class EjmlMatrixContext(private val space: Space) : MatrixContext, b: Matrix): EjmlMatrix = +public fun EjmlMatrixContext.solve(a: Matrix, b: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.solve(b.toEjml().origin)) /** @@ -69,7 +69,7 @@ fun EjmlMatrixContext.solve(a: Matrix, b: Matrix): EjmlMatrix = * @param b n by p vector. * @return the solution for 'x' that is n by p. */ -fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = +public fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) /** @@ -78,4 +78,4 @@ fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = * @param a the matrix. * @return the inverse of this matrix. */ -fun EjmlMatrixContext.inverse(a: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.invert()) +public fun EjmlMatrixContext.inverse(a: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.invert()) diff --git a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt similarity index 90% rename from kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt rename to kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt index dd7969e83..ccd660cc6 100644 --- a/kmath-ejml/src/main/kotlin/scientifik/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.ejml +package kscience.kmath.ejml import org.ejml.simple.SimpleMatrix -import scientifik.kmath.linear.Point -import scientifik.kmath.structures.Buffer +import kscience.kmath.linear.Point +import kscience.kmath.structures.Buffer /** * Represents point over EJML [SimpleMatrix]. From 5910c587e2a019b248aafa52773790e43da25d2b Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 18:59:32 +0700 Subject: [PATCH 058/199] Add missing public visibilities --- .../src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt index 60e3aec8e..478d9c6f8 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt @@ -39,13 +39,13 @@ public class EjmlMatrix(public val origin: SimpleMatrix, features: Set + public override val l: FeaturedMatrix get() = lup.second - override val u: FeaturedMatrix + public override val u: FeaturedMatrix get() = lup.third - override val p: FeaturedMatrix + public override val p: FeaturedMatrix get() = lup.first } ) union features.orEmpty() From 2c21f5669568a6a254c108199ebc68faa9aced09 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 19:00:55 +0700 Subject: [PATCH 059/199] Add missing public visibilities and add @author markers --- .../kotlin/kscience/kmath/ejml/EjmlMatrix.kt | 1 + .../kscience/kmath/ejml/EjmlMatrixContext.kt | 17 +++++++++++------ .../kotlin/kscience/kmath/ejml/EjmlVector.kt | 3 ++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt index 478d9c6f8..15574489e 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt @@ -12,6 +12,7 @@ import kscience.kmath.structures.NDStructure * Represents featured matrix over EJML [SimpleMatrix]. * * @property origin the underlying [SimpleMatrix]. + * @author Iaroslav Postovalov */ public class EjmlMatrix(public val origin: SimpleMatrix, features: Set? = null) : FeaturedMatrix { public override val rowNum: Int diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt index b2d99ac3d..52826a7b1 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt @@ -9,6 +9,8 @@ import kscience.kmath.structures.Matrix /** * Represents context of basic operations operating with [EjmlMatrix]. + * + * @author Iaroslav Postovalov */ public class EjmlMatrixContext(private val space: Space) : MatrixContext { /** @@ -32,22 +34,22 @@ public class EjmlMatrixContext(private val space: Space) : MatrixContext } }) - override fun Matrix.dot(other: Matrix): EjmlMatrix = + public override fun Matrix.dot(other: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) - override fun Matrix.dot(vector: Point): EjmlVector = + public override fun Matrix.dot(vector: Point): EjmlVector = EjmlVector(toEjml().origin.mult(vector.toEjml().origin)) - override fun add(a: Matrix, b: Matrix): EjmlMatrix = + public override fun add(a: Matrix, b: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin + b.toEjml().origin) - override operator fun Matrix.minus(b: Matrix): EjmlMatrix = + public override operator fun Matrix.minus(b: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin - b.toEjml().origin) - override fun multiply(a: Matrix, k: Number): EjmlMatrix = + public override fun multiply(a: Matrix, k: Number): EjmlMatrix = produce(a.rowNum, a.colNum) { i, j -> space { a[i, j] * k } } - override operator fun Matrix.times(value: Double): EjmlMatrix = EjmlMatrix(toEjml().origin.scale(value)) + public override operator fun Matrix.times(value: Double): EjmlMatrix = EjmlMatrix(toEjml().origin.scale(value)) public companion object } @@ -58,6 +60,7 @@ public class EjmlMatrixContext(private val space: Space) : MatrixContext * @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 EjmlMatrixContext.solve(a: Matrix, b: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.solve(b.toEjml().origin)) @@ -68,6 +71,7 @@ public fun EjmlMatrixContext.solve(a: Matrix, b: Matrix): EjmlMa * @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 EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) @@ -77,5 +81,6 @@ public fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVec * * @param a the matrix. * @return the inverse of this matrix. + * @author Iaroslav Postovalov */ public fun EjmlMatrixContext.inverse(a: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.invert()) diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt index ccd660cc6..b3a19849f 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt @@ -8,8 +8,9 @@ import kscience.kmath.structures.Buffer * Represents point over EJML [SimpleMatrix]. * * @property origin the underlying [SimpleMatrix]. + * @author Iaroslav Postavalov */ -class EjmlVector internal constructor(val origin: SimpleMatrix) : Point { +public class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point { override val size: Int get() = origin.numRows() init { From 66d5df7a51e09ee4cfa62c779bc5bb93d84ad0f9 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 19:01:24 +0700 Subject: [PATCH 060/199] Add missing public visibilities --- .../src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt | 6 +++--- .../src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt index 15574489e..140c415b7 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt @@ -40,13 +40,13 @@ public class EjmlMatrix(public val origin: SimpleMatrix, features: Set + override val l: FeaturedMatrix get() = lup.second - public override val u: FeaturedMatrix + override val u: FeaturedMatrix get() = lup.third - public override val p: FeaturedMatrix + override val p: FeaturedMatrix get() = lup.first } ) union features.orEmpty() diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt index b3a19849f..d228e4b39 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt @@ -17,9 +17,9 @@ public class EjmlVector internal constructor(public val origin: SimpleMatrix) : require(origin.numCols() == 1) { error("Only single column matrices are allowed") } } - override operator fun get(index: Int): Double = origin[index] + public override operator fun get(index: Int): Double = origin[index] - override operator fun iterator(): Iterator = object : Iterator { + public override operator fun iterator(): Iterator = object : Iterator { private var cursor: Int = 0 override fun next(): Double { @@ -30,10 +30,10 @@ public class EjmlVector internal constructor(public val origin: SimpleMatrix) : override fun hasNext(): Boolean = cursor < origin.numCols() * origin.numRows() } - override fun contentEquals(other: Buffer<*>): Boolean { + public override fun contentEquals(other: Buffer<*>): Boolean { if (other is EjmlVector) return origin.isIdentical(other.origin, 0.0) return super.contentEquals(other) } - override fun toString(): String = "EjmlVector(origin=$origin)" + public override fun toString(): String = "EjmlVector(origin=$origin)" } From 1c11d25306c453339eee9f687d2efd97986ab9f4 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 19:01:36 +0700 Subject: [PATCH 061/199] Fix typo --- kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt index d228e4b39..66da91fdd 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt @@ -8,7 +8,7 @@ import kscience.kmath.structures.Buffer * Represents point over EJML [SimpleMatrix]. * * @property origin the underlying [SimpleMatrix]. - * @author Iaroslav Postavalov + * @author Iaroslav Postovalov */ public class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point { override val size: Int get() = origin.numRows() From 964ac8a702b8a7fc77f0c41cf415573378ca663b Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 19:02:12 +0700 Subject: [PATCH 062/199] Fix weird guard check --- kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt index 66da91fdd..f7cd1b66d 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlVector.kt @@ -11,10 +11,11 @@ import kscience.kmath.structures.Buffer * @author Iaroslav Postovalov */ public class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point { - override val size: Int get() = origin.numRows() + public override val size: Int + get() = origin.numRows() init { - require(origin.numCols() == 1) { error("Only single column matrices are allowed") } + require(origin.numCols() == 1) { "Only single column matrices are allowed" } } public override operator fun get(index: Int): Double = origin[index] From 91cb95544c055429e89f5d9a218d72fbc6d64989 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 19:29:56 +0700 Subject: [PATCH 063/199] Add tests --- .../kotlin/kscience/kmath/ejml/EjmlMatrix.kt | 4 +- .../kscience/kmath/ejml/EjmlMatrixTest.kt | 75 +++++++++++++++++++ .../kscience/kmath/ejml/EjmlVectorTest.kt | 47 ++++++++++++ 3 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt create mode 100644 kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlVectorTest.kt diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt index 140c415b7..ed6b1571e 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt @@ -36,7 +36,7 @@ public class EjmlMatrix(public val origin: SimpleMatrix, features: Set = + public override fun suggestFeature(vararg features: MatrixFeature): EjmlMatrix = EjmlMatrix(origin, this.features + features) public override operator fun get(i: Int, j: Int): Double = origin[i, j] diff --git a/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt new file mode 100644 index 000000000..e0f15be83 --- /dev/null +++ b/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -0,0 +1,75 @@ +package kscience.kmath.ejml + +import kscience.kmath.linear.DeterminantFeature +import kscience.kmath.linear.LUPDecompositionFeature +import kscience.kmath.linear.MatrixFeature +import kscience.kmath.linear.getFeature +import org.ejml.dense.row.factory.DecompositionFactory_DDRM +import org.ejml.simple.SimpleMatrix +import kotlin.random.Random +import kotlin.random.asJavaRandom +import kotlin.test.* + +internal class EjmlMatrixTest { + private val random = Random(0) + + private val randomMatrix: SimpleMatrix + get() { + val s = random.nextInt(2, 100) + return SimpleMatrix.random_DDRM(s, s, 0.0, 10.0, random.asJavaRandom()) + } + + @Test + fun rowNum() { + val m = randomMatrix + assertEquals(m.numRows(), EjmlMatrix(m).rowNum) + } + + @Test + fun colNum() { + val m = randomMatrix + assertEquals(m.numCols(), EjmlMatrix(m).rowNum) + } + + @Test + fun shape() { + val m = randomMatrix + val w = EjmlMatrix(m) + assertEquals(listOf(m.numRows(), m.numCols()), w.shape.toList()) + } + + @Test + fun features() { + val m = randomMatrix + val w = EjmlMatrix(m) + val det = w.getFeature>() ?: fail() + assertEquals(m.determinant(), det.determinant) + val lup = w.getFeature>() ?: fail() + + val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows(), m.numCols()) + .also { it.decompose(m.ddrm.copy()) } + + assertEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getLower(null))), lup.l) + assertEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getUpper(null))), lup.u) + assertEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getRowPivot(null))), lup.p) + } + + private object SomeFeature : MatrixFeature {} + + @Test + fun suggestFeature() { + assertNotNull(EjmlMatrix(randomMatrix).suggestFeature(SomeFeature).getFeature()) + } + + @Test + fun get() { + val m = randomMatrix + assertEquals(m[0, 0], EjmlMatrix(m)[0, 0]) + } + + @Test + fun origin() { + val m = randomMatrix + assertSame(m, EjmlMatrix(m).origin) + } +} diff --git a/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlVectorTest.kt b/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlVectorTest.kt new file mode 100644 index 000000000..e27f977d2 --- /dev/null +++ b/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlVectorTest.kt @@ -0,0 +1,47 @@ +package kscience.kmath.ejml + +import org.ejml.simple.SimpleMatrix +import kotlin.random.Random +import kotlin.random.asJavaRandom +import kotlin.test.Test +import kotlin.test.assertEquals +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()) + + @Test + fun size() { + val m = randomMatrix + val w = EjmlVector(m) + assertEquals(m.numRows(), w.size) + } + + @Test + fun get() { + val m = randomMatrix + val w = EjmlVector(m) + assertEquals(m[0, 0], w[0]) + } + + @Test + fun iterator() { + val m = randomMatrix + val w = EjmlVector(m) + + assertEquals( + m.iterator(true, 0, 0, m.numRows() - 1, 0).asSequence().toList(), + w.iterator().asSequence().toList() + ) + } + + @Test + fun origin() { + val m = randomMatrix + val w = EjmlVector(m) + assertSame(m, w.origin) + } +} From 02264f84e9051a51dbc031956483bbde6e7ea332 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 19:33:12 +0700 Subject: [PATCH 064/199] Add EJML module references in the readme and doc --- README.md | 4 +++- doc/features.md | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c2e67e815..e6938608b 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,9 @@ can be used for a wide variety of purposes from high performance calculations to * **Commons-math wrapper** It is planned to gradually wrap most parts of [Apache commons-math](http://commons.apache.org/proper/commons-math/) library in Kotlin code and maybe rewrite some parts to better suit the Kotlin programming paradigm, however there is no fixed roadmap for that. Feel free to submit a feature request if you want something to be done first. - + +* **EJML wrapper** Provides EJML `SimpleMatrix` wrapper consistent with the core matrix structures. + ## Planned features * **Messaging** A mathematical notation to support multi-language and multi-node communication for mathematical tasks. diff --git a/doc/features.md b/doc/features.md index 0f2c4203f..ff97310c7 100644 --- a/doc/features.md +++ b/doc/features.md @@ -12,3 +12,5 @@ api and multiple library back-ends. * [Expressions](./expressions.md) * Commons math integration + +* EJML integration From bf569e10f9be41d3aea1ed30d0a547e0f6d44310 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 21 Sep 2020 15:47:47 +0300 Subject: [PATCH 065/199] Implementation for #139 --- README.md | 29 ++++- build.gradle.kts | 81 ++++++++++++- doc/features.md | 14 --- docs/README-STUB.md | 110 ++++++++++++++++++ {doc => docs}/algebra.md | 0 {doc => docs}/buffers.md | 0 {doc => docs}/codestyle.md | 0 {doc => docs}/contexts.md | 0 {doc => docs}/expressions.md | 0 docs/features.md | 14 +++ {doc => docs}/histograms.md | 0 {doc => docs}/linear.md | 0 {doc => docs}/nd-structure.md | 0 kmath-core/{README.md => docs/README-STUB.md} | 14 +-- kmath-core/docs/kscience-module.json | 36 ++++++ settings.gradle.kts | 3 +- 16 files changed, 271 insertions(+), 30 deletions(-) delete mode 100644 doc/features.md create mode 100644 docs/README-STUB.md rename {doc => docs}/algebra.md (100%) rename {doc => docs}/buffers.md (100%) rename {doc => docs}/codestyle.md (100%) rename {doc => docs}/contexts.md (100%) rename {doc => docs}/expressions.md (100%) create mode 100644 docs/features.md rename {doc => docs}/histograms.md (100%) rename {doc => docs}/linear.md (100%) rename {doc => docs}/nd-structure.md (100%) rename kmath-core/{README.md => docs/README-STUB.md} (62%) create mode 100644 kmath-core/docs/kscience-module.json diff --git a/README.md b/README.md index c2e67e815..44363b27a 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ The Kotlin MATHematics library is intended as a Kotlin-based analog to Python's ## Features -Actual feature list is [here](doc/features.md) +Actual feature list is [here](docs/features.md) * **Algebra** * Algebraic structures like rings, spaces and field (**TODO** add example to wiki) @@ -66,6 +66,29 @@ can be used for a wide variety of purposes from high performance calculations to * **Fitting** Non-linear curve fitting facilities +## Modules + +### [kmath-core](kmath-core) + - [algebras](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures: contexts and elements + - [nd](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures + - [buffers](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure + - [expressions](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions) : Functional Expressions + - [domains](kmath-core/src/commonMain/kotlin/kscience/kmath/domains) : Domains + - [autodif](kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt) : Automatic differentiation + +### [kmath-coroutines](kmath-coroutines) +### [kmath-viktor](kmath-viktor) +### [kmath-prob](kmath-prob) +### [kmath-ast](kmath-ast) +### [kmath-commons](kmath-commons) +### [kmath-memory](kmath-memory) +### [kmath-for-real](kmath-for-real) +### [kmath-functions](kmath-functions) +### [kmath-dimensions](kmath-dimensions) +### [kmath-histograms](kmath-histograms) +### [kmath-geometry](kmath-geometry) + + ## Multi-platform support KMath is developed as a multi-platform library, which means that most of interfaces are declared in the [common module](kmath-core/src/commonMain). Implementation is also done in the common module wherever possible. In some cases, features are delegated to platform-specific implementations even if they could be done in the common module for performance reasons. Currently, the JVM is the main focus of development, however Kotlin/Native and Kotlin/JS contributions are also welcome. @@ -84,8 +107,8 @@ repositories{ } dependencies{ - api("kscience.kmath:kmath-core:${kmathVersion}") - //api("kscience.kmath:kmath-core-jvm:${kmathVersion}") for jvm-specific version + api("kscience.kmath:kmath-core:0.2.0-dev-1") + //api("kscience.kmath:kmath-core-jvm:0.2.0-dev-1") for jvm-specific version } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 838a05771..ed3317bf8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,4 +18,83 @@ allprojects { version = kmathVersion } -subprojects { if (name.startsWith("kmath")) apply(plugin = "ru.mipt.npm.publish") } +subprojects { + if (name.startsWith("kmath")) apply() +} + +/** + * TODO move to base plugin + */ +val generateReadme by tasks.creating { + group = "documentation" + + fun List>.generateFeatureString(pathPrefix: String): String = buildString { + this@generateFeatureString.forEach { feature -> + val id by feature + val description by feature + val ref by feature + appendln(" - [$id]($pathPrefix$ref) : $description") + } + } + + doLast { + val reader = groovy.json.JsonSlurper() + val projects = HashMap>() + + project.subprojects { + var properties: Map = mapOf( + "name" to this.name, + "group" to this.group, + "version" to this.version + ) + + val projectProperties = this.file("docs/kscience-module.json") + + @Suppress("UNCHECKED_CAST") + if (projectProperties.exists()) { + val customProperties: Map = + (reader.parse(projectProperties) as? Map ?: emptyMap()).withDefault { null } + val features: List>? by customProperties + val featureString = features?.generateFeatureString("") + properties = customProperties + properties + ("featuresString" to featureString) + } + + projects[name] = properties.withDefault { null } + + val readmeStub = this.file("docs/README-STUB.md") + if (readmeStub.exists()) { + val readmeFile = this.file("README.md") + readmeFile.writeText( + groovy.text.SimpleTemplateEngine().createTemplate(readmeStub).make(properties).toString() + ) + } + } + + val rootReadmeStub = project.file("docs/README-STUB.md") + + val modulesString = buildString { + projects.filter { it.key.startsWith("kmath") }.forEach { (name, properties) -> + appendln("### [$name]($name)") + val features: List>? by properties + if (features != null) { + appendln(features!!.generateFeatureString("$name/")) + } + } + } + + val rootReadmeProperties: Map = mapOf( + "name" to project.name, + "group" to project.group, + "version" to project.version, + "modulesString" to modulesString + ) + + if (rootReadmeStub.exists()) { + val readmeFile = project.file("README.md") + readmeFile.writeText( + groovy.text.SimpleTemplateEngine().createTemplate(rootReadmeStub).make(rootReadmeProperties).toString() + ) + } + + } +} \ No newline at end of file diff --git a/doc/features.md b/doc/features.md deleted file mode 100644 index 0f2c4203f..000000000 --- a/doc/features.md +++ /dev/null @@ -1,14 +0,0 @@ -# Features - -* [Algebra](./algebra.md) - [Context-based](./contexts.md) operations on different primitives and structures. - -* [NDStructures](./nd-structure.md) - -* [Linear algebra](./linear.md) - Matrices, operations and linear equations solving. To be moved to separate module. Currently supports basic -api and multiple library back-ends. - -* [Histograms](./histograms.md) - Multidimensional histogram calculation and operations. - -* [Expressions](./expressions.md) - -* Commons math integration diff --git a/docs/README-STUB.md b/docs/README-STUB.md new file mode 100644 index 000000000..1c6a1f6e0 --- /dev/null +++ b/docs/README-STUB.md @@ -0,0 +1,110 @@ +[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) +[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) + +![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) + +Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) + +Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion) + +# KMath +Could be pronounced as `key-math`. +The Kotlin MATHematics library is intended as a Kotlin-based analog to Python's `numpy` library. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. + +## Publications +* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2) +* [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814) +* [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103) + +# Goal +* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM and JS for now and Native in future). +* Provide basic multiplatform implementations for those abstractions (without significant performance optimization). +* Provide bindings and wrappers with those abstractions for popular optimized platform libraries. + +## Non-goals +* Be like Numpy. It was the idea at the beginning, but we decided that we can do better in terms of API. +* Provide best performance out of the box. We have specialized libraries for that. Need only API wrappers for them. +* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually. +* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like for `Double` in the core. For that we will have specialization modules like `for-real`, which will give better experience for those, who want to work with specific types. + +## Features + +Actual feature list is [here](docs/features.md) + +* **Algebra** + * Algebraic structures like rings, spaces and field (**TODO** add example to wiki) + * Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. + * Complex numbers backed by the `Field` API (meaning that they will be usable in any structure like vectors and N-dimensional arrays). + * Advanced linear algebra operations like matrix inversion and LU decomposition. + +* **Array-like structures** Full support of many-dimensional array-like structures +including mixed arithmetic operations and function operations over arrays and numbers (with the added benefit of static type checking). + +* **Expressions** By writing a single mathematical expression +once, users will be able to apply different types of objects to the expression by providing a context. Expressions +can be used for a wide variety of purposes from high performance calculations to code generation. + +* **Histograms** Fast multi-dimensional histograms. + +* **Streaming** Streaming operations on mathematical objects and objects buffers. + +* **Type-safe dimensions** Type-safe dimensions for matrix operations. + +* **Commons-math wrapper** It is planned to gradually wrap most parts of [Apache commons-math](http://commons.apache.org/proper/commons-math/) + library in Kotlin code and maybe rewrite some parts to better suit the Kotlin programming paradigm, however there is no fixed roadmap for that. Feel free + to submit a feature request if you want something to be done first. + +## Planned features + +* **Messaging** A mathematical notation to support multi-language and multi-node communication for mathematical tasks. + +* **Array statistics** + +* **Integration** Univariate and multivariate integration framework. + +* **Probability and distributions** + +* **Fitting** Non-linear curve fitting facilities + +## Modules + +$modulesString + +## Multi-platform support + +KMath is developed as a multi-platform library, which means that most of interfaces are declared in the [common module](kmath-core/src/commonMain). Implementation is also done in the common module wherever possible. In some cases, features are delegated to platform-specific implementations even if they could be done in the common module for performance reasons. Currently, the JVM is the main focus of development, however Kotlin/Native and Kotlin/JS contributions are also welcome. + +## Performance + +Calculation performance is one of major goals of KMath in the future, but in some cases it is not possible to achieve both performance and flexibility. We expect to focus on creating convenient universal API first and then work on increasing performance for specific cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy. + +### Dependency + +Release artifacts are accessible from bintray with following configuration (see documentation for [kotlin-multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) form more details): + +```kotlin +repositories{ + maven("https://dl.bintray.com/mipt-npm/kscience") +} + +dependencies{ + api("kscience.kmath:kmath-core:$version") + //api("kscience.kmath:kmath-core-jvm:$version") for jvm-specific version +} +``` + +Gradle `6.0+` is required for multiplatform artifacts. + +### Development + +Development builds are accessible from the reposirtory +```kotlin +repositories{ + maven("https://dl.bintray.com/mipt-npm/dev") +} +``` +with the same artifact names. + +## Contributing + +The project requires a lot of additional work. Please feel free to contribute in any way and propose new features. diff --git a/doc/algebra.md b/docs/algebra.md similarity index 100% rename from doc/algebra.md rename to docs/algebra.md diff --git a/doc/buffers.md b/docs/buffers.md similarity index 100% rename from doc/buffers.md rename to docs/buffers.md diff --git a/doc/codestyle.md b/docs/codestyle.md similarity index 100% rename from doc/codestyle.md rename to docs/codestyle.md diff --git a/doc/contexts.md b/docs/contexts.md similarity index 100% rename from doc/contexts.md rename to docs/contexts.md diff --git a/doc/expressions.md b/docs/expressions.md similarity index 100% rename from doc/expressions.md rename to docs/expressions.md diff --git a/docs/features.md b/docs/features.md new file mode 100644 index 000000000..1068a4417 --- /dev/null +++ b/docs/features.md @@ -0,0 +1,14 @@ +# Features + +* [Algebra](algebra.md) - [Context-based](contexts.md) operations on different primitives and structures. + +* [NDStructures](nd-structure.md) + +* [Linear algebra](linear.md) - Matrices, operations and linear equations solving. To be moved to separate module. Currently supports basic +api and multiple library back-ends. + +* [Histograms](histograms.md) - Multidimensional histogram calculation and operations. + +* [Expressions](expressions.md) + +* Commons math integration diff --git a/doc/histograms.md b/docs/histograms.md similarity index 100% rename from doc/histograms.md rename to docs/histograms.md diff --git a/doc/linear.md b/docs/linear.md similarity index 100% rename from doc/linear.md rename to docs/linear.md diff --git a/doc/nd-structure.md b/docs/nd-structure.md similarity index 100% rename from doc/nd-structure.md rename to docs/nd-structure.md diff --git a/kmath-core/README.md b/kmath-core/docs/README-STUB.md similarity index 62% rename from kmath-core/README.md rename to kmath-core/docs/README-STUB.md index 9d05331f9..c2e8f661f 100644 --- a/kmath-core/README.md +++ b/kmath-core/docs/README-STUB.md @@ -1,16 +1,10 @@ # The Core Module (`kmath-core`) The core features of KMath: - -- Algebraic structures: contexts and elements. -- ND structures. -- Buffers. -- Functional Expressions. -- Domains. -- Automatic differentiation. +$featuresString > #### Artifact: -> This module is distributed in the artifact `kscience.kmath:kmath-core:0.1.4-dev-8`. +> This module artifact: `$group:kmath-core:$version`. > > **Gradle:** > @@ -22,7 +16,7 @@ The core features of KMath: > } > > dependencies { -> implementation 'kscience.kmath:kmath-core:0.1.4-dev-8' +> implementation '$group:kmath-core:$version' > } > ``` > **Gradle Kotlin DSL:** @@ -35,6 +29,6 @@ The core features of KMath: > } > > dependencies { -> implementation("kscience.kmath:kmath-core:0.1.4-dev-8") +> implementation("$group:kmath-core:$version") > } > ``` diff --git a/kmath-core/docs/kscience-module.json b/kmath-core/docs/kscience-module.json new file mode 100644 index 000000000..c7ac4f082 --- /dev/null +++ b/kmath-core/docs/kscience-module.json @@ -0,0 +1,36 @@ +{ + "description": "Core classes, algebra definitions, basic linear algebra", + "maturity": "development", + "features": [ + { + "id": "algebras", + "description": "Algebraic structures: contexts and elements", + "ref": "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt" + }, + { + "id": "nd", + "description": "Many-dimensional structures", + "ref": "src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt" + }, + { + "id": "buffers", + "description": "One-dimensional structure", + "ref": "src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt" + }, + { + "id": "expressions", + "description": "Functional Expressions", + "ref": "src/commonMain/kotlin/kscience/kmath/expressions" + }, + { + "id": "domains", + "description": "Domains", + "ref": "src/commonMain/kotlin/kscience/kmath/domains" + }, + { + "id": "autodif", + "description": "Automatic differentiation", + "ref": "src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt" + } + ] +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index c0d729c32..fe0ee6c5d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -32,9 +32,8 @@ include( ":kmath-histograms", ":kmath-commons", ":kmath-viktor", - ":kmath-koma", ":kmath-prob", - ":kmath-io", +// ":kmath-io", ":kmath-dimensions", ":kmath-for-real", ":kmath-geometry", From 1e50587da4cf4f88387bf8bc2895b4a27d32d309 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 21 Sep 2020 15:53:11 +0300 Subject: [PATCH 066/199] Update CHANGELOG.md --- CHANGELOG.md | 1 + kmath-core/README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 kmath-core/README.md diff --git a/CHANGELOG.md b/CHANGELOG.md index bd9d0c2aa..e017fe565 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - `fun` annotation for SAM interfaces in library - Explicit `public` visibility for all public APIs - Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140). +- Automatic documentation generation for features (#139) ### Changed - Package changed from `scientifik` to `kscience.kmath`. diff --git a/kmath-core/README.md b/kmath-core/README.md new file mode 100644 index 000000000..1fcd9edc9 --- /dev/null +++ b/kmath-core/README.md @@ -0,0 +1,40 @@ +# The Core Module (`kmath-core`) + +The core features of KMath: + - [algebras](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures: contexts and elements + - [nd](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures + - [buffers](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure + - [expressions](src/commonMain/kotlin/kscience/kmath/expressions) : Functional Expressions + - [domains](src/commonMain/kotlin/kscience/kmath/domains) : Domains + - [autodif](src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt) : Automatic differentiation + + +> #### Artifact: +> This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-1`. +> +> **Gradle:** +> +> ```gradle +> repositories { +> maven { url 'https://dl.bintray.com/mipt-npm/kscience' } +> maven { url 'https://dl.bintray.com/mipt-npm/dev' } +> maven { url https://dl.bintray.com/hotkeytlt/maven' } +> } +> +> dependencies { +> implementation 'kscience.kmath:kmath-core:0.2.0-dev-1' +> } +> ``` +> **Gradle Kotlin DSL:** +> +> ```kotlin +> repositories { +> maven("https://dl.bintray.com/mipt-npm/kscience") +> maven("https://dl.bintray.com/mipt-npm/dev") +> maven("https://dl.bintray.com/hotkeytlt/maven") +> } +> +> dependencies { +> implementation("kscience.kmath:kmath-core:0.2.0-dev-1") +> } +> ``` From 2ee5d0f325fb7189462b4190497be9efefe420eb Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 20:53:31 +0700 Subject: [PATCH 067/199] Change package name, simplify exposed API types, update build snippet, minor refactor --- examples/build.gradle.kts | 6 +- .../kmath/structures/BoxingNDField.kt | 5 +- .../kmath/structures/BufferedNDAlgebra.kt | 4 +- .../kscience/kmath/structures/NDAlgebra.kt | 2 +- kmath-nd4j/README.md | 7 + kmath-nd4j/build.gradle.kts | 2 +- .../kscience.kmath.nd4j/INDArrayAlgebra.kt | 284 ++++++++++++++++++ .../INDArrayIterators.kt | 4 +- .../kscience.kmath.nd4j/INDArrayStructures.kt | 68 +++++ .../arrays.kt | 2 +- .../scientifik.kmath.nd4j/INDArrayAlgebra.kt | 273 ----------------- .../INDArrayStructures.kt | 80 ----- .../kmath/nd4j/INDArrayAlgebraTest.kt | 11 +- .../kmath/nd4j/INDArrayStructureTest.kt | 41 +-- 14 files changed, 402 insertions(+), 387 deletions(-) create mode 100644 kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayAlgebra.kt rename kmath-nd4j/src/main/kotlin/{scientifik.kmath.nd4j => kscience.kmath.nd4j}/INDArrayIterators.kt (94%) create mode 100644 kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayStructures.kt rename kmath-nd4j/src/main/kotlin/{scientifik.kmath.nd4j => kscience.kmath.nd4j}/arrays.kt (85%) delete mode 100644 kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt delete mode 100644 kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt rename kmath-nd4j/src/test/kotlin/{scientifik => kscience}/kmath/nd4j/INDArrayAlgebraTest.kt (78%) rename kmath-nd4j/src/test/kotlin/{scientifik => kscience}/kmath/nd4j/INDArrayStructureTest.kt (55%) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 3d193efce..f0161afbb 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -26,9 +26,13 @@ dependencies { implementation(project(":kmath-prob")) implementation(project(":kmath-viktor")) implementation(project(":kmath-dimensions")) + implementation(project(":kmath-nd4j")) implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6") implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20") - "benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath + implementation("org.slf4j:slf4j-simple:1.7.30") + implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") + "benchmarksImplementation"("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-8") + "benchmarksImplementation"(sourceSets.main.get().output + sourceSets.main.get().runtimeClasspath) } // Configure benchmark diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt index ddec7bd25..dc65b12c4 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt @@ -15,8 +15,9 @@ public class BoxingNDField>( public fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) - public override fun check(vararg elements: NDBuffer) { - check(elements.all { it.strides == strides }) { "Element strides are not the same as context strides" } + public override fun check(vararg elements: NDBuffer): Array> { + require(elements.all { it.strides == strides }) { "Element strides are not the same as context strides" } + return elements } public override fun produce(initializer: F.(IntArray) -> T): BufferedNDFieldElement = diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt index 66b4f19e1..251b1bcb5 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt @@ -5,8 +5,10 @@ import kscience.kmath.operations.* public interface BufferedNDAlgebra : NDAlgebra> { public val strides: Strides - public override fun check(vararg elements: NDBuffer): Unit = + public override fun check(vararg elements: NDBuffer): Array> { require(elements.all { it.strides == strides }) { ("Strides mismatch") } + return elements + } /** * Convert any [NDStructure] to buffered structure using strides from this context. diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt index 35a65c487..4315f0423 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt @@ -11,7 +11,7 @@ import kscience.kmath.operations.Space * @property expected the expected shape. * @property actual the actual shape. */ -public class ShapeMismatchException(val expected: IntArray, val actual: IntArray) : +public class ShapeMismatchException(public val expected: IntArray, public val actual: IntArray) : RuntimeException("Shape ${actual.contentToString()} doesn't fit in expected shape ${expected.contentToString()}.") /** diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index f8ca5eed2..fac24504a 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -13,26 +13,33 @@ This subproject implements the following features: > > ```gradle > repositories { +> mavenCentral() > maven { url 'https://dl.bintray.com/mipt-npm/scientifik' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { > implementation 'scientifik:kmath-nd4j:0.1.4-dev-8' +> implementation 'org.nd4j:nd4j-native-platform:1.0.0-beta7' > } > ``` > **Gradle Kotlin DSL:** > > ```kotlin > repositories { +> mavenCentral() > maven("https://dl.bintray.com/mipt-npm/scientifik") > maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { > implementation("scientifik:kmath-nd4j:0.1.4-dev-8") +> implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") > } > ``` +> +> This distribution also needs an implementation of ND4J API. The ND4J Native Platform is usually the fastest one, so +> it is included to the snippet. > ## Examples diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 110a2ac30..67569b870 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("scientifik.jvm") + id("ru.mipt.npm.jvm") } dependencies { diff --git a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayAlgebra.kt new file mode 100644 index 000000000..728ce3773 --- /dev/null +++ b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayAlgebra.kt @@ -0,0 +1,284 @@ +package kscience.kmath.nd4j + +import org.nd4j.linalg.api.ndarray.INDArray +import org.nd4j.linalg.factory.Nd4j +import kscience.kmath.operations.* +import kscience.kmath.structures.* + +/** + * Represents [NDAlgebra] over [INDArrayAlgebra]. + * + * @param T the type of ND-structure element. + * @param C the type of the element context. + */ +public interface INDArrayAlgebra : NDAlgebra> { + /** + * Wraps [INDArray] to [N]. + */ + public fun INDArray.wrap(): INDArrayStructure + + public override fun produce(initializer: C.(IntArray) -> T): INDArrayStructure { + val struct = Nd4j.create(*shape)!!.wrap() + struct.indicesIterator().forEach { struct[it] = elementContext.initializer(it) } + return struct + } + + public override fun map(arg: INDArrayStructure, transform: C.(T) -> T): INDArrayStructure { + check(arg) + val newStruct = arg.ndArray.dup().wrap() + newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } + return newStruct + } + + public override fun mapIndexed( + arg: INDArrayStructure, + transform: C.(index: IntArray, T) -> T + ): INDArrayStructure { + check(arg) + val new = Nd4j.create(*shape).wrap() + new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(idx, arg[idx]) } + return new + } + + public override fun combine( + a: INDArrayStructure, + b: INDArrayStructure, + transform: C.(T, T) -> T + ): INDArrayStructure { + check(a, b) + val new = Nd4j.create(*shape).wrap() + new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(a[idx], b[idx]) } + return new + } +} + +/** + * Represents [NDSpace] over [INDArrayStructure]. + * + * @param T the type of the element contained in ND structure. + * @param S the type of space of structure elements. + */ +public interface INDArraySpace : NDSpace>, INDArrayAlgebra where S : Space { + public override val zero: INDArrayStructure + get() = Nd4j.zeros(*shape).wrap() + + public override fun add(a: INDArrayStructure, b: INDArrayStructure): INDArrayStructure { + check(a, b) + return a.ndArray.add(b.ndArray).wrap() + } + + public override operator fun INDArrayStructure.minus(b: INDArrayStructure): INDArrayStructure { + check(this, b) + return ndArray.sub(b.ndArray).wrap() + } + + public override operator fun INDArrayStructure.unaryMinus(): INDArrayStructure { + check(this) + return ndArray.neg().wrap() + } + + public override fun multiply(a: INDArrayStructure, k: Number): INDArrayStructure { + check(a) + return a.ndArray.mul(k).wrap() + } + + public override operator fun INDArrayStructure.div(k: Number): INDArrayStructure { + check(this) + return ndArray.div(k).wrap() + } + + public override operator fun INDArrayStructure.times(k: Number): INDArrayStructure { + check(this) + return ndArray.mul(k).wrap() + } +} + +/** + * Represents [NDRing] over [INDArrayStructure]. + * + * @param T the type of the element contained in ND structure. + * @param R the type of ring of structure elements. + */ +public interface INDArrayRing : NDRing>, INDArraySpace where R : Ring { + public override val one: INDArrayStructure + get() = Nd4j.ones(*shape).wrap() + + public override fun multiply(a: INDArrayStructure, b: INDArrayStructure): INDArrayStructure { + check(a, b) + return a.ndArray.mul(b.ndArray).wrap() + } + + public override operator fun INDArrayStructure.minus(b: Number): INDArrayStructure { + check(this) + return ndArray.sub(b).wrap() + } + + public override operator fun INDArrayStructure.plus(b: Number): INDArrayStructure { + check(this) + return ndArray.add(b).wrap() + } + + public override operator fun Number.minus(b: INDArrayStructure): INDArrayStructure { + check(b) + return b.ndArray.rsub(this).wrap() + } +} + +/** + * Represents [NDField] over [INDArrayStructure]. + * + * @param T the type of the element contained in ND structure. + * @param N the type of ND structure. + * @param F the type field of structure elements. + */ +public interface INDArrayField : NDField>, INDArrayRing where F : Field { + public override fun divide(a: INDArrayStructure, b: INDArrayStructure): INDArrayStructure { + check(a, b) + return a.ndArray.div(b.ndArray).wrap() + } + + public override operator fun Number.div(b: INDArrayStructure): INDArrayStructure { + check(b) + return b.ndArray.rdiv(this).wrap() + } +} + +/** + * Represents [NDField] over [INDArrayRealStructure]. + */ +public class RealINDArrayField(public override val shape: IntArray) : INDArrayField { + public override val elementContext: RealField + get() = RealField + + public override fun INDArray.wrap(): INDArrayStructure = check(asRealStructure()) + + public override operator fun INDArrayStructure.div(arg: Double): INDArrayStructure { + check(this) + return ndArray.div(arg).wrap() + } + + public override operator fun INDArrayStructure.plus(arg: Double): INDArrayStructure { + check(this) + return ndArray.add(arg).wrap() + } + + public override operator fun INDArrayStructure.minus(arg: Double): INDArrayStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + public override operator fun INDArrayStructure.times(arg: Double): INDArrayStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + public override operator fun Double.div(arg: INDArrayStructure): INDArrayStructure { + check(arg) + return arg.ndArray.rdiv(this).wrap() + } + + public override operator fun Double.minus(arg: INDArrayStructure): INDArrayStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } +} + +/** + * Represents [NDField] over [INDArrayStructure] of [Float]. + */ +public class FloatINDArrayField(public override val shape: IntArray) : INDArrayField { + public override val elementContext: FloatField + get() = FloatField + + public override fun INDArray.wrap(): INDArrayStructure = check(asFloatStructure()) + + public override operator fun INDArrayStructure.div(arg: Float): INDArrayStructure { + check(this) + return ndArray.div(arg).wrap() + } + + public override operator fun INDArrayStructure.plus(arg: Float): INDArrayStructure { + check(this) + return ndArray.add(arg).wrap() + } + + public override operator fun INDArrayStructure.minus(arg: Float): INDArrayStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + public override operator fun INDArrayStructure.times(arg: Float): INDArrayStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + public override operator fun Float.div(arg: INDArrayStructure): INDArrayStructure { + check(arg) + return arg.ndArray.rdiv(this).wrap() + } + + public override operator fun Float.minus(arg: INDArrayStructure): INDArrayStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } +} + +/** + * Represents [NDRing] over [INDArrayIntStructure]. + */ +public class IntINDArrayRing(public override val shape: IntArray) : INDArrayRing { + public override val elementContext: IntRing + get() = IntRing + + public override fun INDArray.wrap(): INDArrayStructure = check(asIntStructure()) + + public override operator fun INDArrayStructure.plus(arg: Int): INDArrayStructure { + check(this) + return ndArray.add(arg).wrap() + } + + public override operator fun INDArrayStructure.minus(arg: Int): INDArrayStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + public override operator fun INDArrayStructure.times(arg: Int): INDArrayStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + public override operator fun Int.minus(arg: INDArrayStructure): INDArrayStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } +} + +/** + * Represents [NDRing] over [INDArrayStructure] of [Long]. + */ +public class LongINDArrayRing(public override val shape: IntArray) : INDArrayRing { + public override val elementContext: LongRing + get() = LongRing + + public override fun INDArray.wrap(): INDArrayStructure = check(asLongStructure()) + + public override operator fun INDArrayStructure.plus(arg: Long): INDArrayStructure { + check(this) + return ndArray.add(arg).wrap() + } + + public override operator fun INDArrayStructure.minus(arg: Long): INDArrayStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + public override operator fun INDArrayStructure.times(arg: Long): INDArrayStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + public override operator fun Long.minus(arg: INDArrayStructure): INDArrayStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } +} diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayIterators.kt similarity index 94% rename from kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt rename to kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayIterators.kt index 2759f9fdb..9e7ef9e16 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayIterators.kt +++ b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayIterators.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.nd4j +package kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray import org.nd4j.linalg.api.shape.Shape @@ -18,7 +18,7 @@ private class INDArrayIndicesIterator(private val iterateOver: INDArray) : Itera } } -internal fun INDArray.indicesIterator(): Iterator = INDArrayIndicesIterator(this) +internal fun INDArray.indicesIterator(): Iterator = INDArrayIndicesIterator(this) private sealed class INDArrayIteratorBase(protected val iterateOver: INDArray) : Iterator> { private var i: Int = 0 diff --git a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayStructures.kt b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayStructures.kt new file mode 100644 index 000000000..5d4e1a979 --- /dev/null +++ b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayStructures.kt @@ -0,0 +1,68 @@ +package kscience.kmath.nd4j + +import org.nd4j.linalg.api.ndarray.INDArray +import kscience.kmath.structures.MutableNDStructure +import kscience.kmath.structures.NDStructure + +/** + * Represents a [NDStructure] wrapping an [INDArray] object. + * + * @param T the type of items. + */ +public sealed class INDArrayStructure : MutableNDStructure { + /** + * The wrapped [INDArray]. + */ + public abstract val ndArray: INDArray + + public override val shape: IntArray + get() = ndArray.shape().toIntArray() + + internal abstract fun elementsIterator(): Iterator> + internal fun indicesIterator(): Iterator = ndArray.indicesIterator() + public override fun elements(): Sequence> = Sequence(::elementsIterator) +} + +private data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure() { + override fun elementsIterator(): Iterator> = ndArray.intIterator() + override fun get(index: IntArray): Int = ndArray.getInt(*index) + override fun set(index: IntArray, value: Int): Unit = run { ndArray.putScalar(index, value) } +} + +/** + * Wraps this [INDArray] to [INDArrayStructure]. + */ +public fun INDArray.asIntStructure(): INDArrayStructure = INDArrayIntStructure(this) + +private data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure() { + override fun elementsIterator(): Iterator> = ndArray.longIterator() + override fun get(index: IntArray): Long = ndArray.getLong(*index.toLongArray()) + override fun set(index: IntArray, value: Long): Unit = run { ndArray.putScalar(index, value.toDouble()) } +} + +/** + * Wraps this [INDArray] to [INDArrayStructure]. + */ +public fun INDArray.asLongStructure(): INDArrayStructure = INDArrayLongStructure(this) + +private data class INDArrayRealStructure(override val ndArray: INDArray) : INDArrayStructure() { + override fun elementsIterator(): Iterator> = ndArray.realIterator() + override fun get(index: IntArray): Double = ndArray.getDouble(*index) + override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) } +} + +/** + * Wraps this [INDArray] to [INDArrayStructure]. + */ +public fun INDArray.asRealStructure(): INDArrayStructure = INDArrayRealStructure(this) + +private data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure() { + override fun elementsIterator(): Iterator> = ndArray.floatIterator() + override fun get(index: IntArray): Float = ndArray.getFloat(*index) + override fun set(index: IntArray, value: Float): Unit = run { ndArray.putScalar(index, value) } +} + +/** + * Wraps this [INDArray] to [INDArrayStructure]. + */ +public fun INDArray.asFloatStructure(): INDArrayStructure = INDArrayFloatStructure(this) diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/arrays.kt b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/arrays.kt similarity index 85% rename from kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/arrays.kt rename to kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/arrays.kt index 269fc89c2..798f81c35 100644 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/arrays.kt +++ b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/arrays.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.nd4j +package kscience.kmath.nd4j internal fun IntArray.toLongArray(): LongArray = LongArray(size) { this[it].toLong() } internal fun LongArray.toIntArray(): IntArray = IntArray(size) { this[it].toInt() } diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt deleted file mode 100644 index c24e2ece6..000000000 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayAlgebra.kt +++ /dev/null @@ -1,273 +0,0 @@ -package scientifik.kmath.nd4j - -import org.nd4j.linalg.api.ndarray.INDArray -import org.nd4j.linalg.factory.Nd4j -import scientifik.kmath.operations.* -import scientifik.kmath.structures.* - -/** - * Represents [NDAlgebra] over [INDArrayAlgebra]. - * - * @param T the type of ND-structure element. - * @param C the type of the element context. - * @param N the type of the structure. - */ -interface INDArrayAlgebra : NDAlgebra where N : INDArrayStructure, N : MutableNDStructure { - /** - * Wraps [INDArray] to [N]. - */ - fun INDArray.wrap(): N - - override fun produce(initializer: C.(IntArray) -> T): N { - val struct = Nd4j.create(*shape)!!.wrap() - struct.indicesIterator().forEach { struct[it] = elementContext.initializer(it) } - return struct - } - - override fun map(arg: N, transform: C.(T) -> T): N { - check(arg) - val newStruct = arg.ndArray.dup().wrap() - newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } - return newStruct - } - - override fun mapIndexed(arg: N, transform: C.(index: IntArray, T) -> T): N { - check(arg) - val new = Nd4j.create(*shape).wrap() - new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(idx, arg[idx]) } - return new - } - - override fun combine(a: N, b: N, transform: C.(T, T) -> T): N { - check(a, b) - val new = Nd4j.create(*shape).wrap() - new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(a[idx], b[idx]) } - return new - } -} - -/** - * Represents [NDSpace] over [INDArrayStructure]. - * - * @param T the type of the element contained in ND structure. - * @param N the type of ND structure. - * @param S the type of space of structure elements. - */ -interface INDArraySpace : NDSpace, INDArrayAlgebra - where S : Space, N : INDArrayStructure, N : MutableNDStructure { - - override val zero: N - get() = Nd4j.zeros(*shape).wrap() - - override fun add(a: N, b: N): N { - check(a, b) - return a.ndArray.add(b.ndArray).wrap() - } - - override operator fun N.minus(b: N): N { - check(this, b) - return ndArray.sub(b.ndArray).wrap() - } - - override operator fun N.unaryMinus(): N { - check(this) - return ndArray.neg().wrap() - } - - override fun multiply(a: N, k: Number): N { - check(a) - return a.ndArray.mul(k).wrap() - } - - override operator fun N.div(k: Number): N { - check(this) - return ndArray.div(k).wrap() - } - - override operator fun N.times(k: Number): N { - check(this) - return ndArray.mul(k).wrap() - } -} - -/** - * Represents [NDRing] over [INDArrayStructure]. - * - * @param T the type of the element contained in ND structure. - * @param N the type of ND structure. - * @param R the type of ring of structure elements. - */ -interface INDArrayRing : NDRing, INDArraySpace - where R : Ring, N : INDArrayStructure, N : MutableNDStructure { - - override val one: N - get() = Nd4j.ones(*shape).wrap() - - override fun multiply(a: N, b: N): N { - check(a, b) - return a.ndArray.mul(b.ndArray).wrap() - } - - override operator fun N.minus(b: Number): N { - check(this) - return ndArray.sub(b).wrap() - } - - override operator fun N.plus(b: Number): N { - check(this) - return ndArray.add(b).wrap() - } - - override operator fun Number.minus(b: N): N { - check(b) - return b.ndArray.rsub(this).wrap() - } -} - -/** - * Represents [NDField] over [INDArrayStructure]. - * - * @param T the type of the element contained in ND structure. - * @param N the type of ND structure. - * @param F the type field of structure elements. - */ -interface INDArrayField : NDField, INDArrayRing - where F : Field, N : INDArrayStructure, N : MutableNDStructure { - override fun divide(a: N, b: N): N { - check(a, b) - return a.ndArray.div(b.ndArray).wrap() - } - - override operator fun Number.div(b: N): N { - check(b) - return b.ndArray.rdiv(this).wrap() - } -} - -/** - * Represents [NDField] over [INDArrayRealStructure]. - */ -class RealINDArrayField(override val shape: IntArray, override val elementContext: Field = RealField) : - INDArrayField, INDArrayRealStructure> { - override fun INDArray.wrap(): INDArrayRealStructure = check(asRealStructure()) - override operator fun INDArrayRealStructure.div(arg: Double): INDArrayRealStructure { - check(this) - return ndArray.div(arg).wrap() - } - - override operator fun INDArrayRealStructure.plus(arg: Double): INDArrayRealStructure { - check(this) - return ndArray.add(arg).wrap() - } - - override operator fun INDArrayRealStructure.minus(arg: Double): INDArrayRealStructure { - check(this) - return ndArray.sub(arg).wrap() - } - - override operator fun INDArrayRealStructure.times(arg: Double): INDArrayRealStructure { - check(this) - return ndArray.mul(arg).wrap() - } - - override operator fun Double.div(arg: INDArrayRealStructure): INDArrayRealStructure { - check(arg) - return arg.ndArray.rdiv(this).wrap() - } - - override operator fun Double.minus(arg: INDArrayRealStructure): INDArrayRealStructure { - check(arg) - return arg.ndArray.rsub(this).wrap() - } -} - -/** - * Represents [NDField] over [INDArrayFloatStructure]. - */ -class FloatINDArrayField(override val shape: IntArray, override val elementContext: Field = FloatField) : - INDArrayField, INDArrayFloatStructure> { - override fun INDArray.wrap(): INDArrayFloatStructure = check(asFloatStructure()) - override operator fun INDArrayFloatStructure.div(arg: Float): INDArrayFloatStructure { - check(this) - return ndArray.div(arg).wrap() - } - - override operator fun INDArrayFloatStructure.plus(arg: Float): INDArrayFloatStructure { - check(this) - return ndArray.add(arg).wrap() - } - - override operator fun INDArrayFloatStructure.minus(arg: Float): INDArrayFloatStructure { - check(this) - return ndArray.sub(arg).wrap() - } - - override operator fun INDArrayFloatStructure.times(arg: Float): INDArrayFloatStructure { - check(this) - return ndArray.mul(arg).wrap() - } - - override operator fun Float.div(arg: INDArrayFloatStructure): INDArrayFloatStructure { - check(arg) - return arg.ndArray.rdiv(this).wrap() - } - - override operator fun Float.minus(arg: INDArrayFloatStructure): INDArrayFloatStructure { - check(arg) - return arg.ndArray.rsub(this).wrap() - } -} - -/** - * Represents [NDRing] over [INDArrayIntStructure]. - */ -class IntINDArrayRing(override val shape: IntArray, override val elementContext: Ring = IntRing) : - INDArrayRing, INDArrayIntStructure> { - override fun INDArray.wrap(): INDArrayIntStructure = check(asIntStructure()) - override operator fun INDArrayIntStructure.plus(arg: Int): INDArrayIntStructure { - check(this) - return ndArray.add(arg).wrap() - } - - override operator fun INDArrayIntStructure.minus(arg: Int): INDArrayIntStructure { - check(this) - return ndArray.sub(arg).wrap() - } - - override operator fun INDArrayIntStructure.times(arg: Int): INDArrayIntStructure { - check(this) - return ndArray.mul(arg).wrap() - } - - override operator fun Int.minus(arg: INDArrayIntStructure): INDArrayIntStructure { - check(arg) - return arg.ndArray.rsub(this).wrap() - } -} - -/** - * Represents [NDRing] over [INDArrayLongStructure]. - */ -class LongINDArrayRing(override val shape: IntArray, override val elementContext: Ring = LongRing) : - INDArrayRing, INDArrayLongStructure> { - override fun INDArray.wrap(): INDArrayLongStructure = check(asLongStructure()) - override operator fun INDArrayLongStructure.plus(arg: Long): INDArrayLongStructure { - check(this) - return ndArray.add(arg).wrap() - } - - override operator fun INDArrayLongStructure.minus(arg: Long): INDArrayLongStructure { - check(this) - return ndArray.sub(arg).wrap() - } - - override operator fun INDArrayLongStructure.times(arg: Long): INDArrayLongStructure { - check(this) - return ndArray.mul(arg).wrap() - } - - override operator fun Long.minus(arg: INDArrayLongStructure): INDArrayLongStructure { - check(arg) - return arg.ndArray.rsub(this).wrap() - } -} diff --git a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt b/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt deleted file mode 100644 index 39cefee3d..000000000 --- a/kmath-nd4j/src/main/kotlin/scientifik.kmath.nd4j/INDArrayStructures.kt +++ /dev/null @@ -1,80 +0,0 @@ -package scientifik.kmath.nd4j - -import org.nd4j.linalg.api.ndarray.INDArray -import scientifik.kmath.structures.MutableNDStructure -import scientifik.kmath.structures.NDStructure - -/** - * Represents a [NDStructure] wrapping an [INDArray] object. - * - * @param T the type of items. - */ -sealed class INDArrayStructure : MutableNDStructure { - /** - * The wrapped [INDArray]. - */ - abstract val ndArray: INDArray - - override val shape: IntArray - get() = ndArray.shape().toIntArray() - - internal abstract fun elementsIterator(): Iterator> - internal fun indicesIterator(): Iterator = ndArray.indicesIterator() - override fun elements(): Sequence> = Sequence(::elementsIterator) -} - -/** - * Represents a [NDStructure] over [INDArray] elements of which are accessed as ints. - */ -data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure() { - override fun elementsIterator(): Iterator> = ndArray.intIterator() - override fun get(index: IntArray): Int = ndArray.getInt(*index) - override fun set(index: IntArray, value: Int): Unit = run { ndArray.putScalar(index, value) } -} - -/** - * Wraps this [INDArray] to [INDArrayIntStructure]. - */ -fun INDArray.asIntStructure(): INDArrayIntStructure = INDArrayIntStructure(this) - -/** - * Represents a [NDStructure] over [INDArray] elements of which are accessed as longs. - */ -data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure() { - override fun elementsIterator(): Iterator> = ndArray.longIterator() - override fun get(index: IntArray): Long = ndArray.getLong(*index.toLongArray()) - override fun set(index: IntArray, value: Long): Unit = run { ndArray.putScalar(index, value.toDouble()) } -} - -/** - * Wraps this [INDArray] to [INDArrayLongStructure]. - */ -fun INDArray.asLongStructure(): INDArrayLongStructure = INDArrayLongStructure(this) - -/** - * Represents a [NDStructure] over [INDArray] elements of which are accessed as reals. - */ -data class INDArrayRealStructure(override val ndArray: INDArray) : INDArrayStructure() { - override fun elementsIterator(): Iterator> = ndArray.realIterator() - override fun get(index: IntArray): Double = ndArray.getDouble(*index) - override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) } -} - -/** - * Wraps this [INDArray] to [INDArrayRealStructure]. - */ -fun INDArray.asRealStructure(): INDArrayRealStructure = INDArrayRealStructure(this) - -/** - * Represents a [NDStructure] over [INDArray] elements of which are accessed as floats. - */ -data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure() { - override fun elementsIterator(): Iterator> = ndArray.floatIterator() - override fun get(index: IntArray): Float = ndArray.getFloat(*index) - override fun set(index: IntArray, value: Float): Unit = run { ndArray.putScalar(index, value) } -} - -/** - * Wraps this [INDArray] to [INDArrayFloatStructure]. - */ -fun INDArray.asFloatStructure(): INDArrayFloatStructure = INDArrayFloatStructure(this) diff --git a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayAlgebraTest.kt similarity index 78% rename from kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt rename to kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayAlgebraTest.kt index 4aa40c233..1a4f4c9f3 100644 --- a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayAlgebraTest.kt @@ -1,15 +1,16 @@ -package scientifik.kmath.nd4j +package kscience.kmath.nd4j import org.nd4j.linalg.factory.Nd4j -import scientifik.kmath.operations.invoke +import kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.fail internal class INDArrayAlgebraTest { @Test fun testProduce() { val res = (RealINDArrayField(intArrayOf(2, 2))) { produce { it.sum().toDouble() } } - val expected = Nd4j.create(2, 2)!!.asRealStructure() + val expected = (Nd4j.create(2, 2) ?: fail()).asRealStructure() expected[intArrayOf(0, 0)] = 0.0 expected[intArrayOf(0, 1)] = 1.0 expected[intArrayOf(1, 0)] = 1.0 @@ -20,7 +21,7 @@ internal class INDArrayAlgebraTest { @Test fun testMap() { val res = (IntINDArrayRing(intArrayOf(2, 2))) { map(one) { it + it * 2 } } - val expected = Nd4j.create(2, 2)!!.asIntStructure() + val expected = (Nd4j.create(2, 2) ?: fail()).asIntStructure() expected[intArrayOf(0, 0)] = 3 expected[intArrayOf(0, 1)] = 3 expected[intArrayOf(1, 0)] = 3 @@ -31,7 +32,7 @@ internal class INDArrayAlgebraTest { @Test fun testAdd() { val res = (IntINDArrayRing(intArrayOf(2, 2))) { one + 25 } - val expected = Nd4j.create(2, 2)!!.asIntStructure() + val expected = (Nd4j.create(2, 2) ?: fail()).asIntStructure() expected[intArrayOf(0, 0)] = 26 expected[intArrayOf(0, 1)] = 26 expected[intArrayOf(1, 0)] = 26 diff --git a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayStructureTest.kt similarity index 55% rename from kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt rename to kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayStructureTest.kt index dfede6d32..63426d7f9 100644 --- a/kmath-nd4j/src/test/kotlin/scientifik/kmath/nd4j/INDArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayStructureTest.kt @@ -1,70 +1,71 @@ -package scientifik.kmath.nd4j +package kscience.kmath.nd4j +import kscience.kmath.structures.get import org.nd4j.linalg.factory.Nd4j -import scientifik.kmath.structures.get import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotEquals +import kotlin.test.fail internal class INDArrayStructureTest { @Test fun testElements() { val nd = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct = INDArrayRealStructure(nd) + val struct = nd.asRealStructure() val res = struct.elements().map(Pair::second).toList() assertEquals(listOf(1.0, 2.0, 3.0), res) } @Test fun testShape() { - val nd = Nd4j.rand(10, 2, 3, 6)!! - val struct = INDArrayLongStructure(nd) + val nd = Nd4j.rand(10, 2, 3, 6) ?: fail() + val struct = nd.asRealStructure() assertEquals(intArrayOf(10, 2, 3, 6).toList(), struct.shape.toList()) } @Test fun testEquals() { - val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct1 = INDArrayRealStructure(nd1) + val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail() + val struct1 = nd1.asRealStructure() assertEquals(struct1, struct1) - assertNotEquals(struct1, null as INDArrayRealStructure?) - val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct2 = INDArrayRealStructure(nd2) + assertNotEquals(struct1 as Any?, null) + val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail() + val struct2 = nd2.asRealStructure() assertEquals(struct1, struct2) assertEquals(struct2, struct1) - val nd3 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct3 = INDArrayRealStructure(nd3) + val nd3 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail() + val struct3 = nd3.asRealStructure() assertEquals(struct2, struct3) assertEquals(struct1, struct3) } @Test fun testHashCode() { - val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct1 = INDArrayRealStructure(nd1) - val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct2 = INDArrayRealStructure(nd2) + val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))?:fail() + val struct1 = nd1.asRealStructure() + val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))?:fail() + val struct2 = nd2.asRealStructure() assertEquals(struct1.hashCode(), struct2.hashCode()) } @Test fun testDimension() { val nd = Nd4j.rand(8, 16, 3, 7, 1)!! - val struct = INDArrayFloatStructure(nd) + val struct = nd.asFloatStructure() assertEquals(5, struct.dimension) } @Test fun testGet() { - val nd = Nd4j.rand(10, 2, 3, 6)!! - val struct = INDArrayIntStructure(nd) + val nd = Nd4j.rand(10, 2, 3, 6)?:fail() + val struct = nd.asIntStructure() assertEquals(nd.getInt(0, 0, 0, 0), struct[0, 0, 0, 0]) } @Test fun testSet() { val nd = Nd4j.rand(17, 12, 4, 8)!! - val struct = INDArrayIntStructure(nd) + val struct = nd.asLongStructure() struct[intArrayOf(1, 2, 3, 4)] = 777 assertEquals(777, struct[1, 2, 3, 4]) } From 86793d6faca2a04281fae5d3064679551654def9 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 21 Sep 2020 20:56:30 +0700 Subject: [PATCH 068/199] Fix package --- examples/build.gradle.kts | 4 +++- .../kmath/linear/LinearAlgebraBenchmark.kt | 0 .../kmath/linear/MultiplicationBenchmark.kt | 11 ----------- 3 files changed, 3 insertions(+), 12 deletions(-) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/linear/LinearAlgebraBenchmark.kt (100%) rename examples/src/main/kotlin/{scientifik => kscience}/kmath/linear/MultiplicationBenchmark.kt (76%) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 1c90db101..3046b7ce8 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -29,7 +29,9 @@ dependencies { implementation(project(":kmath-ejml")) implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6") implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20") - "benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath + implementation("org.slf4j:slf4j-simple:1.7.30") + "benchmarksImplementation"("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-8") + "benchmarksImplementation"(sourceSets.main.get().output + sourceSets.main.get().runtimeClasspath) } // Configure benchmark diff --git a/examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/linear/LinearAlgebraBenchmark.kt similarity index 100% rename from examples/src/main/kotlin/scientifik/kmath/linear/LinearAlgebraBenchmark.kt rename to examples/src/main/kotlin/kscience/kmath/linear/LinearAlgebraBenchmark.kt diff --git a/examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/linear/MultiplicationBenchmark.kt similarity index 76% rename from examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt rename to examples/src/main/kotlin/kscience/kmath/linear/MultiplicationBenchmark.kt index b82c8aac4..d1011e8f5 100644 --- a/examples/src/main/kotlin/scientifik/kmath/linear/MultiplicationBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/linear/MultiplicationBenchmark.kt @@ -36,14 +36,3 @@ fun main() { val genericTime = measureTimeMillis { val res = matrix1 dot matrix2 } println("Generic implementation time: $genericTime") } - - (EjmlMatrixContext(RealField)) { - val ejmlMatrix1 = matrix1.toEjml() - val ejmlMatrix2 = matrix2.toEjml() - val ejmlTime = measureTimeMillis { ejmlMatrix1 dot ejmlMatrix2 } - println("EJML implementation time: $ejmlTime") - } - - val genericTime = measureTimeMillis { val res = matrix1 dot matrix2 } - println("Generic implementation time: $genericTime") -} From 12b599fff23afafe97be27ceaa51461d0dd7f86c Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Wed, 23 Sep 2020 21:15:54 +0700 Subject: [PATCH 069/199] Fix some packaging issues, add some KDoc comments, minor refactor --- build.gradle.kts | 6 ++-- .../kmath/structures/ArrayBenchmark.kt | 21 ++++++------ .../kmath/structures/BufferBenchmark.kt | 6 ++-- .../kmath/structures/NDFieldBenchmark.kt | 11 +++--- .../kmath/structures/ViktorBenchmark.kt | 4 +-- .../ast/ExpressionsInterpretersBenchmark.kt | 2 +- .../commons/prob/DistributionBenchmark.kt | 7 ++-- .../structures/StructureReadBenchmark.kt | 8 ++--- .../kscience/kmath/asm/internal/AsmBuilder.kt | 2 +- .../commons/expressions/DiffExpression.kt | 2 +- .../FunctionalExpressionAlgebra.kt | 33 ++++++++++++------ .../kscience/kmath/linear/FeaturedMatrix.kt | 6 +++- .../kotlin/kscience/kmath/misc/AutoDiff.kt | 34 +++++++++++++++---- .../kscience/kmath/operations/BigInt.kt | 4 +-- .../kscience/kmath/operations/Complex.kt | 2 +- .../kmath/structures/FlaggedBuffer.kt | 3 +- .../kscience/kmath/structures/Structure1D.kt | 2 +- .../kmath/coroutines/coroutinesExtra.kt | 3 +- .../kscience/kmath/geometry/GeometrySpace.kt | 2 +- .../histogram/MultivariateHistogramTest.kt | 7 ++-- .../{scientifik => kscience}/memory/Memory.kt | 0 .../memory/MemorySpec.kt | 3 +- .../memory/DataViewMemory.kt | 0 .../memory/ByteBufferMemory.kt | 3 +- .../kscience/kmath/prob/Distribution.kt | 2 +- .../kotlin/kscience/kmath/prob/SamplerTest.kt | 2 +- 26 files changed, 103 insertions(+), 72 deletions(-) rename kmath-memory/src/commonMain/kotlin/{scientifik => kscience}/memory/Memory.kt (100%) rename kmath-memory/src/commonMain/kotlin/{scientifik => kscience}/memory/MemorySpec.kt (95%) rename kmath-memory/src/jsMain/kotlin/{scientifik => kscience}/memory/DataViewMemory.kt (100%) rename kmath-memory/src/jvmMain/kotlin/{scientifik => kscience}/memory/ByteBufferMemory.kt (98%) diff --git a/build.gradle.kts b/build.gradle.kts index 838a05771..8f22b309d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,9 +3,9 @@ plugins { id("org.jetbrains.changelog") version "0.4.0" } -val kmathVersion by extra("0.2.0-dev-1") -val bintrayRepo by extra("kscience") -val githubProject by extra("kmath") +val kmathVersion: String by extra("0.2.0-dev-1") +val bintrayRepo: String by extra("kscience") +val githubProject: String by extra("kmath") allprojects { repositories { diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt index 2673552f5..7772facb0 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt @@ -10,30 +10,29 @@ class ArrayBenchmark { @Benchmark fun benchmarkArrayRead() { var res = 0 - for (i in 1.._root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size) res += _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.array[_root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size - i] + for (i in 1..size) res += array[size - i] } @Benchmark fun benchmarkBufferRead() { var res = 0 - for (i in 1.._root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size) res += _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.arrayBuffer.get( - _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size - i) + for (i in 1..size) res += arrayBuffer.get( + size - i + ) } @Benchmark fun nativeBufferRead() { var res = 0 - for (i in 1.._root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size) res += _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.nativeBuffer.get( - _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size - i) + for (i in 1..size) res += nativeBuffer.get( + size - i + ) } companion object { const val size: Int = 1000 - val array: IntArray = IntArray(_root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size) { it } - val arrayBuffer: IntBuffer = IntBuffer.wrap(_root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.array) - - val nativeBuffer: IntBuffer = IntBuffer.allocate(_root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size).also { - for (i in 0 until _root_ide_package_.kscience.kmath.structures.ArrayBenchmark.Companion.size) it.put(i, i) - } + val array: IntArray = IntArray(size) { it } + val arrayBuffer: IntBuffer = IntBuffer.wrap(array) + val nativeBuffer: IntBuffer = IntBuffer.allocate(size).also { for (i in 0 until size) it.put(i, i) } } } diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt index 009d51001..40ba49a34 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt @@ -11,7 +11,7 @@ class BufferBenchmark { @Benchmark fun genericRealBufferReadWrite() { - val buffer = RealBuffer(size){it.toDouble()} + val buffer = RealBuffer(size) { it.toDouble() } (0 until size).forEach { buffer[it] @@ -20,7 +20,7 @@ class BufferBenchmark { @Benchmark fun complexBufferReadWrite() { - val buffer = MutableBuffer.complex(size / 2){Complex(it.toDouble(), -it.toDouble())} + val buffer = MutableBuffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) } (0 until size / 2).forEach { buffer[it] @@ -28,6 +28,6 @@ class BufferBenchmark { } companion object { - const val size = 100 + const val size: Int = 100 } } \ No newline at end of file diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt index 64f279c39..8f37feda4 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt @@ -40,11 +40,10 @@ class NDFieldBenchmark { } companion object { - val dim = 1000 - val n = 100 - - val bufferedField = NDField.auto(RealField, dim, dim) - val specializedField = NDField.real(dim, dim) - val genericField = NDField.boxing(RealField, dim, dim) + const val dim: Int = 1000 + const val n: Int = 100 + val bufferedField: BufferedNDField = NDField.auto(RealField, dim, dim) + val specializedField: RealNDField = NDField.real(dim, dim) + val genericField: BoxingNDField = NDField.boxing(RealField, dim, dim) } } \ No newline at end of file diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt index a4b831f7c..7f55c0560 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt @@ -10,8 +10,8 @@ import org.openjdk.jmh.annotations.State @State(Scope.Benchmark) class ViktorBenchmark { - final val dim = 1000 - final val n = 100 + final val dim: Int = 1000 + final val n: Int = 100 // automatically build context most suited for given type. final val autoField: BufferedNDField = NDField.auto(RealField, dim, dim) diff --git a/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt index a5768f1f5..f0a32e5bd 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt @@ -1,4 +1,4 @@ -//package kscience.kmath.ast +package kscience.kmath.ast // //import kscience.kmath.asm.compile //import kscience.kmath.expressions.Expression diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt index 57a9c55c5..a2d7a0291 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt @@ -10,10 +10,8 @@ import org.apache.commons.rng.simple.RandomSource import java.time.Duration import java.time.Instant - -private suspend fun runChain(): Duration { +private fun runChain(): Duration { val generator = RandomGenerator.fromSource(RandomSource.MT, 123L) - val normal = Distribution.normal(NormalSamplerMethod.Ziggurat) val chain = normal.sample(generator) as BlockingRealChain @@ -67,5 +65,4 @@ fun main() { println("Chain: ${chainJob.await()}") println("Direct: ${directJob.await()}") } - -} \ No newline at end of file +} diff --git a/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt index a2bfea2f9..00606ec08 100644 --- a/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt @@ -12,24 +12,24 @@ fun main() { val structure = BufferNDStructure(strides, buffer) measureTimeMillis { - var res: Double = 0.0 + var res = 0.0 strides.indices().forEach { res = structure[it] } } // warmup val time1 = measureTimeMillis { - var res: Double = 0.0 + var res = 0.0 strides.indices().forEach { res = structure[it] } } println("Structure reading finished in $time1 millis") val time2 = measureTimeMillis { - var res: Double = 0.0 + var res = 0.0 strides.indices().forEach { res = buffer[strides.offset(it)] } } println("Buffer reading finished in $time2 millis") val time3 = measureTimeMillis { - var res: Double = 0.0 + var res = 0.0 strides.indices().forEach { res = array[strides.offset(it)] } } println("Array reading finished in $time3 millis") diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index ab2de97aa..c64ca1d8f 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -32,7 +32,7 @@ internal class AsmBuilder internal constructor( * Internal classloader of [AsmBuilder] with alias to define class from byte array. */ private class ClassLoader(parent: java.lang.ClassLoader) : java.lang.ClassLoader(parent) { - internal fun defineClass(name: String?, b: ByteArray): Class<*> = defineClass(name, b, 0, b.size) + fun defineClass(name: String?, b: ByteArray): Class<*> = defineClass(name, b, 0, b.size) } /** diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt index 3ac908536..8a09cc793 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt @@ -94,7 +94,7 @@ public class DiffExpression(public val function: DerivativeStructureField.() -> * TODO make result [DiffExpression] */ public fun derivative(orders: Map): Expression = Expression { arguments -> - (DerivativeStructureField(orders.values.max() ?: 0, arguments)) { function().deriv(orders) } + (DerivativeStructureField(orders.values.maxOrNull() ?: 0, arguments)) { function().deriv(orders) } } //TODO add gradient and maybe other vector operators 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 49844a2be..5b050dd36 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -4,7 +4,7 @@ import kscience.kmath.operations.* internal class FunctionalUnaryOperation(val context: Algebra, val name: String, private val expr: Expression) : Expression { - public override operator fun invoke(arguments: Map): T = + override operator fun invoke(arguments: Map): T = context.unaryOperation(name, expr.invoke(arguments)) } @@ -14,17 +14,17 @@ internal class FunctionalBinaryOperation( val first: Expression, val second: Expression ) : Expression { - public override operator fun invoke(arguments: Map): T = + override operator fun invoke(arguments: Map): T = context.binaryOperation(name, first.invoke(arguments), second.invoke(arguments)) } internal class FunctionalVariableExpression(val name: String, val default: T? = null) : Expression { - public override operator fun invoke(arguments: Map): T = + override operator fun invoke(arguments: Map): T = arguments[name] ?: default ?: error("Parameter not found: $name") } internal class FunctionalConstantExpression(val value: T) : Expression { - public override operator fun invoke(arguments: Map): T = value + override operator fun invoke(arguments: Map): T = value } internal class FunctionalConstProductExpression( @@ -32,7 +32,7 @@ internal class FunctionalConstProductExpression( private val expr: Expression, val const: Number ) : Expression { - public override operator fun invoke(arguments: Map): T = context.multiply(expr.invoke(arguments), const) + override operator fun invoke(arguments: Map): T = context.multiply(expr.invoke(arguments), const) } /** @@ -139,16 +139,27 @@ public open class FunctionalExpressionField(algebra: A) : public open class FunctionalExpressionExtendedField(algebra: A) : FunctionalExpressionField(algebra), ExtendedField> where A : ExtendedField, A : NumericAlgebra { - public override fun sin(arg: Expression): Expression = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) - public override fun cos(arg: Expression): Expression = unaryOperation(TrigonometricOperations.COS_OPERATION, arg) - public override fun asin(arg: Expression): Expression = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg) - public override fun acos(arg: Expression): Expression = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg) - public override fun atan(arg: Expression): Expression = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg) + public override fun sin(arg: Expression): Expression = + unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) + + public override fun cos(arg: Expression): Expression = + unaryOperation(TrigonometricOperations.COS_OPERATION, arg) + + public override fun asin(arg: Expression): Expression = + unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg) + + public override fun acos(arg: Expression): Expression = + unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg) + + public override fun atan(arg: Expression): Expression = + unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg) public override fun power(arg: Expression, pow: Number): Expression = binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow)) - public override fun exp(arg: Expression): Expression = unaryOperation(ExponentialOperations.EXP_OPERATION, arg) + public override fun exp(arg: Expression): Expression = + unaryOperation(ExponentialOperations.EXP_OPERATION, arg) + public override fun ln(arg: Expression): Expression = unaryOperation(ExponentialOperations.LN_OPERATION, arg) public override fun unaryOperation(operation: String, arg: Expression): Expression = diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt index 65dc8df76..5d9af8608 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt @@ -24,7 +24,11 @@ public interface FeaturedMatrix : Matrix { public companion object } -public inline fun Structure2D.Companion.real(rows: Int, columns: Int, initializer: (Int, Int) -> Double): Matrix = +public inline fun Structure2D.Companion.real( + rows: Int, + columns: Int, + initializer: (Int, Int) -> Double +): Matrix = MatrixContext.real.produce(rows, columns, initializer) /** diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt index b4a610eb1..bfcd5959f 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt @@ -1,10 +1,7 @@ package kscience.kmath.misc import kscience.kmath.linear.Point -import kscience.kmath.operations.ExtendedField -import kscience.kmath.operations.Field -import kscience.kmath.operations.invoke -import kscience.kmath.operations.sum +import kscience.kmath.operations.* import kscience.kmath.structures.asBuffer import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -17,23 +14,37 @@ import kotlin.contracts.contract /** * Differentiable variable with value and derivative of differentiation ([deriv]) result * with respect to this variable. + * + * @param T the non-nullable type of value. + * @property value The value of this variable. */ public open class Variable(public val value: T) +/** + * Represents result of [deriv] call. + * + * @param T the non-nullable type of value. + * @param value the value of result. + * @property deriv The mapping of differentiated variables to their derivatives. + * @property context The field over [T]. + */ public class DerivationResult( value: T, public val deriv: Map, T>, public val context: Field ) : Variable(value) { + /** + * Returns derivative of [variable] or returns [Ring.zero] in [context]. + */ public fun deriv(variable: Variable): T = deriv[variable] ?: context.zero /** - * compute divergence + * Computes the divergence. */ public fun div(): T = context { sum(deriv.values) } /** - * Compute a gradient for variables in given order + * Computes the gradient for variables in given order. */ public fun grad(vararg variables: Variable): Point { check(variables.isNotEmpty()) { "Variable order is not provided for gradient construction" } @@ -53,6 +64,9 @@ public class DerivationResult( * assertEquals(17.0, y.x) // the value of result (y) * assertEquals(9.0, x.d) // dy/dx * ``` + * + * @param body the action in [AutoDiffField] context returning [Variable] to differentiate with respect to. + * @return the result of differentiation. */ public inline fun > F.deriv(body: AutoDiffField.() -> Variable): DerivationResult { contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) } @@ -65,12 +79,15 @@ public inline fun > F.deriv(body: AutoDiffField.() - } } +/** + * Represents field in context of which functions can be derived. + */ public abstract class AutoDiffField> : Field> { public abstract val context: F /** * A variable accessing inner state of derivatives. - * Use this function in inner builders to avoid creating additional derivative bindings + * Use this value in inner builders to avoid creating additional derivative bindings. */ public abstract var Variable.d: T @@ -87,6 +104,9 @@ public abstract class AutoDiffField> : Field> */ public abstract fun derive(value: R, block: F.(R) -> Unit): R + /** + * + */ public abstract fun variable(value: T): Variable public inline fun variable(block: F.() -> T): Variable = variable(context.block()) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt index 4590c58fc..20f289596 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt @@ -299,7 +299,7 @@ public class BigInt internal constructor( for (i in mag.indices) { val cur: ULong = carry + mag[i].toULong() * x.toULong() - result[i] = (cur and BASE.toULong()).toUInt() + result[i] = (cur and BASE).toUInt() carry = cur shr BASE_SIZE } result[resultLength - 1] = (carry and BASE).toUInt() @@ -316,7 +316,7 @@ public class BigInt internal constructor( for (j in mag2.indices) { val cur: ULong = result[i + j].toULong() + mag1[i].toULong() * mag2[j].toULong() + carry - result[i + j] = (cur and BASE.toULong()).toUInt() + result[i + j] = (cur and BASE).toUInt() carry = cur shr BASE_SIZE } 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 c0faf5dc5..9aec6e178 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt @@ -159,7 +159,7 @@ public object ComplexField : ExtendedField, Norm { } /** - * Represents complex number. + * Represents `double`-based complex number. * * @property re The real part. * @property im The imaginary part. diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/FlaggedBuffer.kt index e3fda0e10..4965e37cf 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/FlaggedBuffer.kt @@ -48,7 +48,8 @@ public fun FlaggedBuffer<*>.isMissing(index: Int): Boolean = hasFlag(index, Valu /** * A real buffer which supports flags for each value like NaN or Missing */ -public class FlaggedRealBuffer(public val values: DoubleArray, public val flags: ByteArray) : FlaggedBuffer, Buffer { +public class FlaggedRealBuffer(public val values: DoubleArray, public val flags: ByteArray) : FlaggedBuffer, + Buffer { init { require(values.size == flags.size) { "Values and flags must have the same dimensions" } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure1D.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure1D.kt index af5cc9e3f..95422ac60 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure1D.kt @@ -17,7 +17,7 @@ public interface Structure1D : NDStructure, Buffer { /** * A 1D wrapper for nd-structure */ -private inline class Structure1DWrapper(public val structure: NDStructure) : Structure1D { +private inline class Structure1DWrapper(val structure: NDStructure) : Structure1D { override val shape: IntArray get() = structure.shape override val size: Int get() = structure.shape[0] diff --git a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/coroutines/coroutinesExtra.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/coroutines/coroutinesExtra.kt index 351207111..7dcdc0d62 100644 --- a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/coroutines/coroutinesExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/coroutines/coroutinesExtra.kt @@ -21,7 +21,8 @@ internal class LazyDeferred(val dispatcher: CoroutineDispatcher, val block: s } public class AsyncFlow internal constructor(internal val deferredFlow: Flow>) : Flow { - override suspend fun collect(collector: FlowCollector): Unit = deferredFlow.collect { collector.emit((it.await())) } + override suspend fun collect(collector: FlowCollector): Unit = + deferredFlow.collect { collector.emit((it.await())) } } public fun Flow.async( diff --git a/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/GeometrySpace.kt index 64badacf5..54d2510cf 100644 --- a/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/GeometrySpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/kscience/kmath/geometry/GeometrySpace.kt @@ -4,7 +4,7 @@ import kscience.kmath.operations.Space public interface Vector -public interface GeometrySpace: Space { +public interface GeometrySpace : Space { /** * L2 distance */ diff --git a/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt index 87292f17e..eebb41019 100644 --- a/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt @@ -5,10 +5,7 @@ import kscience.kmath.histogram.fill import kscience.kmath.histogram.put import kscience.kmath.real.RealVector import kotlin.random.Random -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue +import kotlin.test.* internal class MultivariateHistogramTest { @Test @@ -18,7 +15,7 @@ internal class MultivariateHistogramTest { (-1.0..1.0) ) histogram.put(0.55, 0.55) - val bin = histogram.find { it.value.toInt() > 0 }!! + val bin = histogram.find { it.value.toInt() > 0 } ?: fail() assertTrue { bin.contains(RealVector(0.55, 0.55)) } assertTrue { bin.contains(RealVector(0.6, 0.5)) } assertFalse { bin.contains(RealVector(-0.55, 0.55)) } diff --git a/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt b/kmath-memory/src/commonMain/kotlin/kscience/memory/Memory.kt similarity index 100% rename from kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt rename to kmath-memory/src/commonMain/kotlin/kscience/memory/Memory.kt diff --git a/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt b/kmath-memory/src/commonMain/kotlin/kscience/memory/MemorySpec.kt similarity index 95% rename from kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt rename to kmath-memory/src/commonMain/kotlin/kscience/memory/MemorySpec.kt index d2cbb32fd..5e0eb3cad 100644 --- a/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt +++ b/kmath-memory/src/commonMain/kotlin/kscience/memory/MemorySpec.kt @@ -32,7 +32,8 @@ public fun MemoryReader.read(spec: MemorySpec, offset: Int): T = wi /** * Writes the object [value] with [spec] starting from [offset]. */ -public fun MemoryWriter.write(spec: MemorySpec, offset: Int, value: T): Unit = with(spec) { write(offset, value) } +public fun MemoryWriter.write(spec: MemorySpec, offset: Int, value: T): Unit = + with(spec) { write(offset, value) } /** * Reads array of [size] objects mapped by [spec] at certain [offset]. diff --git a/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt b/kmath-memory/src/jsMain/kotlin/kscience/memory/DataViewMemory.kt similarity index 100% rename from kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt rename to kmath-memory/src/jsMain/kotlin/kscience/memory/DataViewMemory.kt diff --git a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/kscience/memory/ByteBufferMemory.kt similarity index 98% rename from kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt rename to kmath-memory/src/jvmMain/kotlin/kscience/memory/ByteBufferMemory.kt index c912b28ff..3c37e2ffd 100644 --- a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/kscience/memory/ByteBufferMemory.kt @@ -100,7 +100,8 @@ public actual fun Memory.Companion.allocate(length: Int): Memory = * Wraps a [Memory] around existing [ByteArray]. This operation is unsafe since the array is not copied * and could be mutated independently from the resulting [Memory]. */ -public actual fun Memory.Companion.wrap(array: ByteArray): Memory = ByteBufferMemory(checkNotNull(ByteBuffer.wrap(array))) +public actual fun Memory.Companion.wrap(array: ByteArray): Memory = + ByteBufferMemory(checkNotNull(ByteBuffer.wrap(array))) /** * Wraps this [ByteBuffer] to [Memory] object. diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt index d55a52f56..72660e20d 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt @@ -62,7 +62,7 @@ public fun Sampler.sampleBuffer( //clear list from previous run tmp.clear() //Fill list - repeat(size){ + repeat(size) { tmp.add(chain.next()) } //return new buffer with elements from tmp diff --git a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt index 3d8a4f531..75db5c402 100644 --- a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt +++ b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt @@ -6,7 +6,7 @@ import kotlin.test.Test class SamplerTest { @Test - fun bufferSamplerTest(){ + fun bufferSamplerTest() { val sampler: Sampler = BasicSampler { it.chain { nextDouble() } } val data = sampler.sampleBuffer(RandomGenerator.default, 100) From 28137e44e150944f5b7758f008dd1d441585aea7 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 25 Sep 2020 10:13:38 +0300 Subject: [PATCH 070/199] Readme auto-generation via plugin --- README.md | 29 +++++-- build.gradle.kts | 81 +------------------ docs/templates/ARTIFACT-TEMPLATE.md | 29 +++++++ .../README-TEMPLATE.md} | 10 +-- kmath-core/build.gradle.kts | 39 ++++++++- .../{README-STUB.md => README-TEMPLATE.md} | 8 +- kmath-core/docs/kscience-module.json | 36 --------- settings.gradle.kts | 23 +++--- 8 files changed, 112 insertions(+), 143 deletions(-) create mode 100644 docs/templates/ARTIFACT-TEMPLATE.md rename docs/{README-STUB.md => templates/README-TEMPLATE.md} (85%) rename kmath-core/docs/{README-STUB.md => README-TEMPLATE.md} (77%) delete mode 100644 kmath-core/docs/kscience-module.json diff --git a/README.md b/README.md index 44363b27a..4d89337b5 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,12 @@ can be used for a wide variety of purposes from high performance calculations to ## Modules +### [examples](examples) + +### [kmath-ast](kmath-ast) + +### [kmath-commons](kmath-commons) + ### [kmath-core](kmath-core) - [algebras](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures: contexts and elements - [nd](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures @@ -77,17 +83,24 @@ can be used for a wide variety of purposes from high performance calculations to - [autodif](kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt) : Automatic differentiation ### [kmath-coroutines](kmath-coroutines) -### [kmath-viktor](kmath-viktor) -### [kmath-prob](kmath-prob) -### [kmath-ast](kmath-ast) -### [kmath-commons](kmath-commons) -### [kmath-memory](kmath-memory) -### [kmath-for-real](kmath-for-real) -### [kmath-functions](kmath-functions) + ### [kmath-dimensions](kmath-dimensions) -### [kmath-histograms](kmath-histograms) + +### [kmath-for-real](kmath-for-real) + +### [kmath-functions](kmath-functions) + ### [kmath-geometry](kmath-geometry) +### [kmath-histograms](kmath-histograms) + +### [kmath-memory](kmath-memory) + +### [kmath-prob](kmath-prob) + +### [kmath-viktor](kmath-viktor) + + ## Multi-platform support diff --git a/build.gradle.kts b/build.gradle.kts index ed3317bf8..81e0cb973 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.base") - id("org.jetbrains.changelog") version "0.4.0" + //id("ru.mipt.npm.publish") apply false + id("ru.mipt.npm.project") } val kmathVersion by extra("0.2.0-dev-1") @@ -22,79 +22,6 @@ subprojects { if (name.startsWith("kmath")) apply() } -/** - * TODO move to base plugin - */ -val generateReadme by tasks.creating { - group = "documentation" - - fun List>.generateFeatureString(pathPrefix: String): String = buildString { - this@generateFeatureString.forEach { feature -> - val id by feature - val description by feature - val ref by feature - appendln(" - [$id]($pathPrefix$ref) : $description") - } - } - - doLast { - val reader = groovy.json.JsonSlurper() - val projects = HashMap>() - - project.subprojects { - var properties: Map = mapOf( - "name" to this.name, - "group" to this.group, - "version" to this.version - ) - - val projectProperties = this.file("docs/kscience-module.json") - - @Suppress("UNCHECKED_CAST") - if (projectProperties.exists()) { - val customProperties: Map = - (reader.parse(projectProperties) as? Map ?: emptyMap()).withDefault { null } - val features: List>? by customProperties - val featureString = features?.generateFeatureString("") - properties = customProperties + properties + ("featuresString" to featureString) - } - - projects[name] = properties.withDefault { null } - - val readmeStub = this.file("docs/README-STUB.md") - if (readmeStub.exists()) { - val readmeFile = this.file("README.md") - readmeFile.writeText( - groovy.text.SimpleTemplateEngine().createTemplate(readmeStub).make(properties).toString() - ) - } - } - - val rootReadmeStub = project.file("docs/README-STUB.md") - - val modulesString = buildString { - projects.filter { it.key.startsWith("kmath") }.forEach { (name, properties) -> - appendln("### [$name]($name)") - val features: List>? by properties - if (features != null) { - appendln(features!!.generateFeatureString("$name/")) - } - } - } - - val rootReadmeProperties: Map = mapOf( - "name" to project.name, - "group" to project.group, - "version" to project.version, - "modulesString" to modulesString - ) - - if (rootReadmeStub.exists()) { - val readmeFile = project.file("README.md") - readmeFile.writeText( - groovy.text.SimpleTemplateEngine().createTemplate(rootReadmeStub).make(rootReadmeProperties).toString() - ) - } - - } +readme{ + readmeTemplate = file("docs/template/README-TEMPLATE.md") } \ No newline at end of file diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md new file mode 100644 index 000000000..1b354e022 --- /dev/null +++ b/docs/templates/ARTIFACT-TEMPLATE.md @@ -0,0 +1,29 @@ +> #### Artifact: +> This module artifact: `${group}:${name}:${version}`. +> +> **Gradle:** +> +> ```gradle +> repositories { +> maven { url 'https://dl.bintray.com/mipt-npm/kscience' } +> maven { url 'https://dl.bintray.com/mipt-npm/dev' } +> maven { url https://dl.bintray.com/hotkeytlt/maven' } +> } +> +> dependencies { +> implementation '${group}:${name}:${version}' +> } +> ``` +> **Gradle Kotlin DSL:** +> +> ```kotlin +> repositories { +> maven("https://dl.bintray.com/mipt-npm/kscience") +> maven("https://dl.bintray.com/mipt-npm/dev") +> maven("https://dl.bintray.com/hotkeytlt/maven") +> } +> +> dependencies { +> implementation("${group}:${name}:${version}") +> } +> ``` \ No newline at end of file diff --git a/docs/README-STUB.md b/docs/templates/README-TEMPLATE.md similarity index 85% rename from docs/README-STUB.md rename to docs/templates/README-TEMPLATE.md index 1c6a1f6e0..f451adb24 100644 --- a/docs/README-STUB.md +++ b/docs/templates/README-TEMPLATE.md @@ -9,9 +9,9 @@ Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmat # KMath Could be pronounced as `key-math`. -The Kotlin MATHematics library is intended as a Kotlin-based analog to Python's `numpy` library. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. +The Kotlin MATHematics library was initially intended as a Kotlin-based analog to Python's `numpy` library. Later we found that kotlin is much more flexible language and allows superior architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could be achieved with [kmath-for-real](/kmath-for-real) extension module. -## Publications +## Publications and talks * [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2) * [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814) * [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103) @@ -29,7 +29,7 @@ The Kotlin MATHematics library is intended as a Kotlin-based analog to Python's ## Features -Actual feature list is [here](docs/features.md) +Actual feature list is [here](/docs/features.md) * **Algebra** * Algebraic structures like rings, spaces and field (**TODO** add example to wiki) @@ -68,11 +68,11 @@ can be used for a wide variety of purposes from high performance calculations to ## Modules -$modulesString +$modules ## Multi-platform support -KMath is developed as a multi-platform library, which means that most of interfaces are declared in the [common module](kmath-core/src/commonMain). Implementation is also done in the common module wherever possible. In some cases, features are delegated to platform-specific implementations even if they could be done in the common module for performance reasons. Currently, the JVM is the main focus of development, however Kotlin/Native and Kotlin/JS contributions are also welcome. +KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the [common module](/kmath-core/src/commonMain). Implementation is also done in the common module wherever possible. In some cases, features are delegated to platform-specific implementations even if they could be done in the common module for performance reasons. Currently, the JVM is the main focus of development, however Kotlin/Native and Kotlin/JS contributions are also welcome. ## Performance diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index e315e1640..31a16e20b 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,7 +1,44 @@ -plugins { id("ru.mipt.npm.mpp") } +plugins { + id("ru.mipt.npm.mpp") +} kotlin.sourceSets.commonMain { dependencies { api(project(":kmath-memory")) } } + +readme { + description = "Core classes, algebra definitions, basic linear algebra" + maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT + feature( + id = "algebras", + description = "Algebraic structures: contexts and elements", + ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt" + ) + feature( + id = "nd", + description = "Many-dimensional structures", + ref = "src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt" + ) + feature( + id = "buffers", + description = "One-dimensional structure", + ref = "src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt" + ) + feature( + id = "expressions", + description = "Functional Expressions", + ref = "src/commonMain/kotlin/kscience/kmath/expressions" + ) + feature( + id = "domains", + description = "Domains", + ref = "src/commonMain/kotlin/kscience/kmath/domains" + ) + feature( + id = "autodif", + description = "Automatic differentiation", + ref = "src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt" + ) +} \ No newline at end of file diff --git a/kmath-core/docs/README-STUB.md b/kmath-core/docs/README-TEMPLATE.md similarity index 77% rename from kmath-core/docs/README-STUB.md rename to kmath-core/docs/README-TEMPLATE.md index c2e8f661f..183f300ac 100644 --- a/kmath-core/docs/README-STUB.md +++ b/kmath-core/docs/README-TEMPLATE.md @@ -1,10 +1,10 @@ # The Core Module (`kmath-core`) The core features of KMath: -$featuresString +$features > #### Artifact: -> This module artifact: `$group:kmath-core:$version`. +> This module artifact: `${group}:${name}:${version}`. > > **Gradle:** > @@ -16,7 +16,7 @@ $featuresString > } > > dependencies { -> implementation '$group:kmath-core:$version' +> implementation '${group}:${name}:${version}' > } > ``` > **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ $featuresString > } > > dependencies { -> implementation("$group:kmath-core:$version") +> implementation("${group}:${name}:${version}") > } > ``` diff --git a/kmath-core/docs/kscience-module.json b/kmath-core/docs/kscience-module.json deleted file mode 100644 index c7ac4f082..000000000 --- a/kmath-core/docs/kscience-module.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "description": "Core classes, algebra definitions, basic linear algebra", - "maturity": "development", - "features": [ - { - "id": "algebras", - "description": "Algebraic structures: contexts and elements", - "ref": "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt" - }, - { - "id": "nd", - "description": "Many-dimensional structures", - "ref": "src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt" - }, - { - "id": "buffers", - "description": "One-dimensional structure", - "ref": "src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt" - }, - { - "id": "expressions", - "description": "Functional Expressions", - "ref": "src/commonMain/kotlin/kscience/kmath/expressions" - }, - { - "id": "domains", - "description": "Domains", - "ref": "src/commonMain/kotlin/kscience/kmath/domains" - }, - { - "id": "autodif", - "description": "Automatic differentiation", - "ref": "src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt" - } - ] -} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index fe0ee6c5d..ad9014e56 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,15 +1,4 @@ pluginManagement { - val toolsVersion = "0.6.0" - - plugins { - id("kotlinx.benchmark") version "0.2.0-dev-20" - id("ru.mipt.npm.base") version toolsVersion - id("ru.mipt.npm.mpp") version toolsVersion - id("ru.mipt.npm.jvm") version toolsVersion - id("ru.mipt.npm.publish") version toolsVersion - kotlin("plugin.allopen") - } - repositories { mavenLocal() jcenter() @@ -20,6 +9,17 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/kotlin/kotlin-dev/") } + + val toolsVersion = "0.6.1" + + plugins { + id("kotlinx.benchmark") version "0.2.0-dev-20" + id("ru.mipt.npm.project") version toolsVersion + id("ru.mipt.npm.mpp") version toolsVersion + id("ru.mipt.npm.jvm") version toolsVersion + id("ru.mipt.npm.publish") version toolsVersion + kotlin("plugin.allopen") + } } rootProject.name = "kmath" @@ -33,7 +33,6 @@ include( ":kmath-commons", ":kmath-viktor", ":kmath-prob", -// ":kmath-io", ":kmath-dimensions", ":kmath-for-real", ":kmath-geometry", From 8014b3df0bec4acc3e9d0dabbe6422b325329968 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 25 Sep 2020 20:49:08 +0700 Subject: [PATCH 071/199] Simplify asm.kt --- .../jvmMain/kotlin/kscience/kmath/asm/asm.kt | 56 +++++++++---------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt index edfe7f01d..53425e7e3 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt @@ -19,39 +19,37 @@ import kotlin.reflect.KClass * @author Alexander Nozik */ public fun MST.compileWith(type: KClass, algebra: Algebra): Expression { - fun AsmBuilder.visit(node: MST) { - when (node) { - is MST.Symbolic -> { - val symbol = try { - algebra.symbol(node.value) - } catch (ignored: Throwable) { - null - } - - if (symbol != null) - loadTConstant(symbol) - else - loadVariable(node.value) + fun AsmBuilder.visit(node: MST): Unit = when (node) { + is MST.Symbolic -> { + val symbol = try { + algebra.symbol(node.value) + } catch (ignored: Throwable) { + null } - is MST.Numeric -> loadNumeric(node.value) + if (symbol != null) + loadTConstant(symbol) + else + loadVariable(node.value) + } - is MST.Unary -> buildAlgebraOperationCall( - context = algebra, - name = node.operation, - fallbackMethodName = "unaryOperation", - parameterTypes = arrayOf(MstType.fromMst(node.value)) - ) { visit(node.value) } + is MST.Numeric -> loadNumeric(node.value) - is MST.Binary -> buildAlgebraOperationCall( - context = algebra, - name = node.operation, - fallbackMethodName = "binaryOperation", - parameterTypes = arrayOf(MstType.fromMst(node.left), MstType.fromMst(node.right)) - ) { - visit(node.left) - visit(node.right) - } + is MST.Unary -> buildAlgebraOperationCall( + context = algebra, + name = node.operation, + fallbackMethodName = "unaryOperation", + parameterTypes = arrayOf(MstType.fromMst(node.value)) + ) { visit(node.value) } + + is MST.Binary -> buildAlgebraOperationCall( + context = algebra, + name = node.operation, + fallbackMethodName = "binaryOperation", + parameterTypes = arrayOf(MstType.fromMst(node.left), MstType.fromMst(node.right)) + ) { + visit(node.left) + visit(node.right) } } From 4043df7f24d9671aac9d606fa41688d966f2cc56 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 26 Sep 2020 12:15:11 +0300 Subject: [PATCH 072/199] Documentation auto-generation update --- README.md | 102 ++++++++++++++---- build.gradle.kts | 5 +- docs/templates/ARTIFACT-TEMPLATE.md | 2 +- .../commons/expressions/DiffExpression.kt | 2 +- kmath-core/build.gradle.kts | 1 + kmath-core/docs/README-TEMPLATE.md | 33 +----- 6 files changed, 87 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 4d89337b5..8bc85bf2b 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmat # KMath Could be pronounced as `key-math`. -The Kotlin MATHematics library is intended as a Kotlin-based analog to Python's `numpy` library. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. +The Kotlin MATHematics library was initially intended as a Kotlin-based analog to Python's `numpy` library. Later we found that kotlin is much more flexible language and allows superior architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could be achieved with [kmath-for-real](/kmath-for-real) extension module. -## Publications +## Publications and talks * [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2) * [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814) * [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103) @@ -29,7 +29,7 @@ The Kotlin MATHematics library is intended as a Kotlin-based analog to Python's ## Features -Actual feature list is [here](docs/features.md) +Actual feature list is [here](/docs/features.md) * **Algebra** * Algebraic structures like rings, spaces and field (**TODO** add example to wiki) @@ -68,43 +68,99 @@ can be used for a wide variety of purposes from high performance calculations to ## Modules -### [examples](examples) +


-### [kmath-ast](kmath-ast) +* ### [examples](examples) +> +> +> **Maturity**: EXPERIMENTAL +
-### [kmath-commons](kmath-commons) +* ### [kmath-ast](kmath-ast) +> +> +> **Maturity**: EXPERIMENTAL +
-### [kmath-core](kmath-core) - - [algebras](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures: contexts and elements - - [nd](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures - - [buffers](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure - - [expressions](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions) : Functional Expressions - - [domains](kmath-core/src/commonMain/kotlin/kscience/kmath/domains) : Domains - - [autodif](kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt) : Automatic differentiation +* ### [kmath-commons](kmath-commons) +> +> +> **Maturity**: EXPERIMENTAL +
-### [kmath-coroutines](kmath-coroutines) +* ### [kmath-core](kmath-core) +> Core classes, algebra definitions, basic linear algebra +> +> **Maturity**: DEVELOPMENT +> +> **Features:** +> - [algebras](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures: contexts and elements +> - [nd](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures +> - [buffers](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure +> - [expressions](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions) : Functional Expressions +> - [domains](kmath-core/src/commonMain/kotlin/kscience/kmath/domains) : Domains +> - [autodif](kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt) : Automatic differentiation -### [kmath-dimensions](kmath-dimensions) +
-### [kmath-for-real](kmath-for-real) +* ### [kmath-coroutines](kmath-coroutines) +> +> +> **Maturity**: EXPERIMENTAL +
-### [kmath-functions](kmath-functions) +* ### [kmath-dimensions](kmath-dimensions) +> +> +> **Maturity**: EXPERIMENTAL +
-### [kmath-geometry](kmath-geometry) +* ### [kmath-for-real](kmath-for-real) +> +> +> **Maturity**: EXPERIMENTAL +
-### [kmath-histograms](kmath-histograms) +* ### [kmath-functions](kmath-functions) +> +> +> **Maturity**: EXPERIMENTAL +
-### [kmath-memory](kmath-memory) +* ### [kmath-geometry](kmath-geometry) +> +> +> **Maturity**: EXPERIMENTAL +
-### [kmath-prob](kmath-prob) +* ### [kmath-histograms](kmath-histograms) +> +> +> **Maturity**: EXPERIMENTAL +
-### [kmath-viktor](kmath-viktor) +* ### [kmath-memory](kmath-memory) +> +> +> **Maturity**: EXPERIMENTAL +
+* ### [kmath-prob](kmath-prob) +> +> +> **Maturity**: EXPERIMENTAL +
+ +* ### [kmath-viktor](kmath-viktor) +> +> +> **Maturity**: EXPERIMENTAL +
## Multi-platform support -KMath is developed as a multi-platform library, which means that most of interfaces are declared in the [common module](kmath-core/src/commonMain). Implementation is also done in the common module wherever possible. In some cases, features are delegated to platform-specific implementations even if they could be done in the common module for performance reasons. Currently, the JVM is the main focus of development, however Kotlin/Native and Kotlin/JS contributions are also welcome. +KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the [common module](/kmath-core/src/commonMain). Implementation is also done in the common module wherever possible. In some cases, features are delegated to platform-specific implementations even if they could be done in the common module for performance reasons. Currently, the JVM is the main focus of development, however Kotlin/Native and Kotlin/JS contributions are also welcome. ## Performance diff --git a/build.gradle.kts b/build.gradle.kts index 81e0cb973..87862ae8e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,4 @@ plugins { - //id("ru.mipt.npm.publish") apply false id("ru.mipt.npm.project") } @@ -23,5 +22,5 @@ subprojects { } readme{ - readmeTemplate = file("docs/template/README-TEMPLATE.md") -} \ No newline at end of file + readmeTemplate = file("docs/templates/README-TEMPLATE.md") +} diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md index 1b354e022..8630b4b97 100644 --- a/docs/templates/ARTIFACT-TEMPLATE.md +++ b/docs/templates/ARTIFACT-TEMPLATE.md @@ -7,7 +7,7 @@ > repositories { > maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } -> maven { url https://dl.bintray.com/hotkeytlt/maven' } +> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > } > > dependencies { diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt index 3ac908536..8a09cc793 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt @@ -94,7 +94,7 @@ public class DiffExpression(public val function: DerivativeStructureField.() -> * TODO make result [DiffExpression] */ public fun derivative(orders: Map): Expression = Expression { arguments -> - (DerivativeStructureField(orders.values.max() ?: 0, arguments)) { function().deriv(orders) } + (DerivativeStructureField(orders.values.maxOrNull() ?: 0, arguments)) { function().deriv(orders) } } //TODO add gradient and maybe other vector operators diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 31a16e20b..d64a4d8a5 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -11,6 +11,7 @@ kotlin.sourceSets.commonMain { readme { description = "Core classes, algebra definitions, basic linear algebra" maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( id = "algebras", description = "Algebraic structures: contexts and elements", diff --git a/kmath-core/docs/README-TEMPLATE.md b/kmath-core/docs/README-TEMPLATE.md index 183f300ac..83d1ebdce 100644 --- a/kmath-core/docs/README-TEMPLATE.md +++ b/kmath-core/docs/README-TEMPLATE.md @@ -1,34 +1,7 @@ # The Core Module (`kmath-core`) The core features of KMath: -$features -> #### Artifact: -> This module artifact: `${group}:${name}:${version}`. -> -> **Gradle:** -> -> ```gradle -> repositories { -> maven { url 'https://dl.bintray.com/mipt-npm/kscience' } -> maven { url 'https://dl.bintray.com/mipt-npm/dev' } -> maven { url https://dl.bintray.com/hotkeytlt/maven' } -> } -> -> dependencies { -> implementation '${group}:${name}:${version}' -> } -> ``` -> **Gradle Kotlin DSL:** -> -> ```kotlin -> repositories { -> maven("https://dl.bintray.com/mipt-npm/kscience") -> maven("https://dl.bintray.com/mipt-npm/dev") -> maven("https://dl.bintray.com/hotkeytlt/maven") -> } -> -> dependencies { -> implementation("${group}:${name}:${version}") -> } -> ``` +${features} + +${artifact} From b734136b82d09532c61adba08e4c9a058bd19547 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 26 Sep 2020 12:21:08 +0300 Subject: [PATCH 073/199] Add images --- docs/images/KM.svg | 59 ++++++ docs/images/KM_mono.svg | 55 ++++++ docs/images/KMath.svg | 91 +++++++++ docs/images/KMath_mono.svg | 371 +++++++++++++++++++++++++++++++++++++ kmath-core/README.md | 5 +- 5 files changed, 579 insertions(+), 2 deletions(-) create mode 100644 docs/images/KM.svg create mode 100644 docs/images/KM_mono.svg create mode 100644 docs/images/KMath.svg create mode 100644 docs/images/KMath_mono.svg diff --git a/docs/images/KM.svg b/docs/images/KM.svg new file mode 100644 index 000000000..50126cbc5 --- /dev/null +++ b/docs/images/KM.svg @@ -0,0 +1,59 @@ + +image/svg+xml \ No newline at end of file diff --git a/docs/images/KM_mono.svg b/docs/images/KM_mono.svg new file mode 100644 index 000000000..3b6890b6b --- /dev/null +++ b/docs/images/KM_mono.svg @@ -0,0 +1,55 @@ + +image/svg+xml \ No newline at end of file diff --git a/docs/images/KMath.svg b/docs/images/KMath.svg new file mode 100644 index 000000000..d88cfe7b0 --- /dev/null +++ b/docs/images/KMath.svg @@ -0,0 +1,91 @@ + +image/svg+xml \ No newline at end of file diff --git a/docs/images/KMath_mono.svg b/docs/images/KMath_mono.svg new file mode 100644 index 000000000..3a62ac383 --- /dev/null +++ b/docs/images/KMath_mono.svg @@ -0,0 +1,371 @@ + +image/svg+xml \ No newline at end of file diff --git a/kmath-core/README.md b/kmath-core/README.md index 1fcd9edc9..3482502b9 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -1,6 +1,7 @@ # The Core Module (`kmath-core`) The core features of KMath: + - [algebras](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures: contexts and elements - [nd](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures - [buffers](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure @@ -11,14 +12,14 @@ The core features of KMath: > #### Artifact: > This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-1`. -> +> > **Gradle:** > > ```gradle > repositories { > maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } -> maven { url https://dl.bintray.com/hotkeytlt/maven' } +> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > } > > dependencies { From 6b1eb4cfd7bd0e8520a9e49b11eedaa7daf75fde Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 26 Sep 2020 13:57:24 +0300 Subject: [PATCH 074/199] Fix artifact template --- docs/templates/ARTIFACT-TEMPLATE.md | 5 +++++ kmath-core/README.md | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md index 8630b4b97..cbdd98218 100644 --- a/docs/templates/ARTIFACT-TEMPLATE.md +++ b/docs/templates/ARTIFACT-TEMPLATE.md @@ -1,6 +1,11 @@ > #### Artifact: +> > This module artifact: `${group}:${name}:${version}`. > +> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/${name}/images/download.svg) ](https://bintray.com/mipt-npm/kscience/${name}/_latestVersion) +> +> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/${name}/images/download.svg) ](https://bintray.com/mipt-npm/dev/${name}/_latestVersion) +> > **Gradle:** > > ```gradle diff --git a/kmath-core/README.md b/kmath-core/README.md index 3482502b9..2cf7ed5dc 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -11,8 +11,13 @@ The core features of KMath: > #### Artifact: +> > This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-1`. > +> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) +> +> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion) +> > **Gradle:** > > ```gradle From 940fabfac2d9756f9ece8bf8b06673a7f2c6c9d1 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 27 Sep 2020 14:50:07 +0700 Subject: [PATCH 075/199] Add more KDoc comments, fix grammar issue --- doc/linear.md | 4 +- examples/build.gradle.kts | 4 +- .../kmath/structures/ArrayBenchmark.kt | 2 +- .../kmath/structures/BufferBenchmark.kt | 3 +- .../kmath/structures/NDFieldBenchmark.kt | 2 +- .../kmath/structures/ViktorBenchmark.kt | 4 +- .../commons/prob/DistributionBenchmark.kt | 18 +- .../kmath/commons/prob/DistributionDemo.kt | 4 +- .../kscience/kmath/operations/BigIntDemo.kt | 4 +- .../structures/StructureReadBenchmark.kt | 2 - .../structures/StructureWriteBenchmark.kt | 13 +- .../kmath/structures/typeSafeDimensions.kt | 7 +- .../commons/expressions/DiffExpression.kt | 9 +- .../kscience/kmath/operations/Complex.kt | 19 +- .../kmath/structures/BoxingNDField.kt | 7 +- .../kscience/kmath/structures/BoxingNDRing.kt | 5 +- .../kmath/structures/BufferedNDAlgebra.kt | 6 +- .../kscience/kmath/structures/Buffers.kt | 72 +++++--- .../kscience/kmath/structures/MemoryBuffer.kt | 2 +- .../kscience/kmath/structures/NDAlgebra.kt | 167 +++++++++++++++--- .../kscience/kmath/structures/NDStructure.kt | 12 +- .../kscience/kmath/dimensions/Dimensions.kt | 20 ++- .../dimensions/DMatrixContextTest.kt | 0 .../kscience/kmath/histogram/Histogram.kt | 3 +- .../kscience/kmath/prob/RandomGenerator.kt | 56 +++++- 25 files changed, 323 insertions(+), 122 deletions(-) rename kmath-dimensions/src/commonTest/kotlin/{scientifik => kscience}/dimensions/DMatrixContextTest.kt (100%) diff --git a/doc/linear.md b/doc/linear.md index 883df275e..6ccc6caac 100644 --- a/doc/linear.md +++ b/doc/linear.md @@ -6,10 +6,10 @@ back-ends. The new operations added as extensions to contexts instead of being m Two major contexts used for linear algebra and hyper-geometry: -* `VectorSpace` forms a mathematical space on top of array-like structure (`Buffer` and its typealias `Point` used for geometry). +* `VectorSpace` forms a mathematical space on top of array-like structure (`Buffer` and its type alias `Point` used for geometry). * `MatrixContext` forms a space-like context for 2d-structures. It does not store matrix size and therefore does not implement -`Space` interface (it is not possible to create zero element without knowing the matrix size). +`Space` interface (it is impossible to create zero element without knowing the matrix size). ## Vector spaces diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 3d193efce..4e752fc35 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -28,7 +28,9 @@ dependencies { implementation(project(":kmath-dimensions")) implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6") implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20") - "benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath + implementation("org.slf4j:slf4j-simple:1.7.30") + "benchmarksImplementation"("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-8") + "benchmarksImplementation"(sourceSets.main.get().output + sourceSets.main.get().runtimeClasspath) } // Configure benchmark diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt index 7772facb0..a91d02253 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt @@ -6,7 +6,7 @@ import org.openjdk.jmh.annotations.State import java.nio.IntBuffer @State(Scope.Benchmark) -class ArrayBenchmark { +internal class ArrayBenchmark { @Benchmark fun benchmarkArrayRead() { var res = 0 diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt index 40ba49a34..8b6fd4a51 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt @@ -7,8 +7,7 @@ import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State @State(Scope.Benchmark) -class BufferBenchmark { - +internal class BufferBenchmark { @Benchmark fun genericRealBufferReadWrite() { val buffer = RealBuffer(size) { it.toDouble() } diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt index 8f37feda4..8ec47ae81 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt @@ -7,7 +7,7 @@ import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State @State(Scope.Benchmark) -class NDFieldBenchmark { +internal class NDFieldBenchmark { @Benchmark fun autoFieldAdd() { bufferedField { diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt index 7f55c0560..464925ca0 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt @@ -9,7 +9,7 @@ import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State @State(Scope.Benchmark) -class ViktorBenchmark { +internal class ViktorBenchmark { final val dim: Int = 1000 final val n: Int = 100 @@ -42,7 +42,7 @@ class ViktorBenchmark { } @Benchmark - fun realdFieldLog() { + fun realFieldLog() { realField { val fortyTwo = produce { 42.0 } var res = one diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt index a2d7a0291..9c0a01961 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt @@ -14,11 +14,10 @@ private fun runChain(): Duration { val generator = RandomGenerator.fromSource(RandomSource.MT, 123L) val normal = Distribution.normal(NormalSamplerMethod.Ziggurat) val chain = normal.sample(generator) as BlockingRealChain - val startTime = Instant.now() var sum = 0.0 - repeat(10000001) { counter -> + repeat(10000001) { counter -> sum += chain.nextDouble() if (counter % 100000 == 0) { @@ -27,6 +26,7 @@ private fun runChain(): Duration { println("Chain sampler completed $counter elements in $duration: $meanValue") } } + return Duration.between(startTime, Instant.now()) } @@ -34,10 +34,9 @@ private fun runDirect(): Duration { val provider = RandomSource.create(RandomSource.MT, 123L) val sampler = ZigguratNormalizedGaussianSampler(provider) val startTime = Instant.now() - var sum = 0.0 - repeat(10000001) { counter -> + repeat(10000001) { counter -> sum += sampler.sample() if (counter % 100000 == 0) { @@ -46,6 +45,7 @@ private fun runDirect(): Duration { println("Direct sampler completed $counter elements in $duration: $meanValue") } } + return Duration.between(startTime, Instant.now()) } @@ -54,14 +54,8 @@ private fun runDirect(): Duration { */ fun main() { runBlocking(Dispatchers.Default) { - val chainJob = async { - runChain() - } - - val directJob = async { - runDirect() - } - + val chainJob = async { runChain() } + val directJob = async { runDirect() } println("Chain: ${chainJob.await()}") println("Direct: ${directJob.await()}") } diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt index dbb51267b..7d53e5178 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt @@ -7,9 +7,9 @@ import kscience.kmath.prob.Distribution import kscience.kmath.prob.RandomGenerator import kscience.kmath.prob.normal -data class AveragingChainState(var num: Int = 0, var value: Double = 0.0) +private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0) -fun Chain.mean(): Chain = collectWithState(AveragingChainState(), { it.copy() }) { chain -> +private fun Chain.mean(): Chain = collectWithState(AveragingChainState(), { it.copy() }) { chain -> val next = chain.next() num++ value += next diff --git a/examples/src/main/kotlin/kscience/kmath/operations/BigIntDemo.kt b/examples/src/main/kotlin/kscience/kmath/operations/BigIntDemo.kt index 692ea6d8c..0e9811ff8 100644 --- a/examples/src/main/kotlin/kscience/kmath/operations/BigIntDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/operations/BigIntDemo.kt @@ -1,8 +1,6 @@ package kscience.kmath.operations fun main() { - val res = BigIntField { - number(1) * 2 - } + val res = BigIntField { number(1) * 2 } println("bigint:$res") } \ No newline at end of file diff --git a/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt index 00606ec08..51fd4f956 100644 --- a/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt @@ -4,11 +4,9 @@ import kotlin.system.measureTimeMillis fun main() { val n = 6000 - val array = DoubleArray(n * n) { 1.0 } val buffer = RealBuffer(array) val strides = DefaultStrides(intArrayOf(n, n)) - val structure = BufferNDStructure(strides, buffer) measureTimeMillis { diff --git a/examples/src/main/kotlin/kscience/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/structures/StructureWriteBenchmark.kt index b2975393f..db55b454f 100644 --- a/examples/src/main/kotlin/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -4,24 +4,17 @@ import kotlin.system.measureTimeMillis fun main() { val n = 6000 - val structure = NDStructure.build(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 } - structure.mapToBuffer { it + 1 } // warm-up - - val time1 = measureTimeMillis { - val res = structure.mapToBuffer { it + 1 } - } + val time1 = measureTimeMillis { val res = structure.mapToBuffer { it + 1 } } println("Structure mapping finished in $time1 millis") - val array = DoubleArray(n * n) { 1.0 } val time2 = measureTimeMillis { val target = DoubleArray(n * n) - val res = array.forEachIndexed { index, value -> - target[index] = value + 1 - } + val res = array.forEachIndexed { index, value -> target[index] = value + 1 } } + println("Array mapping finished in $time2 millis") val buffer = RealBuffer(DoubleArray(n * n) { 1.0 }) diff --git a/examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt index bf83a9f05..987eea16f 100644 --- a/examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt @@ -6,7 +6,7 @@ import kscience.kmath.dimensions.DMatrixContext import kscience.kmath.dimensions.Dimension import kscience.kmath.operations.RealField -fun DMatrixContext.simple() { +private fun DMatrixContext.simple() { val m1 = produce { i, j -> (i + j).toDouble() } val m2 = produce { i, j -> (i + j).toDouble() } @@ -14,12 +14,11 @@ fun DMatrixContext.simple() { m1.transpose() + m2 } - -object D5 : Dimension { +private object D5 : Dimension { override val dim: UInt = 5u } -fun DMatrixContext.custom() { +private fun DMatrixContext.custom() { val m1 = produce { i, j -> (i + j).toDouble() } val m2 = produce { i, j -> (i - j).toDouble() } val m3 = produce { i, j -> (i - j).toDouble() } diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt index 8a09cc793..c39f0d04c 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt @@ -9,14 +9,17 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import kotlin.properties.ReadOnlyProperty /** - * A field wrapping commons-math derivative structures + * A field over commons-math [DerivativeStructure]. + * + * @property order The derivation order. + * @property parameters The map of free parameters. */ public class DerivativeStructureField( public val order: Int, public val parameters: Map ) : ExtendedField { - public override val zero: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size) } - public override val one: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size, 1.0) } + public override val zero: DerivativeStructure by lazy { DerivativeStructure(parameters.size, order) } + public override val one: DerivativeStructure by lazy { DerivativeStructure(parameters.size, order, 1.0) } private val variables: Map = parameters.mapValues { (key, value) -> DerivativeStructure(parameters.size, order, parameters.keys.indexOf(key), value) 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 9aec6e178..d410d304a 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.structures.Buffer import kscience.kmath.structures.MemoryBuffer import kscience.kmath.structures.MutableBuffer +import kscience.kmath.structures.MutableMemoryBuffer import kscience.memory.MemoryReader import kscience.memory.MemorySpec import kscience.memory.MemoryWriter @@ -177,10 +178,10 @@ public data class Complex(val re: Double, val im: Double) : FieldElement { - override val objectSize: Int = 16 + override val objectSize: Int + get() = 16 - override fun MemoryReader.read(offset: Int): Complex = - Complex(readDouble(offset), readDouble(offset + 8)) + override fun MemoryReader.read(offset: Int): Complex = Complex(readDouble(offset), readDouble(offset + 8)) override fun MemoryWriter.write(offset: Int, value: Complex) { writeDouble(offset, value.re) @@ -197,8 +198,16 @@ public data class Complex(val re: Double, val im: Double) : FieldElement Complex): Buffer = MemoryBuffer.create(Complex, size, init) -public inline fun MutableBuffer.Companion.complex(size: Int, init: (Int) -> Complex): Buffer = - MemoryBuffer.create(Complex, size, init) +/** + * Creates a new buffer of complex numbers with the specified [size], where each element is calculated by calling the + * specified [init] function. + */ +public inline fun MutableBuffer.Companion.complex(size: Int, init: (Int) -> Complex): MutableBuffer = + MutableMemoryBuffer.create(Complex, size, init) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt index c3c859f7a..dc65b12c4 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDField.kt @@ -15,8 +15,9 @@ public class BoxingNDField>( public fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) - public override fun check(vararg elements: NDBuffer) { - check(elements.all { it.strides == strides }) { "Element strides are not the same as context strides" } + public override fun check(vararg elements: NDBuffer): Array> { + require(elements.all { it.strides == strides }) { "Element strides are not the same as context strides" } + return elements } public override fun produce(initializer: F.(IntArray) -> T): BufferedNDFieldElement = @@ -75,6 +76,6 @@ public inline fun , R> F.nd( vararg shape: Int, action: NDField.() -> R ): R { - val ndfield: BoxingNDField = NDField.boxing(this, *shape, bufferFactory = bufferFactory) + val ndfield = NDField.boxing(this, *shape, bufferFactory = bufferFactory) return ndfield.action() } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDRing.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDRing.kt index 461b0387c..b6794984c 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BoxingNDRing.kt @@ -14,8 +14,9 @@ public class BoxingNDRing>( public fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) - override fun check(vararg elements: NDBuffer) { - require(elements.all { it.strides == strides }) { "Element strides are not the same as context strides" } + override fun check(vararg elements: NDBuffer): Array> { + if (!elements.all { it.strides == this.strides }) error("Element strides are not the same as context strides") + return elements } override fun produce(initializer: R.(IntArray) -> T): BufferedNDRingElement = diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt index 66b4f19e1..3dcd0322c 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferedNDAlgebra.kt @@ -5,8 +5,10 @@ import kscience.kmath.operations.* public interface BufferedNDAlgebra : NDAlgebra> { public val strides: Strides - public override fun check(vararg elements: NDBuffer): Unit = - require(elements.all { it.strides == strides }) { ("Strides mismatch") } + public override fun check(vararg elements: NDBuffer): Array> { + require(elements.all { it.strides == strides }) { "Strides mismatch" } + return elements + } /** * Convert any [NDStructure] to buffered structure using strides from this context. diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt index 53587e503..5174eb314 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt @@ -46,35 +46,48 @@ public interface Buffer { asSequence().mapIndexed { index, value -> value == other[index] }.all { it } public companion object { - public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer { - val array = DoubleArray(size) { initializer(it) } - return RealBuffer(array) - } + /** + * Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer = + RealBuffer(size) { initializer(it) } /** - * Create a boxing buffer of given type + * Creates a [ListBuffer] of given type [T] with given [size]. Each element is calculated by calling the + * specified [initializer] function. */ public inline fun boxing(size: Int, initializer: (Int) -> T): Buffer = ListBuffer(List(size, initializer)) + // TODO add resolution based on Annotation or companion resolution + + /** + * Creates a [Buffer] of given [type]. If the type is primitive, specialized buffers are used ([IntBuffer], + * [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * + * The [size] is specified, and each element is calculated by calling the specified [initializer] function. + */ @Suppress("UNCHECKED_CAST") - public inline fun auto(type: KClass, size: Int, crossinline initializer: (Int) -> T): Buffer { - //TODO add resolution based on Annotation or companion resolution - return when (type) { - Double::class -> RealBuffer(DoubleArray(size) { initializer(it) as Double }) as Buffer - Short::class -> ShortBuffer(ShortArray(size) { initializer(it) as Short }) as Buffer - Int::class -> IntBuffer(IntArray(size) { initializer(it) as Int }) as Buffer - Long::class -> LongBuffer(LongArray(size) { initializer(it) as Long }) as Buffer + public inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): Buffer = + when (type) { + Double::class -> RealBuffer(size) { initializer(it) as Double } as Buffer + Short::class -> ShortBuffer(size) { initializer(it) as Short } as Buffer + Int::class -> IntBuffer(size) { initializer(it) as Int } as Buffer + Long::class -> LongBuffer(size) { initializer(it) as Long } as Buffer + Float::class -> FloatBuffer(size) { initializer(it) as Float } as Buffer Complex::class -> complex(size) { initializer(it) as Complex } as Buffer else -> boxing(size, initializer) } - } /** - * Create most appropriate immutable buffer for given type avoiding boxing wherever possible + * Creates a [Buffer] of given type [T]. If the type is primitive, specialized buffers are used ([IntBuffer], + * [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * + * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ @Suppress("UNCHECKED_CAST") - public inline fun auto(size: Int, crossinline initializer: (Int) -> T): Buffer = + public inline fun auto(size: Int, initializer: (Int) -> T): Buffer = auto(T::class, size, initializer) } } @@ -117,25 +130,40 @@ public interface MutableBuffer : Buffer { public inline fun boxing(size: Int, initializer: (Int) -> T): MutableBuffer = MutableListBuffer(MutableList(size, initializer)) + /** + * Creates a [MutableBuffer] of given [type]. If the type is primitive, specialized buffers are used + * ([IntBuffer], [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * + * The [size] is specified, and each element is calculated by calling the specified [initializer] function. + */ @Suppress("UNCHECKED_CAST") public inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): MutableBuffer = when (type) { - Double::class -> RealBuffer(DoubleArray(size) { initializer(it) as Double }) as MutableBuffer - Short::class -> ShortBuffer(ShortArray(size) { initializer(it) as Short }) as MutableBuffer - Int::class -> IntBuffer(IntArray(size) { initializer(it) as Int }) as MutableBuffer - Long::class -> LongBuffer(LongArray(size) { initializer(it) as Long }) as MutableBuffer + Double::class -> RealBuffer(size) { initializer(it) as Double } as MutableBuffer + Short::class -> ShortBuffer(size) { initializer(it) as Short } as MutableBuffer + Int::class -> IntBuffer(size) { initializer(it) as Int } as MutableBuffer + Float::class -> FloatBuffer(size) { initializer(it) as Float } as MutableBuffer + Long::class -> LongBuffer(size) { initializer(it) as Long } as MutableBuffer + Complex::class -> complex(size) { initializer(it) as Complex } as MutableBuffer else -> boxing(size, initializer) } /** - * Create most appropriate mutable buffer for given type avoiding boxing wherever possible + * Creates a [MutableBuffer] of given type [T]. If the type is primitive, specialized buffers are used + * ([IntBuffer], [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * + * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ @Suppress("UNCHECKED_CAST") public inline fun auto(size: Int, initializer: (Int) -> T): MutableBuffer = auto(T::class, size, initializer) - public val real: MutableBufferFactory = - { size, initializer -> RealBuffer(DoubleArray(size) { initializer(it) }) } + /** + * Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer = + RealBuffer(size) { initializer(it) } } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt index b7e6a8218..308256992 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt @@ -53,7 +53,7 @@ public class MutableMemoryBuffer(memory: Memory, spec: MemorySpec) : public inline fun create( spec: MemorySpec, size: Int, - crossinline initializer: (Int) -> T + initializer: (Int) -> T ): MutableMemoryBuffer = MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer -> (0 until size).forEach { buffer[it] = initializer(it) } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt index 28eaef2f1..4315f0423 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt @@ -6,49 +6,77 @@ import kscience.kmath.operations.Ring import kscience.kmath.operations.Space /** - * An exception is thrown when the expected ans actual shape of NDArray differs + * An exception is thrown when the expected ans actual shape of NDArray differs. + * + * @property expected the expected shape. + * @property actual the actual shape. */ -public class ShapeMismatchException(public val expected: IntArray, public val actual: IntArray) : RuntimeException() +public class ShapeMismatchException(public val expected: IntArray, public val actual: IntArray) : + RuntimeException("Shape ${actual.contentToString()} doesn't fit in expected shape ${expected.contentToString()}.") /** - * The base interface for all nd-algebra implementations - * @param T the type of nd-structure element - * @param C the type of the element context - * @param N the type of the structure + * The base interface for all ND-algebra implementations. + * + * @param T the type of ND-structure element. + * @param C the type of the element context. + * @param N the type of the structure. */ public interface NDAlgebra> { + /** + * The shape of ND-structures this algebra operates on. + */ public val shape: IntArray + + /** + * The algebra over elements of ND structure. + */ public val elementContext: C /** - * Produce a new [N] structure using given initializer function + * Produces a new [N] structure using given initializer function. */ public fun produce(initializer: C.(IntArray) -> T): N /** - * Map elements from one structure to another one + * Maps elements from one structure to another one by applying [transform] to them. */ public fun map(arg: N, transform: C.(T) -> T): N /** - * Map indexed elements + * Maps elements from one structure to another one by applying [transform] to them alongside with their indices. */ public fun mapIndexed(arg: N, transform: C.(index: IntArray, T) -> T): N /** - * Combine two structures into one + * Combines two structures into one. */ public fun combine(a: N, b: N, transform: C.(T, T) -> T): N /** - * Check if given elements are consistent with this context + * Checks if given element is consistent with this context. + * + * @param element the structure to check. + * @return the valid structure. */ - public fun check(vararg elements: N): Unit = elements.forEach { - if (!shape.contentEquals(it.shape)) throw ShapeMismatchException(shape, it.shape) + public fun check(element: N): N { + if (!element.shape.contentEquals(shape)) throw ShapeMismatchException(shape, element.shape) + return element } /** - * element-by-element invoke a function working on [T] on a [NDStructure] + * Checks if given elements are consistent with this context. + * + * @param elements the structures to check. + * @return the array of valid structures. + */ + public fun check(vararg elements: N): Array = elements + .map(NDStructure::shape) + .singleOrNull { !shape.contentEquals(it) } + ?.let { throw ShapeMismatchException(shape, it) } + ?: elements + + /** + * Element-wise invocation of function working on [T] on a [NDStructure]. */ public operator fun Function1.invoke(structure: N): N = map(structure) { value -> this@invoke(value) } @@ -56,42 +84,107 @@ public interface NDAlgebra> { } /** - * An nd-space over element space + * Space of [NDStructure]. + * + * @param T the type of the element contained in ND structure. + * @param N the type of ND structure. + * @param S the type of space of structure elements. */ public interface NDSpace, N : NDStructure> : Space, NDAlgebra { /** - * Element-by-element addition + * Element-wise addition. + * + * @param a the addend. + * @param b the augend. + * @return the sum. */ - override fun add(a: N, b: N): N = combine(a, b) { aValue, bValue -> add(aValue, bValue) } + public override fun add(a: N, b: N): N = combine(a, b) { aValue, bValue -> add(aValue, bValue) } /** - * Multiply all elements by constant + * Element-wise multiplication by scalar. + * + * @param a the multiplicand. + * @param k the multiplier. + * @return the product. */ - override fun multiply(a: N, k: Number): N = map(a) { multiply(it, k) } + public override fun multiply(a: N, k: Number): N = map(a) { multiply(it, k) } - //TODO move to extensions after KEEP-176 + // TODO move to extensions after KEEP-176 + + /** + * Adds an ND structure to an element of it. + * + * @receiver the addend. + * @param arg the augend. + * @return the sum. + */ public operator fun N.plus(arg: T): N = map(this) { value -> add(arg, value) } + /** + * Subtracts an element from ND structure of it. + * + * @receiver the dividend. + * @param arg the divisor. + * @return the quotient. + */ public operator fun N.minus(arg: T): N = map(this) { value -> add(arg, -value) } + /** + * Adds an element to ND structure of it. + * + * @receiver the addend. + * @param arg the augend. + * @return the sum. + */ public operator fun T.plus(arg: N): N = map(arg) { value -> add(this@plus, value) } + + /** + * Subtracts an ND structure from an element of it. + * + * @receiver the dividend. + * @param arg the divisor. + * @return the quotient. + */ public operator fun T.minus(arg: N): N = map(arg) { value -> add(-this@minus, value) } public companion object } /** - * An nd-ring over element ring + * Ring of [NDStructure]. + * + * @param T the type of the element contained in ND structure. + * @param N the type of ND structure. + * @param R the type of ring of structure elements. */ public interface NDRing, N : NDStructure> : Ring, NDSpace { /** - * Element-by-element multiplication + * Element-wise multiplication. + * + * @param a the multiplicand. + * @param b the multiplier. + * @return the product. */ - override fun multiply(a: N, b: N): N = combine(a, b) { aValue, bValue -> multiply(aValue, bValue) } + public override fun multiply(a: N, b: N): N = combine(a, b) { aValue, bValue -> multiply(aValue, bValue) } //TODO move to extensions after KEEP-176 + + /** + * Multiplies an ND structure by an element of it. + * + * @receiver the multiplicand. + * @param arg the multiplier. + * @return the product. + */ public operator fun N.times(arg: T): N = map(this) { value -> multiply(arg, value) } + /** + * Multiplies an element by a ND structure of it. + * + * @receiver the multiplicand. + * @param arg the multiplier. + * @return the product. + */ public operator fun T.times(arg: N): N = map(arg) { value -> multiply(this@times, value) } public companion object @@ -102,29 +195,47 @@ public interface NDRing, N : NDStructure> : Ring, NDSpace, N : NDStructure> : Field, NDRing { /** - * Element-by-element division + * Element-wise division. + * + * @param a the dividend. + * @param b the divisor. + * @return the quotient. */ - override fun divide(a: N, b: N): N = combine(a, b) { aValue, bValue -> divide(aValue, bValue) } + public override fun divide(a: N, b: N): N = combine(a, b) { aValue, bValue -> divide(aValue, bValue) } //TODO move to extensions after KEEP-176 + /** + * Divides an ND structure by an element of it. + * + * @receiver the dividend. + * @param arg the divisor. + * @return the quotient. + */ public operator fun N.div(arg: T): N = map(this) { value -> divide(arg, value) } + /** + * Divides an element by an ND structure of it. + * + * @receiver the dividend. + * @param arg the divisor. + * @return the quotient. + */ public operator fun T.div(arg: N): N = map(arg) { divide(it, this@div) } public companion object { private val realNDFieldCache: MutableMap = hashMapOf() /** - * Create a nd-field for [Double] values or pull it from cache if it was created previously + * Create a nd-field for [Double] values or pull it from cache if it was created previously. */ public fun real(vararg shape: Int): RealNDField = realNDFieldCache.getOrPut(shape) { RealNDField(shape) } /** - * Create a nd-field with boxing generic buffer + * Create an ND field with boxing generic buffer. */ public fun > boxing( field: F, diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt index 4ab49c9bc..b8c8c855b 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt @@ -37,9 +37,8 @@ public interface NDStructure { */ public fun elements(): Sequence> - override fun equals(other: Any?): Boolean - - override fun hashCode(): Int + public override fun equals(other: Any?): Boolean + public override fun hashCode(): Int public companion object { /** @@ -49,13 +48,8 @@ public interface NDStructure { if (st1 === st2) return true // fast comparison of buffers if possible - if ( - st1 is NDBuffer && - st2 is NDBuffer && - st1.strides == st2.strides - ) { + if (st1 is NDBuffer && st2 is NDBuffer && st1.strides == st2.strides) return st1.buffer.contentEquals(st2.buffer) - } //element by element comparison if it could not be avoided return st1.elements().all { (index, value) -> value == st2[index] } diff --git a/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Dimensions.kt b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Dimensions.kt index f49e1e0f0..9450f9174 100644 --- a/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Dimensions.kt +++ b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Dimensions.kt @@ -3,8 +3,9 @@ package kscience.kmath.dimensions import kotlin.reflect.KClass /** - * An abstract class which is not used in runtime. Designates a size of some structure. - * Could be replaced later by fully inline constructs + * Represents a quantity of dimensions in certain structure. + * + * @property dim The number of dimensions. */ public interface Dimension { public val dim: UInt @@ -16,18 +17,33 @@ public fun KClass.dim(): UInt = Dimension.resolve(this).dim public expect fun Dimension.Companion.resolve(type: KClass): D +/** + * Finds or creates [Dimension] with [Dimension.dim] equal to [dim]. + */ public expect fun Dimension.Companion.of(dim: UInt): Dimension +/** + * Finds [Dimension.dim] of given type [D]. + */ public inline fun Dimension.Companion.dim(): UInt = D::class.dim() +/** + * Type representing 1 dimension. + */ public object D1 : Dimension { override val dim: UInt get() = 1U } +/** + * Type representing 2 dimensions. + */ public object D2 : Dimension { override val dim: UInt get() = 2U } +/** + * Type representing 3 dimensions. + */ public object D3 : Dimension { override val dim: UInt get() = 3U } diff --git a/kmath-dimensions/src/commonTest/kotlin/scientifik/dimensions/DMatrixContextTest.kt b/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt similarity index 100% rename from kmath-dimensions/src/commonTest/kotlin/scientifik/dimensions/DMatrixContextTest.kt rename to kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt diff --git a/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/Histogram.kt index 98300dada..370a01215 100644 --- a/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/Histogram.kt @@ -10,9 +10,10 @@ import kscience.kmath.structures.RealBuffer */ public interface Bin : Domain { /** - * The value of this bin + * The value of this bin. */ public val value: Number + public val center: Point } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt index 0d95d6f97..2dd4ce51e 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt @@ -3,16 +3,59 @@ package kscience.kmath.prob import kotlin.random.Random /** - * A basic generator + * An interface that is implemented by random number generator algorithms. */ public interface RandomGenerator { + /** + * Gets the next random [Boolean] value. + */ public fun nextBoolean(): Boolean + + /** + * Gets the next random [Double] value uniformly distributed between 0 (inclusive) and 1 (exclusive). + */ public fun nextDouble(): Double + + /** + * Gets the next random `Int` from the random number generator. + * + * Generates an `Int` random value uniformly distributed between [Int.MIN_VALUE] and [Int.MAX_VALUE] (inclusive). + */ public fun nextInt(): Int + + /** + * Gets the next random non-negative `Int` from the random number generator less than the specified [until] bound. + * + * Generates an `Int` random value uniformly distributed between `0` (inclusive) and the specified [until] bound + * (exclusive). + */ public fun nextInt(until: Int): Int + + /** + * Gets the next random `Long` from the random number generator. + * + * Generates a `Long` random value uniformly distributed between [Long.MIN_VALUE] and [Long.MAX_VALUE] (inclusive). + */ public fun nextLong(): Long + + /** + * Gets the next random non-negative `Long` from the random number generator less than the specified [until] bound. + * + * Generates a `Long` random value uniformly distributed between `0` (inclusive) and the specified [until] bound (exclusive). + */ public fun nextLong(until: Long): Long + + /** + * Fills a subrange of the specified byte [array] starting from [fromIndex] inclusive and ending [toIndex] exclusive + * with random bytes. + * + * @return [array] with the subrange filled with random bytes. + */ public fun fillBytes(array: ByteArray, fromIndex: Int = 0, toIndex: Int = array.size) + + /** + * Creates a byte array of the specified [size], filled with random bytes. + */ public fun nextBytes(size: Int): ByteArray = ByteArray(size).also { fillBytes(it) } /** @@ -25,12 +68,21 @@ public interface RandomGenerator { public fun fork(): RandomGenerator public companion object { - public val default: DefaultGenerator by lazy { DefaultGenerator() } + /** + * The [DefaultGenerator] instance. + */ + public val default: DefaultGenerator by lazy(::DefaultGenerator) + /** + * Returns [DefaultGenerator] of given [seed]. + */ public fun default(seed: Long): DefaultGenerator = DefaultGenerator(Random(seed)) } } +/** + * Implements [RandomGenerator] by delegating all operations to [Random]. + */ public inline class DefaultGenerator(public val random: Random = Random) : RandomGenerator { public override fun nextBoolean(): Boolean = random.nextBoolean() public override fun nextDouble(): Double = random.nextDouble() From 7d315e37d172d7726ec93e211ba323328cb6049e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 27 Sep 2020 11:13:30 +0300 Subject: [PATCH 076/199] native memory --- .gitignore | 2 - CHANGELOG.md | 2 +- gradle.properties | 9 ++ kmath-core/build.gradle.kts | 1 + .../kscience/kmath/operations/Complex.kt | 6 +- .../kscience/kmath/structures/MemoryBuffer.kt | 2 +- kmath-memory/build.gradle.kts | 5 +- .../kmath}/memory/Memory.kt | 2 +- .../kmath}/memory/MemorySpec.kt | 2 +- .../kmath}/memory/DataViewMemory.kt | 2 +- .../kmath}/memory/ByteBufferMemory.kt | 2 +- .../kscience/kmath/memory/NativeMemory.kt | 93 +++++++++++++++++++ 12 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 gradle.properties rename kmath-memory/src/commonMain/kotlin/{scientifik => kscience/kmath}/memory/Memory.kt (99%) rename kmath-memory/src/commonMain/kotlin/{scientifik => kscience/kmath}/memory/MemorySpec.kt (98%) rename kmath-memory/src/jsMain/kotlin/{scientifik => kscience/kmath}/memory/DataViewMemory.kt (99%) rename kmath-memory/src/jvmMain/kotlin/{scientifik => kscience/kmath}/memory/ByteBufferMemory.kt (99%) create mode 100644 kmath-memory/src/nativeMain/kotlin/kscience/kmath/memory/NativeMemory.kt diff --git a/.gitignore b/.gitignore index a9294eff9..bade7f08c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,3 @@ out/ # Cache of project .gradletasknamecache - -gradle.properties \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e017fe565..09c6274df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ - `fun` annotation for SAM interfaces in library - Explicit `public` visibility for all public APIs - Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140). -- Automatic documentation generation for features (#139) +- Automatic README generation for features (#139) ### Changed - Package changed from `scientifik` to `kscience.kmath`. diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..930bba550 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,9 @@ +kotlin.code.style=official +kotlin.parallel.tasks.in.project=true +kotlin.mpp.enableGranularSourceSetsMetadata=true +kotlin.native.enableDependencyPropagation=false +kotlin.mpp.stability.nowarn=true + +org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m +org.gradle.parallel=true +systemProp.org.gradle.internal.publish.checksums.insecure=true \ No newline at end of file diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index d64a4d8a5..b56151abe 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("ru.mipt.npm.mpp") + id("ru.mipt.npm.native") } kotlin.sourceSets.commonMain { 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 c0faf5dc5..24bfec054 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt @@ -1,11 +1,11 @@ package kscience.kmath.operations +import kscience.kmath.memory.MemoryReader +import kscience.kmath.memory.MemorySpec +import kscience.kmath.memory.MemoryWriter import kscience.kmath.structures.Buffer import kscience.kmath.structures.MemoryBuffer import kscience.kmath.structures.MutableBuffer -import kscience.memory.MemoryReader -import kscience.memory.MemorySpec -import kscience.memory.MemoryWriter import kotlin.math.* /** diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt index b7e6a8218..c171e7c1d 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/MemoryBuffer.kt @@ -1,6 +1,6 @@ package kscience.kmath.structures -import kscience.memory.* +import kscience.kmath.memory.* /** * A non-boxing buffer over [Memory] object. diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 94527a6a3..9f92cca92 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1 +1,4 @@ -plugins { id("ru.mipt.npm.mpp") } +plugins { + id("ru.mipt.npm.mpp") + id("ru.mipt.npm.native") +} diff --git a/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt b/kmath-memory/src/commonMain/kotlin/kscience/kmath/memory/Memory.kt similarity index 99% rename from kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt rename to kmath-memory/src/commonMain/kotlin/kscience/kmath/memory/Memory.kt index 8de9a7a0c..344a1f1d3 100644 --- a/kmath-memory/src/commonMain/kotlin/scientifik/memory/Memory.kt +++ b/kmath-memory/src/commonMain/kotlin/kscience/kmath/memory/Memory.kt @@ -1,4 +1,4 @@ -package kscience.memory +package kscience.kmath.memory import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt b/kmath-memory/src/commonMain/kotlin/kscience/kmath/memory/MemorySpec.kt similarity index 98% rename from kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt rename to kmath-memory/src/commonMain/kotlin/kscience/kmath/memory/MemorySpec.kt index d2cbb32fd..572dab0fa 100644 --- a/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt +++ b/kmath-memory/src/commonMain/kotlin/kscience/kmath/memory/MemorySpec.kt @@ -1,4 +1,4 @@ -package kscience.memory +package kscience.kmath.memory /** * A specification to read or write custom objects with fixed size in bytes. diff --git a/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt b/kmath-memory/src/jsMain/kotlin/kscience/kmath/memory/DataViewMemory.kt similarity index 99% rename from kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt rename to kmath-memory/src/jsMain/kotlin/kscience/kmath/memory/DataViewMemory.kt index d6b8841e4..2146cd4e1 100644 --- a/kmath-memory/src/jsMain/kotlin/scientifik/memory/DataViewMemory.kt +++ b/kmath-memory/src/jsMain/kotlin/kscience/kmath/memory/DataViewMemory.kt @@ -1,4 +1,4 @@ -package kscience.memory +package kscience.kmath.memory import org.khronos.webgl.ArrayBuffer import org.khronos.webgl.DataView diff --git a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/kscience/kmath/memory/ByteBufferMemory.kt similarity index 99% rename from kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt rename to kmath-memory/src/jvmMain/kotlin/kscience/kmath/memory/ByteBufferMemory.kt index c912b28ff..7a75b423e 100644 --- a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/kscience/kmath/memory/ByteBufferMemory.kt @@ -1,4 +1,4 @@ -package kscience.memory +package kscience.kmath.memory import java.io.IOException import java.nio.ByteBuffer diff --git a/kmath-memory/src/nativeMain/kotlin/kscience/kmath/memory/NativeMemory.kt b/kmath-memory/src/nativeMain/kotlin/kscience/kmath/memory/NativeMemory.kt new file mode 100644 index 000000000..0e007a8ab --- /dev/null +++ b/kmath-memory/src/nativeMain/kotlin/kscience/kmath/memory/NativeMemory.kt @@ -0,0 +1,93 @@ +package kscience.kmath.memory + +@PublishedApi +internal class NativeMemory( + val array: ByteArray, + val startOffset: Int = 0, + override val size: Int = array.size +) : Memory { + @Suppress("NOTHING_TO_INLINE") + private inline fun position(o: Int): Int = startOffset + o + + override fun view(offset: Int, length: Int): Memory { + require(offset >= 0) { "offset shouldn't be negative: $offset" } + require(length >= 0) { "length shouldn't be negative: $length" } + require(offset + length <= size) { "Can't view memory outside the parent region." } + return NativeMemory(array, position(offset), length) + } + + override fun copy(): Memory { + val copy = array.copyOfRange(startOffset, startOffset + size) + return NativeMemory(copy) + } + + private val reader: MemoryReader = object : MemoryReader { + override val memory: Memory get() = this@NativeMemory + + override fun readDouble(offset: Int) = array.getDoubleAt(position(offset)) + + override fun readFloat(offset: Int) = array.getFloatAt(position(offset)) + + override fun readByte(offset: Int) = array[position(offset)] + + override fun readShort(offset: Int) = array.getShortAt(position(offset)) + + override fun readInt(offset: Int) = array.getIntAt(position(offset)) + + override fun readLong(offset: Int) = array.getLongAt(position(offset)) + + override fun release() { + // does nothing on JVM + } + } + + override fun reader(): MemoryReader = reader + + private val writer: MemoryWriter = object : MemoryWriter { + override val memory: Memory get() = this@NativeMemory + + override fun writeDouble(offset: Int, value: Double) { + array.setDoubleAt(position(offset), value) + } + + override fun writeFloat(offset: Int, value: Float) { + array.setFloatAt(position(offset), value) + } + + override fun writeByte(offset: Int, value: Byte) { + array.set(position(offset), value) + } + + override fun writeShort(offset: Int, value: Short) { + array.setShortAt(position(offset), value) + } + + override fun writeInt(offset: Int, value: Int) { + array.setIntAt(position(offset), value) + } + + override fun writeLong(offset: Int, value: Long) { + array.setLongAt(position(offset), value) + } + + override fun release() { + // does nothing on JVM + } + } + + override fun writer(): MemoryWriter = writer +} + +/** + * Wraps a [Memory] around existing [ByteArray]. This operation is unsafe since the array is not copied + * and could be mutated independently from the resulting [Memory]. + */ +public actual fun Memory.Companion.wrap(array: ByteArray): Memory = NativeMemory(array) + +/** + * Allocates the most effective platform-specific memory. + */ +public actual fun Memory.Companion.allocate(length: Int): Memory { + val array = ByteArray(length) + return NativeMemory(array) +} \ No newline at end of file From 0a71c7196d596fc4bc6d0002a933083c5838da39 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 27 Sep 2020 11:43:03 +0300 Subject: [PATCH 077/199] Fix caches on native --- .../commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt | 2 ++ .../commonMain/kotlin/kscience/kmath/structures/NDStructure.kt | 2 ++ .../commonTest/kotlin/kscience/kmath/operations/ComplexTest.kt | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt index 28eaef2f1..03c601717 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt @@ -4,6 +4,7 @@ import kscience.kmath.operations.Complex import kscience.kmath.operations.Field import kscience.kmath.operations.Ring import kscience.kmath.operations.Space +import kotlin.native.concurrent.ThreadLocal /** * An exception is thrown when the expected ans actual shape of NDArray differs @@ -115,6 +116,7 @@ public interface NDField, N : NDStructure> : Field, NDRing public operator fun T.div(arg: N): N = map(arg) { divide(it, this@div) } + @ThreadLocal public companion object { private val realNDFieldCache: MutableMap = hashMapOf() diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt index 4ab49c9bc..fd679d073 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt @@ -1,6 +1,7 @@ package kscience.kmath.structures import kotlin.jvm.JvmName +import kotlin.native.concurrent.ThreadLocal import kotlin.reflect.KClass /** @@ -230,6 +231,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : override fun hashCode(): Int = shape.contentHashCode() + @ThreadLocal public companion object { private val defaultStridesCache = HashMap() diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/ComplexTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/ComplexTest.kt index f8b9b7262..456e41467 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/ComplexTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/ComplexTest.kt @@ -2,6 +2,7 @@ package kscience.kmath.operations import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue internal class ComplexTest { @Test @@ -13,7 +14,7 @@ internal class ComplexTest { @Test fun reciprocal() { - assertEquals(Complex(0.5, -0.0), 2.toComplex().reciprocal) + assertTrue { (Complex(0.5, -0.0) - 2.toComplex().reciprocal).r < 1e-10} } @Test From 53ea704bae1c67536627b0b7967c56a5184518a7 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 27 Sep 2020 19:57:30 +0300 Subject: [PATCH 078/199] Finishing migration to 1.4.20-M1 --- build.gradle.kts | 3 ++- docs/templates/ARTIFACT-TEMPLATE.md | 3 +++ examples/build.gradle.kts | 11 +++++----- kmath-dimensions/build.gradle.kts | 5 ++++- .../kmath/dimensions/{dim.kt => dimJs.kt} | 0 .../kmath/dimensions/{dim.kt => dimJvm.kt} | 0 .../kscience/kmath/dimensions/dimNative.kt | 20 +++++++++++++++++++ settings.gradle.kts | 6 ++++-- 8 files changed, 38 insertions(+), 10 deletions(-) rename kmath-dimensions/src/jsMain/kotlin/kscience/kmath/dimensions/{dim.kt => dimJs.kt} (100%) rename kmath-dimensions/src/jvmMain/kotlin/kscience/kmath/dimensions/{dim.kt => dimJvm.kt} (100%) create mode 100644 kmath-dimensions/src/nativeMain/kotlin/kscience/kmath/dimensions/dimNative.kt diff --git a/build.gradle.kts b/build.gradle.kts index 87862ae8e..499f49d1d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,13 +2,14 @@ plugins { id("ru.mipt.npm.project") } -val kmathVersion by extra("0.2.0-dev-1") +val kmathVersion by extra("0.2.0-dev-2") val bintrayRepo by extra("kscience") val githubProject by extra("kmath") allprojects { repositories { jcenter() + maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/hotkeytlt/maven") } diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md index cbdd98218..c77948d4b 100644 --- a/docs/templates/ARTIFACT-TEMPLATE.md +++ b/docs/templates/ARTIFACT-TEMPLATE.md @@ -10,9 +10,11 @@ > > ```gradle > repositories { +> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } > maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + > } > > dependencies { @@ -23,6 +25,7 @@ > > ```kotlin > repositories { +> maven("https://dl.bintray.com/kotlin/kotlin-eap") > maven("https://dl.bintray.com/mipt-npm/kscience") > maven("https://dl.bintray.com/mipt-npm/dev") > maven("https://dl.bintray.com/hotkeytlt/maven") diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 3d193efce..3f18d3cf3 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -3,8 +3,8 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { java kotlin("jvm") - kotlin("plugin.allopen") version "1.4.20-dev-3898-14" - id("kotlinx.benchmark") version "0.2.0-dev-20" + kotlin("plugin.allopen") + id("kotlinx.benchmark") } allOpen.annotation("org.openjdk.jmh.annotations.State") @@ -26,7 +26,7 @@ dependencies { implementation(project(":kmath-prob")) implementation(project(":kmath-viktor")) implementation(project(":kmath-dimensions")) - implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6") + implementation("org.jetbrains.kotlinx:kotlinx-io:0.2.0-npm-dev-11") implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20") "benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath } @@ -34,9 +34,8 @@ dependencies { // Configure benchmark benchmark { // Setup configurations - targets - // This one matches sourceSet name above - .register("benchmarks") + targets.register("benchmarks") + // This one matches sourceSet name above configurations.register("fast") { warmups = 5 // number of warmup iterations diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index 0a36e4435..412d7162f 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -1,4 +1,7 @@ -plugins { id("ru.mipt.npm.mpp") } +plugins { + id("ru.mipt.npm.mpp") + id("ru.mipt.npm.native") +} description = "A proof of concept module for adding type-safe dimensions to structures" diff --git a/kmath-dimensions/src/jsMain/kotlin/kscience/kmath/dimensions/dim.kt b/kmath-dimensions/src/jsMain/kotlin/kscience/kmath/dimensions/dimJs.kt similarity index 100% rename from kmath-dimensions/src/jsMain/kotlin/kscience/kmath/dimensions/dim.kt rename to kmath-dimensions/src/jsMain/kotlin/kscience/kmath/dimensions/dimJs.kt diff --git a/kmath-dimensions/src/jvmMain/kotlin/kscience/kmath/dimensions/dim.kt b/kmath-dimensions/src/jvmMain/kotlin/kscience/kmath/dimensions/dimJvm.kt similarity index 100% rename from kmath-dimensions/src/jvmMain/kotlin/kscience/kmath/dimensions/dim.kt rename to kmath-dimensions/src/jvmMain/kotlin/kscience/kmath/dimensions/dimJvm.kt diff --git a/kmath-dimensions/src/nativeMain/kotlin/kscience/kmath/dimensions/dimNative.kt b/kmath-dimensions/src/nativeMain/kotlin/kscience/kmath/dimensions/dimNative.kt new file mode 100644 index 000000000..aeaeaf759 --- /dev/null +++ b/kmath-dimensions/src/nativeMain/kotlin/kscience/kmath/dimensions/dimNative.kt @@ -0,0 +1,20 @@ +package kscience.kmath.dimensions + +import kotlin.native.concurrent.ThreadLocal +import kotlin.reflect.KClass + +@ThreadLocal +private val dimensionMap: MutableMap = hashMapOf(1u to D1, 2u to D2, 3u to D3) + +@Suppress("UNCHECKED_CAST") +public actual fun Dimension.Companion.resolve(type: KClass): D = dimensionMap + .entries + .map(MutableMap.MutableEntry::value) + .find { it::class == type } as? D + ?: error("Can't resolve dimension $type") + +public actual fun Dimension.Companion.of(dim: UInt): Dimension = dimensionMap.getOrPut(dim) { + object : Dimension { + override val dim: UInt get() = dim + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index ad9014e56..844fa0d6c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,7 +10,8 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlin-dev/") } - val toolsVersion = "0.6.1" + val toolsVersion = "0.6.1-dev-1.4.20-M1" + val kotlinVersion = "1.4.20-M1" plugins { id("kotlinx.benchmark") version "0.2.0-dev-20" @@ -18,7 +19,8 @@ pluginManagement { id("ru.mipt.npm.mpp") version toolsVersion id("ru.mipt.npm.jvm") version toolsVersion id("ru.mipt.npm.publish") version toolsVersion - kotlin("plugin.allopen") + kotlin("jvm") version kotlinVersion + kotlin("plugin.allopen") version kotlinVersion } } From 1f6834d4188a31c13aa0f5d812f08cca880b9dd6 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 27 Sep 2020 20:05:31 +0300 Subject: [PATCH 079/199] Update readme --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09c6274df..496d961d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Gradle version: 6.6 -> 6.6.1 - Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`) - `Polynomial` secondary constructor made function. +- Kotlin version: 1.3.72 -> 1.4.20-M1 ### Deprecated From 431b574544b231a59d256b6d4fba037cb8a547c9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 27 Sep 2020 20:09:46 +0300 Subject: [PATCH 080/199] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 496d961d8..f3fe37b6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Explicit `public` visibility for all public APIs - Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140). - Automatic README generation for features (#139) +- Native support for `memory`, `core` and `dimensions` ### Changed - Package changed from `scientifik` to `kscience.kmath`. @@ -18,6 +19,7 @@ ### Removed - `kmath-koma` module because it doesn't support Kotlin 1.4. +- Support of `legacy` JS backend (we will support only IR) ### Fixed - `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) From 049ac896671dded53e4482b1b677b02131ef4d93 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 30 Sep 2020 12:30:06 +0300 Subject: [PATCH 081/199] More informative toString for NDBuffer and Complex --- .../kscience/kmath/operations/ComplexDemo.kt | 6 ++- .../kscience/kmath/operations/Complex.kt | 5 +++ .../kscience/kmath/structures/NDStructure.kt | 38 +++++++++++++------ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt b/examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt index 3c97940a8..34b3c9981 100644 --- a/examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt @@ -5,15 +5,19 @@ import kscience.kmath.structures.NDField import kscience.kmath.structures.complex fun main() { + // 2d element val element = NDElement.complex(2, 2) { index: IntArray -> Complex(index[0].toDouble() - index[1].toDouble(), index[0].toDouble() + index[1].toDouble()) } + println(element) - val compute = (NDField.complex(8)) { + // 1d element operation + val result = with(NDField.complex(8)) { val a = produce { (it) -> i * it - it.toDouble() } val b = 3 val c = Complex(1.0, 1.0) (a pow b) + c } + println(result) } 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 24bfec054..7bd7b6085 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt @@ -176,6 +176,11 @@ public data class Complex(val re: Double, val im: Double) : FieldElement { override val objectSize: Int = 16 diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt index fd679d073..c107ef7cc 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt @@ -70,7 +70,7 @@ public interface NDStructure { public fun build( strides: Strides, bufferFactory: BufferFactory = Buffer.Companion::boxing, - initializer: (IntArray) -> T + initializer: (IntArray) -> T, ): BufferNDStructure = BufferNDStructure(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) }) @@ -79,40 +79,40 @@ public interface NDStructure { */ public inline fun auto( strides: Strides, - crossinline initializer: (IntArray) -> T + crossinline initializer: (IntArray) -> T, ): BufferNDStructure = BufferNDStructure(strides, Buffer.auto(strides.linearSize) { i -> initializer(strides.index(i)) }) public inline fun auto( type: KClass, strides: Strides, - crossinline initializer: (IntArray) -> T + crossinline initializer: (IntArray) -> T, ): BufferNDStructure = BufferNDStructure(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) }) public fun build( shape: IntArray, bufferFactory: BufferFactory = Buffer.Companion::boxing, - initializer: (IntArray) -> T + initializer: (IntArray) -> T, ): BufferNDStructure = build(DefaultStrides(shape), bufferFactory, initializer) public inline fun auto( shape: IntArray, - crossinline initializer: (IntArray) -> T + crossinline initializer: (IntArray) -> T, ): BufferNDStructure = auto(DefaultStrides(shape), initializer) @JvmName("autoVarArg") public inline fun auto( vararg shape: Int, - crossinline initializer: (IntArray) -> T + crossinline initializer: (IntArray) -> T, ): BufferNDStructure = auto(DefaultStrides(shape), initializer) public inline fun auto( type: KClass, vararg shape: Int, - crossinline initializer: (IntArray) -> T + crossinline initializer: (IntArray) -> T, ): BufferNDStructure = auto(type, DefaultStrides(shape), initializer) } @@ -274,6 +274,22 @@ public abstract class NDBuffer : NDStructure { result = 31 * result + buffer.hashCode() return result } + + override fun toString(): String { + val bufferRepr: String = when (shape.size) { + 1 -> buffer.asSequence().joinToString(prefix = "[", postfix = "]", separator = ", ") + 2 -> (0 until shape[0]).joinToString(prefix = "[", postfix = "]", separator = ", ") { i -> + (0 until shape[1]).joinToString(prefix = "[", postfix = "]", separator = ", ") { j -> + val offset = strides.offset(intArrayOf(i, j)) + buffer[offset].toString() + } + } + else -> "..." + } + return "NDBuffer(shape=${shape.contentToString()}, buffer=$bufferRepr)" + } + + } /** @@ -281,7 +297,7 @@ public abstract class NDBuffer : NDStructure { */ public class BufferNDStructure( override val strides: Strides, - override val buffer: Buffer + override val buffer: Buffer, ) : NDBuffer() { init { if (strides.linearSize != buffer.size) { @@ -295,7 +311,7 @@ public class BufferNDStructure( */ public inline fun NDStructure.mapToBuffer( factory: BufferFactory = Buffer.Companion::auto, - crossinline transform: (T) -> R + crossinline transform: (T) -> R, ): BufferNDStructure { return if (this is BufferNDStructure) BufferNDStructure(this.strides, factory.invoke(strides.linearSize) { transform(buffer[it]) }) @@ -310,7 +326,7 @@ public inline fun NDStructure.mapToBuffer( */ public class MutableBufferNDStructure( override val strides: Strides, - override val buffer: MutableBuffer + override val buffer: MutableBuffer, ) : NDBuffer(), MutableNDStructure { init { @@ -324,7 +340,7 @@ public class MutableBufferNDStructure( public inline fun NDStructure.combine( struct: NDStructure, - crossinline block: (T, T) -> T + crossinline block: (T, T) -> T, ): NDStructure { require(shape.contentEquals(struct.shape)) { "Shape mismatch in structure combination" } return NDStructure.auto(shape) { block(this[it], struct[it]) } From 7d60fa142d6adf1d922eba6afbce41c476e31a19 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 30 Sep 2020 21:28:39 +0700 Subject: [PATCH 082/199] Remove kotlin-reflect dependency (-2MiB to library size), optimize type copying, optimize reflection usages, optimize lexer --- kmath-ast/build.gradle.kts | 1 - .../jvmMain/kotlin/kscience/kmath/asm/asm.kt | 18 +++-- .../kscience/kmath/asm/internal/AsmBuilder.kt | 69 +++++++++---------- .../kmath/asm/internal/codegenUtils.kt | 12 ++-- .../kotlin/kscience/kmath/ast/parser.kt | 17 ++--- 5 files changed, 63 insertions(+), 54 deletions(-) diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index df876df10..a0afcdc4f 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -14,7 +14,6 @@ kotlin.sourceSets { implementation("org.ow2.asm:asm:8.0.1") implementation("org.ow2.asm:asm-commons:8.0.1") implementation("com.github.h0tk3y.betterParse:better-parse:0.4.0") - implementation(kotlin("reflect")) } } } diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt index 53425e7e3..00b9caf15 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt @@ -6,9 +6,11 @@ import kscience.kmath.asm.internal.buildAlgebraOperationCall import kscience.kmath.asm.internal.buildName import kscience.kmath.ast.MST import kscience.kmath.ast.MstExpression +import kscience.kmath.ast.mstInSpace import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.invoke import kscience.kmath.operations.Algebra -import kotlin.reflect.KClass +import kscience.kmath.operations.RealField /** * Compiles given MST to an Expression using AST compiler. @@ -18,7 +20,8 @@ import kotlin.reflect.KClass * @return the compiled expression. * @author Alexander Nozik */ -public fun MST.compileWith(type: KClass, algebra: Algebra): Expression { +@PublishedApi +internal fun MST.compileWith(type: Class, algebra: Algebra): Expression { fun AsmBuilder.visit(node: MST): Unit = when (node) { is MST.Symbolic -> { val symbol = try { @@ -61,11 +64,18 @@ public fun MST.compileWith(type: KClass, algebra: Algebra): Expr * * @author Alexander Nozik. */ -public inline fun Algebra.expression(mst: MST): Expression = mst.compileWith(T::class, this) +public inline fun Algebra.expression(mst: MST): Expression = + mst.compileWith(T::class.java, this) /** * Optimizes performance of an [MstExpression] using ASM codegen. * * @author Alexander Nozik. */ -public inline fun MstExpression.compile(): Expression = mst.compileWith(T::class, algebra) +public inline fun MstExpression.compile(): Expression = mst.compileWith(T::class.java, algebra) + +public fun main() { + val x = RealField.mstInSpace { symbol("x") + number(2.0) }.compile() + println(x("x" to 1.0)) +} + diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index ab2de97aa..06f02a94d 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -10,7 +10,6 @@ import org.objectweb.asm.Opcodes.* import org.objectweb.asm.commons.InstructionAdapter import java.util.* import java.util.stream.Collectors -import kotlin.reflect.KClass /** * ASM Builder is a structure that abstracts building a class designated to unwrap [MST] to plain Java expression. @@ -23,7 +22,7 @@ import kotlin.reflect.KClass * @author Iaroslav Postovalov */ internal class AsmBuilder internal constructor( - private val classOfT: KClass<*>, + private val classOfT: Class<*>, private val algebra: Algebra, private val className: String, private val invokeLabel0Visitor: AsmBuilder.() -> Unit @@ -32,7 +31,7 @@ internal class AsmBuilder internal constructor( * Internal classloader of [AsmBuilder] with alias to define class from byte array. */ private class ClassLoader(parent: java.lang.ClassLoader) : java.lang.ClassLoader(parent) { - internal fun defineClass(name: String?, b: ByteArray): Class<*> = defineClass(name, b, 0, b.size) + fun defineClass(name: String?, b: ByteArray): Class<*> = defineClass(name, b, 0, b.size) } /** @@ -43,7 +42,7 @@ internal class AsmBuilder internal constructor( /** * ASM Type for [algebra]. */ - private val tAlgebraType: Type = algebra::class.asm + private val tAlgebraType: Type = algebra.javaClass.asm /** * ASM type for [T]. @@ -55,16 +54,6 @@ internal class AsmBuilder internal constructor( */ private val classType: Type = Type.getObjectType(className.replace(oldChar = '.', newChar = '/'))!! - /** - * Index of `this` variable in invoke method of the built subclass. - */ - private val invokeThisVar: Int = 0 - - /** - * Index of `arguments` variable in invoke method of the built subclass. - */ - private val invokeArgumentsVar: Int = 1 - /** * List of constants to provide to the subclass. */ @@ -76,22 +65,22 @@ internal class AsmBuilder internal constructor( private lateinit var invokeMethodVisitor: InstructionAdapter /** - * State if this [AsmBuilder] needs to generate constants field. + * States whether this [AsmBuilder] needs to generate constants field. */ private var hasConstants: Boolean = true /** - * State if [T] a primitive type, so [AsmBuilder] may generate direct primitive calls. + * States whether [T] a primitive type, so [AsmBuilder] may generate direct primitive calls. */ internal var primitiveMode: Boolean = false /** - * Primitive type to apple for specific primitive calls. Use [OBJECT_TYPE], if not in [primitiveMode]. + * Primitive type to apply for specific primitive calls. Use [OBJECT_TYPE], if not in [primitiveMode]. */ internal var primitiveMask: Type = OBJECT_TYPE /** - * Boxed primitive type to apple for specific primitive calls. Use [OBJECT_TYPE], if not in [primitiveMode]. + * Boxed primitive type to apply for specific primitive calls. Use [OBJECT_TYPE], if not in [primitiveMode]. */ internal var primitiveMaskBoxed: Type = OBJECT_TYPE @@ -103,7 +92,7 @@ internal class AsmBuilder internal constructor( /** * Stack of useful objects types on stack expected by algebra calls. */ - internal val expectationStack: ArrayDeque = ArrayDeque(listOf(tType)) + internal val expectationStack: ArrayDeque = ArrayDeque(1).also { it.push(tType) } /** * The cache for instance built by this builder. @@ -361,7 +350,7 @@ internal class AsmBuilder internal constructor( * from it). */ private fun loadNumberConstant(value: Number, mustBeBoxed: Boolean) { - val boxed = value::class.asm + val boxed = value.javaClass.asm val primitive = BOXED_TO_PRIMITIVES[boxed] if (primitive != null) { @@ -475,17 +464,27 @@ internal class AsmBuilder internal constructor( internal fun loadStringConstant(string: String): Unit = invokeMethodVisitor.aconst(string) internal companion object { + /** + * Index of `this` variable in invoke method of the built subclass. + */ + private const val invokeThisVar: Int = 0 + + /** + * Index of `arguments` variable in invoke method of the built subclass. + */ + private const val invokeArgumentsVar: Int = 1 + /** * Maps JVM primitive numbers boxed types to their primitive ASM types. */ - private val SIGNATURE_LETTERS: Map, Type> by lazy { + private val SIGNATURE_LETTERS: Map, Type> by lazy { hashMapOf( - java.lang.Byte::class to Type.BYTE_TYPE, - java.lang.Short::class to Type.SHORT_TYPE, - java.lang.Integer::class to Type.INT_TYPE, - java.lang.Long::class to Type.LONG_TYPE, - java.lang.Float::class to Type.FLOAT_TYPE, - java.lang.Double::class to Type.DOUBLE_TYPE + java.lang.Byte::class.java to Type.BYTE_TYPE, + java.lang.Short::class.java to Type.SHORT_TYPE, + java.lang.Integer::class.java to Type.INT_TYPE, + java.lang.Long::class.java to Type.LONG_TYPE, + java.lang.Float::class.java to Type.FLOAT_TYPE, + java.lang.Double::class.java to Type.DOUBLE_TYPE ) } @@ -523,43 +522,43 @@ internal class AsmBuilder internal constructor( /** * Provides boxed number types values of which can be stored in JVM bytecode constant pool. */ - private val INLINABLE_NUMBERS: Set> by lazy { SIGNATURE_LETTERS.keys } + private val INLINABLE_NUMBERS: Set> by lazy { SIGNATURE_LETTERS.keys } /** * ASM type for [Expression]. */ - internal val EXPRESSION_TYPE: Type by lazy { Expression::class.asm } + internal val EXPRESSION_TYPE: Type by lazy { Type.getObjectType("kscience/kmath/expressions/Expression") } /** * ASM type for [java.lang.Number]. */ - internal val NUMBER_TYPE: Type by lazy { java.lang.Number::class.asm } + internal val NUMBER_TYPE: Type by lazy { Type.getObjectType("java/lang/Number") } /** * ASM type for [java.util.Map]. */ - internal val MAP_TYPE: Type by lazy { java.util.Map::class.asm } + internal val MAP_TYPE: Type by lazy { Type.getObjectType("java/util/Map") } /** * ASM type for [java.lang.Object]. */ - internal val OBJECT_TYPE: Type by lazy { java.lang.Object::class.asm } + internal val OBJECT_TYPE: Type by lazy { Type.getObjectType("java/lang/Object") } /** * ASM type for array of [java.lang.Object]. */ @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "RemoveRedundantQualifierName") - internal val OBJECT_ARRAY_TYPE: Type by lazy { Array::class.asm } + internal val OBJECT_ARRAY_TYPE: Type by lazy { Type.getType("[Ljava/lang/Object;") } /** * ASM type for [Algebra]. */ - internal val ALGEBRA_TYPE: Type by lazy { Algebra::class.asm } + internal val ALGEBRA_TYPE: Type by lazy { Type.getObjectType("kscience/kmath/operations/Algebra") } /** * ASM type for [java.lang.String]. */ - internal val STRING_TYPE: Type by lazy { java.lang.String::class.asm } + internal val STRING_TYPE: Type by lazy { Type.getObjectType("java/lang/String") } /** * ASM type for MapIntrinsics. diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt index 67fce40ac..ef9751502 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt @@ -10,9 +10,9 @@ import org.objectweb.asm.* import org.objectweb.asm.Opcodes.INVOKEVIRTUAL import org.objectweb.asm.commons.InstructionAdapter import java.lang.reflect.Method +import java.util.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract -import kotlin.reflect.KClass private val methodNameAdapters: Map, String> by lazy { hashMapOf( @@ -26,12 +26,12 @@ private val methodNameAdapters: Map, String> by lazy { } /** - * Returns ASM [Type] for given [KClass]. + * Returns ASM [Type] for given [Class]. * * @author Iaroslav Postovalov */ -internal val KClass<*>.asm: Type - get() = Type.getType(java) +internal inline val Class<*>.asm: Type + get() = Type.getType(this) /** * Returns singleton array with this value if the [predicate] is true, returns empty array otherwise. @@ -140,7 +140,7 @@ private fun AsmBuilder.buildExpectationStack( if (specific != null) mapTypes(specific, parameterTypes).reversed().forEach { expectationStack.push(it) } else - repeat(arity) { expectationStack.push(tType) } + expectationStack.addAll(Collections.nCopies(arity, tType)) return specific != null } @@ -169,7 +169,7 @@ private fun AsmBuilder.tryInvokeSpecific( val arity = parameterTypes.size val theName = methodNameAdapters[name to arity] ?: name val spec = findSpecific(context, theName, parameterTypes) ?: return false - val owner = context::class.asm + val owner = context.javaClass.asm invokeAlgebraOperation( owner = owner.internalName, diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt index 15e6625db..94cd3b321 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt @@ -7,6 +7,7 @@ import com.github.h0tk3y.betterParse.grammar.parser import com.github.h0tk3y.betterParse.grammar.tryParseToEnd import com.github.h0tk3y.betterParse.lexer.Token import com.github.h0tk3y.betterParse.lexer.TokenMatch +import com.github.h0tk3y.betterParse.lexer.literalToken import com.github.h0tk3y.betterParse.lexer.regexToken import com.github.h0tk3y.betterParse.parser.ParseResult import com.github.h0tk3y.betterParse.parser.Parser @@ -23,14 +24,14 @@ 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+)?") private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*") - private val lpar: Token by regexToken("\\(") - private val rpar: Token by regexToken("\\)") - private val comma: Token by regexToken(",") - private val mul: Token by regexToken("\\*") - private val pow: Token by regexToken("\\^") - private val div: Token by regexToken("/") - private val minus: Token by regexToken("-") - private val plus: Token by regexToken("\\+") + private val lpar: Token by literalToken("(") + private val rpar: Token by literalToken(")") + private val comma: Token by literalToken(",") + private val mul: Token by literalToken("*") + private val pow: Token by literalToken("^") + private val div: Token by literalToken("/") + private val minus: Token by literalToken("-") + private val plus: Token by literalToken("+") private val ws: Token by regexToken("\\s+", ignore = true) private val number: Parser by num use { MST.Numeric(text.toDouble()) } From a465ab64f035def4de58ff028a912e3367a238de Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 1 Oct 2020 01:21:34 +0700 Subject: [PATCH 083/199] Remove accidentally left main method --- kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt index 00b9caf15..2b6fa6247 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt @@ -6,11 +6,8 @@ import kscience.kmath.asm.internal.buildAlgebraOperationCall import kscience.kmath.asm.internal.buildName import kscience.kmath.ast.MST import kscience.kmath.ast.MstExpression -import kscience.kmath.ast.mstInSpace import kscience.kmath.expressions.Expression -import kscience.kmath.expressions.invoke import kscience.kmath.operations.Algebra -import kscience.kmath.operations.RealField /** * Compiles given MST to an Expression using AST compiler. @@ -73,9 +70,3 @@ public inline fun Algebra.expression(mst: MST): Expression< * @author Alexander Nozik. */ public inline fun MstExpression.compile(): Expression = mst.compileWith(T::class.java, algebra) - -public fun main() { - val x = RealField.mstInSpace { symbol("x") + number(2.0) }.compile() - println(x("x" to 1.0)) -} - From 6e6e71543ee6578d74a9549d839501c6d10fbe9e Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 1 Oct 2020 20:32:07 +0700 Subject: [PATCH 084/199] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3fe37b6b..5d13a360f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`) - `Polynomial` secondary constructor made function. - Kotlin version: 1.3.72 -> 1.4.20-M1 +- `kmath-ast` doesn't depend on heavy `kotlin-reflect` library. ### Deprecated From 6ee0039985d8a8a491fd330c24cd601bda50488b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 1 Oct 2020 21:49:57 +0700 Subject: [PATCH 085/199] Fix build problems --- .../commonMain/kotlin/kscience/kmath/operations/Complex.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 3c3b17d50..37055a5c8 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt @@ -1,12 +1,12 @@ package kscience.kmath.operations +import kscience.kmath.memory.MemoryReader +import kscience.kmath.memory.MemorySpec +import kscience.kmath.memory.MemoryWriter import kscience.kmath.structures.Buffer import kscience.kmath.structures.MemoryBuffer import kscience.kmath.structures.MutableBuffer import kscience.kmath.structures.MutableMemoryBuffer -import kscience.memory.MemoryReader -import kscience.memory.MemorySpec -import kscience.memory.MemoryWriter import kotlin.math.* /** From a12c6454161212b4529a4363d6f846e4308933d7 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 3 Oct 2020 23:13:08 +0700 Subject: [PATCH 086/199] Move to kscience --- .../kotlin/{scietifik => kscience}/kmath/asm/TestAsmAlgebras.kt | 2 +- .../{scietifik => kscience}/kmath/asm/TestAsmExpressions.kt | 2 +- .../{scietifik => kscience}/kmath/asm/TestAsmSpecialization.kt | 2 +- .../{scietifik => kscience}/kmath/asm/TestAsmVariables.kt | 2 +- .../jvmTest/kotlin/{scietifik => kscience}/kmath/ast/AsmTest.kt | 2 +- .../{scietifik => kscience}/kmath/ast/ParserPrecedenceTest.kt | 2 +- .../kotlin/{scietifik => kscience}/kmath/ast/ParserTest.kt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) rename kmath-ast/src/jvmTest/kotlin/{scietifik => kscience}/kmath/asm/TestAsmAlgebras.kt (99%) rename kmath-ast/src/jvmTest/kotlin/{scietifik => kscience}/kmath/asm/TestAsmExpressions.kt (96%) rename kmath-ast/src/jvmTest/kotlin/{scietifik => kscience}/kmath/asm/TestAsmSpecialization.kt (98%) rename kmath-ast/src/jvmTest/kotlin/{scietifik => kscience}/kmath/asm/TestAsmVariables.kt (95%) rename kmath-ast/src/jvmTest/kotlin/{scietifik => kscience}/kmath/ast/AsmTest.kt (96%) rename kmath-ast/src/jvmTest/kotlin/{scietifik => kscience}/kmath/ast/ParserPrecedenceTest.kt (97%) rename kmath-ast/src/jvmTest/kotlin/{scietifik => kscience}/kmath/ast/ParserTest.kt (98%) diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmAlgebras.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt similarity index 99% rename from kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmAlgebras.kt rename to kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt index 5d8f90c9b..0cf1307d1 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmAlgebras.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt @@ -1,4 +1,4 @@ -package scietifik.kmath.asm +package kscience.kmath.asm import kscience.kmath.asm.compile import kscience.kmath.ast.mstInField diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmExpressions.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmExpressions.kt similarity index 96% rename from kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmExpressions.kt rename to kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmExpressions.kt index c2e45b8ff..7f4d453f7 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmExpressions.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmExpressions.kt @@ -1,4 +1,4 @@ -package scietifik.kmath.asm +package kscience.kmath.asm import kscience.kmath.asm.compile import kscience.kmath.ast.mstInField diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt similarity index 98% rename from kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmSpecialization.kt rename to kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt index 2b27fdc0f..8f8175acd 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt @@ -1,4 +1,4 @@ -package scietifik.kmath.asm +package kscience.kmath.asm import kscience.kmath.asm.compile import kscience.kmath.ast.mstInField diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt similarity index 95% rename from kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmVariables.kt rename to kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt index 3511be97c..7b89c74fa 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/asm/TestAsmVariables.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt @@ -1,4 +1,4 @@ -package scietifik.kmath.asm +package kscience.kmath.asm import kscience.kmath.ast.mstInRing import kscience.kmath.expressions.invoke diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt similarity index 96% rename from kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt rename to kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt index bb371bed0..1ca8aa5dd 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/AsmTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt @@ -1,4 +1,4 @@ -package scietifik.kmath.ast +package kscience.kmath.ast import kscience.kmath.asm.compile import kscience.kmath.asm.expression diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserPrecedenceTest.kt similarity index 97% rename from kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt rename to kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserPrecedenceTest.kt index 21ee47d13..1844a0991 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -1,4 +1,4 @@ -package scietifik.kmath.ast +package kscience.kmath.ast import kscience.kmath.ast.evaluate import kscience.kmath.ast.parseMath diff --git a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt similarity index 98% rename from kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt rename to kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt index 8a5d6ba48..2dc24597e 100644 --- a/kmath-ast/src/jvmTest/kotlin/scietifik/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt @@ -1,4 +1,4 @@ -package scietifik.kmath.ast +package kscience.kmath.ast import kscience.kmath.ast.evaluate import kscience.kmath.ast.mstInField From f0fbebd770f186a6a2031923cc17688abbb9e4a2 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 12 Oct 2020 20:26:03 +0700 Subject: [PATCH 087/199] Add adapters of scalar functions to MST and vice versa --- build.gradle.kts | 1 + kmath-ast-kotlingrad/build.gradle.kts | 8 +++ .../kmath/ast/kotlingrad/ScalarsAdapters.kt | 64 +++++++++++++++++++ kmath-prob/build.gradle.kts | 4 +- kmath-viktor/build.gradle.kts | 4 +- settings.gradle.kts | 6 +- 6 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 kmath-ast-kotlingrad/build.gradle.kts create mode 100644 kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt diff --git a/build.gradle.kts b/build.gradle.kts index 05e2d5979..0da2212a7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,6 +12,7 @@ allprojects { maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/hotkeytlt/maven") + maven("https://jitpack.io") } group = "kscience.kmath" diff --git a/kmath-ast-kotlingrad/build.gradle.kts b/kmath-ast-kotlingrad/build.gradle.kts new file mode 100644 index 000000000..0fe6e6b93 --- /dev/null +++ b/kmath-ast-kotlingrad/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + id("ru.mipt.npm.jvm") +} + +dependencies { + api("com.github.breandan:kotlingrad:0.3.2") + api(project(":kmath-ast")) +} diff --git a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt new file mode 100644 index 000000000..70c8c09f8 --- /dev/null +++ b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt @@ -0,0 +1,64 @@ +package kscience.kmath.ast.kotlingrad + +import edu.umontreal.kotlingrad.experimental.* +import kscience.kmath.ast.MST +import kscience.kmath.ast.MstExtendedField +import kscience.kmath.operations.* + +/** + * Maps [SFun] objects to [MST]. Some unsupported operations like [Derivative] are bound and converted then. + * + * @receiver a scalar function. + * @return the [MST]. + */ +public fun > SFun.mst(): MST = MstExtendedField { + when (this@mst) { + is SVar -> symbol(name) + is SConst -> number(doubleValue) + is Sum -> left.mst() + right.mst() + is Prod -> left.mst() * right.mst() + is Power -> power(left.mst(), (right() as SConst<*>).doubleValue) + is Negative -> -input.mst() + is Log -> ln(left.mst()) / ln(right.mst()) + is Sine -> sin(input.mst()) + is Cosine -> cos(input.mst()) + is Tangent -> tan(input.mst()) + is DProd -> this@mst().mst() + is SComposition -> this@mst().mst() + is VSumAll -> this@mst().mst() + is Derivative -> this@mst().mst() + } +} + +/** + * Maps [MST] objects to [SFun]. Unsupported operations throw [IllegalStateException]. + * + * @receiver an [MST]. + * @return the scalar function. + */ +public fun > MST.sfun(proto: X): SFun { + return when (this) { + is MST.Numeric -> SConst(value) + is MST.Symbolic -> SVar(proto, value) + + is MST.Unary -> when (operation) { + SpaceOperations.PLUS_OPERATION -> value.sfun(proto) + SpaceOperations.MINUS_OPERATION -> Negative(value.sfun(proto)) + TrigonometricOperations.SIN_OPERATION -> Sine(value.sfun(proto)) + TrigonometricOperations.COS_OPERATION -> Cosine(value.sfun(proto)) + TrigonometricOperations.TAN_OPERATION -> Tangent(value.sfun(proto)) + PowerOperations.SQRT_OPERATION -> Power(value.sfun(proto), SConst(0.5)) + ExponentialOperations.EXP_OPERATION -> Power(value.sfun(proto), E()) + ExponentialOperations.LN_OPERATION -> Log(value.sfun(proto)) + else -> error("Unary operation $operation not defined in $this") + } + + is MST.Binary -> when (operation) { + SpaceOperations.PLUS_OPERATION -> Sum(left.sfun(proto), right.sfun(proto)) + SpaceOperations.MINUS_OPERATION -> Sum(left.sfun(proto), Negative(right.sfun(proto))) + RingOperations.TIMES_OPERATION -> Prod(left.sfun(proto), right.sfun(proto)) + FieldOperations.DIV_OPERATION -> Prod(left.sfun(proto), Power(right.sfun(proto), Negative(One()))) + else -> error("Binary operation $operation not defined in $this") + } + } +} diff --git a/kmath-prob/build.gradle.kts b/kmath-prob/build.gradle.kts index 4c9663e5f..186aff944 100644 --- a/kmath-prob/build.gradle.kts +++ b/kmath-prob/build.gradle.kts @@ -1,4 +1,6 @@ -plugins { id("ru.mipt.npm.mpp") } +plugins { + id("ru.mipt.npm.mpp") +} kotlin.sourceSets { commonMain { diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 6fe8ad878..3e5c5912c 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -1,4 +1,6 @@ -plugins { id("ru.mipt.npm.jvm") } +plugins { + id("ru.mipt.npm.jvm") +} description = "Binding for https://github.com/JetBrains-Research/viktor" diff --git a/settings.gradle.kts b/settings.gradle.kts index 7ece3f25c..5fd072e1a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,7 +7,6 @@ pluginManagement { maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://dl.bintray.com/mipt-npm/dev") maven("https://dl.bintray.com/kotlin/kotlinx") - maven("https://dl.bintray.com/kotlin/kotlin-dev/") } val toolsVersion = "0.6.1-dev-1.4.20-M1" @@ -25,11 +24,11 @@ pluginManagement { } rootProject.name = "kmath" + include( ":kmath-memory", ":kmath-core", ":kmath-functions", -// ":kmath-io", ":kmath-coroutines", ":kmath-histograms", ":kmath-commons", @@ -40,5 +39,6 @@ include( ":kmath-geometry", ":kmath-ast", ":examples", - ":kmath-ejml" + ":kmath-ejml", + ":kmath-ast-kotlingrad" ) From 84f7535fdd7d59103e2c846eb0413bb2bb482cb7 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 12 Oct 2020 20:36:05 +0700 Subject: [PATCH 088/199] Add pow support --- .../main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt index 70c8c09f8..741a2534c 100644 --- a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt +++ b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt @@ -58,6 +58,7 @@ public fun > MST.sfun(proto: X): SFun { SpaceOperations.MINUS_OPERATION -> Sum(left.sfun(proto), Negative(right.sfun(proto))) RingOperations.TIMES_OPERATION -> Prod(left.sfun(proto), right.sfun(proto)) FieldOperations.DIV_OPERATION -> Prod(left.sfun(proto), Power(right.sfun(proto), Negative(One()))) + PowerOperations.POW_OPERATION -> Power(left.sfun(proto), SConst((right as MST.Numeric).value)) else -> error("Binary operation $operation not defined in $this") } } From 5de9d69237118889b74d4a5074b48db609db92ae Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 12 Oct 2020 21:06:15 +0700 Subject: [PATCH 089/199] Add more fine-grained converters from MST to SVar and SConst --- .../kmath/ast/kotlingrad/ScalarsAdapters.kt | 70 ++++++++++++------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt index 741a2534c..3a1191e6a 100644 --- a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt +++ b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt @@ -8,8 +8,8 @@ import kscience.kmath.operations.* /** * Maps [SFun] objects to [MST]. Some unsupported operations like [Derivative] are bound and converted then. * - * @receiver a scalar function. - * @return the [MST]. + * @receiver the scalar function. + * @return a node. */ public fun > SFun.mst(): MST = MstExtendedField { when (this@mst) { @@ -30,36 +30,52 @@ public fun > SFun.mst(): MST = MstExtendedField { } } +/** + * Maps [MST.Numeric] to [SConst] directly. + * + * @receiver the node. + * @return a new constant. + */ +public fun > MST.Numeric.sconst(): SConst = SConst(value) + +/** + * Maps [MST.Symbolic] to [SVar] directly. + * + * @receiver the node. + * @param proto the prototype instance. + * @return a new variable. + */ +public fun > MST.Symbolic.svar(proto: X): SVar = SVar(proto, value) + /** * Maps [MST] objects to [SFun]. Unsupported operations throw [IllegalStateException]. * - * @receiver an [MST]. - * @return the scalar function. + * @receiver the node. + * @param proto the prototype instance. + * @return a scalar function. */ -public fun > MST.sfun(proto: X): SFun { - return when (this) { - is MST.Numeric -> SConst(value) - is MST.Symbolic -> SVar(proto, value) +public fun > MST.sfun(proto: X): SFun = when (this) { + is MST.Numeric -> sconst() + is MST.Symbolic -> svar(proto) - is MST.Unary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> value.sfun(proto) - SpaceOperations.MINUS_OPERATION -> Negative(value.sfun(proto)) - TrigonometricOperations.SIN_OPERATION -> Sine(value.sfun(proto)) - TrigonometricOperations.COS_OPERATION -> Cosine(value.sfun(proto)) - TrigonometricOperations.TAN_OPERATION -> Tangent(value.sfun(proto)) - PowerOperations.SQRT_OPERATION -> Power(value.sfun(proto), SConst(0.5)) - ExponentialOperations.EXP_OPERATION -> Power(value.sfun(proto), E()) - ExponentialOperations.LN_OPERATION -> Log(value.sfun(proto)) - else -> error("Unary operation $operation not defined in $this") - } + is MST.Unary -> when (operation) { + SpaceOperations.PLUS_OPERATION -> value.sfun(proto) + SpaceOperations.MINUS_OPERATION -> Negative(value.sfun(proto)) + TrigonometricOperations.SIN_OPERATION -> Sine(value.sfun(proto)) + TrigonometricOperations.COS_OPERATION -> Cosine(value.sfun(proto)) + TrigonometricOperations.TAN_OPERATION -> Tangent(value.sfun(proto)) + PowerOperations.SQRT_OPERATION -> Power(value.sfun(proto), SConst(0.5)) + ExponentialOperations.EXP_OPERATION -> Power(value.sfun(proto), E()) + ExponentialOperations.LN_OPERATION -> Log(value.sfun(proto)) + else -> error("Unary operation $operation not defined in $this") + } - is MST.Binary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> Sum(left.sfun(proto), right.sfun(proto)) - SpaceOperations.MINUS_OPERATION -> Sum(left.sfun(proto), Negative(right.sfun(proto))) - RingOperations.TIMES_OPERATION -> Prod(left.sfun(proto), right.sfun(proto)) - FieldOperations.DIV_OPERATION -> Prod(left.sfun(proto), Power(right.sfun(proto), Negative(One()))) - PowerOperations.POW_OPERATION -> Power(left.sfun(proto), SConst((right as MST.Numeric).value)) - else -> error("Binary operation $operation not defined in $this") - } + is MST.Binary -> when (operation) { + SpaceOperations.PLUS_OPERATION -> Sum(left.sfun(proto), right.sfun(proto)) + SpaceOperations.MINUS_OPERATION -> Sum(left.sfun(proto), Negative(right.sfun(proto))) + RingOperations.TIMES_OPERATION -> Prod(left.sfun(proto), right.sfun(proto)) + FieldOperations.DIV_OPERATION -> Prod(left.sfun(proto), Power(right.sfun(proto), Negative(One()))) + PowerOperations.POW_OPERATION -> Power(left.sfun(proto), SConst((right as MST.Numeric).value)) + else -> error("Binary operation $operation not defined in $this") } } From 31c71e0fad0fa8a0c8837cca44e10ea12a9fdf21 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 12 Oct 2020 21:21:08 +0700 Subject: [PATCH 090/199] Add comments on mapping of MST-to-SFun converting --- .../kmath/ast/kotlingrad/ScalarsAdapters.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt index 3a1191e6a..cfd1f2702 100644 --- a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt +++ b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt @@ -3,10 +3,29 @@ package kscience.kmath.ast.kotlingrad import edu.umontreal.kotlingrad.experimental.* import kscience.kmath.ast.MST import kscience.kmath.ast.MstExtendedField +import kscience.kmath.ast.MstExtendedField.unaryMinus import kscience.kmath.operations.* /** * Maps [SFun] objects to [MST]. Some unsupported operations like [Derivative] are bound and converted then. + * [Power] operation is limited to constant right-hand side arguments. + * + * Detailed mapping is: + * + * - [SVar] -> [MstExtendedField.symbol]; + * - [SConst] -> [MstExtendedField.number]; + * - [Sum] -> [MstExtendedField.add]; + * - [Prod] -> [MstExtendedField.multiply]; + * - [Power] -> [MstExtendedField.power] (limited); + * - [Negative] -> [MstExtendedField.unaryMinus]; + * - [Log] -> [MstExtendedField.ln] (left) / [MstExtendedField.ln] (right); + * - [Sine] -> [MstExtendedField.sin]; + * - [Cosine] -> [MstExtendedField.cos]; + * - [Tangent] -> [MstExtendedField.tan]; + * - [DProd] is vector operation, and it is requested to be evaluated; + * - [SComposition] is also requested to be evaluated eagerly; + * - [VSumAll] is requested to be evaluated; + * - [Derivative] is requested to be evaluated. * * @receiver the scalar function. * @return a node. @@ -50,6 +69,13 @@ public fun > MST.Symbolic.svar(proto: X): SVar = SVar(proto, valu /** * Maps [MST] objects to [SFun]. Unsupported operations throw [IllegalStateException]. * + * Detailed mapping is: + * + * - [MST.Numeric] -> [SConst]; + * - [MST.Symbolic] -> [SVar]; + * - [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. From 57bdee49368208c67eea5259b39223f37fcae386 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 12 Oct 2020 22:34:05 +0700 Subject: [PATCH 091/199] Add test, update MstAlgebra a bit to return concrete types --- .../kmath/ast/kotlingrad/ScalarsAdapters.kt | 2 +- .../kmath/ast/kotlingrad/AdaptingTests.kt | 66 ++++++++++ .../kotlin/kscience/kmath/ast/MstAlgebra.kt | 113 +++++++++--------- 3 files changed, 125 insertions(+), 56 deletions(-) create mode 100644 kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt diff --git a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt index cfd1f2702..16c96646a 100644 --- a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt +++ b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt @@ -36,7 +36,7 @@ public fun > SFun.mst(): MST = MstExtendedField { is SConst -> number(doubleValue) is Sum -> left.mst() + right.mst() is Prod -> left.mst() * right.mst() - is Power -> power(left.mst(), (right() as SConst<*>).doubleValue) + is Power -> power(left.mst(), (right as SConst<*>).doubleValue) is Negative -> -input.mst() is Log -> ln(left.mst()) / ln(right.mst()) is Sine -> sin(input.mst()) diff --git a/kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt b/kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt new file mode 100644 index 000000000..94d25e411 --- /dev/null +++ b/kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt @@ -0,0 +1,66 @@ +package kscience.kmath.ast.kotlingrad + +import edu.umontreal.kotlingrad.experimental.* +import kscience.kmath.asm.compile +import kscience.kmath.ast.MstAlgebra +import kscience.kmath.ast.MstExpression +import kscience.kmath.ast.parseMath +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.RealField +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import kotlin.test.fail + +internal class AdaptingTests { + private val proto: DReal = DoublePrecision.prototype + + @Test + fun symbol() { + val c1 = MstAlgebra.symbol("x") + assertTrue(c1.svar(proto).name == "x") + val c2 = "kitten".parseMath().sfun(proto) + if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() + } + + @Test + fun number() { + val c1 = MstAlgebra.number(12354324) + assertTrue(c1.sconst().doubleValue == 12354324.0) + val c2 = "0.234".parseMath().sfun(proto) + if (c2 is SConst) assertTrue(c2.doubleValue == 0.234) else fail() + val c3 = "1e-3".parseMath().sfun(proto) + if (c3 is SConst) assertEquals(0.001, c3.value) else fail() + } + + @Test + fun simpleFunctionShape() { + val linear = "2*x+16".parseMath().sfun(proto) + if (linear !is Sum) fail() + if (linear.left !is Prod) fail() + if (linear.right !is SConst) fail() + } + + @Test + fun simpleFunctionDerivative() { + val x = MstAlgebra.symbol("x").svar(proto) + val quadratic = "x^2-4*x-44".parseMath().sfun(proto) + val actualDerivative = MstExpression(RealField, quadratic.d(x).mst()).compile() + val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() + assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0)) + } + + @Test + fun moreComplexDerivative() { + val x = MstAlgebra.symbol("x").svar(proto) + val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().sfun(proto) + val actualDerivative = MstExpression(RealField, composition.d(x).mst()).compile() + + val expectedDerivative = MstExpression( + RealField, + "-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))".parseMath() + ).compile() + + assertEquals(actualDerivative("x" to 0.1), expectedDerivative("x" to 0.1)) + } +} diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt index 64a820b20..6ee6ab9af 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt @@ -6,14 +6,14 @@ import kscience.kmath.operations.* * [Algebra] over [MST] nodes. */ public object MstAlgebra : NumericAlgebra { - override fun number(value: Number): MST = MST.Numeric(value) + override fun number(value: Number): MST.Numeric = MST.Numeric(value) - override fun symbol(value: String): MST = MST.Symbolic(value) + override fun symbol(value: String): MST.Symbolic = MST.Symbolic(value) - override fun unaryOperation(operation: String, arg: MST): MST = + override fun unaryOperation(operation: String, arg: MST): MST.Unary = MST.Unary(operation, arg) - override fun binaryOperation(operation: String, left: MST, right: MST): MST = + override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary = MST.Binary(operation, left, right) } @@ -21,97 +21,100 @@ public object MstAlgebra : NumericAlgebra { * [Space] over [MST] nodes. */ public object MstSpace : Space, NumericAlgebra { - override val zero: MST = number(0.0) + override val zero: MST.Numeric by lazy { number(0.0) } - override fun number(value: Number): MST = MstAlgebra.number(value) - override fun symbol(value: String): MST = MstAlgebra.symbol(value) - override fun add(a: MST, b: MST): MST = binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) - override fun multiply(a: MST, k: Number): MST = binaryOperation(RingOperations.TIMES_OPERATION, a, number(k)) + override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) + override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value) + override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) + override fun multiply(a: MST, k: Number): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION, a, number(k)) - override fun binaryOperation(operation: String, left: MST, right: MST): MST = + override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary = MstAlgebra.binaryOperation(operation, left, right) - override fun unaryOperation(operation: String, arg: MST): MST = MstAlgebra.unaryOperation(operation, arg) + override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstAlgebra.unaryOperation(operation, arg) } /** * [Ring] over [MST] nodes. */ public object MstRing : Ring, NumericAlgebra { - override val zero: MST + override val zero: MST.Numeric get() = MstSpace.zero - override val one: MST = number(1.0) - override fun number(value: Number): MST = MstSpace.number(value) - override fun symbol(value: String): MST = MstSpace.symbol(value) - override fun add(a: MST, b: MST): MST = MstSpace.add(a, b) + override val one: MST.Numeric by lazy { number(1.0) } - override fun multiply(a: MST, k: Number): MST = MstSpace.multiply(a, k) + override fun number(value: Number): MST.Numeric = MstSpace.number(value) + override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value) + override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b) + override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k) + override fun multiply(a: MST, b: MST): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION, a, b) - override fun multiply(a: MST, b: MST): MST = binaryOperation(RingOperations.TIMES_OPERATION, a, b) - - override fun binaryOperation(operation: String, left: MST, right: MST): MST = + override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary = MstSpace.binaryOperation(operation, left, right) - override fun unaryOperation(operation: String, arg: MST): MST = MstAlgebra.unaryOperation(operation, arg) + override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstSpace.unaryOperation(operation, arg) } /** * [Field] over [MST] nodes. */ public object MstField : Field { - public override val zero: MST + public override val zero: MST.Numeric get() = MstRing.zero - public override val one: MST + public override val one: MST.Numeric get() = MstRing.one - public override fun symbol(value: String): MST = MstRing.symbol(value) - public override fun number(value: Number): MST = MstRing.number(value) - public override fun add(a: MST, b: MST): MST = MstRing.add(a, b) - public override fun multiply(a: MST, k: Number): MST = MstRing.multiply(a, k) - public override fun multiply(a: MST, b: MST): MST = MstRing.multiply(a, b) - public override fun divide(a: MST, b: MST): MST = binaryOperation(FieldOperations.DIV_OPERATION, a, b) + public override fun symbol(value: String): MST.Symbolic = MstRing.symbol(value) + public override fun number(value: Number): MST.Numeric = MstRing.number(value) + public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) + public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k) + public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) + public override fun divide(a: MST, b: MST): MST.Binary = binaryOperation(FieldOperations.DIV_OPERATION, a, b) - public override fun binaryOperation(operation: String, left: MST, right: MST): MST = + public override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary = MstRing.binaryOperation(operation, left, right) - override fun unaryOperation(operation: String, arg: MST): MST = MstRing.unaryOperation(operation, arg) + override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstRing.unaryOperation(operation, arg) } /** * [ExtendedField] over [MST] nodes. */ public object MstExtendedField : ExtendedField { - override val zero: MST + override val zero: MST.Numeric get() = MstField.zero - override val one: MST + override val one: MST.Numeric get() = MstField.one - override fun symbol(value: String): MST = MstField.symbol(value) - override fun sin(arg: MST): MST = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) - override fun cos(arg: MST): MST = unaryOperation(TrigonometricOperations.COS_OPERATION, arg) - override fun tan(arg: MST): MST = unaryOperation(TrigonometricOperations.TAN_OPERATION, arg) - override fun asin(arg: MST): MST = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg) - override fun acos(arg: MST): MST = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg) - override fun atan(arg: MST): MST = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg) - override fun sinh(arg: MST): MST = unaryOperation(HyperbolicOperations.SINH_OPERATION, arg) - override fun cosh(arg: MST): MST = unaryOperation(HyperbolicOperations.COSH_OPERATION, arg) - override fun tanh(arg: MST): MST = unaryOperation(HyperbolicOperations.TANH_OPERATION, arg) - override fun asinh(arg: MST): MST = unaryOperation(HyperbolicOperations.ASINH_OPERATION, arg) - override fun acosh(arg: MST): MST = unaryOperation(HyperbolicOperations.ACOSH_OPERATION, arg) - override fun atanh(arg: MST): MST = unaryOperation(HyperbolicOperations.ATANH_OPERATION, arg) - override fun add(a: MST, b: MST): MST = MstField.add(a, b) - override fun multiply(a: MST, k: Number): MST = MstField.multiply(a, k) - override fun multiply(a: MST, b: MST): MST = MstField.multiply(a, b) - override fun divide(a: MST, b: MST): MST = MstField.divide(a, b) - override fun power(arg: MST, pow: Number): MST = binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow)) - override fun exp(arg: MST): MST = unaryOperation(ExponentialOperations.EXP_OPERATION, arg) - override fun ln(arg: MST): MST = unaryOperation(ExponentialOperations.LN_OPERATION, arg) + override fun symbol(value: String): MST.Symbolic = MstField.symbol(value) + override fun number(value: Number): MST.Numeric = MstField.number(value) + override fun sin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) + override fun cos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.COS_OPERATION, arg) + override fun tan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.TAN_OPERATION, arg) + override fun asin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg) + override fun acos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg) + override fun atan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg) + override fun sinh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.SINH_OPERATION, arg) + override fun cosh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.COSH_OPERATION, arg) + override fun tanh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.TANH_OPERATION, arg) + override fun asinh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ASINH_OPERATION, arg) + override fun acosh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ACOSH_OPERATION, arg) + override fun atanh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ATANH_OPERATION, arg) + override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) + override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k) + override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) + override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b) - override fun binaryOperation(operation: String, left: MST, right: MST): MST = + override fun power(arg: MST, pow: Number): MST.Binary = + binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow)) + + override fun exp(arg: MST): MST.Unary = unaryOperation(ExponentialOperations.EXP_OPERATION, arg) + override fun ln(arg: MST): MST.Unary = unaryOperation(ExponentialOperations.LN_OPERATION, arg) + + override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary = MstField.binaryOperation(operation, left, right) - override fun unaryOperation(operation: String, arg: MST): MST = MstField.unaryOperation(operation, arg) + override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstField.unaryOperation(operation, arg) } From 54069fd37ebc77dc8d40a2d46c3bc290583f23cc Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 12 Oct 2020 22:42:34 +0700 Subject: [PATCH 092/199] Add example of new AST API --- examples/build.gradle.kts | 3 +- .../ast/ExpressionsInterpretersBenchmark.kt | 148 ++++++++++-------- .../kscience/kmath/ast/KotlingradSupport.kt | 22 +++ 3 files changed, 103 insertions(+), 70 deletions(-) create mode 100644 examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 900da966b..968b372c3 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -19,7 +19,8 @@ repositories { sourceSets.register("benchmarks") dependencies { -// implementation(project(":kmath-ast")) + implementation(project(":kmath-ast")) + implementation(project(":kmath-ast-kotlingrad")) implementation(project(":kmath-core")) implementation(project(":kmath-coroutines")) implementation(project(":kmath-commons")) diff --git a/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt index f0a32e5bd..b25a61e96 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt @@ -1,70 +1,80 @@ package kscience.kmath.ast -// -//import kscience.kmath.asm.compile -//import kscience.kmath.expressions.Expression -//import kscience.kmath.expressions.expressionInField -//import kscience.kmath.expressions.invoke -//import kscience.kmath.operations.Field -//import kscience.kmath.operations.RealField -//import kotlin.random.Random -//import kotlin.system.measureTimeMillis -// -//class ExpressionsInterpretersBenchmark { -// private val algebra: Field = RealField -// fun functionalExpression() { -// val expr = algebra.expressionInField { -// variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0) -// } -// -// invokeAndSum(expr) -// } -// -// fun mstExpression() { -// val expr = algebra.mstInField { -// symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) -// } -// -// invokeAndSum(expr) -// } -// -// fun asmExpression() { -// val expr = algebra.mstInField { -// symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) -// }.compile() -// -// invokeAndSum(expr) -// } -// -// private fun invokeAndSum(expr: Expression) { -// val random = Random(0) -// var sum = 0.0 -// -// repeat(1000000) { -// sum += expr("x" to random.nextDouble()) -// } -// -// println(sum) -// } -//} -// -//fun main() { -// val benchmark = ExpressionsInterpretersBenchmark() -// -// val fe = measureTimeMillis { -// benchmark.functionalExpression() -// } -// -// println("fe=$fe") -// -// val mst = measureTimeMillis { -// benchmark.mstExpression() -// } -// -// println("mst=$mst") -// -// val asm = measureTimeMillis { -// benchmark.asmExpression() -// } -// -// println("asm=$asm") -//} + +import kscience.kmath.asm.compile +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.expressionInField +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.Field +import kscience.kmath.operations.RealField +import kotlin.random.Random +import kotlin.system.measureTimeMillis + +internal class ExpressionsInterpretersBenchmark { + private val algebra: Field = RealField + fun functionalExpression() { + val expr = algebra.expressionInField { + variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0) + } + + invokeAndSum(expr) + } + + fun mstExpression() { + val expr = algebra.mstInField { + symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) + } + + invokeAndSum(expr) + } + + fun asmExpression() { + val expr = algebra.mstInField { + symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) + }.compile() + + invokeAndSum(expr) + } + + private fun invokeAndSum(expr: Expression) { + val random = Random(0) + var sum = 0.0 + + repeat(1000000) { + sum += expr("x" to random.nextDouble()) + } + + println(sum) + } +} + +/** + * This benchmark compares basically evaluation of simple function with MstExpression interpreter, ASM backend and + * core FunctionalExpressions API. + * + * The expected rating is: + * + * 1. ASM. + * 2. MST. + * 3. FE. + */ +fun main() { + val benchmark = ExpressionsInterpretersBenchmark() + + val fe = measureTimeMillis { + benchmark.functionalExpression() + } + + println("fe=$fe") + + val mst = measureTimeMillis { + benchmark.mstExpression() + } + + println("mst=$mst") + + val asm = measureTimeMillis { + benchmark.asmExpression() + } + + println("asm=$asm") +} diff --git a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt new file mode 100644 index 000000000..e63b0c9c0 --- /dev/null +++ b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt @@ -0,0 +1,22 @@ +package kscience.kmath.ast + +import edu.umontreal.kotlingrad.experimental.DoublePrecision +import kscience.kmath.asm.compile +import kscience.kmath.ast.kotlingrad.mst +import kscience.kmath.ast.kotlingrad.sfun +import kscience.kmath.ast.kotlingrad.svar +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.RealField + +/** + * In this example, x^2-4*x-44 function is differentiated with Kotlin∇, and the autodiff result is compared with + * valid derivative. + */ +fun main() { + val proto = DoublePrecision.prototype + val x by MstAlgebra.symbol("x").svar(proto) + val quadratic = "x^2-4*x-44".parseMath().sfun(proto) + val actualDerivative = MstExpression(RealField, quadratic.d(x).mst()).compile() + val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() + assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0)) +} From 4bf430b2c07a351d116e383a0d7806802af026c2 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 12 Oct 2020 23:17:54 +0700 Subject: [PATCH 093/199] Rename converter functions, add symbol delegate provider for MstAlgebra --- .../kscience/kmath/ast/KotlingradSupport.kt | 8 ++--- .../kmath/ast/kotlingrad/ScalarsAdapters.kt | 36 +++++++++---------- .../kmath/ast/kotlingrad/AdaptingTests.kt | 20 +++++------ .../kotlin/kscience/kmath/ast/extensions.kt | 22 ++++++++++++ 4 files changed, 54 insertions(+), 32 deletions(-) create mode 100644 kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt diff --git a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt index e63b0c9c0..c2e8456da 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt @@ -3,8 +3,8 @@ package kscience.kmath.ast import edu.umontreal.kotlingrad.experimental.DoublePrecision import kscience.kmath.asm.compile import kscience.kmath.ast.kotlingrad.mst -import kscience.kmath.ast.kotlingrad.sfun -import kscience.kmath.ast.kotlingrad.svar +import kscience.kmath.ast.kotlingrad.sFun +import kscience.kmath.ast.kotlingrad.sVar import kscience.kmath.expressions.invoke import kscience.kmath.operations.RealField @@ -14,8 +14,8 @@ import kscience.kmath.operations.RealField */ fun main() { val proto = DoublePrecision.prototype - val x by MstAlgebra.symbol("x").svar(proto) - val quadratic = "x^2-4*x-44".parseMath().sfun(proto) + val x by MstAlgebra.symbol("x").sVar(proto) + val quadratic = "x^2-4*x-44".parseMath().sFun(proto) val actualDerivative = MstExpression(RealField, quadratic.d(x).mst()).compile() val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0)) diff --git a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt index 16c96646a..3e7cd0439 100644 --- a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt +++ b/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt @@ -55,7 +55,7 @@ public fun > SFun.mst(): MST = MstExtendedField { * @receiver the node. * @return a new constant. */ -public fun > MST.Numeric.sconst(): SConst = SConst(value) +public fun > MST.Numeric.sConst(): SConst = SConst(value) /** * Maps [MST.Symbolic] to [SVar] directly. @@ -64,7 +64,7 @@ public fun > MST.Numeric.sconst(): SConst = SConst(value) * @param proto the prototype instance. * @return a new variable. */ -public fun > MST.Symbolic.svar(proto: X): SVar = SVar(proto, value) +public fun > MST.Symbolic.sVar(proto: X): SVar = SVar(proto, value) /** * Maps [MST] objects to [SFun]. Unsupported operations throw [IllegalStateException]. @@ -80,28 +80,28 @@ public fun > MST.Symbolic.svar(proto: X): SVar = SVar(proto, valu * @param proto the prototype instance. * @return a scalar function. */ -public fun > MST.sfun(proto: X): SFun = when (this) { - is MST.Numeric -> sconst() - is MST.Symbolic -> svar(proto) +public fun > MST.sFun(proto: X): SFun = when (this) { + is MST.Numeric -> sConst() + is MST.Symbolic -> sVar(proto) is MST.Unary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> value.sfun(proto) - SpaceOperations.MINUS_OPERATION -> Negative(value.sfun(proto)) - TrigonometricOperations.SIN_OPERATION -> Sine(value.sfun(proto)) - TrigonometricOperations.COS_OPERATION -> Cosine(value.sfun(proto)) - TrigonometricOperations.TAN_OPERATION -> Tangent(value.sfun(proto)) - PowerOperations.SQRT_OPERATION -> Power(value.sfun(proto), SConst(0.5)) - ExponentialOperations.EXP_OPERATION -> Power(value.sfun(proto), E()) - ExponentialOperations.LN_OPERATION -> Log(value.sfun(proto)) + SpaceOperations.PLUS_OPERATION -> value.sFun(proto) + SpaceOperations.MINUS_OPERATION -> Negative(value.sFun(proto)) + TrigonometricOperations.SIN_OPERATION -> Sine(value.sFun(proto)) + TrigonometricOperations.COS_OPERATION -> Cosine(value.sFun(proto)) + TrigonometricOperations.TAN_OPERATION -> Tangent(value.sFun(proto)) + PowerOperations.SQRT_OPERATION -> Power(value.sFun(proto), SConst(0.5)) + ExponentialOperations.EXP_OPERATION -> Power(value.sFun(proto), E()) + ExponentialOperations.LN_OPERATION -> Log(value.sFun(proto)) else -> error("Unary operation $operation not defined in $this") } is MST.Binary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> Sum(left.sfun(proto), right.sfun(proto)) - SpaceOperations.MINUS_OPERATION -> Sum(left.sfun(proto), Negative(right.sfun(proto))) - RingOperations.TIMES_OPERATION -> Prod(left.sfun(proto), right.sfun(proto)) - FieldOperations.DIV_OPERATION -> Prod(left.sfun(proto), Power(right.sfun(proto), Negative(One()))) - PowerOperations.POW_OPERATION -> Power(left.sfun(proto), SConst((right as MST.Numeric).value)) + SpaceOperations.PLUS_OPERATION -> Sum(left.sFun(proto), right.sFun(proto)) + SpaceOperations.MINUS_OPERATION -> Sum(left.sFun(proto), Negative(right.sFun(proto))) + RingOperations.TIMES_OPERATION -> Prod(left.sFun(proto), right.sFun(proto)) + FieldOperations.DIV_OPERATION -> Prod(left.sFun(proto), Power(right.sFun(proto), Negative(One()))) + PowerOperations.POW_OPERATION -> Power(left.sFun(proto), SConst((right as MST.Numeric).value)) else -> error("Binary operation $operation not defined in $this") } } diff --git a/kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt b/kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt index 94d25e411..c3c4602ad 100644 --- a/kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt +++ b/kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt @@ -18,24 +18,24 @@ internal class AdaptingTests { @Test fun symbol() { val c1 = MstAlgebra.symbol("x") - assertTrue(c1.svar(proto).name == "x") - val c2 = "kitten".parseMath().sfun(proto) + assertTrue(c1.sVar(proto).name == "x") + val c2 = "kitten".parseMath().sFun(proto) if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() } @Test fun number() { val c1 = MstAlgebra.number(12354324) - assertTrue(c1.sconst().doubleValue == 12354324.0) - val c2 = "0.234".parseMath().sfun(proto) + assertTrue(c1.sConst().doubleValue == 12354324.0) + val c2 = "0.234".parseMath().sFun(proto) if (c2 is SConst) assertTrue(c2.doubleValue == 0.234) else fail() - val c3 = "1e-3".parseMath().sfun(proto) + val c3 = "1e-3".parseMath().sFun(proto) if (c3 is SConst) assertEquals(0.001, c3.value) else fail() } @Test fun simpleFunctionShape() { - val linear = "2*x+16".parseMath().sfun(proto) + val linear = "2*x+16".parseMath().sFun(proto) if (linear !is Sum) fail() if (linear.left !is Prod) fail() if (linear.right !is SConst) fail() @@ -43,8 +43,8 @@ internal class AdaptingTests { @Test fun simpleFunctionDerivative() { - val x = MstAlgebra.symbol("x").svar(proto) - val quadratic = "x^2-4*x-44".parseMath().sfun(proto) + val x = MstAlgebra.symbol("x").sVar(proto) + val quadratic = "x^2-4*x-44".parseMath().sFun(proto) val actualDerivative = MstExpression(RealField, quadratic.d(x).mst()).compile() val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0)) @@ -52,8 +52,8 @@ internal class AdaptingTests { @Test fun moreComplexDerivative() { - val x = MstAlgebra.symbol("x").svar(proto) - val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().sfun(proto) + val x = MstAlgebra.symbol("x").sVar(proto) + val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().sFun(proto) val actualDerivative = MstExpression(RealField, composition.d(x).mst()).compile() val expectedDerivative = MstExpression( diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt new file mode 100644 index 000000000..cba4bbb13 --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt @@ -0,0 +1,22 @@ +package kscience.kmath.ast + +import kscience.kmath.operations.Algebra +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty + +/** + * Stores `provideDelegate` method returning property of [MST.Symbolic]. + */ +public object MstSymbolDelegateProvider { + /** + * Returns [ReadOnlyProperty] of [MST.Symbolic] with its value equal to the name of the property. + */ + public operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty = + ReadOnlyProperty { _, property -> MST.Symbolic(property.name) } +} + +/** + * Returns [MstSymbolDelegateProvider]. + */ +public val Algebra.symbol: MstSymbolDelegateProvider + get() = MstSymbolDelegateProvider From 06c3ce5aaf8020b95a18eaae95381fe80186bee7 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 12 Oct 2020 23:42:13 +0700 Subject: [PATCH 094/199] Simplify extensions.kt --- .../kotlin/kscience/kmath/ast/extensions.kt | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt index cba4bbb13..b790a3a88 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt @@ -1,22 +1,12 @@ package kscience.kmath.ast import kscience.kmath.operations.Algebra +import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty /** - * Stores `provideDelegate` method returning property of [MST.Symbolic]. + * Returns [PropertyDelegateProvider] providing [ReadOnlyProperty] of [MST.Symbolic] with its value equal to the name + * of the property. */ -public object MstSymbolDelegateProvider { - /** - * Returns [ReadOnlyProperty] of [MST.Symbolic] with its value equal to the name of the property. - */ - public operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty = - ReadOnlyProperty { _, property -> MST.Symbolic(property.name) } -} - -/** - * Returns [MstSymbolDelegateProvider]. - */ -public val Algebra.symbol: MstSymbolDelegateProvider - get() = MstSymbolDelegateProvider +public val Algebra.symbol: PropertyDelegateProvider, ReadOnlyProperty, MST.Symbolic>> + get() = PropertyDelegateProvider { _, _ -> ReadOnlyProperty { _, p -> MST.Symbolic(p.name) } } From 381137724dc6e6fbb3795b80a988dd64d2578d11 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 13 Oct 2020 19:47:07 +0700 Subject: [PATCH 095/199] Rename KG module --- examples/build.gradle.kts | 2 +- .../kscience/kmath/ast/KotlingradSupport.kt | 12 ++-- .../build.gradle.kts | 0 .../kmath}/kotlingrad/ScalarsAdapters.kt | 66 +++++++++---------- .../kmath}/kotlingrad/AdaptingTests.kt | 26 ++++---- settings.gradle.kts | 2 +- 6 files changed, 54 insertions(+), 54 deletions(-) rename {kmath-ast-kotlingrad => kmath-kotlingrad}/build.gradle.kts (100%) rename {kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast => kmath-kotlingrad/src/main/kotlin/kscience/kmath}/kotlingrad/ScalarsAdapters.kt (51%) rename {kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast => kmath-kotlingrad/src/test/kotlin/kscience/kmath}/kotlingrad/AdaptingTests.kt (74%) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 968b372c3..46b677304 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -20,7 +20,7 @@ sourceSets.register("benchmarks") dependencies { implementation(project(":kmath-ast")) - implementation(project(":kmath-ast-kotlingrad")) + implementation(project(":kmath-kotlingrad")) implementation(project(":kmath-core")) implementation(project(":kmath-coroutines")) implementation(project(":kmath-commons")) diff --git a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt index c2e8456da..366a2b4fd 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt @@ -2,9 +2,9 @@ package kscience.kmath.ast import edu.umontreal.kotlingrad.experimental.DoublePrecision import kscience.kmath.asm.compile -import kscience.kmath.ast.kotlingrad.mst -import kscience.kmath.ast.kotlingrad.sFun -import kscience.kmath.ast.kotlingrad.sVar +import kscience.kmath.kotlingrad.toMst +import kscience.kmath.kotlingrad.tSFun +import kscience.kmath.kotlingrad.toSVar import kscience.kmath.expressions.invoke import kscience.kmath.operations.RealField @@ -14,9 +14,9 @@ import kscience.kmath.operations.RealField */ fun main() { val proto = DoublePrecision.prototype - val x by MstAlgebra.symbol("x").sVar(proto) - val quadratic = "x^2-4*x-44".parseMath().sFun(proto) - val actualDerivative = MstExpression(RealField, quadratic.d(x).mst()).compile() + val x by MstAlgebra.symbol("x").toSVar(proto) + val quadratic = "x^2-4*x-44".parseMath().tSFun(proto) + val actualDerivative = MstExpression(RealField, quadratic.d(x).toMst()).compile() val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0)) } diff --git a/kmath-ast-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts similarity index 100% rename from kmath-ast-kotlingrad/build.gradle.kts rename to kmath-kotlingrad/build.gradle.kts diff --git a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt similarity index 51% rename from kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt rename to kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt index 3e7cd0439..f6f0c7a76 100644 --- a/kmath-ast-kotlingrad/src/main/kotlin/kscience/kmath/ast/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -1,4 +1,4 @@ -package kscience.kmath.ast.kotlingrad +package kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.experimental.* import kscience.kmath.ast.MST @@ -30,22 +30,22 @@ import kscience.kmath.operations.* * @receiver the scalar function. * @return a node. */ -public fun > SFun.mst(): MST = MstExtendedField { - when (this@mst) { +public fun > SFun.toMst(): MST = MstExtendedField { + when (this@toMst) { is SVar -> symbol(name) is SConst -> number(doubleValue) - is Sum -> left.mst() + right.mst() - is Prod -> left.mst() * right.mst() - is Power -> power(left.mst(), (right as SConst<*>).doubleValue) - is Negative -> -input.mst() - is Log -> ln(left.mst()) / ln(right.mst()) - is Sine -> sin(input.mst()) - is Cosine -> cos(input.mst()) - is Tangent -> tan(input.mst()) - is DProd -> this@mst().mst() - is SComposition -> this@mst().mst() - is VSumAll -> this@mst().mst() - is Derivative -> this@mst().mst() + is Sum -> left.toMst() + right.toMst() + is Prod -> left.toMst() * right.toMst() + is Power -> power(left.toMst(), (right as SConst<*>).doubleValue) + is Negative -> -input.toMst() + is Log -> ln(left.toMst()) / ln(right.toMst()) + is Sine -> sin(input.toMst()) + is Cosine -> cos(input.toMst()) + is Tangent -> tan(input.toMst()) + is DProd -> this@toMst().toMst() + is SComposition -> this@toMst().toMst() + is VSumAll -> this@toMst().toMst() + is Derivative -> this@toMst().toMst() } } @@ -55,7 +55,7 @@ public fun > SFun.mst(): MST = MstExtendedField { * @receiver the node. * @return a new constant. */ -public fun > MST.Numeric.sConst(): SConst = SConst(value) +public fun > MST.Numeric.toSConst(): SConst = SConst(value) /** * Maps [MST.Symbolic] to [SVar] directly. @@ -64,7 +64,7 @@ public fun > MST.Numeric.sConst(): SConst = SConst(value) * @param proto the prototype instance. * @return a new variable. */ -public fun > MST.Symbolic.sVar(proto: X): SVar = SVar(proto, value) +public fun > MST.Symbolic.toSVar(proto: X): SVar = SVar(proto, value) /** * Maps [MST] objects to [SFun]. Unsupported operations throw [IllegalStateException]. @@ -80,28 +80,28 @@ public fun > MST.Symbolic.sVar(proto: X): SVar = SVar(proto, valu * @param proto the prototype instance. * @return a scalar function. */ -public fun > MST.sFun(proto: X): SFun = when (this) { - is MST.Numeric -> sConst() - is MST.Symbolic -> sVar(proto) +public fun > MST.tSFun(proto: X): SFun = when (this) { + is MST.Numeric -> toSConst() + is MST.Symbolic -> toSVar(proto) is MST.Unary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> value.sFun(proto) - SpaceOperations.MINUS_OPERATION -> Negative(value.sFun(proto)) - TrigonometricOperations.SIN_OPERATION -> Sine(value.sFun(proto)) - TrigonometricOperations.COS_OPERATION -> Cosine(value.sFun(proto)) - TrigonometricOperations.TAN_OPERATION -> Tangent(value.sFun(proto)) - PowerOperations.SQRT_OPERATION -> Power(value.sFun(proto), SConst(0.5)) - ExponentialOperations.EXP_OPERATION -> Power(value.sFun(proto), E()) - ExponentialOperations.LN_OPERATION -> Log(value.sFun(proto)) + SpaceOperations.PLUS_OPERATION -> value.tSFun(proto) + SpaceOperations.MINUS_OPERATION -> Negative(value.tSFun(proto)) + TrigonometricOperations.SIN_OPERATION -> Sine(value.tSFun(proto)) + TrigonometricOperations.COS_OPERATION -> Cosine(value.tSFun(proto)) + TrigonometricOperations.TAN_OPERATION -> Tangent(value.tSFun(proto)) + PowerOperations.SQRT_OPERATION -> Power(value.tSFun(proto), SConst(0.5)) + ExponentialOperations.EXP_OPERATION -> Power(value.tSFun(proto), E()) + ExponentialOperations.LN_OPERATION -> Log(value.tSFun(proto)) else -> error("Unary operation $operation not defined in $this") } is MST.Binary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> Sum(left.sFun(proto), right.sFun(proto)) - SpaceOperations.MINUS_OPERATION -> Sum(left.sFun(proto), Negative(right.sFun(proto))) - RingOperations.TIMES_OPERATION -> Prod(left.sFun(proto), right.sFun(proto)) - FieldOperations.DIV_OPERATION -> Prod(left.sFun(proto), Power(right.sFun(proto), Negative(One()))) - PowerOperations.POW_OPERATION -> Power(left.sFun(proto), SConst((right as MST.Numeric).value)) + SpaceOperations.PLUS_OPERATION -> Sum(left.tSFun(proto), right.tSFun(proto)) + SpaceOperations.MINUS_OPERATION -> Sum(left.tSFun(proto), Negative(right.tSFun(proto))) + RingOperations.TIMES_OPERATION -> Prod(left.tSFun(proto), right.tSFun(proto)) + FieldOperations.DIV_OPERATION -> Prod(left.tSFun(proto), Power(right.tSFun(proto), Negative(One()))) + PowerOperations.POW_OPERATION -> Power(left.tSFun(proto), SConst((right as MST.Numeric).value)) else -> error("Binary operation $operation not defined in $this") } } diff --git a/kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt similarity index 74% rename from kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt rename to kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt index c3c4602ad..25bdbf4be 100644 --- a/kmath-ast-kotlingrad/src/test/kotlin/kscience/kmath/ast/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -1,4 +1,4 @@ -package kscience.kmath.ast.kotlingrad +package kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.experimental.* import kscience.kmath.asm.compile @@ -18,24 +18,24 @@ internal class AdaptingTests { @Test fun symbol() { val c1 = MstAlgebra.symbol("x") - assertTrue(c1.sVar(proto).name == "x") - val c2 = "kitten".parseMath().sFun(proto) + assertTrue(c1.toSVar(proto).name == "x") + val c2 = "kitten".parseMath().tSFun(proto) if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() } @Test fun number() { val c1 = MstAlgebra.number(12354324) - assertTrue(c1.sConst().doubleValue == 12354324.0) - val c2 = "0.234".parseMath().sFun(proto) + assertTrue(c1.toSConst().doubleValue == 12354324.0) + val c2 = "0.234".parseMath().tSFun(proto) if (c2 is SConst) assertTrue(c2.doubleValue == 0.234) else fail() - val c3 = "1e-3".parseMath().sFun(proto) + val c3 = "1e-3".parseMath().tSFun(proto) if (c3 is SConst) assertEquals(0.001, c3.value) else fail() } @Test fun simpleFunctionShape() { - val linear = "2*x+16".parseMath().sFun(proto) + val linear = "2*x+16".parseMath().tSFun(proto) if (linear !is Sum) fail() if (linear.left !is Prod) fail() if (linear.right !is SConst) fail() @@ -43,18 +43,18 @@ internal class AdaptingTests { @Test fun simpleFunctionDerivative() { - val x = MstAlgebra.symbol("x").sVar(proto) - val quadratic = "x^2-4*x-44".parseMath().sFun(proto) - val actualDerivative = MstExpression(RealField, quadratic.d(x).mst()).compile() + val x = MstAlgebra.symbol("x").toSVar(proto) + val quadratic = "x^2-4*x-44".parseMath().tSFun(proto) + val actualDerivative = MstExpression(RealField, quadratic.d(x).toMst()).compile() val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0)) } @Test fun moreComplexDerivative() { - val x = MstAlgebra.symbol("x").sVar(proto) - val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().sFun(proto) - val actualDerivative = MstExpression(RealField, composition.d(x).mst()).compile() + val x = MstAlgebra.symbol("x").toSVar(proto) + val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().tSFun(proto) + val actualDerivative = MstExpression(RealField, composition.d(x).toMst()).compile() val expectedDerivative = MstExpression( RealField, diff --git a/settings.gradle.kts b/settings.gradle.kts index 5fd072e1a..9343db854 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -40,5 +40,5 @@ include( ":kmath-ast", ":examples", ":kmath-ejml", - ":kmath-ast-kotlingrad" + ":kmath-kotlingrad" ) From 2723c376d9b123cb0d311411d6757d6fb8f379b7 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 13 Oct 2020 22:09:39 +0700 Subject: [PATCH 096/199] Use KG DSL instead of raw scalar construction --- .../kmath/kotlingrad/ScalarsAdapters.kt | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt index f6f0c7a76..e4777282f 100644 --- a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -16,7 +16,7 @@ import kscience.kmath.operations.* * - [SConst] -> [MstExtendedField.number]; * - [Sum] -> [MstExtendedField.add]; * - [Prod] -> [MstExtendedField.multiply]; - * - [Power] -> [MstExtendedField.power] (limited); + * - [Power] -> [MstExtendedField.power] (limited to constant exponents only); * - [Negative] -> [MstExtendedField.unaryMinus]; * - [Log] -> [MstExtendedField.ln] (left) / [MstExtendedField.ln] (right); * - [Sine] -> [MstExtendedField.sin]; @@ -36,7 +36,7 @@ public fun > SFun.toMst(): MST = MstExtendedField { is SConst -> number(doubleValue) is Sum -> left.toMst() + right.toMst() is Prod -> left.toMst() * right.toMst() - is Power -> power(left.toMst(), (right as SConst<*>).doubleValue) + is Power -> left.toMst() pow ((right as? SConst<*>)?.doubleValue ?: (right() as SConst<*>).doubleValue) is Negative -> -input.toMst() is Log -> ln(left.toMst()) / ln(right.toMst()) is Sine -> sin(input.toMst()) @@ -86,22 +86,22 @@ public fun > MST.tSFun(proto: X): SFun = when (this) { is MST.Unary -> when (operation) { SpaceOperations.PLUS_OPERATION -> value.tSFun(proto) - SpaceOperations.MINUS_OPERATION -> Negative(value.tSFun(proto)) - TrigonometricOperations.SIN_OPERATION -> Sine(value.tSFun(proto)) - TrigonometricOperations.COS_OPERATION -> Cosine(value.tSFun(proto)) - TrigonometricOperations.TAN_OPERATION -> Tangent(value.tSFun(proto)) - PowerOperations.SQRT_OPERATION -> Power(value.tSFun(proto), SConst(0.5)) - ExponentialOperations.EXP_OPERATION -> Power(value.tSFun(proto), E()) - ExponentialOperations.LN_OPERATION -> Log(value.tSFun(proto)) + SpaceOperations.MINUS_OPERATION -> -value.tSFun(proto) + TrigonometricOperations.SIN_OPERATION -> sin(value.tSFun(proto)) + TrigonometricOperations.COS_OPERATION -> cos(value.tSFun(proto)) + TrigonometricOperations.TAN_OPERATION -> tan(value.tSFun(proto)) + PowerOperations.SQRT_OPERATION -> value.tSFun(proto) pow SConst(0.5) + ExponentialOperations.EXP_OPERATION -> E() pow value.tSFun(proto) + ExponentialOperations.LN_OPERATION -> value.tSFun(proto).ln() else -> error("Unary operation $operation not defined in $this") } is MST.Binary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> Sum(left.tSFun(proto), right.tSFun(proto)) - SpaceOperations.MINUS_OPERATION -> Sum(left.tSFun(proto), Negative(right.tSFun(proto))) - RingOperations.TIMES_OPERATION -> Prod(left.tSFun(proto), right.tSFun(proto)) - FieldOperations.DIV_OPERATION -> Prod(left.tSFun(proto), Power(right.tSFun(proto), Negative(One()))) - PowerOperations.POW_OPERATION -> Power(left.tSFun(proto), SConst((right as MST.Numeric).value)) + SpaceOperations.PLUS_OPERATION -> left.tSFun(proto) + right.tSFun(proto) + SpaceOperations.MINUS_OPERATION -> left.tSFun(proto) - right.tSFun(proto) + RingOperations.TIMES_OPERATION -> left.tSFun(proto) * right.tSFun(proto) + FieldOperations.DIV_OPERATION -> left.tSFun(proto) / right.tSFun(proto) + PowerOperations.POW_OPERATION -> left.tSFun(proto) pow (right as MST.Numeric).toSConst() else -> error("Binary operation $operation not defined in $this") } } From ea0ecc0fba58b31cb9e24020db20332cfb9e73bd Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 13 Oct 2020 22:18:44 +0700 Subject: [PATCH 097/199] Use postfix op. form --- .../main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt index e4777282f..99ab5e635 100644 --- a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -90,7 +90,7 @@ public fun > MST.tSFun(proto: X): SFun = when (this) { TrigonometricOperations.SIN_OPERATION -> sin(value.tSFun(proto)) TrigonometricOperations.COS_OPERATION -> cos(value.tSFun(proto)) TrigonometricOperations.TAN_OPERATION -> tan(value.tSFun(proto)) - PowerOperations.SQRT_OPERATION -> value.tSFun(proto) pow SConst(0.5) + PowerOperations.SQRT_OPERATION -> value.tSFun(proto).sqrt() ExponentialOperations.EXP_OPERATION -> E() pow value.tSFun(proto) ExponentialOperations.LN_OPERATION -> value.tSFun(proto).ln() else -> error("Unary operation $operation not defined in $this") From e44423192d8b3923893752d4c32056a384fadcb9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 13 Oct 2020 20:34:17 +0300 Subject: [PATCH 098/199] Tools version update --- build.gradle.kts | 2 +- .../main/kotlin/kscience/kmath/operations/ComplexDemo.kt | 4 ++-- .../kscience/kmath/commons/expressions/DiffExpression.kt | 7 ++++--- .../kscience/kmath/commons/expressions/AutoDiffTest.kt | 2 +- .../commonMain/kotlin/kscience/kmath/operations/Complex.kt | 1 + settings.gradle.kts | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 05e2d5979..239ea1296 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,4 +24,4 @@ subprojects { readme { readmeTemplate = file("docs/templates/README-TEMPLATE.md") -} +} \ No newline at end of file diff --git a/examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt b/examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt index 34b3c9981..e84fd8df3 100644 --- a/examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/operations/ComplexDemo.kt @@ -6,8 +6,8 @@ import kscience.kmath.structures.complex fun main() { // 2d element - val element = NDElement.complex(2, 2) { index: IntArray -> - Complex(index[0].toDouble() - index[1].toDouble(), index[0].toDouble() + index[1].toDouble()) + val element = NDElement.complex(2, 2) { (i,j) -> + Complex(i.toDouble() - j.toDouble(), i.toDouble() + j.toDouble()) } println(element) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt index c39f0d04c..1eca1a773 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt @@ -16,7 +16,7 @@ import kotlin.properties.ReadOnlyProperty */ public class DerivativeStructureField( public val order: Int, - public val parameters: Map + public val parameters: Map, ) : ExtendedField { public override val zero: DerivativeStructure by lazy { DerivativeStructure(parameters.size, order) } public override val one: DerivativeStructure by lazy { DerivativeStructure(parameters.size, order, 1.0) } @@ -85,8 +85,9 @@ public class DerivativeStructureField( /** * A constructs that creates a derivative structure with required order on-demand */ -public class DiffExpression(public val function: DerivativeStructureField.() -> DerivativeStructure) : - Expression { +public class DiffExpression( + public val function: DerivativeStructureField.() -> DerivativeStructure, +) : Expression { public override operator fun invoke(arguments: Map): Double = DerivativeStructureField( 0, arguments diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/AutoDiffTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/AutoDiffTest.kt index f905e6818..197faaf49 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/AutoDiffTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/AutoDiffTest.kt @@ -18,7 +18,7 @@ internal inline fun diff( internal class AutoDiffTest { @Test fun derivativeStructureFieldTest() { - val res = diff(3, "x" to 1.0, "y" to 1.0) { + val res: Double = diff(3, "x" to 1.0, "y" to 1.0) { val x by variable val y = variable("y") val z = x * (-sin(x * y) + y) 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 37055a5c8..703931c7c 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt @@ -195,6 +195,7 @@ public data class Complex(val re: Double, val im: Double) : FieldElement Date: Mon, 19 Oct 2020 22:51:33 +0300 Subject: [PATCH 099/199] New Expression API --- README.md | 14 +- build.gradle.kts | 4 + docs/templates/README-TEMPLATE.md | 2 +- .../kscience/kmath/ast/MstExpression.kt | 10 +- .../kmath/asm/internal/mapIntrinsics.kt | 4 +- .../kscience/kmath/asm/TestAsmAlgebras.kt | 2 +- ...on.kt => DerivativeStructureExpression.kt} | 93 ++--- ...t => DerivativeStructureExpressionTest.kt} | 28 +- kmath-core/README.md | 9 +- kmath-core/build.gradle.kts | 2 +- .../kscience/kmath/expressions/Expression.kt | 81 ++++- .../FunctionalExpressionAlgebra.kt | 62 +--- .../kmath/expressions/SimpleAutoDiff.kt | 329 ++++++++++++++++++ .../kotlin/kscience/kmath/misc/AutoDiff.kt | 266 -------------- .../kmath/expressions/ExpressionFieldTest.kt | 22 +- .../kmath/expressions/SimpleAutoDiffTest.kt | 277 +++++++++++++++ .../kscience/kmath/misc/AutoDiffTest.kt | 261 -------------- 17 files changed, 794 insertions(+), 672 deletions(-) rename kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/{DiffExpression.kt => DerivativeStructureExpression.kt} (50%) rename kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/{AutoDiffTest.kt => DerivativeStructureExpressionTest.kt} (51%) create mode 100644 kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt delete mode 100644 kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt create mode 100644 kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt delete mode 100644 kmath-core/src/commonTest/kotlin/kscience/kmath/misc/AutoDiffTest.kt diff --git a/README.md b/README.md index 708bd8eb1..cbdf98afb 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,7 @@ can be used for a wide variety of purposes from high performance calculations to * **Commons-math wrapper** It is planned to gradually wrap most parts of [Apache commons-math](http://commons.apache.org/proper/commons-math/) library in Kotlin code and maybe rewrite some parts to better suit the Kotlin programming paradigm, however there is no fixed roadmap for that. Feel free to submit a feature request if you want something to be done first. - -* **EJML wrapper** Provides EJML `SimpleMatrix` wrapper consistent with the core matrix structures. - + ## Planned features * **Messaging** A mathematical notation to support multi-language and multi-node communication for mathematical tasks. @@ -117,6 +115,12 @@ can be used for a wide variety of purposes from high performance calculations to > **Maturity**: EXPERIMENTAL
+* ### [kmath-ejml](kmath-ejml) +> +> +> **Maturity**: EXPERIMENTAL +
+ * ### [kmath-for-real](kmath-for-real) > > @@ -178,8 +182,8 @@ repositories{ } dependencies{ - api("kscience.kmath:kmath-core:0.2.0-dev-1") - //api("kscience.kmath:kmath-core-jvm:0.2.0-dev-1") for jvm-specific version + api("kscience.kmath:kmath-core:0.2.0-dev-2") + //api("kscience.kmath:kmath-core-jvm:0.2.0-dev-2") for jvm-specific version } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 239ea1296..74b76d731 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,4 +24,8 @@ subprojects { readme { readmeTemplate = file("docs/templates/README-TEMPLATE.md") +} + +apiValidation{ + validationDisabled = true } \ No newline at end of file diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index f451adb24..5117e0694 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -107,4 +107,4 @@ with the same artifact names. ## Contributing -The project requires a lot of additional work. Please feel free to contribute in any way and propose new features. +The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to open feature issues with requests. We are also welcome to code contributions, especially in issues marked as [waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero). \ No newline at end of file diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt index 483bc530c..5ca75e993 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt @@ -14,8 +14,8 @@ import kotlin.contracts.contract * @author Alexander Nozik */ public class MstExpression(public val algebra: Algebra, public val mst: MST) : Expression { - private inner class InnerAlgebra(val arguments: Map) : NumericAlgebra { - override fun symbol(value: String): T = arguments[value] ?: algebra.symbol(value) + private inner class InnerAlgebra(val arguments: Map) : NumericAlgebra { + override fun symbol(value: String): T = arguments[StringSymbol(value)] ?: algebra.symbol(value) override fun unaryOperation(operation: String, arg: T): T = algebra.unaryOperation(operation, arg) override fun binaryOperation(operation: String, left: T, right: T): T = @@ -27,7 +27,7 @@ public class MstExpression(public val algebra: Algebra, public val mst: MS error("Numeric nodes are not supported by $this") } - override operator fun invoke(arguments: Map): T = InnerAlgebra(arguments).evaluate(mst) + override operator fun invoke(arguments: Map): T = InnerAlgebra(arguments).evaluate(mst) } /** @@ -37,7 +37,7 @@ public class MstExpression(public val algebra: Algebra, public val mst: MS */ public inline fun , E : Algebra> A.mst( mstAlgebra: E, - block: E.() -> MST + block: E.() -> MST, ): MstExpression = MstExpression(this, mstAlgebra.block()) /** @@ -116,7 +116,7 @@ public inline fun > FunctionalExpressionField> FunctionalExpressionExtendedField.mstInExtendedField( - block: MstExtendedField.() -> MST + block: MstExtendedField.() -> MST, ): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return algebra.mstInExtendedField(block) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt index 708b3c2b4..09e9a71b0 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt @@ -2,6 +2,8 @@ package kscience.kmath.asm.internal +import kscience.kmath.expressions.StringSymbol + /** * Gets value with given [key] or throws [IllegalStateException] whenever it is not present. * @@ -9,4 +11,4 @@ package kscience.kmath.asm.internal */ @JvmOverloads internal fun Map.getOrFail(key: K, default: V? = null): V = - this[key] ?: default ?: error("Parameter not found: $key") + this[StringSymbol(key.toString())] ?: default ?: error("Parameter not found: $key") diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt index 0cf1307d1..5eebfe43d 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt @@ -1,6 +1,5 @@ package kscience.kmath.asm -import kscience.kmath.asm.compile import kscience.kmath.ast.mstInField import kscience.kmath.ast.mstInRing import kscience.kmath.ast.mstInSpace @@ -11,6 +10,7 @@ import kotlin.test.Test import kotlin.test.assertEquals internal class TestAsmAlgebras { + @Test fun space() { val res1 = ByteRing.mstInSpace { diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt similarity index 50% rename from kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt rename to kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 1eca1a773..9a27e40cd 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -1,48 +1,57 @@ package kscience.kmath.commons.expressions +import kscience.kmath.expressions.DifferentiableExpression import kscience.kmath.expressions.Expression import kscience.kmath.expressions.ExpressionAlgebra +import kscience.kmath.expressions.Symbol import kscience.kmath.operations.ExtendedField -import kscience.kmath.operations.Field -import kscience.kmath.operations.invoke import org.apache.commons.math3.analysis.differentiation.DerivativeStructure -import kotlin.properties.ReadOnlyProperty /** * A field over commons-math [DerivativeStructure]. * * @property order The derivation order. - * @property parameters The map of free parameters. + * @property bindings The map of bindings values. All bindings are considered free parameters */ public class DerivativeStructureField( public val order: Int, - public val parameters: Map, -) : ExtendedField { - public override val zero: DerivativeStructure by lazy { DerivativeStructure(parameters.size, order) } - public override val one: DerivativeStructure by lazy { DerivativeStructure(parameters.size, order, 1.0) } + private val bindings: Map +) : ExtendedField, ExpressionAlgebra { + public override val zero: DerivativeStructure by lazy { DerivativeStructure(bindings.size, order) } + public override val one: DerivativeStructure by lazy { DerivativeStructure(bindings.size, order, 1.0) } - private val variables: Map = parameters.mapValues { (key, value) -> - DerivativeStructure(parameters.size, order, parameters.keys.indexOf(key), value) + /** + * A class that implements both [DerivativeStructure] and a [Symbol] + */ + public inner class DerivativeStructureSymbol(symbol: Symbol, value: Double) : + DerivativeStructure(bindings.size, order, bindings.keys.indexOf(symbol), value), Symbol { + override val identity: Any = symbol.identity } - public val variable: ReadOnlyProperty = ReadOnlyProperty { _, property -> - variables[property.name] ?: error("A variable with name ${property.name} does not exist") + /** + * Identity-based symbol bindings map + */ + private val variables: Map = bindings.entries.associate { (key, value) -> + key.identity to DerivativeStructureSymbol(key, value) } - public fun variable(name: String, default: DerivativeStructure? = null): DerivativeStructure = - variables[name] ?: default ?: error("A variable with name $name does not exist") + override fun const(value: Double): DerivativeStructure = DerivativeStructure(order, bindings.size, value) - public fun Number.const(): DerivativeStructure = DerivativeStructure(order, parameters.size, toDouble()) + public override fun bindOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity] - public fun DerivativeStructure.deriv(parName: String, order: Int = 1): Double { - return deriv(mapOf(parName to order)) + public fun bind(symbol: Symbol): DerivativeStructureSymbol = variables.getValue(symbol.identity) + + public fun Number.const(): DerivativeStructure = const(toDouble()) + + public fun DerivativeStructure.derivative(parameter: Symbol, order: Int = 1): Double { + return derivative(mapOf(parameter to order)) } - public fun DerivativeStructure.deriv(orders: Map): Double { - return getPartialDerivative(*parameters.keys.map { orders[it] ?: 0 }.toIntArray()) + public fun DerivativeStructure.derivative(orders: Map): Double { + return getPartialDerivative(*bindings.keys.map { orders[it] ?: 0 }.toIntArray()) } - public fun DerivativeStructure.deriv(vararg orders: Pair): Double = deriv(mapOf(*orders)) + public fun DerivativeStructure.derivative(vararg orders: Pair): Double = derivative(mapOf(*orders)) public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b) public override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) { @@ -85,48 +94,16 @@ public class DerivativeStructureField( /** * A constructs that creates a derivative structure with required order on-demand */ -public class DiffExpression( +public class DerivativeStructureExpression( public val function: DerivativeStructureField.() -> DerivativeStructure, -) : Expression { - public override operator fun invoke(arguments: Map): Double = DerivativeStructureField( - 0, - arguments - ).function().value +) : DifferentiableExpression { + public override operator fun invoke(arguments: Map): Double = + DerivativeStructureField(0, arguments).function().value /** * Get the derivative expression with given orders - * TODO make result [DiffExpression] */ - public fun derivative(orders: Map): Expression = Expression { arguments -> - (DerivativeStructureField(orders.values.maxOrNull() ?: 0, arguments)) { function().deriv(orders) } + public override fun derivative(orders: Map): Expression = Expression { arguments -> + with(DerivativeStructureField(orders.values.maxOrNull() ?: 0, arguments)) { function().derivative(orders) } } - - //TODO add gradient and maybe other vector operators -} - -public fun DiffExpression.derivative(vararg orders: Pair): Expression = derivative(mapOf(*orders)) -public fun DiffExpression.derivative(name: String): Expression = derivative(name to 1) - -/** - * A context for [DiffExpression] (not to be confused with [DerivativeStructure]) - */ -public object DiffExpressionAlgebra : ExpressionAlgebra, Field { - public override val zero: DiffExpression = DiffExpression { 0.0.const() } - public override val one: DiffExpression = DiffExpression { 1.0.const() } - - public override fun variable(name: String, default: Double?): DiffExpression = - DiffExpression { variable(name, default?.const()) } - - public override fun const(value: Double): DiffExpression = DiffExpression { value.const() } - - public override fun add(a: DiffExpression, b: DiffExpression): DiffExpression = - DiffExpression { a.function(this) + b.function(this) } - - public override fun multiply(a: DiffExpression, k: Number): DiffExpression = DiffExpression { a.function(this) * k } - - public override fun multiply(a: DiffExpression, b: DiffExpression): DiffExpression = - DiffExpression { a.function(this) * b.function(this) } - - public override fun divide(a: DiffExpression, b: DiffExpression): DiffExpression = - DiffExpression { a.function(this) / b.function(this) } } diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/AutoDiffTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt similarity index 51% rename from kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/AutoDiffTest.kt rename to kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt index 197faaf49..8886e123f 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/AutoDiffTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt @@ -1,6 +1,6 @@ package kscience.kmath.commons.expressions -import kscience.kmath.expressions.invoke +import kscience.kmath.expressions.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.test.Test @@ -8,33 +8,37 @@ import kotlin.test.assertEquals internal inline fun diff( order: Int, - vararg parameters: Pair, - block: DerivativeStructureField.() -> R + vararg parameters: Pair, + block: DerivativeStructureField.() -> R, ): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return DerivativeStructureField(order, mapOf(*parameters)).run(block) } internal class AutoDiffTest { + private val x by symbol + private val y by symbol + @Test fun derivativeStructureFieldTest() { - val res: Double = diff(3, "x" to 1.0, "y" to 1.0) { - val x by variable - val y = variable("y") + val res: Double = diff(3, x to 1.0, y to 1.0) { + val x = bind(x)//by binding() + val y = symbol("y") val z = x * (-sin(x * y) + y) - z.deriv("x") + z.derivative(x) } + println(res) } @Test fun autoDifTest() { - val f = DiffExpression { - val x by variable - val y by variable + val f = DerivativeStructureExpression { + val x by binding() + val y by binding() x.pow(2) + 2 * x * y + y.pow(2) + 1 } - assertEquals(10.0, f("x" to 1.0, "y" to 2.0)) - assertEquals(6.0, f.derivative("x")("x" to 1.0, "y" to 2.0)) + assertEquals(10.0, f(x to 1.0, y to 2.0)) + assertEquals(6.0, f.derivative(x)(x to 1.0, y to 2.0)) } } diff --git a/kmath-core/README.md b/kmath-core/README.md index 2cf7ed5dc..6935c0d3c 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -12,7 +12,7 @@ The core features of KMath: > #### Artifact: > -> This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-1`. +> This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-2`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) > @@ -22,25 +22,28 @@ The core features of KMath: > > ```gradle > repositories { +> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } > maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + > } > > dependencies { -> implementation 'kscience.kmath:kmath-core:0.2.0-dev-1' +> implementation 'kscience.kmath:kmath-core:0.2.0-dev-2' > } > ``` > **Gradle Kotlin DSL:** > > ```kotlin > repositories { +> maven("https://dl.bintray.com/kotlin/kotlin-eap") > maven("https://dl.bintray.com/mipt-npm/kscience") > maven("https://dl.bintray.com/mipt-npm/dev") > maven("https://dl.bintray.com/hotkeytlt/maven") > } > > dependencies { -> implementation("kscience.kmath:kmath-core:0.2.0-dev-1") +> implementation("kscience.kmath:kmath-core:0.2.0-dev-2") > } > ``` diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index b56151abe..bd254c39d 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -41,6 +41,6 @@ readme { feature( id = "autodif", description = "Automatic differentiation", - ref = "src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt" + ref = "src/commonMain/kotlin/kscience/kmath/misc/SimpleAutoDiff.kt" ) } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index 5ade9e3ca..d64eb5a55 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -1,6 +1,26 @@ package kscience.kmath.expressions import kscience.kmath.operations.Algebra +import kotlin.jvm.JvmName +import kotlin.properties.ReadOnlyProperty + +/** + * A marker interface for a symbol. A symbol mus have an identity + */ +public interface Symbol { + /** + * Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol. + * By default uses object identity + */ + public val identity: Any get() = this +} + +/** + * A [Symbol] with a [String] identity + */ +public inline class StringSymbol(override val identity: String) : Symbol { + override fun toString(): String = identity +} /** * An elementary function that could be invoked on a map of arguments @@ -12,30 +32,81 @@ public fun interface Expression { * @param arguments the map of arguments. * @return the value. */ - public operator fun invoke(arguments: Map): T + public operator fun invoke(arguments: Map): T public companion object } +/** + * Invlode an expression without parameters + */ +public operator fun Expression.invoke(): T = invoke(emptyMap()) +//This method exists to avoid resolution ambiguity of vararg methods + /** * Calls this expression from arguments. * * @param pairs the pair of arguments' names to values. * @return the value. */ -public operator fun Expression.invoke(vararg pairs: Pair): T = invoke(mapOf(*pairs)) +@JvmName("callBySymbol") +public operator fun Expression.invoke(vararg pairs: Pair): T = invoke(mapOf(*pairs)) + +@JvmName("callByString") +public operator fun Expression.invoke(vararg pairs: Pair): T = + invoke(mapOf(*pairs).mapKeys { StringSymbol(it.key) }) + +/** + * And object that could be differentiated + */ +public interface Differentiable { + public fun derivative(orders: Map): T +} + +public interface DifferentiableExpression : Differentiable>, Expression + +public fun DifferentiableExpression.derivative(vararg orders: Pair): Expression = + derivative(mapOf(*orders)) + +public fun DifferentiableExpression.derivative(symbol: Symbol): Expression = derivative(symbol to 1) + +public fun DifferentiableExpression.derivative(name: String): Expression = derivative(StringSymbol(name) to 1) /** * A context for expression construction + * + * @param T type of the constants for the expression + * @param E type of the actual expression state */ -public interface ExpressionAlgebra : Algebra { +public interface ExpressionAlgebra : Algebra { + /** - * Introduce a variable into expression context + * Bind a given [Symbol] to this context variable and produce context-specific object. Return null if symbol could not be bound in current context. */ - public fun variable(name: String, default: T? = null): E + public fun bindOrNull(symbol: Symbol): E? + + /** + * Bind a string to a context using [StringSymbol] + */ + override fun symbol(value: String): E = bind(StringSymbol(value)) /** * A constant expression which does not depend on arguments */ public fun const(value: T): E } + +/** + * Bind a given [Symbol] to this context variable and produce context-specific object. + */ +public fun ExpressionAlgebra.bind(symbol: Symbol): E = + bindOrNull(symbol) ?: error("Symbol $symbol could not be bound to $this") + +public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> + StringSymbol(property.name) +} + +public fun ExpressionAlgebra.binding(): ReadOnlyProperty = + ReadOnlyProperty { _, property -> + bind(StringSymbol(property.name)) ?: error("A variable with name ${property.name} does not exist") + } \ 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 5b050dd36..9fd15238a 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -2,39 +2,6 @@ package kscience.kmath.expressions import kscience.kmath.operations.* -internal class FunctionalUnaryOperation(val context: Algebra, val name: String, private val expr: Expression) : - Expression { - override operator fun invoke(arguments: Map): T = - context.unaryOperation(name, expr.invoke(arguments)) -} - -internal class FunctionalBinaryOperation( - val context: Algebra, - val name: String, - val first: Expression, - val second: Expression -) : Expression { - override operator fun invoke(arguments: Map): T = - context.binaryOperation(name, first.invoke(arguments), second.invoke(arguments)) -} - -internal class FunctionalVariableExpression(val name: String, val default: T? = null) : Expression { - override operator fun invoke(arguments: Map): T = - arguments[name] ?: default ?: error("Parameter not found: $name") -} - -internal class FunctionalConstantExpression(val value: T) : Expression { - override operator fun invoke(arguments: Map): T = value -} - -internal class FunctionalConstProductExpression( - val context: Space, - private val expr: Expression, - val const: Number -) : Expression { - override operator fun invoke(arguments: Map): T = context.multiply(expr.invoke(arguments), const) -} - /** * A context class for [Expression] construction. * @@ -45,24 +12,32 @@ public abstract class FunctionalExpressionAlgebra>(public val /** * Builds an Expression of constant expression which does not depend on arguments. */ - public override fun const(value: T): Expression = FunctionalConstantExpression(value) + public override fun const(value: T): Expression = Expression { value } /** * Builds an Expression to access a variable. */ - public override fun variable(name: String, default: T?): Expression = FunctionalVariableExpression(name, default) + public override fun bindOrNull(symbol: Symbol): Expression? = Expression { arguments -> + arguments[symbol] ?: error("Argument not found: $symbol") + } /** * Builds an Expression of dynamic call of binary operation [operation] on [left] and [right]. */ - public override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = - FunctionalBinaryOperation(algebra, operation, left, right) + public override fun binaryOperation( + operation: String, + left: Expression, + right: Expression, + ): Expression = Expression { arguments -> + algebra.binaryOperation(operation, left.invoke(arguments), right.invoke(arguments)) + } /** * Builds an Expression of dynamic call of unary operation with name [operation] on [arg]. */ - public override fun unaryOperation(operation: String, arg: Expression): Expression = - FunctionalUnaryOperation(algebra, operation, arg) + public override fun unaryOperation(operation: String, arg: Expression): Expression = Expression { arguments -> + algebra.unaryOperation(operation, arg.invoke(arguments)) + } } /** @@ -81,8 +56,9 @@ public open class FunctionalExpressionSpace>(algebra: A) : /** * Builds an Expression of multiplication of expression by number. */ - public override fun multiply(a: Expression, k: Number): Expression = - FunctionalConstProductExpression(algebra, a, k) + public override fun multiply(a: Expression, k: Number): Expression = Expression { arguments -> + algebra.multiply(a.invoke(arguments), k) + } public operator fun Expression.plus(arg: T): Expression = this + const(arg) public operator fun Expression.minus(arg: T): Expression = this - const(arg) @@ -118,8 +94,8 @@ public open class FunctionalExpressionRing(algebra: A) : FunctionalExpress } public open class FunctionalExpressionField(algebra: A) : - FunctionalExpressionRing(algebra), - Field> where A : Field, A : NumericAlgebra { + FunctionalExpressionRing(algebra), Field> + where A : Field, A : NumericAlgebra { /** * Builds an Expression of division an expression by another one. */ diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt new file mode 100644 index 000000000..5e8fe3e99 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -0,0 +1,329 @@ +package kscience.kmath.expressions + +import kscience.kmath.linear.Point +import kscience.kmath.operations.* +import kscience.kmath.structures.asBuffer +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +/* + * Implementation of backward-mode automatic differentiation. + * Initial gist by Roman Elizarov: https://gist.github.com/elizarov/1ad3a8583e88cb6ea7a0ad09bb591d3d + */ + + +/** + * A [Symbol] with bound value + */ +public interface BoundSymbol : Symbol { + public val value: T +} + +/** + * Bind a [Symbol] to a [value] and produce [BoundSymbol] + */ +public fun Symbol.bind(value: T): BoundSymbol = object : BoundSymbol { + override val identity = this@bind.identity + override val value: T = value +} + +/** + * Represents result of [withAutoDiff] call. + * + * @param T the non-nullable type of value. + * @param value the value of result. + * @property withAutoDiff The mapping of differentiated variables to their derivatives. + * @property context The field over [T]. + */ +public class DerivationResult( + override val value: T, + private val derivativeValues: Map, + public val context: Field, +) : BoundSymbol { + /** + * Returns derivative of [variable] or returns [Ring.zero] in [context]. + */ + public fun derivative(variable: Symbol): T = derivativeValues[variable.identity] ?: context.zero + + /** + * Computes the divergence. + */ + public fun div(): T = context { sum(derivativeValues.values) } +} + +/** + * Computes the gradient for variables in given order. + */ +public fun DerivationResult.grad(vararg variables: Symbol): Point { + check(variables.isNotEmpty()) { "Variable order is not provided for gradient construction" } + return variables.map(::derivative).asBuffer() +} + +/** + * Runs differentiation and establishes [AutoDiffField] context inside the block of code. + * + * The partial derivatives are placed in argument `d` variable + * + * Example: + * ``` + * val x by symbol // define variable(s) and their values + * val y = RealField.withAutoDiff() { sqr(x) + 5 * x + 3 } // write formulate in deriv context + * assertEquals(17.0, y.x) // the value of result (y) + * assertEquals(9.0, x.d) // dy/dx + * ``` + * + * @param body the action in [AutoDiffField] context returning [AutoDiffVariable] to differentiate with respect to. + * @return the result of differentiation. + */ +public fun > F.withAutoDiff( + bindings: Collection>, + body: AutoDiffField.() -> BoundSymbol, +): DerivationResult { + contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) } + + return AutoDiffContext(this, bindings).derivate(body) +} + +public fun > F.withAutoDiff( + vararg bindings: Pair, + body: AutoDiffField.() -> BoundSymbol, +): DerivationResult = withAutoDiff(bindings.map { it.first.bind(it.second) }, body) + +/** + * Represents field in context of which functions can be derived. + */ +public abstract class AutoDiffField> + : Field>, ExpressionAlgebra> { + + public abstract val context: F + + /** + * A variable accessing inner state of derivatives. + * Use this value in inner builders to avoid creating additional derivative bindings. + */ + public abstract var BoundSymbol.d: T + + /** + * Performs update of derivative after the rest of the formula in the back-pass. + * + * For example, implementation of `sin` function is: + * + * ``` + * fun AD.sin(x: Variable): Variable = derive(Variable(sin(x.x)) { z -> // call derive with function result + * x.d += z.d * cos(x.x) // update derivative using chain rule and derivative of the function + * } + * ``` + */ + public abstract fun derive(value: R, block: F.(R) -> Unit): R + + public inline fun const(block: F.() -> T): BoundSymbol = const(context.block()) + + // Overloads for Double constants + + override operator fun Number.plus(b: BoundSymbol): BoundSymbol = + derive(const { this@plus.toDouble() * one + b.value }) { z -> + b.d += z.d + } + + override operator fun BoundSymbol.plus(b: Number): BoundSymbol = b.plus(this) + + override operator fun Number.minus(b: BoundSymbol): BoundSymbol = + derive(const { this@minus.toDouble() * one - b.value }) { z -> b.d -= z.d } + + override operator fun BoundSymbol.minus(b: Number): BoundSymbol = + derive(const { this@minus.value - one * b.toDouble() }) { z -> this@minus.d += z.d } +} + +/** + * Automatic Differentiation context class. + */ +private class AutoDiffContext>( + override val context: F, + bindings: Collection>, +) : AutoDiffField() { + // this stack contains pairs of blocks and values to apply them to + private var stack: Array = arrayOfNulls(8) + private var sp: Int = 0 + private val derivatives: MutableMap = hashMapOf() + override val zero: BoundSymbol get() = const(context.zero) + override val one: BoundSymbol get() = const(context.one) + + /** + * Differentiable variable with value and derivative of differentiation ([withAutoDiff]) result + * with respect to this variable. + * + * @param T the non-nullable type of value. + * @property value The value of this variable. + */ + private class AutoDiffVariableWithDeriv(override val value: T, var d: T) : BoundSymbol + + private val bindings: Map> = bindings.associateBy { it.identity } + + override fun bindOrNull(symbol: Symbol): BoundSymbol? = bindings[symbol.identity] + + override fun const(value: T): BoundSymbol = AutoDiffVariableWithDeriv(value, context.zero) + + override var BoundSymbol.d: T + get() = (this as? AutoDiffVariableWithDeriv)?.d ?: derivatives[identity] ?: context.zero + set(value) = if (this is AutoDiffVariableWithDeriv) d = value else derivatives[identity] = value + + @Suppress("UNCHECKED_CAST") + override fun derive(value: R, block: F.(R) -> Unit): R { + // save block to stack for backward pass + if (sp >= stack.size) stack = stack.copyOf(stack.size * 2) + stack[sp++] = block + stack[sp++] = value + return value + } + + @Suppress("UNCHECKED_CAST") + fun runBackwardPass() { + while (sp > 0) { + val value = stack[--sp] + val block = stack[--sp] as F.(Any?) -> Unit + context.block(value) + } + } + + // Basic math (+, -, *, /) + + override fun add(a: BoundSymbol, b: BoundSymbol): BoundSymbol = + derive(const { a.value + b.value }) { z -> + a.d += z.d + b.d += z.d + } + + override fun multiply(a: BoundSymbol, b: BoundSymbol): BoundSymbol = + derive(const { a.value * b.value }) { z -> + a.d += z.d * b.value + b.d += z.d * a.value + } + + override fun divide(a: BoundSymbol, b: BoundSymbol): BoundSymbol = + derive(const { a.value / b.value }) { z -> + a.d += z.d / b.value + b.d -= z.d * a.value / (b.value * b.value) + } + + override fun multiply(a: BoundSymbol, k: Number): BoundSymbol = + derive(const { k.toDouble() * a.value }) { z -> + a.d += z.d * k.toDouble() + } + + inline fun derivate(function: AutoDiffField.() -> BoundSymbol): DerivationResult { + val result = function() + result.d = context.one // computing derivative w.r.t result + runBackwardPass() + return DerivationResult(result.value, derivatives, context) + } +} + +/** + * A constructs that creates a derivative structure with required order on-demand + */ +public class SimpleAutoDiffExpression>( + public val field: F, + public val function: AutoDiffField.() -> BoundSymbol, +) : DifferentiableExpression { + public override operator fun invoke(arguments: Map): T { + val bindings = arguments.entries.map { it.key.bind(it.value) } + return AutoDiffContext(field, bindings).function().value + } + + /** + * Get the derivative expression with given orders + */ + public override fun derivative(orders: Map): Expression { + val dSymbol = orders.entries.singleOrNull { it.value == 1 } + ?: error("SimpleAutoDiff supports only first order derivatives") + return Expression { arguments -> + val bindings = arguments.entries.map { it.key.bind(it.value) } + val derivationResult = AutoDiffContext(field, bindings).derivate(function) + derivationResult.derivative(dSymbol.key) + } + } +} + + +// Extensions for differentiation of various basic mathematical functions + +// x ^ 2 +public fun > AutoDiffField.sqr(x: BoundSymbol): BoundSymbol = + derive(const { x.value * x.value }) { z -> x.d += z.d * 2 * x.value } + +// x ^ 1/2 +public fun > AutoDiffField.sqrt(x: BoundSymbol): BoundSymbol = + derive(const { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value } + +// x ^ y (const) +public fun > AutoDiffField.pow( + x: BoundSymbol, + y: Double, +): BoundSymbol = + derive(const { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) } + +public fun > AutoDiffField.pow( + x: BoundSymbol, + y: Int, +): BoundSymbol = + pow(x, y.toDouble()) + +// exp(x) +public fun > AutoDiffField.exp(x: BoundSymbol): BoundSymbol = + derive(const { exp(x.value) }) { z -> x.d += z.d * z.value } + +// ln(x) +public fun > AutoDiffField.ln(x: BoundSymbol): BoundSymbol = + derive(const { ln(x.value) }) { z -> x.d += z.d / x.value } + +// x ^ y (any) +public fun > AutoDiffField.pow( + x: BoundSymbol, + y: BoundSymbol, +): BoundSymbol = + exp(y * ln(x)) + +// sin(x) +public fun > AutoDiffField.sin(x: BoundSymbol): BoundSymbol = + derive(const { sin(x.value) }) { z -> x.d += z.d * cos(x.value) } + +// cos(x) +public fun > AutoDiffField.cos(x: BoundSymbol): BoundSymbol = + derive(const { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) } + +public fun > AutoDiffField.tan(x: BoundSymbol): BoundSymbol = + derive(const { tan(x.value) }) { z -> + val c = cos(x.value) + x.d += z.d / (c * c) + } + +public fun > AutoDiffField.asin(x: BoundSymbol): BoundSymbol = + derive(const { asin(x.value) }) { z -> x.d += z.d / sqrt(one - x.value * x.value) } + +public fun > AutoDiffField.acos(x: BoundSymbol): BoundSymbol = + derive(const { acos(x.value) }) { z -> x.d -= z.d / sqrt(one - x.value * x.value) } + +public fun > AutoDiffField.atan(x: BoundSymbol): BoundSymbol = + derive(const { atan(x.value) }) { z -> x.d += z.d / (one + x.value * x.value) } + +public fun > AutoDiffField.sinh(x: BoundSymbol): BoundSymbol = + derive(const { sin(x.value) }) { z -> x.d += z.d * cosh(x.value) } + +public fun > AutoDiffField.cosh(x: BoundSymbol): BoundSymbol = + derive(const { cos(x.value) }) { z -> x.d += z.d * sinh(x.value) } + +public fun > AutoDiffField.tanh(x: BoundSymbol): BoundSymbol = + derive(const { tan(x.value) }) { z -> + val c = cosh(x.value) + x.d += z.d / (c * c) + } + +public fun > AutoDiffField.asinh(x: BoundSymbol): BoundSymbol = + derive(const { asinh(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) } + +public fun > AutoDiffField.acosh(x: BoundSymbol): BoundSymbol = + derive(const { acosh(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) } + +public fun > AutoDiffField.atanh(x: BoundSymbol): BoundSymbol = + derive(const { atanh(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) } + diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt deleted file mode 100644 index bfcd5959f..000000000 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt +++ /dev/null @@ -1,266 +0,0 @@ -package kscience.kmath.misc - -import kscience.kmath.linear.Point -import kscience.kmath.operations.* -import kscience.kmath.structures.asBuffer -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - -/* - * Implementation of backward-mode automatic differentiation. - * Initial gist by Roman Elizarov: https://gist.github.com/elizarov/1ad3a8583e88cb6ea7a0ad09bb591d3d - */ - -/** - * Differentiable variable with value and derivative of differentiation ([deriv]) result - * with respect to this variable. - * - * @param T the non-nullable type of value. - * @property value The value of this variable. - */ -public open class Variable(public val value: T) - -/** - * Represents result of [deriv] call. - * - * @param T the non-nullable type of value. - * @param value the value of result. - * @property deriv The mapping of differentiated variables to their derivatives. - * @property context The field over [T]. - */ -public class DerivationResult( - value: T, - public val deriv: Map, T>, - public val context: Field -) : Variable(value) { - /** - * Returns derivative of [variable] or returns [Ring.zero] in [context]. - */ - public fun deriv(variable: Variable): T = deriv[variable] ?: context.zero - - /** - * Computes the divergence. - */ - public fun div(): T = context { sum(deriv.values) } - - /** - * Computes the gradient for variables in given order. - */ - public fun grad(vararg variables: Variable): Point { - check(variables.isNotEmpty()) { "Variable order is not provided for gradient construction" } - return variables.map(::deriv).asBuffer() - } -} - -/** - * Runs differentiation and establishes [AutoDiffField] context inside the block of code. - * - * The partial derivatives are placed in argument `d` variable - * - * Example: - * ``` - * val x = Variable(2) // define variable(s) and their values - * val y = deriv { sqr(x) + 5 * x + 3 } // write formulate in deriv context - * assertEquals(17.0, y.x) // the value of result (y) - * assertEquals(9.0, x.d) // dy/dx - * ``` - * - * @param body the action in [AutoDiffField] context returning [Variable] to differentiate with respect to. - * @return the result of differentiation. - */ -public inline fun > F.deriv(body: AutoDiffField.() -> Variable): DerivationResult { - contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) } - - return (AutoDiffContext(this)) { - val result = body() - result.d = context.one // computing derivative w.r.t result - runBackwardPass() - DerivationResult(result.value, derivatives, this@deriv) - } -} - -/** - * Represents field in context of which functions can be derived. - */ -public abstract class AutoDiffField> : Field> { - public abstract val context: F - - /** - * A variable accessing inner state of derivatives. - * Use this value in inner builders to avoid creating additional derivative bindings. - */ - public abstract var Variable.d: T - - /** - * Performs update of derivative after the rest of the formula in the back-pass. - * - * For example, implementation of `sin` function is: - * - * ``` - * fun AD.sin(x: Variable): Variable = derive(Variable(sin(x.x)) { z -> // call derive with function result - * x.d += z.d * cos(x.x) // update derivative using chain rule and derivative of the function - * } - * ``` - */ - public abstract fun derive(value: R, block: F.(R) -> Unit): R - - /** - * - */ - public abstract fun variable(value: T): Variable - - public inline fun variable(block: F.() -> T): Variable = variable(context.block()) - - // Overloads for Double constants - - override operator fun Number.plus(b: Variable): Variable = - derive(variable { this@plus.toDouble() * one + b.value }) { z -> - b.d += z.d - } - - override operator fun Variable.plus(b: Number): Variable = b.plus(this) - - override operator fun Number.minus(b: Variable): Variable = - derive(variable { this@minus.toDouble() * one - b.value }) { z -> b.d -= z.d } - - override operator fun Variable.minus(b: Number): Variable = - derive(variable { this@minus.value - one * b.toDouble() }) { z -> this@minus.d += z.d } -} - -/** - * Automatic Differentiation context class. - */ -@PublishedApi -internal class AutoDiffContext>(override val context: F) : AutoDiffField() { - // this stack contains pairs of blocks and values to apply them to - private var stack: Array = arrayOfNulls(8) - private var sp: Int = 0 - val derivatives: MutableMap, T> = hashMapOf() - override val zero: Variable get() = Variable(context.zero) - override val one: Variable get() = Variable(context.one) - - /** - * A variable coupled with its derivative. For internal use only - */ - private class VariableWithDeriv(x: T, var d: T) : Variable(x) - - override fun variable(value: T): Variable = - VariableWithDeriv(value, context.zero) - - override var Variable.d: T - get() = (this as? VariableWithDeriv)?.d ?: derivatives[this] ?: context.zero - set(value) = if (this is VariableWithDeriv) d = value else derivatives[this] = value - - @Suppress("UNCHECKED_CAST") - override fun derive(value: R, block: F.(R) -> Unit): R { - // save block to stack for backward pass - if (sp >= stack.size) stack = stack.copyOf(stack.size * 2) - stack[sp++] = block - stack[sp++] = value - return value - } - - @Suppress("UNCHECKED_CAST") - fun runBackwardPass() { - while (sp > 0) { - val value = stack[--sp] - val block = stack[--sp] as F.(Any?) -> Unit - context.block(value) - } - } - - // Basic math (+, -, *, /) - - override fun add(a: Variable, b: Variable): Variable = derive(variable { a.value + b.value }) { z -> - a.d += z.d - b.d += z.d - } - - override fun multiply(a: Variable, b: Variable): Variable = derive(variable { a.value * b.value }) { z -> - a.d += z.d * b.value - b.d += z.d * a.value - } - - override fun divide(a: Variable, b: Variable): Variable = derive(variable { a.value / b.value }) { z -> - a.d += z.d / b.value - b.d -= z.d * a.value / (b.value * b.value) - } - - override fun multiply(a: Variable, k: Number): Variable = derive(variable { k.toDouble() * a.value }) { z -> - a.d += z.d * k.toDouble() - } -} - -// Extensions for differentiation of various basic mathematical functions - -// x ^ 2 -public fun > AutoDiffField.sqr(x: Variable): Variable = - derive(variable { x.value * x.value }) { z -> x.d += z.d * 2 * x.value } - -// x ^ 1/2 -public fun > AutoDiffField.sqrt(x: Variable): Variable = - derive(variable { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value } - -// x ^ y (const) -public fun > AutoDiffField.pow(x: Variable, y: Double): Variable = - derive(variable { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) } - -public fun > AutoDiffField.pow(x: Variable, y: Int): Variable = - pow(x, y.toDouble()) - -// exp(x) -public fun > AutoDiffField.exp(x: Variable): Variable = - derive(variable { exp(x.value) }) { z -> x.d += z.d * z.value } - -// ln(x) -public fun > AutoDiffField.ln(x: Variable): Variable = - derive(variable { ln(x.value) }) { z -> x.d += z.d / x.value } - -// x ^ y (any) -public fun > AutoDiffField.pow(x: Variable, y: Variable): Variable = - exp(y * ln(x)) - -// sin(x) -public fun > AutoDiffField.sin(x: Variable): Variable = - derive(variable { sin(x.value) }) { z -> x.d += z.d * cos(x.value) } - -// cos(x) -public fun > AutoDiffField.cos(x: Variable): Variable = - derive(variable { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) } - -public fun > AutoDiffField.tan(x: Variable): Variable = - derive(variable { tan(x.value) }) { z -> - val c = cos(x.value) - x.d += z.d / (c * c) - } - -public fun > AutoDiffField.asin(x: Variable): Variable = - derive(variable { asin(x.value) }) { z -> x.d += z.d / sqrt(one - x.value * x.value) } - -public fun > AutoDiffField.acos(x: Variable): Variable = - derive(variable { acos(x.value) }) { z -> x.d -= z.d / sqrt(one - x.value * x.value) } - -public fun > AutoDiffField.atan(x: Variable): Variable = - derive(variable { atan(x.value) }) { z -> x.d += z.d / (one + x.value * x.value) } - -public fun > AutoDiffField.sinh(x: Variable): Variable = - derive(variable { sin(x.value) }) { z -> x.d += z.d * cosh(x.value) } - -public fun > AutoDiffField.cosh(x: Variable): Variable = - derive(variable { cos(x.value) }) { z -> x.d += z.d * sinh(x.value) } - -public fun > AutoDiffField.tanh(x: Variable): Variable = - derive(variable { tan(x.value) }) { z -> - val c = cosh(x.value) - x.d += z.d / (c * c) - } - -public fun > AutoDiffField.asinh(x: Variable): Variable = - derive(variable { asinh(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) } - -public fun > AutoDiffField.acosh(x: Variable): Variable = - derive(variable { acosh(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) } - -public fun > AutoDiffField.atanh(x: Variable): Variable = - derive(variable { atanh(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) } - diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/ExpressionFieldTest.kt index 1d3f520f6..484993eef 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/ExpressionFieldTest.kt @@ -6,19 +6,21 @@ import kscience.kmath.operations.RealField import kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFails class ExpressionFieldTest { + val x by symbol @Test fun testExpression() { val context = FunctionalExpressionField(RealField) val expression = context { - val x = variable("x", 2.0) + val x by binding() x * x + 2 * x + one } - assertEquals(expression("x" to 1.0), 4.0) - assertEquals(expression(), 9.0) + assertEquals(expression(x to 1.0), 4.0) + assertFails { expression()} } @Test @@ -26,33 +28,33 @@ class ExpressionFieldTest { val context = FunctionalExpressionField(ComplexField) val expression = context { - val x = variable("x", Complex(2.0, 0.0)) + val x = bind(x) x * x + 2 * x + one } - assertEquals(expression("x" to Complex(1.0, 0.0)), Complex(4.0, 0.0)) - assertEquals(expression(), Complex(9.0, 0.0)) + assertEquals(expression(x to Complex(1.0, 0.0)), Complex(4.0, 0.0)) + //assertEquals(expression(), Complex(9.0, 0.0)) } @Test fun separateContext() { fun FunctionalExpressionField.expression(): Expression { - val x = variable("x") + val x by binding() return x * x + 2 * x + one } val expression = FunctionalExpressionField(RealField).expression() - assertEquals(expression("x" to 1.0), 4.0) + assertEquals(expression(x to 1.0), 4.0) } @Test fun valueExpression() { val expressionBuilder: FunctionalExpressionField.() -> Expression = { - val x = variable("x") + val x by binding() x * x + 2 * x + one } val expression = FunctionalExpressionField(RealField).expressionBuilder() - assertEquals(expression("x" to 1.0), 4.0) + assertEquals(expression(x to 1.0), 4.0) } } diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt new file mode 100644 index 000000000..ca5b626fd --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -0,0 +1,277 @@ +package kscience.kmath.expressions + +import kscience.kmath.operations.RealField +import kscience.kmath.structures.asBuffer +import kotlin.math.PI +import kotlin.math.pow +import kotlin.math.sqrt +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class SimpleAutoDiffTest { + fun d( + vararg bindings: Pair, + body: AutoDiffField.() -> BoundSymbol, + ): DerivationResult = RealField.withAutoDiff(bindings = bindings, body) + + fun dx( + xBinding: Pair, + body: AutoDiffField.(x: BoundSymbol) -> BoundSymbol, + ): DerivationResult = RealField.withAutoDiff(xBinding) { body(bind(xBinding.first)) } + + fun dxy( + xBinding: Pair, + yBinding: Pair, + body: AutoDiffField.(x: BoundSymbol, y: BoundSymbol) -> BoundSymbol, + ): DerivationResult = RealField.withAutoDiff(xBinding, yBinding) { + body(bind(xBinding.first), bind(yBinding.first)) + } + + fun diff(block: AutoDiffField.() -> BoundSymbol): SimpleAutoDiffExpression { + return SimpleAutoDiffExpression(RealField, block) + } + + val x by symbol + val y by symbol + val z by symbol + + @Test + fun testPlusX2() { + val y = d(x to 3.0) { + // diff w.r.t this x at 3 + val x = bind(x) + x + x + } + assertEquals(6.0, y.value) // y = x + x = 6 + assertEquals(2.0, y.derivative(x)) // dy/dx = 2 + } + + @Test + fun testPlus() { + // two variables + val z = d(x to 2.0, y to 3.0) { + val x = bind(x) + val y = bind(y) + x + y + } + assertEquals(5.0, z.value) // z = x + y = 5 + assertEquals(1.0, z.derivative(x)) // dz/dx = 1 + assertEquals(1.0, z.derivative(y)) // dz/dy = 1 + } + + @Test + fun testMinus() { + // two variables + val z = d(x to 7.0, y to 3.0) { + val x = bind(x) + val y = bind(y) + + x - y + } + assertEquals(4.0, z.value) // z = x - y = 4 + assertEquals(1.0, z.derivative(x)) // dz/dx = 1 + assertEquals(-1.0, z.derivative(y)) // dz/dy = -1 + } + + @Test + fun testMulX2() { + val y = dx(x to 3.0) { x -> + // diff w.r.t this x at 3 + x * x + } + assertEquals(9.0, y.value) // y = x * x = 9 + assertEquals(6.0, y.derivative(x)) // dy/dx = 2 * x = 7 + } + + @Test + fun testSqr() { + val y = dx(x to 3.0) { x -> sqr(x) } + assertEquals(9.0, y.value) // y = x ^ 2 = 9 + assertEquals(6.0, y.derivative(x)) // dy/dx = 2 * x = 7 + } + + @Test + fun testSqrSqr() { + val y = dx(x to 2.0) { x -> sqr(sqr(x)) } + assertEquals(16.0, y.value) // y = x ^ 4 = 16 + assertEquals(32.0, y.derivative(x)) // dy/dx = 4 * x^3 = 32 + } + + @Test + fun testX3() { + val y = dx(x to 2.0) { x -> + // diff w.r.t this x at 2 + x * x * x + } + assertEquals(8.0, y.value) // y = x * x * x = 8 + assertEquals(12.0, y.derivative(x)) // dy/dx = 3 * x * x = 12 + } + + @Test + fun testDiv() { + val z = dxy(x to 5.0, y to 2.0) { x, y -> + x / y + } + assertEquals(2.5, z.value) // z = x / y = 2.5 + assertEquals(0.5, z.derivative(x)) // dz/dx = 1 / y = 0.5 + assertEquals(-1.25, z.derivative(y)) // dz/dy = -x / y^2 = -1.25 + } + + @Test + fun testPow3() { + val y = dx(x to 2.0) { x -> + // diff w.r.t this x at 2 + pow(x, 3) + } + assertEquals(8.0, y.value) // y = x ^ 3 = 8 + assertEquals(12.0, y.derivative(x)) // dy/dx = 3 * x ^ 2 = 12 + } + + @Test + fun testPowFull() { + val z = dxy(x to 2.0, y to 3.0) { x, y -> + pow(x, y) + } + assertApprox(8.0, z.value) // z = x ^ y = 8 + assertApprox(12.0, z.derivative(x)) // dz/dx = y * x ^ (y - 1) = 12 + assertApprox(8.0 * kotlin.math.ln(2.0), z.derivative(y)) // dz/dy = x ^ y * ln(x) + } + + @Test + fun testFromPaper() { + val y = dx(x to 3.0) { x -> 2 * x + x * x * x } + assertEquals(33.0, y.value) // y = 2 * x + x * x * x = 33 + assertEquals(29.0, y.derivative(x)) // dy/dx = 2 + 3 * x * x = 29 + } + + @Test + fun testInnerVariable() { + val y = dx(x to 1.0) { x -> + const(1.0) * x + } + assertEquals(1.0, y.value) // y = x ^ n = 1 + assertEquals(1.0, y.derivative(x)) // dy/dx = n * x ^ (n - 1) = n - 1 + } + + @Test + fun testLongChain() { + val n = 10_000 + val y = dx(x to 1.0) { x -> + var res = const(1.0) + for (i in 1..n) res *= x + res + } + assertEquals(1.0, y.value) // y = x ^ n = 1 + assertEquals(n.toDouble(), y.derivative(x)) // dy/dx = n * x ^ (n - 1) = n - 1 + } + + @Test + fun testExample() { + val y = dx(x to 2.0) { x -> sqr(x) + 5 * x + 3 } + assertEquals(17.0, y.value) // the value of result (y) + assertEquals(9.0, y.derivative(x)) // dy/dx + } + + @Test + fun testSqrt() { + val y = dx(x to 16.0) { x -> sqrt(x) } + assertEquals(4.0, y.value) // y = x ^ 1/2 = 4 + assertEquals(1.0 / 8, y.derivative(x)) // dy/dx = 1/2 / x ^ 1/4 = 1/8 + } + + @Test + fun testSin() { + val y = dx(x to PI / 6.0) { x -> sin(x) } + assertApprox(0.5, y.value) // y = sin(PI/6) = 0.5 + assertApprox(sqrt(3.0) / 2, y.derivative(x)) // dy/dx = cos(pi/6) = sqrt(3)/2 + } + + @Test + fun testCos() { + val y = dx(x to PI / 6) { x -> cos(x) } + assertApprox(sqrt(3.0) / 2, y.value) //y = cos(pi/6) = sqrt(3)/2 + assertApprox(-0.5, y.derivative(x)) // dy/dx = -sin(pi/6) = -0.5 + } + + @Test + fun testTan() { + val y = dx(x to PI / 6) { x -> tan(x) } + assertApprox(1.0 / sqrt(3.0), y.value) // y = tan(pi/6) = 1/sqrt(3) + assertApprox(4.0 / 3.0, y.derivative(x)) // dy/dx = sec(pi/6)^2 = 4/3 + } + + @Test + fun testAsin() { + val y = dx(x to PI / 6) { x -> asin(x) } + assertApprox(kotlin.math.asin(PI / 6.0), y.value) // y = asin(pi/6) + assertApprox(6.0 / sqrt(36 - PI * PI), y.derivative(x)) // dy/dx = 6/sqrt(36-pi^2) + } + + @Test + fun testAcos() { + val y = dx(x to PI / 6) { x -> acos(x) } + assertApprox(kotlin.math.acos(PI / 6.0), y.value) // y = acos(pi/6) + assertApprox(-6.0 / sqrt(36.0 - PI * PI), y.derivative(x)) // dy/dx = -6/sqrt(36-pi^2) + } + + @Test + fun testAtan() { + val y = dx(x to PI / 6) { x -> atan(x) } + assertApprox(kotlin.math.atan(PI / 6.0), y.value) // y = atan(pi/6) + assertApprox(36.0 / (36.0 + PI * PI), y.derivative(x)) // dy/dx = 36/(36+pi^2) + } + + @Test + fun testSinh() { + val y = dx(x to 0.0) { x -> sinh(x) } + assertApprox(kotlin.math.sinh(0.0), y.value) // y = sinh(0) + assertApprox(kotlin.math.cosh(0.0), y.derivative(x)) // dy/dx = cosh(0) + } + + @Test + fun testCosh() { + val y = dx(x to 0.0) { x -> cosh(x) } + assertApprox(1.0, y.value) //y = cosh(0) + assertApprox(0.0, y.derivative(x)) // dy/dx = sinh(0) + } + + @Test + fun testTanh() { + val y = dx(x to PI / 6) { x -> tanh(x) } + assertApprox(1.0 / sqrt(3.0), y.value) // y = tanh(pi/6) + assertApprox(1.0 / kotlin.math.cosh(PI / 6.0).pow(2), y.derivative(x)) // dy/dx = sech(pi/6)^2 + } + + @Test + fun testAsinh() { + val y = dx(x to PI / 6) { x -> asinh(x) } + assertApprox(kotlin.math.asinh(PI / 6.0), y.value) // y = asinh(pi/6) + assertApprox(6.0 / sqrt(36 + PI * PI), y.derivative(x)) // dy/dx = 6/sqrt(pi^2+36) + } + + @Test + fun testAcosh() { + val y = dx(x to PI / 6) { x -> acosh(x) } + assertApprox(kotlin.math.acosh(PI / 6.0), y.value) // y = acosh(pi/6) + assertApprox(-6.0 / sqrt(36.0 - PI * PI), y.derivative(x)) // dy/dx = -6/sqrt(36-pi^2) + } + + @Test + fun testAtanh() { + val y = dx(x to PI / 6) { x -> atanh(x) } + assertApprox(kotlin.math.atanh(PI / 6.0), y.value) // y = atanh(pi/6) + assertApprox(-36.0 / (PI * PI - 36.0), y.derivative(x)) // dy/dx = -36/(pi^2-36) + } + + @Test + fun testDivGrad() { + val res = dxy(x to 1.0, y to 2.0) { x, y -> x * x + y * y } + assertEquals(6.0, res.div()) + assertTrue(res.grad(x, y).contentEquals(doubleArrayOf(2.0, 4.0).asBuffer())) + } + + private fun assertApprox(a: Double, b: Double) { + if ((a - b) > 1e-10) assertEquals(a, b) + } +} diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/misc/AutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/misc/AutoDiffTest.kt deleted file mode 100644 index 3b1813185..000000000 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/misc/AutoDiffTest.kt +++ /dev/null @@ -1,261 +0,0 @@ -package kscience.kmath.misc - -import kscience.kmath.operations.RealField -import kscience.kmath.structures.asBuffer -import kotlin.math.PI -import kotlin.math.pow -import kotlin.math.sqrt -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class AutoDiffTest { - inline fun deriv(body: AutoDiffField.() -> Variable): DerivationResult = - RealField.deriv(body) - - @Test - fun testPlusX2() { - val x = Variable(3.0) // diff w.r.t this x at 3 - val y = deriv { x + x } - assertEquals(6.0, y.value) // y = x + x = 6 - assertEquals(2.0, y.deriv(x)) // dy/dx = 2 - } - - @Test - fun testPlus() { - // two variables - val x = Variable(2.0) - val y = Variable(3.0) - val z = deriv { x + y } - assertEquals(5.0, z.value) // z = x + y = 5 - assertEquals(1.0, z.deriv(x)) // dz/dx = 1 - assertEquals(1.0, z.deriv(y)) // dz/dy = 1 - } - - @Test - fun testMinus() { - // two variables - val x = Variable(7.0) - val y = Variable(3.0) - val z = deriv { x - y } - assertEquals(4.0, z.value) // z = x - y = 4 - assertEquals(1.0, z.deriv(x)) // dz/dx = 1 - assertEquals(-1.0, z.deriv(y)) // dz/dy = -1 - } - - @Test - fun testMulX2() { - val x = Variable(3.0) // diff w.r.t this x at 3 - val y = deriv { x * x } - assertEquals(9.0, y.value) // y = x * x = 9 - assertEquals(6.0, y.deriv(x)) // dy/dx = 2 * x = 7 - } - - @Test - fun testSqr() { - val x = Variable(3.0) - val y = deriv { sqr(x) } - assertEquals(9.0, y.value) // y = x ^ 2 = 9 - assertEquals(6.0, y.deriv(x)) // dy/dx = 2 * x = 7 - } - - @Test - fun testSqrSqr() { - val x = Variable(2.0) - val y = deriv { sqr(sqr(x)) } - assertEquals(16.0, y.value) // y = x ^ 4 = 16 - assertEquals(32.0, y.deriv(x)) // dy/dx = 4 * x^3 = 32 - } - - @Test - fun testX3() { - val x = Variable(2.0) // diff w.r.t this x at 2 - val y = deriv { x * x * x } - assertEquals(8.0, y.value) // y = x * x * x = 8 - assertEquals(12.0, y.deriv(x)) // dy/dx = 3 * x * x = 12 - } - - @Test - fun testDiv() { - val x = Variable(5.0) - val y = Variable(2.0) - val z = deriv { x / y } - assertEquals(2.5, z.value) // z = x / y = 2.5 - assertEquals(0.5, z.deriv(x)) // dz/dx = 1 / y = 0.5 - assertEquals(-1.25, z.deriv(y)) // dz/dy = -x / y^2 = -1.25 - } - - @Test - fun testPow3() { - val x = Variable(2.0) // diff w.r.t this x at 2 - val y = deriv { pow(x, 3) } - assertEquals(8.0, y.value) // y = x ^ 3 = 8 - assertEquals(12.0, y.deriv(x)) // dy/dx = 3 * x ^ 2 = 12 - } - - @Test - fun testPowFull() { - val x = Variable(2.0) - val y = Variable(3.0) - val z = deriv { pow(x, y) } - assertApprox(8.0, z.value) // z = x ^ y = 8 - assertApprox(12.0, z.deriv(x)) // dz/dx = y * x ^ (y - 1) = 12 - assertApprox(8.0 * kotlin.math.ln(2.0), z.deriv(y)) // dz/dy = x ^ y * ln(x) - } - - @Test - fun testFromPaper() { - val x = Variable(3.0) - val y = deriv { 2 * x + x * x * x } - assertEquals(33.0, y.value) // y = 2 * x + x * x * x = 33 - assertEquals(29.0, y.deriv(x)) // dy/dx = 2 + 3 * x * x = 29 - } - - @Test - fun testInnerVariable() { - val x = Variable(1.0) - val y = deriv { - Variable(1.0) * x - } - assertEquals(1.0, y.value) // y = x ^ n = 1 - assertEquals(1.0, y.deriv(x)) // dy/dx = n * x ^ (n - 1) = n - 1 - } - - @Test - fun testLongChain() { - val n = 10_000 - val x = Variable(1.0) - val y = deriv { - var res = Variable(1.0) - for (i in 1..n) res *= x - res - } - assertEquals(1.0, y.value) // y = x ^ n = 1 - assertEquals(n.toDouble(), y.deriv(x)) // dy/dx = n * x ^ (n - 1) = n - 1 - } - - @Test - fun testExample() { - val x = Variable(2.0) - val y = deriv { sqr(x) + 5 * x + 3 } - assertEquals(17.0, y.value) // the value of result (y) - assertEquals(9.0, y.deriv(x)) // dy/dx - } - - @Test - fun testSqrt() { - val x = Variable(16.0) - val y = deriv { sqrt(x) } - assertEquals(4.0, y.value) // y = x ^ 1/2 = 4 - assertEquals(1.0 / 8, y.deriv(x)) // dy/dx = 1/2 / x ^ 1/4 = 1/8 - } - - @Test - fun testSin() { - val x = Variable(PI / 6.0) - val y = deriv { sin(x) } - assertApprox(0.5, y.value) // y = sin(PI/6) = 0.5 - assertApprox(sqrt(3.0) / 2, y.deriv(x)) // dy/dx = cos(pi/6) = sqrt(3)/2 - } - - @Test - fun testCos() { - val x = Variable(PI / 6) - val y = deriv { cos(x) } - assertApprox(sqrt(3.0) / 2, y.value) //y = cos(pi/6) = sqrt(3)/2 - assertApprox(-0.5, y.deriv(x)) // dy/dx = -sin(pi/6) = -0.5 - } - - @Test - fun testTan() { - val x = Variable(PI / 6) - val y = deriv { tan(x) } - assertApprox(1.0 / sqrt(3.0), y.value) // y = tan(pi/6) = 1/sqrt(3) - assertApprox(4.0 / 3.0, y.deriv(x)) // dy/dx = sec(pi/6)^2 = 4/3 - } - - @Test - fun testAsin() { - val x = Variable(PI / 6) - val y = deriv { asin(x) } - assertApprox(kotlin.math.asin(PI / 6.0), y.value) // y = asin(pi/6) - assertApprox(6.0 / sqrt(36 - PI * PI), y.deriv(x)) // dy/dx = 6/sqrt(36-pi^2) - } - - @Test - fun testAcos() { - val x = Variable(PI / 6) - val y = deriv { acos(x) } - assertApprox(kotlin.math.acos(PI / 6.0), y.value) // y = acos(pi/6) - assertApprox(-6.0 / sqrt(36.0 - PI * PI), y.deriv(x)) // dy/dx = -6/sqrt(36-pi^2) - } - - @Test - fun testAtan() { - val x = Variable(PI / 6) - val y = deriv { atan(x) } - assertApprox(kotlin.math.atan(PI / 6.0), y.value) // y = atan(pi/6) - assertApprox(36.0 / (36.0 + PI * PI), y.deriv(x)) // dy/dx = 36/(36+pi^2) - } - - @Test - fun testSinh() { - val x = Variable(0.0) - val y = deriv { sinh(x) } - assertApprox(kotlin.math.sinh(0.0), y.value) // y = sinh(0) - assertApprox(kotlin.math.cosh(0.0), y.deriv(x)) // dy/dx = cosh(0) - } - - @Test - fun testCosh() { - val x = Variable(0.0) - val y = deriv { cosh(x) } - assertApprox(1.0, y.value) //y = cosh(0) - assertApprox(0.0, y.deriv(x)) // dy/dx = sinh(0) - } - - @Test - fun testTanh() { - val x = Variable(PI / 6) - val y = deriv { tanh(x) } - assertApprox(1.0 / sqrt(3.0), y.value) // y = tanh(pi/6) - assertApprox(1.0 / kotlin.math.cosh(PI / 6.0).pow(2), y.deriv(x)) // dy/dx = sech(pi/6)^2 - } - - @Test - fun testAsinh() { - val x = Variable(PI / 6) - val y = deriv { asinh(x) } - assertApprox(kotlin.math.asinh(PI / 6.0), y.value) // y = asinh(pi/6) - assertApprox(6.0 / sqrt(36 + PI * PI), y.deriv(x)) // dy/dx = 6/sqrt(pi^2+36) - } - - @Test - fun testAcosh() { - val x = Variable(PI / 6) - val y = deriv { acosh(x) } - assertApprox(kotlin.math.acosh(PI / 6.0), y.value) // y = acosh(pi/6) - assertApprox(-6.0 / sqrt(36.0 - PI * PI), y.deriv(x)) // dy/dx = -6/sqrt(36-pi^2) - } - - @Test - fun testAtanh() { - val x = Variable(PI / 6.0) - val y = deriv { atanh(x) } - assertApprox(kotlin.math.atanh(PI / 6.0), y.value) // y = atanh(pi/6) - assertApprox(-36.0 / (PI * PI - 36.0), y.deriv(x)) // dy/dx = -36/(pi^2-36) - } - - @Test - fun testDivGrad() { - val x = Variable(1.0) - val y = Variable(2.0) - val res = deriv { x * x + y * y } - assertEquals(6.0, res.div()) - assertTrue(res.grad(x, y).contentEquals(doubleArrayOf(2.0, 4.0).asBuffer())) - } - - private fun assertApprox(a: Double, b: Double) { - if ((a - b) > 1e-10) assertEquals(a, b) - } -} From 6386f2b894cf27f7d257d25d33d7d7b20e679b06 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 20 Oct 2020 10:03:09 +0300 Subject: [PATCH 100/199] Update build tools --- settings.gradle.kts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 323d5d15f..0f549f9ab 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,8 +10,8 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlin-dev/") } - val toolsVersion = "0.6.3-dev-1.4.20-M1" - val kotlinVersion = "1.4.20-M1" + val toolsVersion = "0.6.4-dev-1.4.20-M2" + val kotlinVersion = "1.4.20-M2" plugins { id("kotlinx.benchmark") version "0.2.0-dev-20" @@ -39,6 +39,6 @@ include( ":kmath-for-real", ":kmath-geometry", ":kmath-ast", - ":examples", - ":kmath-ejml" + ":kmath-ejml", + ":examples" ) From 457931dd86c89a61130a881fa8629c1467b47eef Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 21 Oct 2020 02:26:54 +0700 Subject: [PATCH 101/199] Update Gradle --- CHANGELOG.md | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89e02d3b1..214730ecc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ ### Changed - Package changed from `scientifik` to `kscience.kmath`. -- Gradle version: 6.6 -> 6.6.1 +- Gradle version: 6.6 -> 6.7 - Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`) - `Polynomial` secondary constructor made function. - Kotlin version: 1.3.72 -> 1.4.20-M1 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 12d38de6a..be52383ef 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From ae07652d9ec60ba632d985281c799d9493653e36 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 21 Oct 2020 11:38:28 +0300 Subject: [PATCH 102/199] Symbol identity is always a string --- .../DerivativeStructureExpression.kt | 4 +- .../kscience/kmath/expressions/Expression.kt | 2 +- .../kmath/expressions/SimpleAutoDiff.kt | 140 +++++++++--------- .../kmath/expressions/SimpleAutoDiffTest.kt | 8 +- 4 files changed, 73 insertions(+), 81 deletions(-) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 9a27e40cd..2ec69255e 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -25,13 +25,13 @@ public class DerivativeStructureField( */ public inner class DerivativeStructureSymbol(symbol: Symbol, value: Double) : DerivativeStructure(bindings.size, order, bindings.keys.indexOf(symbol), value), Symbol { - override val identity: Any = symbol.identity + override val identity: String = symbol.identity } /** * Identity-based symbol bindings map */ - private val variables: Map = bindings.entries.associate { (key, value) -> + private val variables: Map = bindings.entries.associate { (key, value) -> key.identity to DerivativeStructureSymbol(key, value) } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index d64eb5a55..bd83261f7 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -12,7 +12,7 @@ public interface Symbol { * Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol. * By default uses object identity */ - public val identity: Any get() = this + public val identity: String } /** diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt index 5e8fe3e99..a718154d3 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -12,20 +12,7 @@ import kotlin.contracts.contract */ -/** - * A [Symbol] with bound value - */ -public interface BoundSymbol : Symbol { - public val value: T -} - -/** - * Bind a [Symbol] to a [value] and produce [BoundSymbol] - */ -public fun Symbol.bind(value: T): BoundSymbol = object : BoundSymbol { - override val identity = this@bind.identity - override val value: T = value -} +public open class AutoDiffValue(public val value: T) /** * Represents result of [withAutoDiff] call. @@ -36,10 +23,10 @@ public fun Symbol.bind(value: T): BoundSymbol = object : BoundSymbol { * @property context The field over [T]. */ public class DerivationResult( - override val value: T, - private val derivativeValues: Map, + public val value: T, + private val derivativeValues: Map, public val context: Field, -) : BoundSymbol { +) { /** * Returns derivative of [variable] or returns [Ring.zero] in [context]. */ @@ -76,8 +63,8 @@ public fun DerivationResult.grad(vararg variables: Symbol): Point> F.withAutoDiff( - bindings: Collection>, - body: AutoDiffField.() -> BoundSymbol, + bindings: Map, + body: AutoDiffField.() -> AutoDiffValue, ): DerivationResult { contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) } @@ -86,14 +73,14 @@ public fun > F.withAutoDiff( public fun > F.withAutoDiff( vararg bindings: Pair, - body: AutoDiffField.() -> BoundSymbol, -): DerivationResult = withAutoDiff(bindings.map { it.first.bind(it.second) }, body) + body: AutoDiffField.() -> AutoDiffValue, +): DerivationResult = withAutoDiff(bindings.toMap(), body) /** * Represents field in context of which functions can be derived. */ public abstract class AutoDiffField> - : Field>, ExpressionAlgebra> { + : Field>, ExpressionAlgebra> { public abstract val context: F @@ -101,7 +88,7 @@ public abstract class AutoDiffField> * A variable accessing inner state of derivatives. * Use this value in inner builders to avoid creating additional derivative bindings. */ - public abstract var BoundSymbol.d: T + public abstract var AutoDiffValue.d: T /** * Performs update of derivative after the rest of the formula in the back-pass. @@ -116,21 +103,21 @@ public abstract class AutoDiffField> */ public abstract fun derive(value: R, block: F.(R) -> Unit): R - public inline fun const(block: F.() -> T): BoundSymbol = const(context.block()) + public inline fun const(block: F.() -> T): AutoDiffValue = const(context.block()) // Overloads for Double constants - override operator fun Number.plus(b: BoundSymbol): BoundSymbol = + override operator fun Number.plus(b: AutoDiffValue): AutoDiffValue = derive(const { this@plus.toDouble() * one + b.value }) { z -> b.d += z.d } - override operator fun BoundSymbol.plus(b: Number): BoundSymbol = b.plus(this) + override operator fun AutoDiffValue.plus(b: Number): AutoDiffValue = b.plus(this) - override operator fun Number.minus(b: BoundSymbol): BoundSymbol = + override operator fun Number.minus(b: AutoDiffValue): AutoDiffValue = derive(const { this@minus.toDouble() * one - b.value }) { z -> b.d -= z.d } - override operator fun BoundSymbol.minus(b: Number): BoundSymbol = + override operator fun AutoDiffValue.minus(b: Number): AutoDiffValue = derive(const { this@minus.value - one * b.toDouble() }) { z -> this@minus.d += z.d } } @@ -139,14 +126,14 @@ public abstract class AutoDiffField> */ private class AutoDiffContext>( override val context: F, - bindings: Collection>, + bindings: Map, ) : AutoDiffField() { // this stack contains pairs of blocks and values to apply them to private var stack: Array = arrayOfNulls(8) private var sp: Int = 0 - private val derivatives: MutableMap = hashMapOf() - override val zero: BoundSymbol get() = const(context.zero) - override val one: BoundSymbol get() = const(context.one) + private val derivatives: MutableMap, T> = hashMapOf() + override val zero: AutoDiffValue get() = const(context.zero) + override val one: AutoDiffValue get() = const(context.one) /** * Differentiable variable with value and derivative of differentiation ([withAutoDiff]) result @@ -155,17 +142,23 @@ private class AutoDiffContext>( * @param T the non-nullable type of value. * @property value The value of this variable. */ - private class AutoDiffVariableWithDeriv(override val value: T, var d: T) : BoundSymbol + private class AutoDiffVariableWithDeriv( + override val identity: String, + value: T, + var d: T, + ) : AutoDiffValue(value), Symbol - private val bindings: Map> = bindings.associateBy { it.identity } + private val bindings: Map> = bindings.entries.associate { + it.key.identity to AutoDiffVariableWithDeriv(it.key.identity, it.value, context.zero) + } - override fun bindOrNull(symbol: Symbol): BoundSymbol? = bindings[symbol.identity] + override fun bindOrNull(symbol: Symbol): AutoDiffVariableWithDeriv? = bindings[symbol.identity] - override fun const(value: T): BoundSymbol = AutoDiffVariableWithDeriv(value, context.zero) + override fun const(value: T): AutoDiffValue = AutoDiffValue(value) - override var BoundSymbol.d: T - get() = (this as? AutoDiffVariableWithDeriv)?.d ?: derivatives[identity] ?: context.zero - set(value) = if (this is AutoDiffVariableWithDeriv) d = value else derivatives[identity] = value + override var AutoDiffValue.d: T + get() = (this as? AutoDiffVariableWithDeriv)?.d ?: derivatives[this] ?: context.zero + set(value) = if (this is AutoDiffVariableWithDeriv) d = value else derivatives[this] = value @Suppress("UNCHECKED_CAST") override fun derive(value: R, block: F.(R) -> Unit): R { @@ -187,34 +180,34 @@ private class AutoDiffContext>( // Basic math (+, -, *, /) - override fun add(a: BoundSymbol, b: BoundSymbol): BoundSymbol = + override fun add(a: AutoDiffValue, b: AutoDiffValue): AutoDiffValue = derive(const { a.value + b.value }) { z -> a.d += z.d b.d += z.d } - override fun multiply(a: BoundSymbol, b: BoundSymbol): BoundSymbol = + override fun multiply(a: AutoDiffValue, b: AutoDiffValue): AutoDiffValue = derive(const { a.value * b.value }) { z -> a.d += z.d * b.value b.d += z.d * a.value } - override fun divide(a: BoundSymbol, b: BoundSymbol): BoundSymbol = + override fun divide(a: AutoDiffValue, b: AutoDiffValue): AutoDiffValue = derive(const { a.value / b.value }) { z -> a.d += z.d / b.value b.d -= z.d * a.value / (b.value * b.value) } - override fun multiply(a: BoundSymbol, k: Number): BoundSymbol = + override fun multiply(a: AutoDiffValue, k: Number): AutoDiffValue = derive(const { k.toDouble() * a.value }) { z -> a.d += z.d * k.toDouble() } - inline fun derivate(function: AutoDiffField.() -> BoundSymbol): DerivationResult { + inline fun derivate(function: AutoDiffField.() -> AutoDiffValue): DerivationResult { val result = function() result.d = context.one // computing derivative w.r.t result runBackwardPass() - return DerivationResult(result.value, derivatives, context) + return DerivationResult(result.value, bindings.mapValues { it.value.d }, context) } } @@ -223,11 +216,11 @@ private class AutoDiffContext>( */ public class SimpleAutoDiffExpression>( public val field: F, - public val function: AutoDiffField.() -> BoundSymbol, + public val function: AutoDiffField.() -> AutoDiffValue, ) : DifferentiableExpression { public override operator fun invoke(arguments: Map): T { - val bindings = arguments.entries.map { it.key.bind(it.value) } - return AutoDiffContext(field, bindings).function().value + //val bindings = arguments.entries.map { it.key.bind(it.value) } + return AutoDiffContext(field, arguments).function().value } /** @@ -237,8 +230,8 @@ public class SimpleAutoDiffExpression>( val dSymbol = orders.entries.singleOrNull { it.value == 1 } ?: error("SimpleAutoDiff supports only first order derivatives") return Expression { arguments -> - val bindings = arguments.entries.map { it.key.bind(it.value) } - val derivationResult = AutoDiffContext(field, bindings).derivate(function) + //val bindings = arguments.entries.map { it.key.bind(it.value) } + val derivationResult = AutoDiffContext(field, arguments).derivate(function) derivationResult.derivative(dSymbol.key) } } @@ -248,82 +241,81 @@ public class SimpleAutoDiffExpression>( // Extensions for differentiation of various basic mathematical functions // x ^ 2 -public fun > AutoDiffField.sqr(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.sqr(x: AutoDiffValue): AutoDiffValue = derive(const { x.value * x.value }) { z -> x.d += z.d * 2 * x.value } // x ^ 1/2 -public fun > AutoDiffField.sqrt(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.sqrt(x: AutoDiffValue): AutoDiffValue = derive(const { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value } // x ^ y (const) public fun > AutoDiffField.pow( - x: BoundSymbol, + x: AutoDiffValue, y: Double, -): BoundSymbol = +): AutoDiffValue = derive(const { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) } public fun > AutoDiffField.pow( - x: BoundSymbol, + x: AutoDiffValue, y: Int, -): BoundSymbol = - pow(x, y.toDouble()) +): AutoDiffValue = pow(x, y.toDouble()) // exp(x) -public fun > AutoDiffField.exp(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.exp(x: AutoDiffValue): AutoDiffValue = derive(const { exp(x.value) }) { z -> x.d += z.d * z.value } // ln(x) -public fun > AutoDiffField.ln(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.ln(x: AutoDiffValue): AutoDiffValue = derive(const { ln(x.value) }) { z -> x.d += z.d / x.value } // x ^ y (any) public fun > AutoDiffField.pow( - x: BoundSymbol, - y: BoundSymbol, -): BoundSymbol = + x: AutoDiffValue, + y: AutoDiffValue, +): AutoDiffValue = exp(y * ln(x)) // sin(x) -public fun > AutoDiffField.sin(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.sin(x: AutoDiffValue): AutoDiffValue = derive(const { sin(x.value) }) { z -> x.d += z.d * cos(x.value) } // cos(x) -public fun > AutoDiffField.cos(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.cos(x: AutoDiffValue): AutoDiffValue = derive(const { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) } -public fun > AutoDiffField.tan(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.tan(x: AutoDiffValue): AutoDiffValue = derive(const { tan(x.value) }) { z -> val c = cos(x.value) x.d += z.d / (c * c) } -public fun > AutoDiffField.asin(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.asin(x: AutoDiffValue): AutoDiffValue = derive(const { asin(x.value) }) { z -> x.d += z.d / sqrt(one - x.value * x.value) } -public fun > AutoDiffField.acos(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.acos(x: AutoDiffValue): AutoDiffValue = derive(const { acos(x.value) }) { z -> x.d -= z.d / sqrt(one - x.value * x.value) } -public fun > AutoDiffField.atan(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.atan(x: AutoDiffValue): AutoDiffValue = derive(const { atan(x.value) }) { z -> x.d += z.d / (one + x.value * x.value) } -public fun > AutoDiffField.sinh(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.sinh(x: AutoDiffValue): AutoDiffValue = derive(const { sin(x.value) }) { z -> x.d += z.d * cosh(x.value) } -public fun > AutoDiffField.cosh(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.cosh(x: AutoDiffValue): AutoDiffValue = derive(const { cos(x.value) }) { z -> x.d += z.d * sinh(x.value) } -public fun > AutoDiffField.tanh(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.tanh(x: AutoDiffValue): AutoDiffValue = derive(const { tan(x.value) }) { z -> val c = cosh(x.value) x.d += z.d / (c * c) } -public fun > AutoDiffField.asinh(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.asinh(x: AutoDiffValue): AutoDiffValue = derive(const { asinh(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) } -public fun > AutoDiffField.acosh(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.acosh(x: AutoDiffValue): AutoDiffValue = derive(const { acosh(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) } -public fun > AutoDiffField.atanh(x: BoundSymbol): BoundSymbol = +public fun > AutoDiffField.atanh(x: AutoDiffValue): AutoDiffValue = derive(const { atanh(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) } diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt index ca5b626fd..ef4a6a06a 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -12,23 +12,23 @@ import kotlin.test.assertTrue class SimpleAutoDiffTest { fun d( vararg bindings: Pair, - body: AutoDiffField.() -> BoundSymbol, + body: AutoDiffField.() -> AutoDiffValue, ): DerivationResult = RealField.withAutoDiff(bindings = bindings, body) fun dx( xBinding: Pair, - body: AutoDiffField.(x: BoundSymbol) -> BoundSymbol, + body: AutoDiffField.(x: AutoDiffValue) -> AutoDiffValue, ): DerivationResult = RealField.withAutoDiff(xBinding) { body(bind(xBinding.first)) } fun dxy( xBinding: Pair, yBinding: Pair, - body: AutoDiffField.(x: BoundSymbol, y: BoundSymbol) -> BoundSymbol, + body: AutoDiffField.(x: AutoDiffValue, y: AutoDiffValue) -> AutoDiffValue, ): DerivationResult = RealField.withAutoDiff(xBinding, yBinding) { body(bind(xBinding.first), bind(yBinding.first)) } - fun diff(block: AutoDiffField.() -> BoundSymbol): SimpleAutoDiffExpression { + fun diff(block: AutoDiffField.() -> AutoDiffValue): SimpleAutoDiffExpression { return SimpleAutoDiffExpression(RealField, block) } From 04d3f4a99f313132c451697099994d64b1ae1453 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 22 Oct 2020 09:28:18 +0300 Subject: [PATCH 103/199] Fix ASM --- gradle/wrapper/gradle-wrapper.properties | 2 +- .../kscience/kmath/asm/internal/AsmBuilder.kt | 16 ++++------------ .../kscience/kmath/asm/internal/mapIntrinsics.kt | 7 +++---- .../kscience/kmath/expressions/SimpleAutoDiff.kt | 4 +++- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 12d38de6a..be52383ef 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index 06f02a94d..a1e482103 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -25,7 +25,7 @@ internal class AsmBuilder internal constructor( private val classOfT: Class<*>, private val algebra: Algebra, private val className: String, - private val invokeLabel0Visitor: AsmBuilder.() -> Unit + private val invokeLabel0Visitor: AsmBuilder.() -> Unit, ) { /** * Internal classloader of [AsmBuilder] with alias to define class from byte array. @@ -379,22 +379,14 @@ internal class AsmBuilder internal constructor( * Loads a variable [name] from arguments [Map] parameter of [Expression.invoke]. The [defaultValue] may be * provided. */ - internal fun loadVariable(name: String, defaultValue: T? = null): Unit = invokeMethodVisitor.run { + internal fun loadVariable(name: String): Unit = invokeMethodVisitor.run { load(invokeArgumentsVar, MAP_TYPE) aconst(name) - if (defaultValue != null) - loadTConstant(defaultValue) - invokestatic( MAP_INTRINSICS_TYPE.internalName, "getOrFail", - - Type.getMethodDescriptor( - OBJECT_TYPE, - MAP_TYPE, - OBJECT_TYPE, - *OBJECT_TYPE.wrapToArrayIf { defaultValue != null }), + Type.getMethodDescriptor(OBJECT_TYPE, MAP_TYPE, STRING_TYPE), false ) @@ -429,7 +421,7 @@ internal class AsmBuilder internal constructor( method: String, descriptor: String, expectedArity: Int, - opcode: Int = INVOKEINTERFACE + opcode: Int = INVOKEINTERFACE, ) { run loop@{ repeat(expectedArity) { diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt index 09e9a71b0..588b9611a 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/mapIntrinsics.kt @@ -3,12 +3,11 @@ package kscience.kmath.asm.internal import kscience.kmath.expressions.StringSymbol +import kscience.kmath.expressions.Symbol /** - * Gets value with given [key] or throws [IllegalStateException] whenever it is not present. + * Gets value with given [key] or throws [NoSuchElementException] whenever it is not present. * * @author Iaroslav Postovalov */ -@JvmOverloads -internal fun Map.getOrFail(key: K, default: V? = null): V = - this[StringSymbol(key.toString())] ?: default ?: error("Parameter not found: $key") +internal fun Map.getOrFail(key: String): V = getValue(StringSymbol(key)) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt index a718154d3..af7c8fbf2 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -146,7 +146,9 @@ private class AutoDiffContext>( override val identity: String, value: T, var d: T, - ) : AutoDiffValue(value), Symbol + ) : AutoDiffValue(value), Symbol{ + override fun toString(): String = identity + } private val bindings: Map> = bindings.entries.associate { it.key.identity to AutoDiffVariableWithDeriv(it.key.identity, it.value, context.zero) From f7614da230a9e1491263b71b955110382f58a9e4 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 22 Oct 2020 11:27:08 +0300 Subject: [PATCH 104/199] Refactoring --- .../DerivativeStructureExpression.kt | 3 +++ .../expressions/DifferentiableExpression.kt | 21 ++++++++++++++++ .../kscience/kmath/expressions/Expression.kt | 19 +++----------- .../FunctionalExpressionAlgebra.kt | 5 ++-- .../kmath/expressions/SimpleAutoDiff.kt | 14 ++++++----- .../kmath/expressions/SimpleAutoDiffTest.kt | 25 ++++++++++++------- 6 files changed, 55 insertions(+), 32 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 2ec69255e..a1ee91419 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -26,6 +26,9 @@ public class DerivativeStructureField( public inner class DerivativeStructureSymbol(symbol: Symbol, value: Double) : DerivativeStructure(bindings.size, order, bindings.keys.indexOf(symbol), value), Symbol { override val identity: String = symbol.identity + override fun toString(): String = identity + override fun equals(other: Any?): Boolean = this.identity == (other as? Symbol)?.identity + override fun hashCode(): Int = identity.hashCode() } /** diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt new file mode 100644 index 000000000..841531d01 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt @@ -0,0 +1,21 @@ +package kscience.kmath.expressions + +/** + * And object that could be differentiated + */ +public interface Differentiable { + public fun derivative(orders: Map): T +} + +public interface DifferentiableExpression : Differentiable>, Expression + +public fun DifferentiableExpression.derivative(vararg orders: Pair): Expression = + derivative(mapOf(*orders)) + +public fun DifferentiableExpression.derivative(symbol: Symbol): Expression = derivative(symbol to 1) + +public fun DifferentiableExpression.derivative(name: String): Expression = derivative(StringSymbol(name) to 1) + +//public interface DifferentiableExpressionBuilder>: ExpressionBuilder { +// public override fun expression(block: A.() -> E): DifferentiableExpression +//} diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index bd83261f7..7da5a2529 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -56,21 +56,6 @@ public operator fun Expression.invoke(vararg pairs: Pair): T = public operator fun Expression.invoke(vararg pairs: Pair): T = invoke(mapOf(*pairs).mapKeys { StringSymbol(it.key) }) -/** - * And object that could be differentiated - */ -public interface Differentiable { - public fun derivative(orders: Map): T -} - -public interface DifferentiableExpression : Differentiable>, Expression - -public fun DifferentiableExpression.derivative(vararg orders: Pair): Expression = - derivative(mapOf(*orders)) - -public fun DifferentiableExpression.derivative(symbol: Symbol): Expression = derivative(symbol to 1) - -public fun DifferentiableExpression.derivative(name: String): Expression = derivative(StringSymbol(name) to 1) /** * A context for expression construction @@ -96,6 +81,10 @@ public interface ExpressionAlgebra : Algebra { public fun const(value: T): E } +//public interface ExpressionBuilder> { +// public fun expression(block: A.() -> E): Expression +//} + /** * Bind a given [Symbol] to this context variable and produce context-specific object. */ 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 9fd15238a..0630e8e4b 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -7,8 +7,9 @@ import kscience.kmath.operations.* * * @param algebra The algebra to provide for Expressions built. */ -public abstract class FunctionalExpressionAlgebra>(public val algebra: A) : - ExpressionAlgebra> { +public abstract class FunctionalExpressionAlgebra>( + public val algebra: A, +) : ExpressionAlgebra> { /** * Builds an Expression of constant expression which does not depend on arguments. */ diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt index af7c8fbf2..e5ea33c81 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -15,11 +15,11 @@ import kotlin.contracts.contract public open class AutoDiffValue(public val value: T) /** - * Represents result of [withAutoDiff] call. + * Represents result of [simpleAutoDiff] call. * * @param T the non-nullable type of value. * @param value the value of result. - * @property withAutoDiff The mapping of differentiated variables to their derivatives. + * @property simpleAutoDiff The mapping of differentiated variables to their derivatives. * @property context The field over [T]. */ public class DerivationResult( @@ -62,7 +62,7 @@ public fun DerivationResult.grad(vararg variables: Symbol): Point> F.withAutoDiff( +public fun > F.simpleAutoDiff( bindings: Map, body: AutoDiffField.() -> AutoDiffValue, ): DerivationResult { @@ -71,10 +71,10 @@ public fun > F.withAutoDiff( return AutoDiffContext(this, bindings).derivate(body) } -public fun > F.withAutoDiff( +public fun > F.simpleAutoDiff( vararg bindings: Pair, body: AutoDiffField.() -> AutoDiffValue, -): DerivationResult = withAutoDiff(bindings.toMap(), body) +): DerivationResult = simpleAutoDiff(bindings.toMap(), body) /** * Represents field in context of which functions can be derived. @@ -136,7 +136,7 @@ private class AutoDiffContext>( override val one: AutoDiffValue get() = const(context.one) /** - * Differentiable variable with value and derivative of differentiation ([withAutoDiff]) result + * Differentiable variable with value and derivative of differentiation ([simpleAutoDiff]) result * with respect to this variable. * * @param T the non-nullable type of value. @@ -148,6 +148,8 @@ private class AutoDiffContext>( var d: T, ) : AutoDiffValue(value), Symbol{ override fun toString(): String = identity + override fun equals(other: Any?): Boolean = this.identity == (other as? Symbol)?.identity + override fun hashCode(): Int = identity.hashCode() } private val bindings: Map> = bindings.entries.associate { diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt index ef4a6a06a..ca8ec1e17 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -10,21 +10,17 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue class SimpleAutoDiffTest { - fun d( - vararg bindings: Pair, - body: AutoDiffField.() -> AutoDiffValue, - ): DerivationResult = RealField.withAutoDiff(bindings = bindings, body) fun dx( xBinding: Pair, body: AutoDiffField.(x: AutoDiffValue) -> AutoDiffValue, - ): DerivationResult = RealField.withAutoDiff(xBinding) { body(bind(xBinding.first)) } + ): DerivationResult = RealField.simpleAutoDiff(xBinding) { body(bind(xBinding.first)) } fun dxy( xBinding: Pair, yBinding: Pair, body: AutoDiffField.(x: AutoDiffValue, y: AutoDiffValue) -> AutoDiffValue, - ): DerivationResult = RealField.withAutoDiff(xBinding, yBinding) { + ): DerivationResult = RealField.simpleAutoDiff(xBinding, yBinding) { body(bind(xBinding.first), bind(yBinding.first)) } @@ -38,7 +34,7 @@ class SimpleAutoDiffTest { @Test fun testPlusX2() { - val y = d(x to 3.0) { + val y = RealField.simpleAutoDiff(x to 3.0) { // diff w.r.t this x at 3 val x = bind(x) x + x @@ -47,10 +43,21 @@ class SimpleAutoDiffTest { assertEquals(2.0, y.derivative(x)) // dy/dx = 2 } + @Test + fun testPlusX2Expr() { + val expr = diff{ + val x = bind(x) + x + x + } + assertEquals(6.0, expr(x to 3.0)) // y = x + x = 6 + assertEquals(2.0, expr.derivative(x)(x to 3.0)) // dy/dx = 2 + } + + @Test fun testPlus() { // two variables - val z = d(x to 2.0, y to 3.0) { + val z = RealField.simpleAutoDiff(x to 2.0, y to 3.0) { val x = bind(x) val y = bind(y) x + y @@ -63,7 +70,7 @@ class SimpleAutoDiffTest { @Test fun testMinus() { // two variables - val z = d(x to 7.0, y to 3.0) { + val z = RealField.simpleAutoDiff(x to 7.0, y to 3.0) { val x = bind(x) val y = bind(y) From 94df61cd439f41873d407902566e0ea279fa1330 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 24 Oct 2020 13:05:36 +0300 Subject: [PATCH 105/199] cleanup --- .../kotlin/kscience/kmath/expressions/Expression.kt | 9 +-------- .../kscience/kmath/expressions/expressionBuilders.kt | 6 ++++++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index 7da5a2529..b523d99b1 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -10,7 +10,6 @@ import kotlin.properties.ReadOnlyProperty public interface Symbol { /** * Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol. - * By default uses object identity */ public val identity: String } @@ -33,8 +32,6 @@ public fun interface Expression { * @return the value. */ public operator fun invoke(arguments: Map): T - - public companion object } /** @@ -81,17 +78,13 @@ public interface ExpressionAlgebra : Algebra { public fun const(value: T): E } -//public interface ExpressionBuilder> { -// public fun expression(block: A.() -> E): Expression -//} - /** * Bind a given [Symbol] to this context variable and produce context-specific object. */ public fun ExpressionAlgebra.bind(symbol: Symbol): E = bindOrNull(symbol) ?: error("Symbol $symbol could not be bound to $this") -public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> +public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> StringSymbol(property.name) } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt index 1702a5921..defbb14ad 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt @@ -7,6 +7,12 @@ import kscience.kmath.operations.Space import kotlin.contracts.InvocationKind import kotlin.contracts.contract + +//public interface ExpressionBuilder> { +// public fun expression(block: A.() -> E): Expression +//} + + /** * Creates a functional expression with this [Space]. */ From d826dd9e8311d04253ffc08ab47d01a02e37d2dc Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 24 Oct 2020 20:33:19 +0300 Subject: [PATCH 106/199] Initial optimization implementation for CM --- CHANGELOG.md | 4 + .../kmath/commons/optimization/optimize.kt | 103 ++++++++++++++++++ .../commons/optimization/OptimizeTest.kt | 37 +++++++ .../kscience/kmath/expressions/Expression.kt | 2 +- .../kmath/expressions/SymbolIndexer.kt | 45 ++++++++ 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt create mode 100644 kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt create mode 100644 kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SymbolIndexer.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 89e02d3b1..109168475 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ - Automatic README generation for features (#139) - Native support for `memory`, `core` and `dimensions` - `kmath-ejml` to supply EJML SimpleMatrix wrapper. +- A separate `Symbol` entity, which is used for global unbound symbol. +- A `Symbol` indexing scope. +- Basic optimization API for Commons-math. ### Changed - Package changed from `scientifik` to `kscience.kmath`. @@ -16,6 +19,7 @@ - `Polynomial` secondary constructor made function. - Kotlin version: 1.3.72 -> 1.4.20-M1 - `kmath-ast` doesn't depend on heavy `kotlin-reflect` library. +- Full autodiff refactoring based on `Symbol` ### Deprecated diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt new file mode 100644 index 000000000..3bf6354ea --- /dev/null +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt @@ -0,0 +1,103 @@ +package kscience.kmath.commons.optimization + +import kscience.kmath.expressions.* +import org.apache.commons.math3.optim.* +import org.apache.commons.math3.optim.nonlinear.scalar.GoalType +import org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer +import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction +import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunctionGradient +import org.apache.commons.math3.optim.nonlinear.scalar.gradient.NonLinearConjugateGradientOptimizer +import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex +import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer + +public typealias ParameterSpacePoint = Map + +public class OptimizationResult(public val point: ParameterSpacePoint, public val value: Double) + +public operator fun PointValuePair.component1(): DoubleArray = point +public operator fun PointValuePair.component2(): Double = value + +public object Optimization { + public const val DEFAULT_RELATIVE_TOLERANCE: Double = 1e-4 + public const val DEFAULT_ABSOLUTE_TOLERANCE: Double = 1e-4 + public const val DEFAULT_MAX_ITER: Int = 1000 +} + + +private fun SymbolIndexer.objectiveFunction(expression: Expression) = ObjectiveFunction { + val args = it.toMap() + expression(args) +} + +private fun SymbolIndexer.objectiveFunctionGradient( + expression: DifferentiableExpression, +) = ObjectiveFunctionGradient { + val args = it.toMap() + DoubleArray(symbols.size) { index -> + expression.derivative(symbols[index])(args) + } +} + +private fun SymbolIndexer.initialGuess(point: ParameterSpacePoint) = InitialGuess(point.toArray()) + +/** + * Optimize expression without derivatives + */ +public fun Expression.optimize( + startingPoint: ParameterSpacePoint, + goalType: GoalType = GoalType.MAXIMIZE, + vararg additionalArguments: OptimizationData, + optimizerBuilder: () -> MultivariateOptimizer = { + SimplexOptimizer( + SimpleValueChecker( + Optimization.DEFAULT_RELATIVE_TOLERANCE, + Optimization.DEFAULT_ABSOLUTE_TOLERANCE, + Optimization.DEFAULT_MAX_ITER + ) + ) + }, +): OptimizationResult = withSymbols(startingPoint.keys) { + val optimizer = optimizerBuilder() + val objectiveFunction = objectiveFunction(this@optimize) + val (point, value) = optimizer.optimize( + objectiveFunction, + initialGuess(startingPoint), + goalType, + MaxEval.unlimited(), + NelderMeadSimplex(symbols.size, 1.0), + *additionalArguments + ) + OptimizationResult(point.toMap(), value) +} + +/** + * Optimize differentiable expression + */ +public fun DifferentiableExpression.optimize( + startingPoint: ParameterSpacePoint, + goalType: GoalType = GoalType.MAXIMIZE, + vararg additionalArguments: OptimizationData, + optimizerBuilder: () -> NonLinearConjugateGradientOptimizer = { + NonLinearConjugateGradientOptimizer( + NonLinearConjugateGradientOptimizer.Formula.FLETCHER_REEVES, + SimpleValueChecker( + Optimization.DEFAULT_RELATIVE_TOLERANCE, + Optimization.DEFAULT_ABSOLUTE_TOLERANCE, + Optimization.DEFAULT_MAX_ITER + ) + ) + }, +): OptimizationResult = withSymbols(startingPoint.keys) { + val optimizer = optimizerBuilder() + val objectiveFunction = objectiveFunction(this@optimize) + val objectiveGradient = objectiveFunctionGradient(this@optimize) + val (point, value) = optimizer.optimize( + objectiveFunction, + objectiveGradient, + initialGuess(startingPoint), + goalType, + MaxEval.unlimited(), + *additionalArguments + ) + OptimizationResult(point.toMap(), value) +} \ No newline at end of file diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt new file mode 100644 index 000000000..779f37dad --- /dev/null +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -0,0 +1,37 @@ +package kscience.kmath.commons.optimization + +import kscience.kmath.commons.expressions.DerivativeStructureExpression +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.Symbol +import kscience.kmath.expressions.symbol +import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer +import org.junit.jupiter.api.Test + +internal class OptimizeTest { + val x by symbol + val y by symbol + + val normal = DerivativeStructureExpression { + val x = bind(x) + val y = bind(y) + exp(-x.pow(2)/2) + exp(-y.pow(2)/2) + } + + val startingPoint: Map = mapOf(x to 1.0, y to 1.0) + + @Test + fun testOptimization() { + val result = normal.optimize(startingPoint) + println(result.point) + println(result.value) + } + + @Test + fun testSimplexOptimization() { + val result = (normal as Expression).optimize(startingPoint){ + SimplexOptimizer(1e-4,1e-4) + } + println(result.point) + println(result.value) + } +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index b523d99b1..7e1eb0cd7 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -35,7 +35,7 @@ public fun interface Expression { } /** - * Invlode an expression without parameters + * Invoke an expression without parameters */ public operator fun Expression.invoke(): T = invoke(emptyMap()) //This method exists to avoid resolution ambiguity of vararg methods diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SymbolIndexer.kt new file mode 100644 index 000000000..aef30c6dd --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SymbolIndexer.kt @@ -0,0 +1,45 @@ +package kscience.kmath.expressions + +/** + * An environment to easy transform indexed variables to symbols and back. + */ +public interface SymbolIndexer { + public val symbols: List + public fun indexOf(symbol: Symbol): Int = symbols.indexOf(symbol) + + public operator fun List.get(symbol: Symbol): T { + require(size == symbols.size) { "The input list size for indexer should be ${symbols.size} but $size found" } + return get(this@SymbolIndexer.indexOf(symbol)) + } + + public operator fun Array.get(symbol: Symbol): T { + require(size == symbols.size) { "The input array size for indexer should be ${symbols.size} but $size found" } + return get(this@SymbolIndexer.indexOf(symbol)) + } + + 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)) + } + + public fun DoubleArray.toMap(): Map { + require(size == symbols.size) { "The input array size for indexer should be ${symbols.size} but $size found" } + return symbols.indices.associate { symbols[it] to get(it) } + } + + + public fun Map.toList(): List = symbols.map { getValue(it) } + + public fun Map.toArray(): DoubleArray = DoubleArray(symbols.size) { getValue(symbols[it]) } +} + +public inline class SimpleSymbolIndexer(override val symbols: List) : SymbolIndexer + +/** + * Execute the block with symbol indexer based on given symbol order + */ +public inline fun withSymbols(vararg symbols: Symbol, block: SymbolIndexer.() -> R): R = + with(SimpleSymbolIndexer(symbols.toList()), block) + +public inline fun withSymbols(symbols: Collection, block: SymbolIndexer.() -> R): R = + with(SimpleSymbolIndexer(symbols.toList()), block) \ No newline at end of file From 1fbe12149dfeae360f93e1c7d2c5d2da29aaa5eb Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 25 Oct 2020 19:31:12 +0300 Subject: [PATCH 107/199] Advanced configuration API for cm-optimization --- .space.kts | 4 +- .../DerivativeStructureExpression.kt | 2 +- .../optimization/CMOptimizationProblem.kt | 100 +++++++++++++++++ .../optimization/OptimizationProblem.kt | 17 +++ .../kmath/commons/optimization/optimize.kt | 105 +++--------------- .../commons/optimization/OptimizeTest.kt | 18 +-- .../expressions/DifferentiableExpression.kt | 21 +++- .../kmath/expressions/SimpleAutoDiff.kt | 17 +-- .../kmath/expressions/SymbolIndexer.kt | 18 ++- 9 files changed, 188 insertions(+), 114 deletions(-) create mode 100644 kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt create mode 100644 kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt diff --git a/.space.kts b/.space.kts index 9dda0cbf7..d70ad6d59 100644 --- a/.space.kts +++ b/.space.kts @@ -1 +1,3 @@ -job("Build") { gradlew("openjdk:11", "build") } +job("Build") { + gradlew("openjdk:11", "build") +} diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index a1ee91419..376fea7a3 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -106,7 +106,7 @@ public class DerivativeStructureExpression( /** * Get the derivative expression with given orders */ - public override fun derivative(orders: Map): Expression = Expression { arguments -> + public override fun derivativeOrNull(orders: Map): Expression = Expression { arguments -> with(DerivativeStructureField(orders.values.maxOrNull() ?: 0, arguments)) { function().derivative(orders) } } } diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt new file mode 100644 index 000000000..f7c136ed2 --- /dev/null +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt @@ -0,0 +1,100 @@ +package kscience.kmath.commons.optimization + +import kscience.kmath.expressions.* +import org.apache.commons.math3.optim.* +import org.apache.commons.math3.optim.nonlinear.scalar.GoalType +import org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer +import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction +import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunctionGradient +import org.apache.commons.math3.optim.nonlinear.scalar.gradient.NonLinearConjugateGradientOptimizer +import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.AbstractSimplex +import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex +import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer +import kotlin.reflect.KClass + +public operator fun PointValuePair.component1(): DoubleArray = point +public operator fun PointValuePair.component2(): Double = value + +public class CMOptimizationProblem( + override val symbols: List, +) : OptimizationProblem, SymbolIndexer { + protected val optimizationData: HashMap, OptimizationData> = HashMap() + private var optimizatorBuilder: (() -> MultivariateOptimizer)? = null + + public var convergenceChecker: ConvergenceChecker = SimpleValueChecker(DEFAULT_RELATIVE_TOLERANCE, + DEFAULT_ABSOLUTE_TOLERANCE, DEFAULT_MAX_ITER) + + private fun addOptimizationData(data: OptimizationData) { + optimizationData[data::class] = data + } + + init { + addOptimizationData(MaxEval.unlimited()) + } + + public fun initialGuess(map: Map): Unit { + addOptimizationData(InitialGuess(map.toDoubleArray())) + } + + public fun expression(expression: Expression): Unit { + val objectiveFunction = ObjectiveFunction { + val args = it.toMap() + expression(args) + } + addOptimizationData(objectiveFunction) + } + + public fun derivatives(expression: DifferentiableExpression): Unit { + expression(expression) + val gradientFunction = ObjectiveFunctionGradient { + val args = it.toMap() + DoubleArray(symbols.size) { index -> + expression.derivative(symbols[index])(args) + } + } + addOptimizationData(gradientFunction) + if (optimizatorBuilder == null) { + optimizatorBuilder = { + NonLinearConjugateGradientOptimizer( + NonLinearConjugateGradientOptimizer.Formula.FLETCHER_REEVES, + convergenceChecker + ) + } + } + } + + public fun simplex(simplex: AbstractSimplex) { + addOptimizationData(simplex) + //Set optimization builder to simplex if it is not present + if (optimizatorBuilder == null) { + optimizatorBuilder = { SimplexOptimizer(convergenceChecker) } + } + } + + public fun simplexSteps(steps: Map) { + simplex(NelderMeadSimplex(steps.toDoubleArray())) + } + + public fun goal(goalType: GoalType) { + addOptimizationData(goalType) + } + + public fun optimizer(block: () -> MultivariateOptimizer) { + optimizatorBuilder = block + } + + override fun optimize(): OptimizationResult { + val optimizer = optimizatorBuilder?.invoke() ?: error("Optimizer not defined") + val (point, value) = optimizer.optimize(*optimizationData.values.toTypedArray()) + return OptimizationResult(point.toMap(), value) + } + + public companion object { + public const val DEFAULT_RELATIVE_TOLERANCE: Double = 1e-4 + public const val DEFAULT_ABSOLUTE_TOLERANCE: Double = 1e-4 + public const val DEFAULT_MAX_ITER: Int = 1000 + } +} + +public fun CMOptimizationProblem.initialGuess(vararg pairs: Pair): Unit = initialGuess(pairs.toMap()) +public fun CMOptimizationProblem.simplexSteps(vararg pairs: Pair): Unit = simplexSteps(pairs.toMap()) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt new file mode 100644 index 000000000..56291e09c --- /dev/null +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt @@ -0,0 +1,17 @@ +package kscience.kmath.commons.optimization + +import kscience.kmath.expressions.Symbol +import kotlin.reflect.KClass + +public typealias ParameterSpacePoint = Map + +public class OptimizationResult( + public val point: ParameterSpacePoint, + public val value: T, + public val extra: Map, Any> = emptyMap() +) + +public interface OptimizationProblem { + public fun optimize(): OptimizationResult +} + diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt index 3bf6354ea..a49949b93 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt @@ -1,103 +1,32 @@ package kscience.kmath.commons.optimization -import kscience.kmath.expressions.* -import org.apache.commons.math3.optim.* -import org.apache.commons.math3.optim.nonlinear.scalar.GoalType -import org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer -import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction -import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunctionGradient -import org.apache.commons.math3.optim.nonlinear.scalar.gradient.NonLinearConjugateGradientOptimizer -import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex -import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer +import kscience.kmath.expressions.DifferentiableExpression +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.Symbol -public typealias ParameterSpacePoint = Map - -public class OptimizationResult(public val point: ParameterSpacePoint, public val value: Double) - -public operator fun PointValuePair.component1(): DoubleArray = point -public operator fun PointValuePair.component2(): Double = value - -public object Optimization { - public const val DEFAULT_RELATIVE_TOLERANCE: Double = 1e-4 - public const val DEFAULT_ABSOLUTE_TOLERANCE: Double = 1e-4 - public const val DEFAULT_MAX_ITER: Int = 1000 -} - - -private fun SymbolIndexer.objectiveFunction(expression: Expression) = ObjectiveFunction { - val args = it.toMap() - expression(args) -} - -private fun SymbolIndexer.objectiveFunctionGradient( - expression: DifferentiableExpression, -) = ObjectiveFunctionGradient { - val args = it.toMap() - DoubleArray(symbols.size) { index -> - expression.derivative(symbols[index])(args) - } -} - -private fun SymbolIndexer.initialGuess(point: ParameterSpacePoint) = InitialGuess(point.toArray()) /** * Optimize expression without derivatives */ public fun Expression.optimize( - startingPoint: ParameterSpacePoint, - goalType: GoalType = GoalType.MAXIMIZE, - vararg additionalArguments: OptimizationData, - optimizerBuilder: () -> MultivariateOptimizer = { - SimplexOptimizer( - SimpleValueChecker( - Optimization.DEFAULT_RELATIVE_TOLERANCE, - Optimization.DEFAULT_ABSOLUTE_TOLERANCE, - Optimization.DEFAULT_MAX_ITER - ) - ) - }, -): OptimizationResult = withSymbols(startingPoint.keys) { - val optimizer = optimizerBuilder() - val objectiveFunction = objectiveFunction(this@optimize) - val (point, value) = optimizer.optimize( - objectiveFunction, - initialGuess(startingPoint), - goalType, - MaxEval.unlimited(), - NelderMeadSimplex(symbols.size, 1.0), - *additionalArguments - ) - OptimizationResult(point.toMap(), value) + vararg symbols: Symbol, + configuration: CMOptimizationProblem.() -> Unit, +): OptimizationResult { + require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = CMOptimizationProblem(symbols.toList()).apply(configuration).apply(configuration) + problem.expression(this) + return problem.optimize() } /** * Optimize differentiable expression */ public fun DifferentiableExpression.optimize( - startingPoint: ParameterSpacePoint, - goalType: GoalType = GoalType.MAXIMIZE, - vararg additionalArguments: OptimizationData, - optimizerBuilder: () -> NonLinearConjugateGradientOptimizer = { - NonLinearConjugateGradientOptimizer( - NonLinearConjugateGradientOptimizer.Formula.FLETCHER_REEVES, - SimpleValueChecker( - Optimization.DEFAULT_RELATIVE_TOLERANCE, - Optimization.DEFAULT_ABSOLUTE_TOLERANCE, - Optimization.DEFAULT_MAX_ITER - ) - ) - }, -): OptimizationResult = withSymbols(startingPoint.keys) { - val optimizer = optimizerBuilder() - val objectiveFunction = objectiveFunction(this@optimize) - val objectiveGradient = objectiveFunctionGradient(this@optimize) - val (point, value) = optimizer.optimize( - objectiveFunction, - objectiveGradient, - initialGuess(startingPoint), - goalType, - MaxEval.unlimited(), - *additionalArguments - ) - OptimizationResult(point.toMap(), value) + vararg symbols: Symbol, + configuration: CMOptimizationProblem.() -> Unit, +): OptimizationResult { + require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = CMOptimizationProblem(symbols.toList()).apply(configuration).apply(configuration) + problem.derivatives(this) + return problem.optimize() } \ No newline at end of file diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index 779f37dad..65d61dcd1 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -1,10 +1,7 @@ package kscience.kmath.commons.optimization import kscience.kmath.commons.expressions.DerivativeStructureExpression -import kscience.kmath.expressions.Expression -import kscience.kmath.expressions.Symbol import kscience.kmath.expressions.symbol -import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer import org.junit.jupiter.api.Test internal class OptimizeTest { @@ -14,22 +11,25 @@ internal class OptimizeTest { val normal = DerivativeStructureExpression { val x = bind(x) val y = bind(y) - exp(-x.pow(2)/2) + exp(-y.pow(2)/2) + exp(-x.pow(2) / 2) + exp(-y.pow(2) / 2) } - val startingPoint: Map = mapOf(x to 1.0, y to 1.0) - @Test fun testOptimization() { - val result = normal.optimize(startingPoint) + val result = normal.optimize(x, y) { + initialGuess(x to 1.0, y to 1.0) + //no need to select optimizer. Gradient optimizer is used by default + } println(result.point) println(result.value) } @Test fun testSimplexOptimization() { - val result = (normal as Expression).optimize(startingPoint){ - SimplexOptimizer(1e-4,1e-4) + val result = normal.optimize(x, y) { + initialGuess(x to 1.0, y to 1.0) + simplexSteps(x to 2.0, y to 0.5) + //this sets simplex optimizer } println(result.point) println(result.value) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt index 841531d01..5fe31caca 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt @@ -4,9 +4,15 @@ package kscience.kmath.expressions * And object that could be differentiated */ public interface Differentiable { - public fun derivative(orders: Map): T + public fun derivativeOrNull(orders: Map): T? } +public fun Differentiable.derivative(orders: Map): T = + derivativeOrNull(orders) ?: error("Derivative with orders $orders not provided") + +/** + * An expression that provid + */ public interface DifferentiableExpression : Differentiable>, Expression public fun DifferentiableExpression.derivative(vararg orders: Pair): Expression = @@ -14,8 +20,19 @@ public fun DifferentiableExpression.derivative(vararg orders: Pair DifferentiableExpression.derivative(symbol: Symbol): Expression = derivative(symbol to 1) -public fun DifferentiableExpression.derivative(name: String): Expression = derivative(StringSymbol(name) to 1) +public fun DifferentiableExpression.derivative(name: String): Expression = + derivative(StringSymbol(name) to 1) //public interface DifferentiableExpressionBuilder>: ExpressionBuilder { // public override fun expression(block: A.() -> E): DifferentiableExpression //} + +public abstract class FirstDerivativeExpression : DifferentiableExpression { + + public abstract fun derivativeOrNull(symbol: Symbol): Expression? + + public override fun derivativeOrNull(orders: Map): Expression? { + val dSymbol = orders.entries.singleOrNull { it.value == 1 }?.key ?: return null + return derivativeOrNull(dSymbol) + } +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt index e5ea33c81..6231a40c1 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -221,23 +221,16 @@ private class AutoDiffContext>( public class SimpleAutoDiffExpression>( public val field: F, public val function: AutoDiffField.() -> AutoDiffValue, -) : DifferentiableExpression { +) : FirstDerivativeExpression() { public override operator fun invoke(arguments: Map): T { //val bindings = arguments.entries.map { it.key.bind(it.value) } return AutoDiffContext(field, arguments).function().value } - /** - * Get the derivative expression with given orders - */ - public override fun derivative(orders: Map): Expression { - val dSymbol = orders.entries.singleOrNull { it.value == 1 } - ?: error("SimpleAutoDiff supports only first order derivatives") - return Expression { arguments -> - //val bindings = arguments.entries.map { it.key.bind(it.value) } - val derivationResult = AutoDiffContext(field, arguments).derivate(function) - derivationResult.derivative(dSymbol.key) - } + override fun derivativeOrNull(symbol: Symbol): Expression = Expression { arguments -> + //val bindings = arguments.entries.map { it.key.bind(it.value) } + val derivationResult = AutoDiffContext(field, arguments).derivate(function) + derivationResult.derivative(symbol) } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SymbolIndexer.kt index aef30c6dd..6c61c7c7d 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SymbolIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SymbolIndexer.kt @@ -1,7 +1,12 @@ package kscience.kmath.expressions +import kscience.kmath.linear.Point +import kscience.kmath.structures.BufferFactory +import kscience.kmath.structures.Structure2D + /** * An environment to easy transform indexed variables to symbols and back. + * TODO requires multi-receivers to be beutiful */ public interface SymbolIndexer { public val symbols: List @@ -22,15 +27,26 @@ public interface SymbolIndexer { return get(this@SymbolIndexer.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)) + } + public fun DoubleArray.toMap(): Map { require(size == symbols.size) { "The input array size for indexer should be ${symbols.size} but $size found" } return symbols.indices.associate { symbols[it] to get(it) } } + public operator fun Structure2D.get(rowSymbol: Symbol, columnSymbol: Symbol): T = + get(indexOf(rowSymbol), indexOf(columnSymbol)) + public fun Map.toList(): List = symbols.map { getValue(it) } - public fun Map.toArray(): DoubleArray = DoubleArray(symbols.size) { getValue(symbols[it]) } + public fun Map.toPoint(bufferFactory: BufferFactory): Point = + bufferFactory(symbols.size) { getValue(symbols[it]) } + + public fun Map.toDoubleArray(): DoubleArray = DoubleArray(symbols.size) { getValue(symbols[it]) } } public inline class SimpleSymbolIndexer(override val symbols: List) : SymbolIndexer From 57781678e5e6aa295fca25b00ee3dd2dc2ae8f4f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 25 Oct 2020 19:46:22 +0300 Subject: [PATCH 108/199] Cleanup --- .../optimization/CMOptimizationProblem.kt | 8 +++++-- .../optimization/OptimizationProblem.kt | 23 +++++++++++++++---- .../kmath/commons/optimization/optimize.kt | 6 ++--- .../commons/optimization/OptimizeTest.kt | 6 ++--- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt index f7c136ed2..b5ea59d6b 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt @@ -36,7 +36,7 @@ public class CMOptimizationProblem( addOptimizationData(InitialGuess(map.toDoubleArray())) } - public fun expression(expression: Expression): Unit { + public override fun expression(expression: Expression): Unit { val objectiveFunction = ObjectiveFunction { val args = it.toMap() expression(args) @@ -44,7 +44,7 @@ public class CMOptimizationProblem( addOptimizationData(objectiveFunction) } - public fun derivatives(expression: DifferentiableExpression): Unit { + public override fun diffExpression(expression: DifferentiableExpression): Unit { expression(expression) val gradientFunction = ObjectiveFunctionGradient { val args = it.toMap() @@ -83,6 +83,10 @@ public class CMOptimizationProblem( optimizatorBuilder = block } + override fun update(result: OptimizationResult) { + initialGuess(result.point) + } + override fun optimize(): OptimizationResult { val optimizer = optimizatorBuilder?.invoke() ?: error("Optimizer not defined") val (point, value) = optimizer.optimize(*optimizationData.values.toTypedArray()) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt index 56291e09c..e52450be1 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt @@ -1,17 +1,32 @@ package kscience.kmath.commons.optimization +import kscience.kmath.expressions.DifferentiableExpression +import kscience.kmath.expressions.Expression import kscience.kmath.expressions.Symbol -import kotlin.reflect.KClass -public typealias ParameterSpacePoint = Map +public interface OptimizationResultFeature + public class OptimizationResult( - public val point: ParameterSpacePoint, + public val point: Map, public val value: T, - public val extra: Map, Any> = emptyMap() + public val features: Set = emptySet(), ) +/** + * A configuration builder for optimization problem + */ public interface OptimizationProblem { + /** + * Set an objective function expression + */ + public fun expression(expression: Expression): Unit + + /** + * + */ + public fun diffExpression(expression: DifferentiableExpression): Unit + public fun update(result: OptimizationResult) public fun optimize(): OptimizationResult } diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt index a49949b93..c4bd5704e 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt @@ -13,7 +13,7 @@ public fun Expression.optimize( configuration: CMOptimizationProblem.() -> Unit, ): OptimizationResult { require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = CMOptimizationProblem(symbols.toList()).apply(configuration).apply(configuration) + val problem = CMOptimizationProblem(symbols.toList()).apply(configuration) problem.expression(this) return problem.optimize() } @@ -26,7 +26,7 @@ public fun DifferentiableExpression.optimize( configuration: CMOptimizationProblem.() -> Unit, ): OptimizationResult { require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = CMOptimizationProblem(symbols.toList()).apply(configuration).apply(configuration) - problem.derivatives(this) + val problem = CMOptimizationProblem(symbols.toList()).apply(configuration) + problem.diffExpression(this) return problem.optimize() } \ No newline at end of file diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index 65d61dcd1..bd7870573 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -9,16 +9,14 @@ internal class OptimizeTest { val y by symbol val normal = DerivativeStructureExpression { - val x = bind(x) - val y = bind(y) - exp(-x.pow(2) / 2) + exp(-y.pow(2) / 2) + exp(-bind(x).pow(2) / 2) + exp(- bind(y).pow(2) / 2) } @Test fun testOptimization() { val result = normal.optimize(x, y) { initialGuess(x to 1.0, y to 1.0) - //no need to select optimizer. Gradient optimizer is used by default + //no need to select optimizer. Gradient optimizer is used by default because gradients are provided by function } println(result.point) println(result.value) From 30132964dd35f4d039ee84729a96bdc2a9014086 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 26 Oct 2020 10:01:30 +0300 Subject: [PATCH 109/199] Separate object for fitting. Chi-squared --- CHANGELOG.md | 1 + .../kmath/commons/optimization/CMFit.kt | 103 ++++++++++++++++++ .../kmath/commons/optimization/optimize.kt | 32 ------ .../commons/optimization/OptimizeTest.kt | 2 +- 4 files changed, 105 insertions(+), 33 deletions(-) create mode 100644 kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt delete mode 100644 kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 109168475..f28041adf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - A separate `Symbol` entity, which is used for global unbound symbol. - A `Symbol` indexing scope. - Basic optimization API for Commons-math. +- Chi squared optimization for array-like data in CM ### Changed - Package changed from `scientifik` to `kscience.kmath`. diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt new file mode 100644 index 000000000..4ffd0559d --- /dev/null +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt @@ -0,0 +1,103 @@ +package kscience.kmath.commons.optimization + +import kscience.kmath.commons.expressions.DerivativeStructureExpression +import kscience.kmath.commons.expressions.DerivativeStructureField +import kscience.kmath.expressions.DifferentiableExpression +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.StringSymbol +import kscience.kmath.expressions.Symbol +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.indices +import org.apache.commons.math3.analysis.differentiation.DerivativeStructure +import org.apache.commons.math3.optim.nonlinear.scalar.GoalType +import kotlin.math.pow + + +public object CMFit { + + /** + * Generate a chi squared expression from given x-y-sigma model represented by an expression. Does not provide derivatives + * TODO move to core/separate module + */ + public fun chiSquaredExpression( + x: Buffer, + y: Buffer, + yErr: Buffer, + model: Expression, + xSymbol: Symbol = StringSymbol("x"), + ): Expression { + require(x.size == y.size) { "X and y buffers should be of the same size" } + require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + return Expression { arguments -> + x.indices.sumByDouble { + val xValue = x[it] + val yValue = y[it] + val yErrValue = yErr[it] + val modifiedArgs = arguments + (xSymbol to xValue) + val modelValue = model(modifiedArgs) + ((yValue - modelValue) / yErrValue).pow(2) / 2 + } + } + } + + /** + * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation + */ + public fun chiSquaredExpression( + x: Buffer, + y: Buffer, + yErr: Buffer, + model: DerivativeStructureField.(x: DerivativeStructure) -> DerivativeStructure, + ): DerivativeStructureExpression { + require(x.size == y.size) { "X and y buffers should be of the same size" } + require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + return DerivativeStructureExpression { + var sum = zero + x.indices.forEach { + val xValue = x[it] + val yValue = y[it] + val yErrValue = yErr[it] + val modelValue = model(const(xValue)) + sum += ((yValue - modelValue) / yErrValue).pow(2) / 2 + } + sum + } + } +} + +/** + * Optimize expression without derivatives + */ +public fun Expression.optimize( + vararg symbols: Symbol, + configuration: CMOptimizationProblem.() -> Unit, +): OptimizationResult { + require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = CMOptimizationProblem(symbols.toList()).apply(configuration) + problem.expression(this) + return problem.optimize() +} + +/** + * Optimize differentiable expression + */ +public fun DifferentiableExpression.optimize( + vararg symbols: Symbol, + configuration: CMOptimizationProblem.() -> Unit, +): OptimizationResult { + require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = CMOptimizationProblem(symbols.toList()).apply(configuration) + problem.diffExpression(this) + return problem.optimize() +} + +public fun DifferentiableExpression.minimize( + vararg symbols: Symbol, + configuration: CMOptimizationProblem.() -> Unit, +): OptimizationResult { + require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = CMOptimizationProblem(symbols.toList()).apply(configuration) + problem.diffExpression(this) + problem.goal(GoalType.MINIMIZE) + return problem.optimize() +} \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt deleted file mode 100644 index c4bd5704e..000000000 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/optimize.kt +++ /dev/null @@ -1,32 +0,0 @@ -package kscience.kmath.commons.optimization - -import kscience.kmath.expressions.DifferentiableExpression -import kscience.kmath.expressions.Expression -import kscience.kmath.expressions.Symbol - - -/** - * Optimize expression without derivatives - */ -public fun Expression.optimize( - vararg symbols: Symbol, - configuration: CMOptimizationProblem.() -> Unit, -): OptimizationResult { - require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = CMOptimizationProblem(symbols.toList()).apply(configuration) - problem.expression(this) - return problem.optimize() -} - -/** - * Optimize differentiable expression - */ -public fun DifferentiableExpression.optimize( - vararg symbols: Symbol, - configuration: CMOptimizationProblem.() -> Unit, -): OptimizationResult { - require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = CMOptimizationProblem(symbols.toList()).apply(configuration) - problem.diffExpression(this) - return problem.optimize() -} \ No newline at end of file diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index bd7870573..07bda2aa4 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -13,7 +13,7 @@ internal class OptimizeTest { } @Test - fun testOptimization() { + fun testGradientOptimization() { val result = normal.optimize(x, y) { initialGuess(x to 1.0, y to 1.0) //no need to select optimizer. Gradient optimizer is used by default because gradients are provided by function From 4450c0fcc7941896968283bdc120a3a1661dec09 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 26 Oct 2020 14:44:57 +0300 Subject: [PATCH 110/199] Fix orders in DerivativeStructures --- .../DerivativeStructureExpression.kt | 4 +-- .../kmath/commons/optimization/CMFit.kt | 19 +++++------ .../optimization/CMOptimizationProblem.kt | 11 ++++--- .../optimization/OptimizationProblem.kt | 11 +++++-- .../random/CMRandomGeneratorWrapper.kt | 5 +-- .../commons/optimization/OptimizeTest.kt | 32 ++++++++++++++++++- 6 files changed, 60 insertions(+), 22 deletions(-) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 376fea7a3..272501729 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -38,13 +38,13 @@ public class DerivativeStructureField( key.identity to DerivativeStructureSymbol(key, value) } - override fun const(value: Double): DerivativeStructure = DerivativeStructure(order, bindings.size, value) + override fun const(value: Double): DerivativeStructure = DerivativeStructure(bindings.size, order, value) public override fun bindOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity] public fun bind(symbol: Symbol): DerivativeStructureSymbol = variables.getValue(symbol.identity) - public fun Number.const(): DerivativeStructure = const(toDouble()) + //public fun Number.const(): DerivativeStructure = const(toDouble()) public fun DerivativeStructure.derivative(parameter: Symbol, order: Int = 1): Double { return derivative(mapOf(parameter to order)) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt index 4ffd0559d..a62630ed3 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt @@ -17,9 +17,9 @@ public object CMFit { /** * Generate a chi squared expression from given x-y-sigma model represented by an expression. Does not provide derivatives - * TODO move to core/separate module + * TODO move to prob/stat */ - public fun chiSquaredExpression( + public fun chiSquared( x: Buffer, y: Buffer, yErr: Buffer, @@ -35,7 +35,7 @@ public object CMFit { val yErrValue = yErr[it] val modifiedArgs = arguments + (xSymbol to xValue) val modelValue = model(modifiedArgs) - ((yValue - modelValue) / yErrValue).pow(2) / 2 + ((yValue - modelValue) / yErrValue).pow(2) } } } @@ -43,7 +43,7 @@ public object CMFit { /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation */ - public fun chiSquaredExpression( + public fun chiSquared( x: Buffer, y: Buffer, yErr: Buffer, @@ -58,7 +58,7 @@ public object CMFit { val yValue = y[it] val yErrValue = yErr[it] val modelValue = model(const(xValue)) - sum += ((yValue - modelValue) / yErrValue).pow(2) / 2 + sum += ((yValue - modelValue) / yErrValue).pow(2) } sum } @@ -92,12 +92,13 @@ public fun DifferentiableExpression.optimize( } public fun DifferentiableExpression.minimize( - vararg symbols: Symbol, - configuration: CMOptimizationProblem.() -> Unit, + vararg startPoint: Pair, + configuration: CMOptimizationProblem.() -> Unit = {}, ): OptimizationResult { - require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = CMOptimizationProblem(symbols.toList()).apply(configuration) + require(startPoint.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = CMOptimizationProblem(startPoint.map { it.first }).apply(configuration) problem.diffExpression(this) + problem.initialGuess(startPoint.toMap()) problem.goal(GoalType.MINIMIZE) return problem.optimize() } \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt index b5ea59d6b..2ca907d05 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt @@ -17,14 +17,13 @@ public operator fun PointValuePair.component2(): Double = value public class CMOptimizationProblem( override val symbols: List, -) : OptimizationProblem, SymbolIndexer { - protected val optimizationData: HashMap, OptimizationData> = HashMap() +) : OptimizationProblem, SymbolIndexer, OptimizationFeature { + private val optimizationData: HashMap, OptimizationData> = HashMap() private var optimizatorBuilder: (() -> MultivariateOptimizer)? = null - public var convergenceChecker: ConvergenceChecker = SimpleValueChecker(DEFAULT_RELATIVE_TOLERANCE, DEFAULT_ABSOLUTE_TOLERANCE, DEFAULT_MAX_ITER) - private fun addOptimizationData(data: OptimizationData) { + public fun addOptimizationData(data: OptimizationData) { optimizationData[data::class] = data } @@ -32,6 +31,8 @@ public class CMOptimizationProblem( addOptimizationData(MaxEval.unlimited()) } + public fun exportOptimizationData(): List = optimizationData.values.toList() + public fun initialGuess(map: Map): Unit { addOptimizationData(InitialGuess(map.toDoubleArray())) } @@ -90,7 +91,7 @@ public class CMOptimizationProblem( override fun optimize(): OptimizationResult { val optimizer = optimizatorBuilder?.invoke() ?: error("Optimizer not defined") val (point, value) = optimizer.optimize(*optimizationData.values.toTypedArray()) - return OptimizationResult(point.toMap(), value) + return OptimizationResult(point.toMap(), value, setOf(this)) } public companion object { diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt index e52450be1..a246a817b 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt @@ -4,14 +4,19 @@ import kscience.kmath.expressions.DifferentiableExpression import kscience.kmath.expressions.Expression import kscience.kmath.expressions.Symbol -public interface OptimizationResultFeature +public interface OptimizationFeature +//TODO move to prob/stat public class OptimizationResult( public val point: Map, public val value: T, - public val features: Set = emptySet(), -) + public val features: Set = emptySet(), +){ + override fun toString(): String { + return "OptimizationResult(point=$point, value=$value)" + } +} /** * A configuration builder for optimization problem diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt index 58609deae..9600f6901 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt @@ -2,8 +2,9 @@ package kscience.kmath.commons.random import kscience.kmath.prob.RandomGenerator -public class CMRandomGeneratorWrapper(public val factory: (IntArray) -> RandomGenerator) : - org.apache.commons.math3.random.RandomGenerator { +public class CMRandomGeneratorWrapper( + public val factory: (IntArray) -> RandomGenerator, +) : org.apache.commons.math3.random.RandomGenerator { private var generator: RandomGenerator = factory(intArrayOf()) public override fun nextBoolean(): Boolean = generator.nextBoolean() diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index 07bda2aa4..ff5542235 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -2,14 +2,19 @@ package kscience.kmath.commons.optimization import kscience.kmath.commons.expressions.DerivativeStructureExpression import kscience.kmath.expressions.symbol +import kscience.kmath.prob.Distribution +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.normal +import kscience.kmath.structures.asBuffer import org.junit.jupiter.api.Test +import kotlin.math.pow internal class OptimizeTest { val x by symbol val y by symbol val normal = DerivativeStructureExpression { - exp(-bind(x).pow(2) / 2) + exp(- bind(y).pow(2) / 2) + exp(-bind(x).pow(2) / 2) + exp(-bind(y).pow(2) / 2) } @Test @@ -32,4 +37,29 @@ internal class OptimizeTest { println(result.point) println(result.value) } + + @Test + fun testFit() { + val a by symbol + val b by symbol + val c by symbol + + val sigma = 1.0 + val generator = Distribution.normal(0.0, sigma) + val chain = generator.sample(RandomGenerator.default(1126)) + val x = (1..100).map { it.toDouble() } + val y = x.map { it -> + it.pow(2) + it + 1 + chain.nextDouble() + } + val yErr = x.map { sigma } + with(CMFit) { + val chi2 = chiSquared(x.asBuffer(), y.asBuffer(), yErr.asBuffer()) { x -> + bind(a) * x.pow(2) + bind(b) * x + bind(c) + } + + val result = chi2.minimize(a to 1.5, b to 0.9, c to 1.0) + println(result) + println("Chi2/dof = ${result.value / (x.size - 3)}") + } + } } \ No newline at end of file From 9a147d033e02abd2647df344a09bb802d3e359e7 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 27 Oct 2020 17:57:17 +0300 Subject: [PATCH 111/199] Another refactor of SimpleAutoDiff --- .../DerivativeStructureExpression.kt | 11 +- .../kmath/commons/optimization/CMFit.kt | 15 +- .../optimization/CMOptimizationProblem.kt | 6 +- .../optimization/OptimizationProblem.kt | 37 --- .../expressions/DifferentiableExpression.kt | 14 +- .../kmath/expressions/SimpleAutoDiff.kt | 286 +++++++++++------- .../kmath/expressions/expressionBuilders.kt | 5 - .../kmath/expressions/SimpleAutoDiffTest.kt | 15 +- 8 files changed, 214 insertions(+), 175 deletions(-) delete mode 100644 kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 272501729..c593f5103 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -1,9 +1,6 @@ package kscience.kmath.commons.expressions -import kscience.kmath.expressions.DifferentiableExpression -import kscience.kmath.expressions.Expression -import kscience.kmath.expressions.ExpressionAlgebra -import kscience.kmath.expressions.Symbol +import kscience.kmath.expressions.* import kscience.kmath.operations.ExtendedField import org.apache.commons.math3.analysis.differentiation.DerivativeStructure @@ -92,6 +89,12 @@ public class DerivativeStructureField( public override operator fun DerivativeStructure.minus(b: Number): DerivativeStructure = subtract(b.toDouble()) public override operator fun Number.plus(b: DerivativeStructure): DerivativeStructure = b + this public override operator fun Number.minus(b: DerivativeStructure): DerivativeStructure = b - this + + public companion object : AutoDiffProcessor { + override fun process(function: DerivativeStructureField.() -> DerivativeStructure): DifferentiableExpression { + return DerivativeStructureExpression(function) + } + } } /** diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt index a62630ed3..3143dcca5 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt @@ -71,12 +71,8 @@ public object CMFit { public fun Expression.optimize( vararg symbols: Symbol, configuration: CMOptimizationProblem.() -> Unit, -): OptimizationResult { - require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = CMOptimizationProblem(symbols.toList()).apply(configuration) - problem.expression(this) - return problem.optimize() -} +): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) + /** * Optimize differentiable expression @@ -84,12 +80,7 @@ public fun Expression.optimize( public fun DifferentiableExpression.optimize( vararg symbols: Symbol, configuration: CMOptimizationProblem.() -> Unit, -): OptimizationResult { - require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = CMOptimizationProblem(symbols.toList()).apply(configuration) - problem.diffExpression(this) - return problem.optimize() -} +): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) public fun DifferentiableExpression.minimize( vararg startPoint: Pair, diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt index 2ca907d05..0d96faaa3 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt @@ -33,7 +33,7 @@ public class CMOptimizationProblem( public fun exportOptimizationData(): List = optimizationData.values.toList() - public fun initialGuess(map: Map): Unit { + public override fun initialGuess(map: Map): Unit { addOptimizationData(InitialGuess(map.toDoubleArray())) } @@ -94,10 +94,12 @@ public class CMOptimizationProblem( return OptimizationResult(point.toMap(), value, setOf(this)) } - public companion object { + public companion object : OptimizationProblemFactory { public const val DEFAULT_RELATIVE_TOLERANCE: Double = 1e-4 public const val DEFAULT_ABSOLUTE_TOLERANCE: Double = 1e-4 public const val DEFAULT_MAX_ITER: Int = 1000 + + override fun build(symbols: List): CMOptimizationProblem = CMOptimizationProblem(symbols) } } diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt deleted file mode 100644 index a246a817b..000000000 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/OptimizationProblem.kt +++ /dev/null @@ -1,37 +0,0 @@ -package kscience.kmath.commons.optimization - -import kscience.kmath.expressions.DifferentiableExpression -import kscience.kmath.expressions.Expression -import kscience.kmath.expressions.Symbol - -public interface OptimizationFeature - -//TODO move to prob/stat - -public class OptimizationResult( - public val point: Map, - public val value: T, - public val features: Set = emptySet(), -){ - override fun toString(): String { - return "OptimizationResult(point=$point, value=$value)" - } -} - -/** - * A configuration builder for optimization problem - */ -public interface OptimizationProblem { - /** - * Set an objective function expression - */ - public fun expression(expression: Expression): Unit - - /** - * - */ - public fun diffExpression(expression: DifferentiableExpression): Unit - public fun update(result: OptimizationResult) - public fun optimize(): OptimizationResult -} - diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt index 5fe31caca..705839b57 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt @@ -23,10 +23,9 @@ public fun DifferentiableExpression.derivative(symbol: Symbol): Expressio public fun DifferentiableExpression.derivative(name: String): Expression = derivative(StringSymbol(name) to 1) -//public interface DifferentiableExpressionBuilder>: ExpressionBuilder { -// public override fun expression(block: A.() -> E): DifferentiableExpression -//} - +/** + * A [DifferentiableExpression] that defines only first derivatives + */ public abstract class FirstDerivativeExpression : DifferentiableExpression { public abstract fun derivativeOrNull(symbol: Symbol): Expression? @@ -35,4 +34,11 @@ public abstract class FirstDerivativeExpression : DifferentiableExpression val dSymbol = orders.entries.singleOrNull { it.value == 1 }?.key ?: return null return derivativeOrNull(dSymbol) } +} + +/** + * A factory that converts an expression in autodiff variables to a [DifferentiableExpression] + */ +public interface AutoDiffProcessor> { + public fun process(function: A.() -> I): DifferentiableExpression } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt index 6231a40c1..e66832fdb 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -47,7 +47,7 @@ public fun DerivationResult.grad(vararg variables: Symbol): Point DerivationResult.grad(vararg variables: Symbol): Point> F.simpleAutoDiff( bindings: Map, - body: AutoDiffField.() -> AutoDiffValue, + body: SimpleAutoDiffField.() -> AutoDiffValue, ): DerivationResult { contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) } - return AutoDiffContext(this, bindings).derivate(body) + return SimpleAutoDiffField(this, bindings).derivate(body) } public fun > F.simpleAutoDiff( vararg bindings: Pair, - body: AutoDiffField.() -> AutoDiffValue, + body: SimpleAutoDiffField.() -> AutoDiffValue, ): DerivationResult = simpleAutoDiff(bindings.toMap(), body) /** * Represents field in context of which functions can be derived. */ -public abstract class AutoDiffField> - : Field>, ExpressionAlgebra> { +public open class SimpleAutoDiffField>( + public val context: F, + bindings: Map, +) : Field>, ExpressionAlgebra> { - public abstract val context: F + // this stack contains pairs of blocks and values to apply them to + private var stack: Array = arrayOfNulls(8) + private var sp: Int = 0 + private val derivatives: MutableMap, T> = hashMapOf() + + /** + * Differentiable variable with value and derivative of differentiation ([simpleAutoDiff]) result + * with respect to this variable. + * + * @param T the non-nullable type of value. + * @property value The value of this variable. + */ + private class AutoDiffVariableWithDerivative( + override val identity: String, + value: T, + var d: T, + ) : AutoDiffValue(value), Symbol { + override fun toString(): String = identity + override fun equals(other: Any?): Boolean = this.identity == (other as? Symbol)?.identity + override fun hashCode(): Int = identity.hashCode() + } + + private val bindings: Map> = bindings.entries.associate { + it.key.identity to AutoDiffVariableWithDerivative(it.key.identity, it.value, context.zero) + } + + override fun bindOrNull(symbol: Symbol): AutoDiffValue? = bindings[symbol.identity] + + private fun getDerivative(variable: AutoDiffValue): T = + (variable as? AutoDiffVariableWithDerivative)?.d ?: derivatives[variable] ?: context.zero + + private fun setDerivative(variable: AutoDiffValue, value: T) { + if (variable is AutoDiffVariableWithDerivative) variable.d = value else derivatives[variable] = value + } + + + @Suppress("UNCHECKED_CAST") + private fun runBackwardPass() { + while (sp > 0) { + val value = stack[--sp] + val block = stack[--sp] as F.(Any?) -> Unit + context.block(value) + } + } + + override val zero: AutoDiffValue get() = const(context.zero) + override val one: AutoDiffValue get() = const(context.one) + + override fun const(value: T): AutoDiffValue = AutoDiffValue(value) /** * A variable accessing inner state of derivatives. * Use this value in inner builders to avoid creating additional derivative bindings. */ - public abstract var AutoDiffValue.d: T + public var AutoDiffValue.d: T + get() = getDerivative(this) + set(value) = setDerivative(this, value) + + public inline fun const(block: F.() -> T): AutoDiffValue = const(context.block()) /** * Performs update of derivative after the rest of the formula in the back-pass. @@ -101,9 +155,22 @@ public abstract class AutoDiffField> * } * ``` */ - public abstract fun derive(value: R, block: F.(R) -> Unit): R + @Suppress("UNCHECKED_CAST") + public fun derive(value: R, block: F.(R) -> Unit): R { + // save block to stack for backward pass + if (sp >= stack.size) stack = stack.copyOf(stack.size * 2) + stack[sp++] = block + stack[sp++] = value + return value + } - public inline fun const(block: F.() -> T): AutoDiffValue = const(context.block()) + + internal fun derivate(function: SimpleAutoDiffField.() -> AutoDiffValue): DerivationResult { + val result = function() + result.d = context.one // computing derivative w.r.t result + runBackwardPass() + return DerivationResult(result.value, bindings.mapValues { it.value.d }, context) + } // Overloads for Double constants @@ -119,68 +186,7 @@ public abstract class AutoDiffField> override operator fun AutoDiffValue.minus(b: Number): AutoDiffValue = derive(const { this@minus.value - one * b.toDouble() }) { z -> this@minus.d += z.d } -} -/** - * Automatic Differentiation context class. - */ -private class AutoDiffContext>( - override val context: F, - bindings: Map, -) : AutoDiffField() { - // this stack contains pairs of blocks and values to apply them to - private var stack: Array = arrayOfNulls(8) - private var sp: Int = 0 - private val derivatives: MutableMap, T> = hashMapOf() - override val zero: AutoDiffValue get() = const(context.zero) - override val one: AutoDiffValue get() = const(context.one) - - /** - * Differentiable variable with value and derivative of differentiation ([simpleAutoDiff]) result - * with respect to this variable. - * - * @param T the non-nullable type of value. - * @property value The value of this variable. - */ - private class AutoDiffVariableWithDeriv( - override val identity: String, - value: T, - var d: T, - ) : AutoDiffValue(value), Symbol{ - override fun toString(): String = identity - override fun equals(other: Any?): Boolean = this.identity == (other as? Symbol)?.identity - override fun hashCode(): Int = identity.hashCode() - } - - private val bindings: Map> = bindings.entries.associate { - it.key.identity to AutoDiffVariableWithDeriv(it.key.identity, it.value, context.zero) - } - - override fun bindOrNull(symbol: Symbol): AutoDiffVariableWithDeriv? = bindings[symbol.identity] - - override fun const(value: T): AutoDiffValue = AutoDiffValue(value) - - override var AutoDiffValue.d: T - get() = (this as? AutoDiffVariableWithDeriv)?.d ?: derivatives[this] ?: context.zero - set(value) = if (this is AutoDiffVariableWithDeriv) d = value else derivatives[this] = value - - @Suppress("UNCHECKED_CAST") - override fun derive(value: R, block: F.(R) -> Unit): R { - // save block to stack for backward pass - if (sp >= stack.size) stack = stack.copyOf(stack.size * 2) - stack[sp++] = block - stack[sp++] = value - return value - } - - @Suppress("UNCHECKED_CAST") - fun runBackwardPass() { - while (sp > 0) { - val value = stack[--sp] - val block = stack[--sp] as F.(Any?) -> Unit - context.block(value) - } - } // Basic math (+, -, *, /) @@ -206,13 +212,6 @@ private class AutoDiffContext>( derive(const { k.toDouble() * a.value }) { z -> a.d += z.d * k.toDouble() } - - inline fun derivate(function: AutoDiffField.() -> AutoDiffValue): DerivationResult { - val result = function() - result.d = context.one // computing derivative w.r.t result - runBackwardPass() - return DerivationResult(result.value, bindings.mapValues { it.value.d }, context) - } } /** @@ -220,99 +219,178 @@ private class AutoDiffContext>( */ public class SimpleAutoDiffExpression>( public val field: F, - public val function: AutoDiffField.() -> AutoDiffValue, + public val function: SimpleAutoDiffField.() -> AutoDiffValue, ) : FirstDerivativeExpression() { public override operator fun invoke(arguments: Map): T { //val bindings = arguments.entries.map { it.key.bind(it.value) } - return AutoDiffContext(field, arguments).function().value + return SimpleAutoDiffField(field, arguments).function().value } override fun derivativeOrNull(symbol: Symbol): Expression = Expression { arguments -> //val bindings = arguments.entries.map { it.key.bind(it.value) } - val derivationResult = AutoDiffContext(field, arguments).derivate(function) + val derivationResult = SimpleAutoDiffField(field, arguments).derivate(function) derivationResult.derivative(symbol) } } +/** + * Generate [AutoDiffProcessor] for [SimpleAutoDiffExpression] + */ +public fun > simpleAutoDiff(field: F): AutoDiffProcessor, SimpleAutoDiffField> { + return object : AutoDiffProcessor, SimpleAutoDiffField> { + override fun process(function: SimpleAutoDiffField.() -> AutoDiffValue): DifferentiableExpression { + return SimpleAutoDiffExpression(field, function) + } + } +} + // Extensions for differentiation of various basic mathematical functions // x ^ 2 -public fun > AutoDiffField.sqr(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.sqr(x: AutoDiffValue): AutoDiffValue = derive(const { x.value * x.value }) { z -> x.d += z.d * 2 * x.value } // x ^ 1/2 -public fun > AutoDiffField.sqrt(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.sqrt(x: AutoDiffValue): AutoDiffValue = derive(const { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value } // x ^ y (const) -public fun > AutoDiffField.pow( +public fun > SimpleAutoDiffField.pow( x: AutoDiffValue, y: Double, ): AutoDiffValue = derive(const { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) } -public fun > AutoDiffField.pow( +public fun > SimpleAutoDiffField.pow( x: AutoDiffValue, y: Int, ): AutoDiffValue = pow(x, y.toDouble()) // exp(x) -public fun > AutoDiffField.exp(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.exp(x: AutoDiffValue): AutoDiffValue = derive(const { exp(x.value) }) { z -> x.d += z.d * z.value } // ln(x) -public fun > AutoDiffField.ln(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.ln(x: AutoDiffValue): AutoDiffValue = derive(const { ln(x.value) }) { z -> x.d += z.d / x.value } // x ^ y (any) -public fun > AutoDiffField.pow( +public fun > SimpleAutoDiffField.pow( x: AutoDiffValue, y: AutoDiffValue, ): AutoDiffValue = exp(y * ln(x)) // sin(x) -public fun > AutoDiffField.sin(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.sin(x: AutoDiffValue): AutoDiffValue = derive(const { sin(x.value) }) { z -> x.d += z.d * cos(x.value) } // cos(x) -public fun > AutoDiffField.cos(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.cos(x: AutoDiffValue): AutoDiffValue = derive(const { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) } -public fun > AutoDiffField.tan(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.tan(x: AutoDiffValue): AutoDiffValue = derive(const { tan(x.value) }) { z -> val c = cos(x.value) x.d += z.d / (c * c) } -public fun > AutoDiffField.asin(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.asin(x: AutoDiffValue): AutoDiffValue = derive(const { asin(x.value) }) { z -> x.d += z.d / sqrt(one - x.value * x.value) } -public fun > AutoDiffField.acos(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.acos(x: AutoDiffValue): AutoDiffValue = derive(const { acos(x.value) }) { z -> x.d -= z.d / sqrt(one - x.value * x.value) } -public fun > AutoDiffField.atan(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.atan(x: AutoDiffValue): AutoDiffValue = derive(const { atan(x.value) }) { z -> x.d += z.d / (one + x.value * x.value) } -public fun > AutoDiffField.sinh(x: AutoDiffValue): AutoDiffValue = - derive(const { sin(x.value) }) { z -> x.d += z.d * cosh(x.value) } +public fun > SimpleAutoDiffField.sinh(x: AutoDiffValue): AutoDiffValue = + derive(const { sinh(x.value) }) { z -> x.d += z.d * cosh(x.value) } -public fun > AutoDiffField.cosh(x: AutoDiffValue): AutoDiffValue = - derive(const { cos(x.value) }) { z -> x.d += z.d * sinh(x.value) } +public fun > SimpleAutoDiffField.cosh(x: AutoDiffValue): AutoDiffValue = + derive(const { cosh(x.value) }) { z -> x.d += z.d * sinh(x.value) } -public fun > AutoDiffField.tanh(x: AutoDiffValue): AutoDiffValue = - derive(const { tan(x.value) }) { z -> +public fun > SimpleAutoDiffField.tanh(x: AutoDiffValue): AutoDiffValue = + derive(const { tanh(x.value) }) { z -> val c = cosh(x.value) x.d += z.d / (c * c) } -public fun > AutoDiffField.asinh(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.asinh(x: AutoDiffValue): AutoDiffValue = derive(const { asinh(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) } -public fun > AutoDiffField.acosh(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.acosh(x: AutoDiffValue): AutoDiffValue = derive(const { acosh(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) } -public fun > AutoDiffField.atanh(x: AutoDiffValue): AutoDiffValue = +public fun > SimpleAutoDiffField.atanh(x: AutoDiffValue): AutoDiffValue = derive(const { atanh(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) } +public class SimpleAutoDiffExtendedField>( + context: F, + bindings: Map, +) : ExtendedField>, SimpleAutoDiffField(context, bindings) { + // x ^ 2 + public fun sqr(x: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).sqr(x) + + // x ^ 1/2 + public override fun sqrt(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).sqrt(arg) + + // x ^ y (const) + public override fun power(arg: AutoDiffValue, pow: Number): AutoDiffValue = + (this as SimpleAutoDiffField).pow(arg, pow.toDouble()) + + // exp(x) + public override fun exp(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).exp(arg) + + // ln(x) + public override fun ln(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).ln(arg) + + // x ^ y (any) + public fun pow( + x: AutoDiffValue, + y: AutoDiffValue, + ): AutoDiffValue = exp(y * ln(x)) + + // sin(x) + public override fun sin(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).sin(arg) + + // cos(x) + public override fun cos(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).cos(arg) + + public override fun tan(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).tan(arg) + + public override fun asin(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).asin(arg) + + public override fun acos(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).acos(arg) + + public override fun atan(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).atan(arg) + + public override fun sinh(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).sinh(arg) + + public override fun cosh(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).cosh(arg) + + public override fun tanh(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).tanh(arg) + + public override fun asinh(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).asinh(arg) + + public override fun acosh(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).acosh(arg) + + public override fun atanh(arg: AutoDiffValue): AutoDiffValue = + (this as SimpleAutoDiffField).atanh(arg) +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt index defbb14ad..1603bc21d 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/expressionBuilders.kt @@ -8,11 +8,6 @@ import kotlin.contracts.InvocationKind import kotlin.contracts.contract -//public interface ExpressionBuilder> { -// public fun expression(block: A.() -> E): Expression -//} - - /** * Creates a functional expression with this [Space]. */ diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt index ca8ec1e17..510ed23a9 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -2,6 +2,7 @@ package kscience.kmath.expressions import kscience.kmath.operations.RealField import kscience.kmath.structures.asBuffer +import kotlin.math.E import kotlin.math.PI import kotlin.math.pow import kotlin.math.sqrt @@ -13,18 +14,18 @@ class SimpleAutoDiffTest { fun dx( xBinding: Pair, - body: AutoDiffField.(x: AutoDiffValue) -> AutoDiffValue, + body: SimpleAutoDiffField.(x: AutoDiffValue) -> AutoDiffValue, ): DerivationResult = RealField.simpleAutoDiff(xBinding) { body(bind(xBinding.first)) } fun dxy( xBinding: Pair, yBinding: Pair, - body: AutoDiffField.(x: AutoDiffValue, y: AutoDiffValue) -> AutoDiffValue, + body: SimpleAutoDiffField.(x: AutoDiffValue, y: AutoDiffValue) -> AutoDiffValue, ): DerivationResult = RealField.simpleAutoDiff(xBinding, yBinding) { body(bind(xBinding.first), bind(yBinding.first)) } - fun diff(block: AutoDiffField.() -> AutoDiffValue): SimpleAutoDiffExpression { + fun diff(block: SimpleAutoDiffField.() -> AutoDiffValue): SimpleAutoDiffExpression { return SimpleAutoDiffExpression(RealField, block) } @@ -45,7 +46,7 @@ class SimpleAutoDiffTest { @Test fun testPlusX2Expr() { - val expr = diff{ + val expr = diff { val x = bind(x) x + x } @@ -245,9 +246,9 @@ class SimpleAutoDiffTest { @Test fun testTanh() { - val y = dx(x to PI / 6) { x -> tanh(x) } - assertApprox(1.0 / sqrt(3.0), y.value) // y = tanh(pi/6) - assertApprox(1.0 / kotlin.math.cosh(PI / 6.0).pow(2), y.derivative(x)) // dy/dx = sech(pi/6)^2 + val y = dx(x to 1.0) { x -> tanh(x) } + assertApprox((E * E - 1) / (E * E + 1), y.value) // y = tanh(pi/6) + assertApprox(1.0 / kotlin.math.cosh(1.0).pow(2), y.derivative(x)) // dy/dx = sech(pi/6)^2 } @Test From 1c1580c8e6c411fe792143882b2e5b67ea2b2c46 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 27 Oct 2020 17:57:49 +0300 Subject: [PATCH 112/199] Generification of autodiff and chi2 --- kmath-commons/build.gradle.kts | 2 +- .../commons/optimization/OptimizeTest.kt | 5 +- .../kscience/kmath/functions/Polynomial.kt | 12 +-- .../kscience/kmath/functions/functions.kt | 34 ------- .../kotlin/kscience/kmath/prob/Fit.kt | 36 ++++++++ .../kmath/prob/OptimizationProblem.kt | 91 +++++++++++++++++++ 6 files changed, 133 insertions(+), 47 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/functions.kt create mode 100644 kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fit.kt create mode 100644 kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/OptimizationProblem.kt diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index ed6452ad8..f0b20e82f 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -7,6 +7,6 @@ dependencies { api(project(":kmath-core")) api(project(":kmath-coroutines")) api(project(":kmath-prob")) -// api(project(":kmath-functions")) + api(project(":kmath-functions")) api("org.apache.commons:commons-math3:3.6.1") } diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index ff5542235..d9fc5ebef 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -46,7 +46,7 @@ internal class OptimizeTest { val sigma = 1.0 val generator = Distribution.normal(0.0, sigma) - val chain = generator.sample(RandomGenerator.default(1126)) + val chain = generator.sample(RandomGenerator.default(112667)) val x = (1..100).map { it.toDouble() } val y = x.map { it -> it.pow(2) + it + 1 + chain.nextDouble() @@ -54,7 +54,8 @@ internal class OptimizeTest { val yErr = x.map { sigma } with(CMFit) { val chi2 = chiSquared(x.asBuffer(), y.asBuffer(), yErr.asBuffer()) { x -> - bind(a) * x.pow(2) + bind(b) * x + bind(c) + val cWithDefault = bindOrNull(c)?: one + bind(a) * x.pow(2) + bind(b) * x + cWithDefault } val result = chi2.minimize(a to 1.5, b to 0.9, c to 1.0) diff --git a/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt index c513a6889..820076c4c 100644 --- a/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt @@ -8,13 +8,13 @@ import kotlin.contracts.contract import kotlin.math.max import kotlin.math.pow -// TODO make `inline`, when KT-41771 gets fixed /** * Polynomial coefficients without fixation on specific context they are applied to * @param coefficients constant is the leftmost coefficient */ public inline class Polynomial(public val coefficients: List) +@Suppress("FunctionName") public fun Polynomial(vararg coefficients: T): Polynomial = Polynomial(coefficients.toList()) public fun Polynomial.value(): Double = coefficients.reduceIndexed { index, acc, d -> acc + d.pow(index) } @@ -33,14 +33,6 @@ public fun > Polynomial.value(ring: C, arg: T): T = ring res } -/** - * Represent a polynomial as a context-dependent function - */ -public fun > Polynomial.asMathFunction(): MathFunction = - object : MathFunction { - override fun C.invoke(arg: T): T = value(this, arg) - } - /** * Represent the polynomial as a regular context-less function */ @@ -49,7 +41,7 @@ public fun > Polynomial.asFunction(ring: C): (T) -> T = /** * An algebra for polynomials */ -public class PolynomialSpace>(public val ring: C) : Space> { +public class PolynomialSpace>(private val ring: C) : Space> { public override val zero: Polynomial = Polynomial(emptyList()) public override fun add(a: Polynomial, b: Polynomial): Polynomial { diff --git a/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/functions.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/functions.kt deleted file mode 100644 index d780c16f3..000000000 --- a/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/functions.kt +++ /dev/null @@ -1,34 +0,0 @@ -package kscience.kmath.functions - -import kscience.kmath.operations.Algebra -import kscience.kmath.operations.RealField - -// TODO make fun interface when KT-41770 is fixed -/** - * A regular function that could be called only inside specific algebra context - * @param T source type - * @param C source algebra constraint - * @param R result type - */ -public /*fun*/ interface MathFunction, R> { - public operator fun C.invoke(arg: T): R -} - -public fun MathFunction.invoke(arg: Double): R = RealField.invoke(arg) - -/** - * A suspendable function defined in algebraic context - */ -// TODO make fun interface, when the new JVM IR is enabled -public interface SuspendableMathFunction, R> { - public suspend operator fun C.invoke(arg: T): R -} - -public suspend fun SuspendableMathFunction.invoke(arg: Double): R = RealField.invoke(arg) - -/** - * A parametric function with parameter - */ -public fun interface ParametricFunction> { - public operator fun C.invoke(arg: T, parameter: P): T -} diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fit.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fit.kt new file mode 100644 index 000000000..efe582212 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fit.kt @@ -0,0 +1,36 @@ +package kscience.kmath.prob + +import kscience.kmath.expressions.AutoDiffProcessor +import kscience.kmath.expressions.DifferentiableExpression +import kscience.kmath.expressions.ExpressionAlgebra +import kscience.kmath.operations.ExtendedField +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.indices + +public object Fit { + + /** + * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation + */ + public fun chiSquared( + autoDiff: AutoDiffProcessor, + x: Buffer, + y: Buffer, + yErr: Buffer, + model: A.(I) -> I, + ): DifferentiableExpression where A : ExtendedField, A : ExpressionAlgebra { + require(x.size == y.size) { "X and y buffers should be of the same size" } + require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + return autoDiff.process { + var sum = zero + x.indices.forEach { + val xValue = const(x[it]) + val yValue = const(y[it]) + val yErrValue = const(yErr[it]) + val modelValue = model(xValue) + sum += ((yValue - modelValue) / yErrValue).pow(2) + } + sum + } + } +} \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/OptimizationProblem.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/OptimizationProblem.kt new file mode 100644 index 000000000..c5fb3fa54 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/OptimizationProblem.kt @@ -0,0 +1,91 @@ +package kscience.kmath.commons.optimization + +import kscience.kmath.expressions.DifferentiableExpression +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.Symbol + +public interface OptimizationFeature + +public class OptimizationResult( + public val point: Map, + public val value: T, + public val features: Set = emptySet(), +) { + override fun toString(): String { + return "OptimizationResult(point=$point, value=$value)" + } +} + +public operator fun OptimizationResult.plus( + feature: OptimizationFeature, +): OptimizationResult = OptimizationResult(point, value, features + feature) + +/** + * A configuration builder for optimization problem + */ +public interface OptimizationProblem { + /** + * Define the initial guess for the optimization problem + */ + public fun initialGuess(map: Map): Unit + + /** + * Set an objective function expression + */ + public fun expression(expression: Expression): Unit + + /** + * Set a differentiable expression as objective function as function and gradient provider + */ + public fun diffExpression(expression: DifferentiableExpression): Unit + + /** + * Update the problem from previous optimization run + */ + public fun update(result: OptimizationResult) + + /** + * Make an optimization run + */ + public fun optimize(): OptimizationResult +} + +public interface OptimizationProblemFactory> { + public fun build(symbols: List): P + +} + +public operator fun > OptimizationProblemFactory.invoke( + symbols: List, + block: P.() -> Unit, +): P = build(symbols).apply(block) + + +/** + * Optimize expression without derivatives using specific [OptimizationProblemFactory] + */ +public fun > Expression.optimizeWith( + factory: OptimizationProblemFactory, + vararg symbols: Symbol, + configuration: F.() -> Unit, +): OptimizationResult { + require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = factory(symbols.toList(),configuration) + problem.expression(this) + return problem.optimize() +} + +/** + * Optimize differentiable expression using specific [OptimizationProblemFactory] + */ +public fun > DifferentiableExpression.optimizeWith( + factory: OptimizationProblemFactory, + vararg symbols: Symbol, + configuration: F.() -> Unit, +): OptimizationResult { + require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = factory(symbols.toList(), configuration) + problem.diffExpression(this) + return problem.optimize() +} + From f8c3d1793c80f7f6fcdbd53b39e9c004cd535a3a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 28 Oct 2020 09:08:37 +0300 Subject: [PATCH 113/199] Fitting refactor --- .../kmath/commons/optimization/CMFit.kt | 95 ------------------- .../kmath/commons/optimization/cmFit.kt | 68 +++++++++++++ .../commons/optimization/OptimizeTest.kt | 20 ++-- .../kmath/prob/{Fit.kt => Fitting.kt} | 31 +++++- 4 files changed, 105 insertions(+), 109 deletions(-) delete mode 100644 kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt create mode 100644 kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt rename kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/{Fit.kt => Fitting.kt} (52%) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt deleted file mode 100644 index 3143dcca5..000000000 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMFit.kt +++ /dev/null @@ -1,95 +0,0 @@ -package kscience.kmath.commons.optimization - -import kscience.kmath.commons.expressions.DerivativeStructureExpression -import kscience.kmath.commons.expressions.DerivativeStructureField -import kscience.kmath.expressions.DifferentiableExpression -import kscience.kmath.expressions.Expression -import kscience.kmath.expressions.StringSymbol -import kscience.kmath.expressions.Symbol -import kscience.kmath.structures.Buffer -import kscience.kmath.structures.indices -import org.apache.commons.math3.analysis.differentiation.DerivativeStructure -import org.apache.commons.math3.optim.nonlinear.scalar.GoalType -import kotlin.math.pow - - -public object CMFit { - - /** - * Generate a chi squared expression from given x-y-sigma model represented by an expression. Does not provide derivatives - * TODO move to prob/stat - */ - public fun chiSquared( - x: Buffer, - y: Buffer, - yErr: Buffer, - model: Expression, - xSymbol: Symbol = StringSymbol("x"), - ): Expression { - require(x.size == y.size) { "X and y buffers should be of the same size" } - require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } - return Expression { arguments -> - x.indices.sumByDouble { - val xValue = x[it] - val yValue = y[it] - val yErrValue = yErr[it] - val modifiedArgs = arguments + (xSymbol to xValue) - val modelValue = model(modifiedArgs) - ((yValue - modelValue) / yErrValue).pow(2) - } - } - } - - /** - * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation - */ - public fun chiSquared( - x: Buffer, - y: Buffer, - yErr: Buffer, - model: DerivativeStructureField.(x: DerivativeStructure) -> DerivativeStructure, - ): DerivativeStructureExpression { - require(x.size == y.size) { "X and y buffers should be of the same size" } - require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } - return DerivativeStructureExpression { - var sum = zero - x.indices.forEach { - val xValue = x[it] - val yValue = y[it] - val yErrValue = yErr[it] - val modelValue = model(const(xValue)) - sum += ((yValue - modelValue) / yErrValue).pow(2) - } - sum - } - } -} - -/** - * Optimize expression without derivatives - */ -public fun Expression.optimize( - vararg symbols: Symbol, - configuration: CMOptimizationProblem.() -> Unit, -): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) - - -/** - * Optimize differentiable expression - */ -public fun DifferentiableExpression.optimize( - vararg symbols: Symbol, - configuration: CMOptimizationProblem.() -> Unit, -): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) - -public fun DifferentiableExpression.minimize( - vararg startPoint: Pair, - configuration: CMOptimizationProblem.() -> Unit = {}, -): OptimizationResult { - require(startPoint.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = CMOptimizationProblem(startPoint.map { it.first }).apply(configuration) - problem.diffExpression(this) - problem.initialGuess(startPoint.toMap()) - problem.goal(GoalType.MINIMIZE) - return problem.optimize() -} \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt new file mode 100644 index 000000000..24df3177d --- /dev/null +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt @@ -0,0 +1,68 @@ +package kscience.kmath.commons.optimization + +import kscience.kmath.commons.expressions.DerivativeStructureField +import kscience.kmath.expressions.DifferentiableExpression +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.Symbol +import kscience.kmath.prob.Fitting +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.asBuffer +import org.apache.commons.math3.analysis.differentiation.DerivativeStructure +import org.apache.commons.math3.optim.nonlinear.scalar.GoalType + + +/** + * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation + */ +public fun Fitting.chiSquared( + x: Buffer, + y: Buffer, + yErr: Buffer, + model: DerivativeStructureField.(x: DerivativeStructure) -> DerivativeStructure, +): DifferentiableExpression = chiSquared(DerivativeStructureField, x, y, yErr, model) + +/** + * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation + */ +public fun Fitting.chiSquared( + x: Iterable, + y: Iterable, + yErr: Iterable, + model: DerivativeStructureField.(x: DerivativeStructure) -> DerivativeStructure, +): DifferentiableExpression = chiSquared( + DerivativeStructureField, + x.toList().asBuffer(), + y.toList().asBuffer(), + yErr.toList().asBuffer(), + model +) + + +/** + * Optimize expression without derivatives + */ +public fun Expression.optimize( + vararg symbols: Symbol, + configuration: CMOptimizationProblem.() -> Unit, +): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) + + +/** + * Optimize differentiable expression + */ +public fun DifferentiableExpression.optimize( + vararg symbols: Symbol, + configuration: CMOptimizationProblem.() -> Unit, +): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) + +public fun DifferentiableExpression.minimize( + vararg startPoint: Pair, + configuration: CMOptimizationProblem.() -> Unit = {}, +): OptimizationResult { + require(startPoint.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = CMOptimizationProblem(startPoint.map { it.first }).apply(configuration) + problem.diffExpression(this) + problem.initialGuess(startPoint.toMap()) + problem.goal(GoalType.MINIMIZE) + return problem.optimize() +} \ No newline at end of file diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index d9fc5ebef..502ed40f8 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -3,6 +3,7 @@ package kscience.kmath.commons.optimization import kscience.kmath.commons.expressions.DerivativeStructureExpression import kscience.kmath.expressions.symbol import kscience.kmath.prob.Distribution +import kscience.kmath.prob.Fitting import kscience.kmath.prob.RandomGenerator import kscience.kmath.prob.normal import kscience.kmath.structures.asBuffer @@ -39,7 +40,7 @@ internal class OptimizeTest { } @Test - fun testFit() { + fun testCmFit() { val a by symbol val b by symbol val c by symbol @@ -52,15 +53,14 @@ internal class OptimizeTest { it.pow(2) + it + 1 + chain.nextDouble() } val yErr = x.map { sigma } - with(CMFit) { - val chi2 = chiSquared(x.asBuffer(), y.asBuffer(), yErr.asBuffer()) { x -> - val cWithDefault = bindOrNull(c)?: one - bind(a) * x.pow(2) + bind(b) * x + cWithDefault - } - - val result = chi2.minimize(a to 1.5, b to 0.9, c to 1.0) - println(result) - println("Chi2/dof = ${result.value / (x.size - 3)}") + val chi2 = Fitting.chiSquared(x.asBuffer(), y.asBuffer(), yErr.asBuffer()) { x -> + val cWithDefault = bindOrNull(c) ?: one + bind(a) * x.pow(2) + bind(b) * x + cWithDefault } + + val result = chi2.minimize(a to 1.5, b to 0.9, c to 1.0) + println(result) + println("Chi2/dof = ${result.value / (x.size - 3)}") } + } \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fit.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fitting.kt similarity index 52% rename from kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fit.kt rename to kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fitting.kt index efe582212..97548d676 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fit.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fitting.kt @@ -1,13 +1,12 @@ package kscience.kmath.prob -import kscience.kmath.expressions.AutoDiffProcessor -import kscience.kmath.expressions.DifferentiableExpression -import kscience.kmath.expressions.ExpressionAlgebra +import kscience.kmath.expressions.* import kscience.kmath.operations.ExtendedField import kscience.kmath.structures.Buffer import kscience.kmath.structures.indices +import kotlin.math.pow -public object Fit { +public object Fitting { /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation @@ -33,4 +32,28 @@ public object Fit { sum } } + + /** + * Generate a chi squared expression from given x-y-sigma model represented by an expression. Does not provide derivatives + */ + public fun chiSquared( + x: Buffer, + y: Buffer, + yErr: Buffer, + model: Expression, + xSymbol: Symbol = StringSymbol("x"), + ): Expression { + require(x.size == y.size) { "X and y buffers should be of the same size" } + require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + return Expression { arguments -> + x.indices.sumByDouble { + val xValue = x[it] + val yValue = y[it] + val yErrValue = yErr[it] + val modifiedArgs = arguments + (xSymbol to xValue) + val modelValue = model(modifiedArgs) + ((yValue - modelValue) / yErrValue).pow(2) + } + } + } } \ No newline at end of file From dfa1bcaf01a2dbbf3eed62706be17a09d92a8618 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 28 Oct 2020 09:16:21 +0300 Subject: [PATCH 114/199] prob renamed to stat --- CHANGELOG.md | 2 ++ README.md | 6 +++--- build.gradle.kts | 2 +- examples/build.gradle.kts | 2 +- .../kscience/kmath/commons/prob/DistributionBenchmark.kt | 2 +- .../kscience/kmath/commons/prob/DistributionDemo.kt | 6 +++--- kmath-commons/build.gradle.kts | 2 +- .../kmath/commons/optimization/CMOptimizationProblem.kt | 4 ++++ .../kotlin/kscience/kmath/commons/optimization/cmFit.kt | 4 +++- .../kmath/commons/random/CMRandomGeneratorWrapper.kt | 2 +- .../kscience/kmath/commons/optimization/OptimizeTest.kt | 8 ++++---- kmath-core/README.md | 2 +- kmath-core/build.gradle.kts | 2 +- {kmath-prob => kmath-stat}/build.gradle.kts | 0 .../kotlin/kscience/kmath/stat}/Distribution.kt | 2 +- .../kotlin/kscience/kmath/stat}/FactorizedDistribution.kt | 2 +- .../src/commonMain/kotlin/kscience/kmath/stat}/Fitting.kt | 2 +- .../kotlin/kscience/kmath/stat}/OptimizationProblem.kt | 2 +- .../commonMain/kotlin/kscience/kmath/stat}/RandomChain.kt | 2 +- .../kotlin/kscience/kmath/stat}/RandomGenerator.kt | 2 +- .../kotlin/kscience/kmath/stat}/SamplerAlgebra.kt | 2 +- .../commonMain/kotlin/kscience/kmath/stat}/Statistic.kt | 2 +- .../kotlin/kscience/kmath/stat}/UniformDistribution.kt | 2 +- .../kotlin/kscience/kmath/stat}/RandomSourceGenerator.kt | 2 +- .../jvmMain/kotlin/kscience/kmath/stat}/distributions.kt | 2 +- .../kscience/kmath/stat}/CommonsDistributionsTest.kt | 2 +- .../jvmTest/kotlin/kscience/kmath/stat}/SamplerTest.kt | 2 +- .../jvmTest/kotlin/kscience/kmath/stat}/StatisticTest.kt | 2 +- settings.gradle.kts | 2 +- 29 files changed, 41 insertions(+), 33 deletions(-) rename {kmath-prob => kmath-stat}/build.gradle.kts (100%) rename {kmath-prob/src/commonMain/kotlin/kscience/kmath/prob => kmath-stat/src/commonMain/kotlin/kscience/kmath/stat}/Distribution.kt (98%) rename {kmath-prob/src/commonMain/kotlin/kscience/kmath/prob => kmath-stat/src/commonMain/kotlin/kscience/kmath/stat}/FactorizedDistribution.kt (98%) rename {kmath-prob/src/commonMain/kotlin/kscience/kmath/prob => kmath-stat/src/commonMain/kotlin/kscience/kmath/stat}/Fitting.kt (98%) rename {kmath-prob/src/commonMain/kotlin/kscience/kmath/prob => kmath-stat/src/commonMain/kotlin/kscience/kmath/stat}/OptimizationProblem.kt (98%) rename {kmath-prob/src/commonMain/kotlin/kscience/kmath/prob => kmath-stat/src/commonMain/kotlin/kscience/kmath/stat}/RandomChain.kt (94%) rename {kmath-prob/src/commonMain/kotlin/kscience/kmath/prob => kmath-stat/src/commonMain/kotlin/kscience/kmath/stat}/RandomGenerator.kt (99%) rename {kmath-prob/src/commonMain/kotlin/kscience/kmath/prob => kmath-stat/src/commonMain/kotlin/kscience/kmath/stat}/SamplerAlgebra.kt (97%) rename {kmath-prob/src/commonMain/kotlin/kscience/kmath/prob => kmath-stat/src/commonMain/kotlin/kscience/kmath/stat}/Statistic.kt (99%) rename {kmath-prob/src/commonMain/kotlin/kscience/kmath/prob => kmath-stat/src/commonMain/kotlin/kscience/kmath/stat}/UniformDistribution.kt (96%) rename {kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob => kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat}/RandomSourceGenerator.kt (98%) rename {kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob => kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat}/distributions.kt (99%) rename {kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob => kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat}/CommonsDistributionsTest.kt (96%) rename {kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob => kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat}/SamplerTest.kt (92%) rename {kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob => kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat}/StatisticTest.kt (96%) diff --git a/CHANGELOG.md b/CHANGELOG.md index f28041adf..2f802d85d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - A `Symbol` indexing scope. - Basic optimization API for Commons-math. - Chi squared optimization for array-like data in CM +- `Fitting` utility object in prob/stat ### Changed - Package changed from `scientifik` to `kscience.kmath`. @@ -21,6 +22,7 @@ - Kotlin version: 1.3.72 -> 1.4.20-M1 - `kmath-ast` doesn't depend on heavy `kotlin-reflect` library. - Full autodiff refactoring based on `Symbol` +- `kmath-prob` renamed to `kmath-stat` ### Deprecated diff --git a/README.md b/README.md index cbdf98afb..afab32dcf 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ can be used for a wide variety of purposes from high performance calculations to > - [buffers](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure > - [expressions](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions) : Functional Expressions > - [domains](kmath-core/src/commonMain/kotlin/kscience/kmath/domains) : Domains -> - [autodif](kmath-core/src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt) : Automatic differentiation +> - [autodif](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
@@ -151,7 +151,7 @@ can be used for a wide variety of purposes from high performance calculations to > **Maturity**: EXPERIMENTAL
-* ### [kmath-prob](kmath-prob) +* ### [kmath-stat](kmath-stat) > > > **Maturity**: EXPERIMENTAL @@ -201,4 +201,4 @@ with the same artifact names. ## Contributing -The project requires a lot of additional work. Please feel free to contribute in any way and propose new features. +The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to open feature issues with requests. We are also welcome to code contributions, especially in issues marked as [waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero). \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 74b76d731..acb9f3b68 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("ru.mipt.npm.project") } -val kmathVersion: String by extra("0.2.0-dev-2") +val kmathVersion: String by extra("0.2.0-dev-3") val bintrayRepo: String by extra("kscience") val githubProject: String by extra("kmath") diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 900da966b..9ba1ec5be 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -23,7 +23,7 @@ dependencies { implementation(project(":kmath-core")) implementation(project(":kmath-coroutines")) implementation(project(":kmath-commons")) - implementation(project(":kmath-prob")) + implementation(project(":kmath-stat")) implementation(project(":kmath-viktor")) implementation(project(":kmath-dimensions")) implementation(project(":kmath-ejml")) diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt index 9c0a01961..ef554aeff 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking import kscience.kmath.chains.BlockingRealChain -import kscience.kmath.prob.* +import kscience.kmath.stat.* import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler import org.apache.commons.rng.simple.RandomSource import java.time.Duration diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt index 7d53e5178..6146e17af 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt @@ -3,9 +3,9 @@ package kscience.kmath.commons.prob import kotlinx.coroutines.runBlocking import kscience.kmath.chains.Chain import kscience.kmath.chains.collectWithState -import kscience.kmath.prob.Distribution -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.normal +import kscience.kmath.stat.Distribution +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.normal private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0) diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index f0b20e82f..6a44c92f2 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -6,7 +6,7 @@ description = "Commons math binding for kmath" dependencies { api(project(":kmath-core")) api(project(":kmath-coroutines")) - api(project(":kmath-prob")) + api(project(":kmath-stat")) api(project(":kmath-functions")) api("org.apache.commons:commons-math3:3.6.1") } diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt index 0d96faaa3..13f9af7bb 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt @@ -1,6 +1,10 @@ package kscience.kmath.commons.optimization import kscience.kmath.expressions.* +import kscience.kmath.stat.OptimizationFeature +import kscience.kmath.stat.OptimizationProblem +import kscience.kmath.stat.OptimizationProblemFactory +import kscience.kmath.stat.OptimizationResult import org.apache.commons.math3.optim.* import org.apache.commons.math3.optim.nonlinear.scalar.GoalType import org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt index 24df3177d..42475db6c 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt @@ -4,7 +4,9 @@ import kscience.kmath.commons.expressions.DerivativeStructureField import kscience.kmath.expressions.DifferentiableExpression import kscience.kmath.expressions.Expression import kscience.kmath.expressions.Symbol -import kscience.kmath.prob.Fitting +import kscience.kmath.stat.Fitting +import kscience.kmath.stat.OptimizationResult +import kscience.kmath.stat.optimizeWith import kscience.kmath.structures.Buffer import kscience.kmath.structures.asBuffer import org.apache.commons.math3.analysis.differentiation.DerivativeStructure diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt index 9600f6901..1eab5f2bd 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt @@ -1,6 +1,6 @@ package kscience.kmath.commons.random -import kscience.kmath.prob.RandomGenerator +import kscience.kmath.stat.RandomGenerator public class CMRandomGeneratorWrapper( public val factory: (IntArray) -> RandomGenerator, diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index 502ed40f8..4384a5124 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -2,10 +2,10 @@ package kscience.kmath.commons.optimization import kscience.kmath.commons.expressions.DerivativeStructureExpression import kscience.kmath.expressions.symbol -import kscience.kmath.prob.Distribution -import kscience.kmath.prob.Fitting -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.normal +import kscience.kmath.stat.Distribution +import kscience.kmath.stat.Fitting +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.normal import kscience.kmath.structures.asBuffer import org.junit.jupiter.api.Test import kotlin.math.pow diff --git a/kmath-core/README.md b/kmath-core/README.md index 6935c0d3c..5501b1d7a 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -7,7 +7,7 @@ The core features of KMath: - [buffers](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure - [expressions](src/commonMain/kotlin/kscience/kmath/expressions) : Functional Expressions - [domains](src/commonMain/kotlin/kscience/kmath/domains) : Domains - - [autodif](src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt) : Automatic differentiation + - [autodif](src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation > #### Artifact: diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index bd254c39d..b0849eca5 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -41,6 +41,6 @@ readme { feature( id = "autodif", description = "Automatic differentiation", - ref = "src/commonMain/kotlin/kscience/kmath/misc/SimpleAutoDiff.kt" + ref = "src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt" ) } \ No newline at end of file diff --git a/kmath-prob/build.gradle.kts b/kmath-stat/build.gradle.kts similarity index 100% rename from kmath-prob/build.gradle.kts rename to kmath-stat/build.gradle.kts diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Distribution.kt similarity index 98% rename from kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt rename to kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Distribution.kt index 72660e20d..c4ceb29eb 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Distribution.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kscience.kmath.chains.Chain import kscience.kmath.chains.collect diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/FactorizedDistribution.kt similarity index 98% rename from kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt rename to kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/FactorizedDistribution.kt index 4d713fc4e..1ed9deba9 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/FactorizedDistribution.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kscience.kmath.chains.Chain import kscience.kmath.chains.SimpleChain diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fitting.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt similarity index 98% rename from kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fitting.kt rename to kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt index 97548d676..01fdf4c5e 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Fitting.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kscience.kmath.expressions.* import kscience.kmath.operations.ExtendedField diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/OptimizationProblem.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt similarity index 98% rename from kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/OptimizationProblem.kt rename to kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt index c5fb3fa54..ea522bff9 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/OptimizationProblem.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt @@ -1,4 +1,4 @@ -package kscience.kmath.commons.optimization +package kscience.kmath.stat import kscience.kmath.expressions.DifferentiableExpression import kscience.kmath.expressions.Expression diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomChain.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/RandomChain.kt similarity index 94% rename from kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomChain.kt rename to kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/RandomChain.kt index b4a80f6c5..0f10851b9 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomChain.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/RandomChain.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kscience.kmath.chains.Chain diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/RandomGenerator.kt similarity index 99% rename from kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt rename to kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/RandomGenerator.kt index 2dd4ce51e..4486ae016 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/RandomGenerator.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kotlin.random.Random diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/SamplerAlgebra.kt similarity index 97% rename from kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/SamplerAlgebra.kt rename to kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/SamplerAlgebra.kt index e363ba30b..f416028a5 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/SamplerAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/SamplerAlgebra.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kscience.kmath.chains.Chain import kscience.kmath.chains.ConstantChain diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Statistic.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Statistic.kt similarity index 99% rename from kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Statistic.kt rename to kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Statistic.kt index 6720a3d7f..a4624fc21 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Statistic.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Statistic.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/UniformDistribution.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/UniformDistribution.kt similarity index 96% rename from kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/UniformDistribution.kt rename to kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/UniformDistribution.kt index 8df2c01e1..1ba5c96f1 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/UniformDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/UniformDistribution.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kscience.kmath.chains.Chain import kscience.kmath.chains.SimpleChain diff --git a/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt b/kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat/RandomSourceGenerator.kt similarity index 98% rename from kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt rename to kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat/RandomSourceGenerator.kt index 18be6f019..5cba28a95 100644 --- a/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt +++ b/kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat/RandomSourceGenerator.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import org.apache.commons.rng.UniformRandomProvider import org.apache.commons.rng.simple.RandomSource diff --git a/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/distributions.kt b/kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat/distributions.kt similarity index 99% rename from kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/distributions.kt rename to kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat/distributions.kt index ff20572cc..9a77b0bd2 100644 --- a/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/distributions.kt +++ b/kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat/distributions.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kscience.kmath.chains.BlockingIntChain import kscience.kmath.chains.BlockingRealChain diff --git a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/CommonsDistributionsTest.kt similarity index 96% rename from kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/CommonsDistributionsTest.kt rename to kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/CommonsDistributionsTest.kt index 12a00684b..fe58fac08 100644 --- a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList diff --git a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/SamplerTest.kt similarity index 92% rename from kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt rename to kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/SamplerTest.kt index 75db5c402..afed4c5d0 100644 --- a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/SamplerTest.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kotlinx.coroutines.runBlocking import kotlin.test.Test diff --git a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/StatisticTest.kt b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/StatisticTest.kt similarity index 96% rename from kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/StatisticTest.kt rename to kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/StatisticTest.kt index 22ca472a8..5cee4d172 100644 --- a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/StatisticTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/StatisticTest.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob +package kscience.kmath.stat import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.first diff --git a/settings.gradle.kts b/settings.gradle.kts index 0f549f9ab..fa9edcf22 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -34,7 +34,7 @@ include( ":kmath-histograms", ":kmath-commons", ":kmath-viktor", - ":kmath-prob", + ":kmath-stat", ":kmath-dimensions", ":kmath-for-real", ":kmath-geometry", From 5fa4d40f415e95303f17b7af34850eeeb0508602 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 28 Oct 2020 09:25:37 +0300 Subject: [PATCH 115/199] Remove Differentiable --- .../kmath/expressions/DifferentiableExpression.kt | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt index 705839b57..4fe73f283 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt @@ -1,20 +1,15 @@ package kscience.kmath.expressions /** - * And object that could be differentiated + * An expression that provides derivatives */ -public interface Differentiable { - public fun derivativeOrNull(orders: Map): T? +public interface DifferentiableExpression : Expression{ + public fun derivativeOrNull(orders: Map): Expression? } -public fun Differentiable.derivative(orders: Map): T = +public fun DifferentiableExpression.derivative(orders: Map): Expression = derivativeOrNull(orders) ?: error("Derivative with orders $orders not provided") -/** - * An expression that provid - */ -public interface DifferentiableExpression : Differentiable>, Expression - public fun DifferentiableExpression.derivative(vararg orders: Pair): Expression = derivative(mapOf(*orders)) From 73b4294122a966095eddf26942cd6bff5a673405 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 28 Oct 2020 09:56:33 +0300 Subject: [PATCH 116/199] Try to fix Native compilation bug --- .../kotlin/kscience/kmath/expressions/Expression.kt | 5 +++-- .../kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index 7e1eb0cd7..9743363c6 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -3,6 +3,7 @@ package kscience.kmath.expressions import kscience.kmath.operations.Algebra import kotlin.jvm.JvmName import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty /** * A marker interface for a symbol. A symbol mus have an identity @@ -84,8 +85,8 @@ public interface ExpressionAlgebra : Algebra { public fun ExpressionAlgebra.bind(symbol: Symbol): E = bindOrNull(symbol) ?: error("Symbol $symbol could not be bound to $this") -public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> - StringSymbol(property.name) +public val symbol: ReadOnlyProperty = object : ReadOnlyProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): StringSymbol = StringSymbol(property.name) } public fun ExpressionAlgebra.binding(): ReadOnlyProperty = diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt index e66832fdb..5a9642690 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -244,7 +244,6 @@ public fun > simpleAutoDiff(field: F): AutoDiffProcessor Date: Wed, 28 Oct 2020 10:07:50 +0300 Subject: [PATCH 117/199] Fix did not work, rolled back. --- .../kscience/kmath/expressions/Expression.kt | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index 9743363c6..ab9ff0e72 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -3,7 +3,6 @@ package kscience.kmath.expressions import kscience.kmath.operations.Algebra import kotlin.jvm.JvmName import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty /** * A marker interface for a symbol. A symbol mus have an identity @@ -85,11 +84,16 @@ public interface ExpressionAlgebra : Algebra { public fun ExpressionAlgebra.bind(symbol: Symbol): E = bindOrNull(symbol) ?: error("Symbol $symbol could not be bound to $this") -public val symbol: ReadOnlyProperty = object : ReadOnlyProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): StringSymbol = StringSymbol(property.name) +/** + * A delegate to create a symbol with a string identity in this scope + */ +public val symbol: ReadOnlyProperty = ReadOnlyProperty { thisRef, property -> + StringSymbol(property.name) } -public fun ExpressionAlgebra.binding(): ReadOnlyProperty = - ReadOnlyProperty { _, property -> - bind(StringSymbol(property.name)) ?: error("A variable with name ${property.name} does not exist") - } \ No newline at end of file +/** + * Bind a symbol by name inside the [ExpressionAlgebra] + */ +public fun ExpressionAlgebra.binding(): ReadOnlyProperty = ReadOnlyProperty { _, property -> + bind(StringSymbol(property.name)) ?: error("A variable with name ${property.name} does not exist") +} \ No newline at end of file From 7f8abbdd206f41da85c834508efa53815e234183 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 29 Oct 2020 02:22:34 +0700 Subject: [PATCH 118/199] Fix typo, introduce KG protocol delegating to algebra --- .../kscience/kmath/ast/KotlingradSupport.kt | 8 +-- .../kmath/kotlingrad/ScalarsAdapters.kt | 57 ++++++++++++++----- .../kmath/kotlingrad/AdaptingTests.kt | 12 ++-- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt index 366a2b4fd..c8478a631 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt @@ -2,10 +2,10 @@ package kscience.kmath.ast import edu.umontreal.kotlingrad.experimental.DoublePrecision import kscience.kmath.asm.compile -import kscience.kmath.kotlingrad.toMst -import kscience.kmath.kotlingrad.tSFun -import kscience.kmath.kotlingrad.toSVar import kscience.kmath.expressions.invoke +import kscience.kmath.kotlingrad.toMst +import kscience.kmath.kotlingrad.toSFun +import kscience.kmath.kotlingrad.toSVar import kscience.kmath.operations.RealField /** @@ -15,7 +15,7 @@ import kscience.kmath.operations.RealField fun main() { val proto = DoublePrecision.prototype val x by MstAlgebra.symbol("x").toSVar(proto) - val quadratic = "x^2-4*x-44".parseMath().tSFun(proto) + val quadratic = "x^2-4*x-44".parseMath().toSFun(proto) val actualDerivative = MstExpression(RealField, quadratic.d(x).toMst()).compile() val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0)) diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt index 99ab5e635..a9a8a14b2 100644 --- a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -2,8 +2,13 @@ package kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.experimental.* import kscience.kmath.ast.MST +import kscience.kmath.ast.MstAlgebra +import kscience.kmath.ast.MstExpression import kscience.kmath.ast.MstExtendedField import kscience.kmath.ast.MstExtendedField.unaryMinus +import kscience.kmath.expressions.DifferentiableExpression +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.Symbol import kscience.kmath.operations.* /** @@ -80,28 +85,52 @@ public fun > MST.Symbolic.toSVar(proto: X): SVar = SVar(proto, va * @param proto the prototype instance. * @return a scalar function. */ -public fun > MST.tSFun(proto: X): SFun = when (this) { +public fun > MST.toSFun(proto: X): SFun = when (this) { is MST.Numeric -> toSConst() is MST.Symbolic -> toSVar(proto) is MST.Unary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> value.tSFun(proto) - SpaceOperations.MINUS_OPERATION -> -value.tSFun(proto) - TrigonometricOperations.SIN_OPERATION -> sin(value.tSFun(proto)) - TrigonometricOperations.COS_OPERATION -> cos(value.tSFun(proto)) - TrigonometricOperations.TAN_OPERATION -> tan(value.tSFun(proto)) - PowerOperations.SQRT_OPERATION -> value.tSFun(proto).sqrt() - ExponentialOperations.EXP_OPERATION -> E() pow value.tSFun(proto) - ExponentialOperations.LN_OPERATION -> value.tSFun(proto).ln() + SpaceOperations.PLUS_OPERATION -> value.toSFun(proto) + SpaceOperations.MINUS_OPERATION -> -value.toSFun(proto) + TrigonometricOperations.SIN_OPERATION -> sin(value.toSFun(proto)) + TrigonometricOperations.COS_OPERATION -> cos(value.toSFun(proto)) + TrigonometricOperations.TAN_OPERATION -> tan(value.toSFun(proto)) + PowerOperations.SQRT_OPERATION -> value.toSFun(proto).sqrt() + ExponentialOperations.EXP_OPERATION -> E() pow value.toSFun(proto) + ExponentialOperations.LN_OPERATION -> value.toSFun(proto).ln() else -> error("Unary operation $operation not defined in $this") } is MST.Binary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> left.tSFun(proto) + right.tSFun(proto) - SpaceOperations.MINUS_OPERATION -> left.tSFun(proto) - right.tSFun(proto) - RingOperations.TIMES_OPERATION -> left.tSFun(proto) * right.tSFun(proto) - FieldOperations.DIV_OPERATION -> left.tSFun(proto) / right.tSFun(proto) - PowerOperations.POW_OPERATION -> left.tSFun(proto) pow (right as MST.Numeric).toSConst() + SpaceOperations.PLUS_OPERATION -> left.toSFun(proto) + right.toSFun(proto) + SpaceOperations.MINUS_OPERATION -> left.toSFun(proto) - right.toSFun(proto) + RingOperations.TIMES_OPERATION -> left.toSFun(proto) * right.toSFun(proto) + FieldOperations.DIV_OPERATION -> left.toSFun(proto) / right.toSFun(proto) + PowerOperations.POW_OPERATION -> left.toSFun(proto) pow (right as MST.Numeric).toSConst() else -> error("Binary operation $operation not defined in $this") } } + +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)) + override val proto: KMathNumber by lazy { KMathNumber(algebra, algebra.number(Double.NaN)) } +} + +public class KMathProtocol(algebra: A) : + Protocol>(KMathNumber(algebra, algebra.number(Double.NaN))) + where T : Number, A : NumericAlgebra + +public class DifferentiableMstExpression(public val algebra: A, public val mst: MST) : + DifferentiableExpression where A : NumericAlgebra, T : Number { + public val proto by lazy { KMathProtocol(algebra).prototype } + public val expr by lazy { MstExpression(algebra, mst) } + + public override fun invoke(arguments: Map): T = expr(arguments) + + public override fun derivativeOrNull(orders: Map): Expression { + val sfun = mst.toSFun(proto) + val orders2 = orders.mapKeys { (k, _) -> MstAlgebra.symbol(k.identity).toSVar(proto) } + TODO() + } +} diff --git a/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt index 25bdbf4be..682b0cf2e 100644 --- a/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -19,7 +19,7 @@ internal class AdaptingTests { fun symbol() { val c1 = MstAlgebra.symbol("x") assertTrue(c1.toSVar(proto).name == "x") - val c2 = "kitten".parseMath().tSFun(proto) + val c2 = "kitten".parseMath().toSFun(proto) if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() } @@ -27,15 +27,15 @@ internal class AdaptingTests { fun number() { val c1 = MstAlgebra.number(12354324) assertTrue(c1.toSConst().doubleValue == 12354324.0) - val c2 = "0.234".parseMath().tSFun(proto) + val c2 = "0.234".parseMath().toSFun(proto) if (c2 is SConst) assertTrue(c2.doubleValue == 0.234) else fail() - val c3 = "1e-3".parseMath().tSFun(proto) + val c3 = "1e-3".parseMath().toSFun(proto) if (c3 is SConst) assertEquals(0.001, c3.value) else fail() } @Test fun simpleFunctionShape() { - val linear = "2*x+16".parseMath().tSFun(proto) + val linear = "2*x+16".parseMath().toSFun(proto) if (linear !is Sum) fail() if (linear.left !is Prod) fail() if (linear.right !is SConst) fail() @@ -44,7 +44,7 @@ internal class AdaptingTests { @Test fun simpleFunctionDerivative() { val x = MstAlgebra.symbol("x").toSVar(proto) - val quadratic = "x^2-4*x-44".parseMath().tSFun(proto) + val quadratic = "x^2-4*x-44".parseMath().toSFun(proto) val actualDerivative = MstExpression(RealField, quadratic.d(x).toMst()).compile() val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0)) @@ -53,7 +53,7 @@ internal class AdaptingTests { @Test fun moreComplexDerivative() { val x = MstAlgebra.symbol("x").toSVar(proto) - val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().tSFun(proto) + val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun(proto) val actualDerivative = MstExpression(RealField, composition.d(x).toMst()).compile() val expectedDerivative = MstExpression( From 6f0f6577de5c555993d19ae3c2b19f5ab27f1e5b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 29 Oct 2020 13:34:12 +0700 Subject: [PATCH 119/199] Refactor toSFun, update KG, delete KMath algebra protocol, update DifferentiableMstExpr. --- kmath-kotlingrad/build.gradle.kts | 2 +- .../kmath/kotlingrad/ScalarsAdapters.kt | 50 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index 0fe6e6b93..f2245c3d5 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -3,6 +3,6 @@ plugins { } dependencies { - api("com.github.breandan:kotlingrad:0.3.2") + api("com.github.breandan:kotlingrad:0.3.7") api(project(":kmath-ast")) } diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt index a9a8a14b2..24e8377bd 100644 --- a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -69,7 +69,7 @@ public fun > MST.Numeric.toSConst(): SConst = SConst(value) * @param proto the prototype instance. * @return a new variable. */ -public fun > MST.Symbolic.toSVar(proto: X): SVar = SVar(proto, value) +public fun > MST.Symbolic.toSVar(): SVar = SVar(value) /** * Maps [MST] objects to [SFun]. Unsupported operations throw [IllegalStateException]. @@ -85,28 +85,28 @@ public fun > MST.Symbolic.toSVar(proto: X): SVar = SVar(proto, va * @param proto the prototype instance. * @return a scalar function. */ -public fun > MST.toSFun(proto: X): SFun = when (this) { +public fun > MST.toSFun(): SFun = when (this) { is MST.Numeric -> toSConst() - is MST.Symbolic -> toSVar(proto) + is MST.Symbolic -> toSVar() is MST.Unary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> value.toSFun(proto) - SpaceOperations.MINUS_OPERATION -> -value.toSFun(proto) - TrigonometricOperations.SIN_OPERATION -> sin(value.toSFun(proto)) - TrigonometricOperations.COS_OPERATION -> cos(value.toSFun(proto)) - TrigonometricOperations.TAN_OPERATION -> tan(value.toSFun(proto)) - PowerOperations.SQRT_OPERATION -> value.toSFun(proto).sqrt() - ExponentialOperations.EXP_OPERATION -> E() pow value.toSFun(proto) - ExponentialOperations.LN_OPERATION -> value.toSFun(proto).ln() + SpaceOperations.PLUS_OPERATION -> value.toSFun() + SpaceOperations.MINUS_OPERATION -> (-value).toSFun() + TrigonometricOperations.SIN_OPERATION -> sin(value.toSFun()) + TrigonometricOperations.COS_OPERATION -> cos(value.toSFun()) + TrigonometricOperations.TAN_OPERATION -> tan(value.toSFun()) + PowerOperations.SQRT_OPERATION -> value.toSFun().sqrt() + ExponentialOperations.EXP_OPERATION -> exp(value.toSFun()) + ExponentialOperations.LN_OPERATION -> value.toSFun().ln() else -> error("Unary operation $operation not defined in $this") } is MST.Binary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> left.toSFun(proto) + right.toSFun(proto) - SpaceOperations.MINUS_OPERATION -> left.toSFun(proto) - right.toSFun(proto) - RingOperations.TIMES_OPERATION -> left.toSFun(proto) * right.toSFun(proto) - FieldOperations.DIV_OPERATION -> left.toSFun(proto) / right.toSFun(proto) - PowerOperations.POW_OPERATION -> left.toSFun(proto) pow (right as MST.Numeric).toSConst() + SpaceOperations.PLUS_OPERATION -> left.toSFun() + right.toSFun() + SpaceOperations.MINUS_OPERATION -> left.toSFun() - right.toSFun() + RingOperations.TIMES_OPERATION -> left.toSFun() * right.toSFun() + FieldOperations.DIV_OPERATION -> left.toSFun() / right.toSFun() + PowerOperations.POW_OPERATION -> left.toSFun() pow (right as MST.Numeric).toSConst() else -> error("Binary operation $operation not defined in $this") } } @@ -114,23 +114,23 @@ public fun > MST.toSFun(proto: X): SFun = when (this) { 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)) - override val proto: KMathNumber by lazy { KMathNumber(algebra, algebra.number(Double.NaN)) } } -public class KMathProtocol(algebra: A) : - Protocol>(KMathNumber(algebra, algebra.number(Double.NaN))) - where T : Number, A : NumericAlgebra - public class DifferentiableMstExpression(public val algebra: A, public val mst: MST) : DifferentiableExpression where A : NumericAlgebra, T : Number { - public val proto by lazy { KMathProtocol(algebra).prototype } public val expr by lazy { MstExpression(algebra, mst) } - public override fun invoke(arguments: Map): T = expr(arguments) + public override fun invoke(arguments: Map): T = expr(arguments) public override fun derivativeOrNull(orders: Map): Expression { - val sfun = mst.toSFun(proto) - val orders2 = orders.mapKeys { (k, _) -> MstAlgebra.symbol(k.identity).toSVar(proto) } + TODO() + } + + public fun derivativeOrNull(orders: List): Expression { + orders.map { MstAlgebra.symbol(it.identity).toSVar>() } + .fold>, SFun>>(mst.toSFun()) { result, sVar -> result.d(sVar) } + .toMst() + TODO() } } From 57910f617ab71493a4299a62b4134505a07b4aab Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 29 Oct 2020 15:39:53 +0700 Subject: [PATCH 120/199] Rename API classes, update readme files --- README.md | 92 ++++-- build.gradle.kts | 11 +- docs/templates/README-TEMPLATE.md | 78 +++-- kmath-core/README.md | 6 +- kmath-core/build.gradle.kts | 12 +- .../kscience/kmath/expressions/Expression.kt | 20 +- .../kscience/kmath/structures/NDAlgebra.kt | 2 +- kmath-nd4j/build.gradle.kts | 26 ++ kmath-nd4j/docs/README-TEMPLATE.md | 43 +++ .../kscience.kmath.nd4j/INDArrayAlgebra.kt | 284 ----------------- .../kscience.kmath.nd4j/Nd4jArrayAlgebra.kt | 288 ++++++++++++++++++ ...ArrayIterators.kt => Nd4jArrayIterator.kt} | 22 +- ...rayStructures.kt => Nd4jArrayStructure.kt} | 28 +- ...AlgebraTest.kt => Nd4jArrayAlgebraTest.kt} | 8 +- ...ctureTest.kt => Nd4jArrayStructureTest.kt} | 2 +- 15 files changed, 534 insertions(+), 388 deletions(-) create mode 100644 kmath-nd4j/docs/README-TEMPLATE.md delete mode 100644 kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayAlgebra.kt create mode 100644 kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt rename kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/{INDArrayIterators.kt => Nd4jArrayIterator.kt} (63%) rename kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/{INDArrayStructures.kt => Nd4jArrayStructure.kt} (63%) rename kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/{INDArrayAlgebraTest.kt => Nd4jArrayAlgebraTest.kt} (79%) rename kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/{INDArrayStructureTest.kt => Nd4jArrayStructureTest.kt} (98%) diff --git a/README.md b/README.md index afab32dcf..2df9d3246 100644 --- a/README.md +++ b/README.md @@ -8,41 +8,50 @@ Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion) # KMath -Could be pronounced as `key-math`. -The Kotlin MATHematics library was initially intended as a Kotlin-based analog to Python's `numpy` library. Later we found that kotlin is much more flexible language and allows superior architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could be achieved with [kmath-for-real](/kmath-for-real) extension module. + +Could be pronounced as `key-math`. The Kotlin MATHematics library was initially intended as a Kotlin-based analog to +Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior architecture +designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could +be achieved with [kmath-for-real](/kmath-for-real) extension module. ## Publications and talks + * [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2) * [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814) * [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103) # Goal -* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM and JS for now and Native in future). + +* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native). * Provide basic multiplatform implementations for those abstractions (without significant performance optimization). * Provide bindings and wrappers with those abstractions for popular optimized platform libraries. ## Non-goals -* Be like Numpy. It was the idea at the beginning, but we decided that we can do better in terms of API. -* Provide best performance out of the box. We have specialized libraries for that. Need only API wrappers for them. + +* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in terms of API. +* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them. * Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually. -* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like for `Double` in the core. For that we will have specialization modules like `for-real`, which will give better experience for those, who want to work with specific types. +* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like +for `Double` in the core. For that we will have specialization modules like `for-real`, which will give better +experience for those, who want to work with specific types. ## Features -Actual feature list is [here](/docs/features.md) +Current feature list is [here](/docs/features.md) * **Algebra** - * Algebraic structures like rings, spaces and field (**TODO** add example to wiki) + * Algebraic structures like rings, spaces and fields (**TODO** add example to wiki) * Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. - * Complex numbers backed by the `Field` API (meaning that they will be usable in any structure like vectors and N-dimensional arrays). + * Complex numbers backed by the `Field` API (meaning they will be usable in any structure like vectors and + N-dimensional arrays). * Advanced linear algebra operations like matrix inversion and LU decomposition. * **Array-like structures** Full support of many-dimensional array-like structures including mixed arithmetic operations and function operations over arrays and numbers (with the added benefit of static type checking). -* **Expressions** By writing a single mathematical expression -once, users will be able to apply different types of objects to the expression by providing a context. Expressions -can be used for a wide variety of purposes from high performance calculations to code generation. +* **Expressions** By writing a single mathematical expression once, users will be able to apply different types of +objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high +performance calculations to code generation. * **Histograms** Fast multi-dimensional histograms. @@ -50,9 +59,10 @@ can be used for a wide variety of purposes from high performance calculations to * **Type-safe dimensions** Type-safe dimensions for matrix operations. -* **Commons-math wrapper** It is planned to gradually wrap most parts of [Apache commons-math](http://commons.apache.org/proper/commons-math/) - library in Kotlin code and maybe rewrite some parts to better suit the Kotlin programming paradigm, however there is no fixed roadmap for that. Feel free - to submit a feature request if you want something to be done first. +* **Commons-math wrapper** It is planned to gradually wrap most parts of +[Apache commons-math](http://commons.apache.org/proper/commons-math/) library in Kotlin code and maybe rewrite some +parts to better suit the Kotlin programming paradigm, however there is no established roadmap for that. Feel free to +submit a feature request if you want something to be implemented first. ## Planned features @@ -151,6 +161,18 @@ can be used for a wide variety of purposes from high performance calculations to > **Maturity**: EXPERIMENTAL
+* ### [kmath-nd4j](kmath-nd4j) +> ND4J NDStructure implementation and according NDAlgebra classes +> +> **Maturity**: EXPERIMENTAL +> +> **Features:** +> - [nd4jarraystrucure](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray +> - [nd4jarrayrings](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long +> - [nd4jarrayfields](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double + +
+ * ### [kmath-stat](kmath-stat) > > @@ -166,39 +188,53 @@ can be used for a wide variety of purposes from high performance calculations to ## Multi-platform support -KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the [common module](/kmath-core/src/commonMain). Implementation is also done in the common module wherever possible. In some cases, features are delegated to platform-specific implementations even if they could be done in the common module for performance reasons. Currently, the JVM is the main focus of development, however Kotlin/Native and Kotlin/JS contributions are also welcome. +KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the +[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features +are delegated to platform-specific implementations even if they could be provided in the common module for performance +reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and +feedback are also welcome. ## Performance -Calculation performance is one of major goals of KMath in the future, but in some cases it is not possible to achieve both performance and flexibility. We expect to focus on creating convenient universal API first and then work on increasing performance for specific cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy. +Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve +both performance and flexibility. -### Dependency +We expect to focus on creating convenient universal API first and then work on increasing performance for specific +cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized +native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be +better than SciPy. -Release artifacts are accessible from bintray with following configuration (see documentation for [kotlin-multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) form more details): +### Repositories + +Release artifacts are accessible from bintray with following configuration (see documentation of +[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details): ```kotlin -repositories{ +repositories { maven("https://dl.bintray.com/mipt-npm/kscience") } -dependencies{ - api("kscience.kmath:kmath-core:0.2.0-dev-2") - //api("kscience.kmath:kmath-core-jvm:0.2.0-dev-2") for jvm-specific version +dependencies { + api("kscience.kmath:kmath-core:0.2.0-dev-3") + // api("kscience.kmath:kmath-core-jvm:0.2.0-dev-3") for jvm-specific version } ``` Gradle `6.0+` is required for multiplatform artifacts. -### Development +#### Development + +Development builds are uploaded to the separate repository: -Development builds are accessible from the reposirtory ```kotlin -repositories{ +repositories { maven("https://dl.bintray.com/mipt-npm/dev") } ``` -with the same artifact names. ## Contributing -The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to open feature issues with requests. We are also welcome to code contributions, especially in issues marked as [waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero). \ No newline at end of file +The project requires a lot of additional work. The most important thing we need is a feedback about what features are +required the most. Feel free to create feature requests. We are also welcome to code contributions, +especially in issues marked with +[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. diff --git a/build.gradle.kts b/build.gradle.kts index b03c03ab8..de0714543 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,16 +2,15 @@ plugins { id("ru.mipt.npm.project") } -val kmathVersion: String by extra("0.2.0-dev-3") -val bintrayRepo: String by extra("kscience") -val githubProject: String by extra("kmath") +internal val kmathVersion: String by extra("0.2.0-dev-3") +internal val bintrayRepo: String by extra("kscience") +internal val githubProject: String by extra("kmath") allprojects { repositories { jcenter() maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlinx") - mavenCentral() maven("https://dl.bintray.com/hotkeytlt/maven") } @@ -27,6 +26,6 @@ readme { readmeTemplate = file("docs/templates/README-TEMPLATE.md") } -apiValidation{ +apiValidation { validationDisabled = true -} \ No newline at end of file +} diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index 5117e0694..ee1df818c 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -8,41 +8,50 @@ Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion) # KMath -Could be pronounced as `key-math`. -The Kotlin MATHematics library was initially intended as a Kotlin-based analog to Python's `numpy` library. Later we found that kotlin is much more flexible language and allows superior architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could be achieved with [kmath-for-real](/kmath-for-real) extension module. + +Could be pronounced as `key-math`. The Kotlin MATHematics library was initially intended as a Kotlin-based analog to +Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior architecture +designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could +be achieved with [kmath-for-real](/kmath-for-real) extension module. ## Publications and talks + * [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2) * [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814) * [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103) # Goal -* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM and JS for now and Native in future). + +* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native). * Provide basic multiplatform implementations for those abstractions (without significant performance optimization). * Provide bindings and wrappers with those abstractions for popular optimized platform libraries. ## Non-goals -* Be like Numpy. It was the idea at the beginning, but we decided that we can do better in terms of API. -* Provide best performance out of the box. We have specialized libraries for that. Need only API wrappers for them. + +* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in terms of API. +* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them. * Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually. -* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like for `Double` in the core. For that we will have specialization modules like `for-real`, which will give better experience for those, who want to work with specific types. +* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like +for `Double` in the core. For that we will have specialization modules like `for-real`, which will give better +experience for those, who want to work with specific types. ## Features -Actual feature list is [here](/docs/features.md) +Current feature list is [here](/docs/features.md) * **Algebra** - * Algebraic structures like rings, spaces and field (**TODO** add example to wiki) + * Algebraic structures like rings, spaces and fields (**TODO** add example to wiki) * Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. - * Complex numbers backed by the `Field` API (meaning that they will be usable in any structure like vectors and N-dimensional arrays). + * Complex numbers backed by the `Field` API (meaning they will be usable in any structure like vectors and + N-dimensional arrays). * Advanced linear algebra operations like matrix inversion and LU decomposition. * **Array-like structures** Full support of many-dimensional array-like structures including mixed arithmetic operations and function operations over arrays and numbers (with the added benefit of static type checking). -* **Expressions** By writing a single mathematical expression -once, users will be able to apply different types of objects to the expression by providing a context. Expressions -can be used for a wide variety of purposes from high performance calculations to code generation. +* **Expressions** By writing a single mathematical expression once, users will be able to apply different types of +objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high +performance calculations to code generation. * **Histograms** Fast multi-dimensional histograms. @@ -50,9 +59,10 @@ can be used for a wide variety of purposes from high performance calculations to * **Type-safe dimensions** Type-safe dimensions for matrix operations. -* **Commons-math wrapper** It is planned to gradually wrap most parts of [Apache commons-math](http://commons.apache.org/proper/commons-math/) - library in Kotlin code and maybe rewrite some parts to better suit the Kotlin programming paradigm, however there is no fixed roadmap for that. Feel free - to submit a feature request if you want something to be done first. +* **Commons-math wrapper** It is planned to gradually wrap most parts of +[Apache commons-math](http://commons.apache.org/proper/commons-math/) library in Kotlin code and maybe rewrite some +parts to better suit the Kotlin programming paradigm, however there is no established roadmap for that. Feel free to +submit a feature request if you want something to be implemented first. ## Planned features @@ -72,39 +82,53 @@ $modules ## Multi-platform support -KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the [common module](/kmath-core/src/commonMain). Implementation is also done in the common module wherever possible. In some cases, features are delegated to platform-specific implementations even if they could be done in the common module for performance reasons. Currently, the JVM is the main focus of development, however Kotlin/Native and Kotlin/JS contributions are also welcome. +KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the +[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features +are delegated to platform-specific implementations even if they could be provided in the common module for performance +reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and +feedback are also welcome. ## Performance -Calculation performance is one of major goals of KMath in the future, but in some cases it is not possible to achieve both performance and flexibility. We expect to focus on creating convenient universal API first and then work on increasing performance for specific cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy. +Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve +both performance and flexibility. -### Dependency +We expect to focus on creating convenient universal API first and then work on increasing performance for specific +cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized +native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be +better than SciPy. -Release artifacts are accessible from bintray with following configuration (see documentation for [kotlin-multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) form more details): +### Repositories + +Release artifacts are accessible from bintray with following configuration (see documentation of +[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details): ```kotlin -repositories{ +repositories { maven("https://dl.bintray.com/mipt-npm/kscience") } -dependencies{ +dependencies { api("kscience.kmath:kmath-core:$version") - //api("kscience.kmath:kmath-core-jvm:$version") for jvm-specific version + // api("kscience.kmath:kmath-core-jvm:$version") for jvm-specific version } ``` Gradle `6.0+` is required for multiplatform artifacts. -### Development +#### Development + +Development builds are uploaded to the separate repository: -Development builds are accessible from the reposirtory ```kotlin -repositories{ +repositories { maven("https://dl.bintray.com/mipt-npm/dev") } ``` -with the same artifact names. ## Contributing -The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to open feature issues with requests. We are also welcome to code contributions, especially in issues marked as [waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero). \ No newline at end of file +The project requires a lot of additional work. The most important thing we need is a feedback about what features are +required the most. Feel free to create feature requests. We are also welcome to code contributions, +especially in issues marked with +[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. diff --git a/kmath-core/README.md b/kmath-core/README.md index 5501b1d7a..42a513a10 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -12,7 +12,7 @@ The core features of KMath: > #### Artifact: > -> This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-2`. +> This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-3`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) > @@ -30,7 +30,7 @@ The core features of KMath: > } > > dependencies { -> implementation 'kscience.kmath:kmath-core:0.2.0-dev-2' +> implementation 'kscience.kmath:kmath-core:0.2.0-dev-3' > } > ``` > **Gradle Kotlin DSL:** @@ -44,6 +44,6 @@ The core features of KMath: > } > > dependencies { -> implementation("kscience.kmath:kmath-core:0.2.0-dev-2") +> implementation("kscience.kmath:kmath-core:0.2.0-dev-3") > } > ``` diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index b0849eca5..7f889d9b4 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,3 +1,5 @@ +import ru.mipt.npm.gradle.Maturity + plugins { id("ru.mipt.npm.mpp") id("ru.mipt.npm.native") @@ -11,36 +13,42 @@ kotlin.sourceSets.commonMain { readme { description = "Core classes, algebra definitions, basic linear algebra" - maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT + maturity = Maturity.DEVELOPMENT propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + feature( id = "algebras", description = "Algebraic structures: contexts and elements", ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt" ) + feature( id = "nd", description = "Many-dimensional structures", ref = "src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt" ) + feature( id = "buffers", description = "One-dimensional structure", ref = "src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt" ) + feature( id = "expressions", description = "Functional Expressions", ref = "src/commonMain/kotlin/kscience/kmath/expressions" ) + feature( id = "domains", description = "Domains", ref = "src/commonMain/kotlin/kscience/kmath/domains" ) + feature( id = "autodif", description = "Automatic differentiation", ref = "src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt" ) -} \ No newline at end of file +} diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index ab9ff0e72..568de255e 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -35,20 +35,27 @@ public fun interface Expression { } /** - * Invoke an expression without parameters + * Calls this expression without providing any arguments. + * + * @return a value. */ public operator fun Expression.invoke(): T = invoke(emptyMap()) -//This method exists to avoid resolution ambiguity of vararg methods /** * Calls this expression from arguments. * - * @param pairs the pair of arguments' names to values. - * @return the value. + * @param pairs the pairs of arguments to values. + * @return a value. */ @JvmName("callBySymbol") public operator fun Expression.invoke(vararg pairs: Pair): T = invoke(mapOf(*pairs)) +/** + * Calls this expression from arguments. + * + * @param pairs the pairs of arguments' names to values. + * @return a value. + */ @JvmName("callByString") public operator fun Expression.invoke(vararg pairs: Pair): T = invoke(mapOf(*pairs).mapKeys { StringSymbol(it.key) }) @@ -61,7 +68,6 @@ public operator fun Expression.invoke(vararg pairs: Pair): T = * @param E type of the actual expression state */ public interface ExpressionAlgebra : Algebra { - /** * Bind a given [Symbol] to this context variable and produce context-specific object. Return null if symbol could not be bound in current context. */ @@ -87,7 +93,7 @@ public fun ExpressionAlgebra.bind(symbol: Symbol): E = /** * A delegate to create a symbol with a string identity in this scope */ -public val symbol: ReadOnlyProperty = ReadOnlyProperty { thisRef, property -> +public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> StringSymbol(property.name) } @@ -96,4 +102,4 @@ public val symbol: ReadOnlyProperty = ReadOnlyProperty { */ public fun ExpressionAlgebra.binding(): ReadOnlyProperty = ReadOnlyProperty { _, property -> bind(StringSymbol(property.name)) ?: error("A variable with name ${property.name} does not exist") -} \ No newline at end of file +} diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt index c1cfcbe49..d7b019c65 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDAlgebra.kt @@ -73,7 +73,7 @@ public interface NDAlgebra> { public fun check(vararg elements: N): Array = elements .map(NDStructure::shape) .singleOrNull { !shape.contentEquals(it) } - ?.let { throw ShapeMismatchException(shape, it) } + ?.let> { throw ShapeMismatchException(shape, it) } ?: elements /** diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 67569b870..953530b01 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,3 +1,5 @@ +import ru.mipt.npm.gradle.Maturity + plugins { id("ru.mipt.npm.jvm") } @@ -9,3 +11,27 @@ dependencies { testImplementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") testImplementation("org.slf4j:slf4j-simple:1.7.30") } + +readme { + description = "ND4J NDStructure implementation and according NDAlgebra classes" + maturity = Maturity.EXPERIMENTAL + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + + feature( + id = "nd4jarraystrucure", + description = "NDStructure wrapper for INDArray", + ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt" + ) + + feature( + id = "nd4jarrayrings", + description = "Rings over Nd4jArrayStructure of Int and Long", + ref = "src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt" + ) + + feature( + id = "nd4jarrayfields", + description = "Fields over Nd4jArrayStructure of Float and Double", + ref = "src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt" + ) +} diff --git a/kmath-nd4j/docs/README-TEMPLATE.md b/kmath-nd4j/docs/README-TEMPLATE.md new file mode 100644 index 000000000..76ce8c9a7 --- /dev/null +++ b/kmath-nd4j/docs/README-TEMPLATE.md @@ -0,0 +1,43 @@ +# ND4J NDStructure implementation (`kmath-nd4j`) + +This subproject implements the following features: + +${features} + +${artifact} + +## Examples + +NDStructure wrapper for INDArray: + +```kotlin +import org.nd4j.linalg.factory.* +import scientifik.kmath.nd4j.* +import scientifik.kmath.structures.* + +val array = Nd4j.ones(2, 2).asRealStructure() +println(array[0, 0]) // 1.0 +array[intArrayOf(0, 0)] = 24.0 +println(array[0, 0]) // 24.0 +``` + +Fast element-wise and in-place arithmetics for INDArray: + +```kotlin +import org.nd4j.linalg.factory.* +import scientifik.kmath.nd4j.* +import scientifik.kmath.operations.* + +val field = RealNd4jArrayField(intArrayOf(2, 2)) +val array = Nd4j.rand(2, 2).asRealStructure() + +val res = field { + (25.0 / array + 20) * 4 +} + +println(res.ndArray) +// [[ 250.6449, 428.5840], +// [ 269.7913, 202.2077]] +``` + +Contributed by [Iaroslav Postovalov](https://github.com/CommanderTvis). diff --git a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayAlgebra.kt deleted file mode 100644 index 728ce3773..000000000 --- a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayAlgebra.kt +++ /dev/null @@ -1,284 +0,0 @@ -package kscience.kmath.nd4j - -import org.nd4j.linalg.api.ndarray.INDArray -import org.nd4j.linalg.factory.Nd4j -import kscience.kmath.operations.* -import kscience.kmath.structures.* - -/** - * Represents [NDAlgebra] over [INDArrayAlgebra]. - * - * @param T the type of ND-structure element. - * @param C the type of the element context. - */ -public interface INDArrayAlgebra : NDAlgebra> { - /** - * Wraps [INDArray] to [N]. - */ - public fun INDArray.wrap(): INDArrayStructure - - public override fun produce(initializer: C.(IntArray) -> T): INDArrayStructure { - val struct = Nd4j.create(*shape)!!.wrap() - struct.indicesIterator().forEach { struct[it] = elementContext.initializer(it) } - return struct - } - - public override fun map(arg: INDArrayStructure, transform: C.(T) -> T): INDArrayStructure { - check(arg) - val newStruct = arg.ndArray.dup().wrap() - newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } - return newStruct - } - - public override fun mapIndexed( - arg: INDArrayStructure, - transform: C.(index: IntArray, T) -> T - ): INDArrayStructure { - check(arg) - val new = Nd4j.create(*shape).wrap() - new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(idx, arg[idx]) } - return new - } - - public override fun combine( - a: INDArrayStructure, - b: INDArrayStructure, - transform: C.(T, T) -> T - ): INDArrayStructure { - check(a, b) - val new = Nd4j.create(*shape).wrap() - new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(a[idx], b[idx]) } - return new - } -} - -/** - * Represents [NDSpace] over [INDArrayStructure]. - * - * @param T the type of the element contained in ND structure. - * @param S the type of space of structure elements. - */ -public interface INDArraySpace : NDSpace>, INDArrayAlgebra where S : Space { - public override val zero: INDArrayStructure - get() = Nd4j.zeros(*shape).wrap() - - public override fun add(a: INDArrayStructure, b: INDArrayStructure): INDArrayStructure { - check(a, b) - return a.ndArray.add(b.ndArray).wrap() - } - - public override operator fun INDArrayStructure.minus(b: INDArrayStructure): INDArrayStructure { - check(this, b) - return ndArray.sub(b.ndArray).wrap() - } - - public override operator fun INDArrayStructure.unaryMinus(): INDArrayStructure { - check(this) - return ndArray.neg().wrap() - } - - public override fun multiply(a: INDArrayStructure, k: Number): INDArrayStructure { - check(a) - return a.ndArray.mul(k).wrap() - } - - public override operator fun INDArrayStructure.div(k: Number): INDArrayStructure { - check(this) - return ndArray.div(k).wrap() - } - - public override operator fun INDArrayStructure.times(k: Number): INDArrayStructure { - check(this) - return ndArray.mul(k).wrap() - } -} - -/** - * Represents [NDRing] over [INDArrayStructure]. - * - * @param T the type of the element contained in ND structure. - * @param R the type of ring of structure elements. - */ -public interface INDArrayRing : NDRing>, INDArraySpace where R : Ring { - public override val one: INDArrayStructure - get() = Nd4j.ones(*shape).wrap() - - public override fun multiply(a: INDArrayStructure, b: INDArrayStructure): INDArrayStructure { - check(a, b) - return a.ndArray.mul(b.ndArray).wrap() - } - - public override operator fun INDArrayStructure.minus(b: Number): INDArrayStructure { - check(this) - return ndArray.sub(b).wrap() - } - - public override operator fun INDArrayStructure.plus(b: Number): INDArrayStructure { - check(this) - return ndArray.add(b).wrap() - } - - public override operator fun Number.minus(b: INDArrayStructure): INDArrayStructure { - check(b) - return b.ndArray.rsub(this).wrap() - } -} - -/** - * Represents [NDField] over [INDArrayStructure]. - * - * @param T the type of the element contained in ND structure. - * @param N the type of ND structure. - * @param F the type field of structure elements. - */ -public interface INDArrayField : NDField>, INDArrayRing where F : Field { - public override fun divide(a: INDArrayStructure, b: INDArrayStructure): INDArrayStructure { - check(a, b) - return a.ndArray.div(b.ndArray).wrap() - } - - public override operator fun Number.div(b: INDArrayStructure): INDArrayStructure { - check(b) - return b.ndArray.rdiv(this).wrap() - } -} - -/** - * Represents [NDField] over [INDArrayRealStructure]. - */ -public class RealINDArrayField(public override val shape: IntArray) : INDArrayField { - public override val elementContext: RealField - get() = RealField - - public override fun INDArray.wrap(): INDArrayStructure = check(asRealStructure()) - - public override operator fun INDArrayStructure.div(arg: Double): INDArrayStructure { - check(this) - return ndArray.div(arg).wrap() - } - - public override operator fun INDArrayStructure.plus(arg: Double): INDArrayStructure { - check(this) - return ndArray.add(arg).wrap() - } - - public override operator fun INDArrayStructure.minus(arg: Double): INDArrayStructure { - check(this) - return ndArray.sub(arg).wrap() - } - - public override operator fun INDArrayStructure.times(arg: Double): INDArrayStructure { - check(this) - return ndArray.mul(arg).wrap() - } - - public override operator fun Double.div(arg: INDArrayStructure): INDArrayStructure { - check(arg) - return arg.ndArray.rdiv(this).wrap() - } - - public override operator fun Double.minus(arg: INDArrayStructure): INDArrayStructure { - check(arg) - return arg.ndArray.rsub(this).wrap() - } -} - -/** - * Represents [NDField] over [INDArrayStructure] of [Float]. - */ -public class FloatINDArrayField(public override val shape: IntArray) : INDArrayField { - public override val elementContext: FloatField - get() = FloatField - - public override fun INDArray.wrap(): INDArrayStructure = check(asFloatStructure()) - - public override operator fun INDArrayStructure.div(arg: Float): INDArrayStructure { - check(this) - return ndArray.div(arg).wrap() - } - - public override operator fun INDArrayStructure.plus(arg: Float): INDArrayStructure { - check(this) - return ndArray.add(arg).wrap() - } - - public override operator fun INDArrayStructure.minus(arg: Float): INDArrayStructure { - check(this) - return ndArray.sub(arg).wrap() - } - - public override operator fun INDArrayStructure.times(arg: Float): INDArrayStructure { - check(this) - return ndArray.mul(arg).wrap() - } - - public override operator fun Float.div(arg: INDArrayStructure): INDArrayStructure { - check(arg) - return arg.ndArray.rdiv(this).wrap() - } - - public override operator fun Float.minus(arg: INDArrayStructure): INDArrayStructure { - check(arg) - return arg.ndArray.rsub(this).wrap() - } -} - -/** - * Represents [NDRing] over [INDArrayIntStructure]. - */ -public class IntINDArrayRing(public override val shape: IntArray) : INDArrayRing { - public override val elementContext: IntRing - get() = IntRing - - public override fun INDArray.wrap(): INDArrayStructure = check(asIntStructure()) - - public override operator fun INDArrayStructure.plus(arg: Int): INDArrayStructure { - check(this) - return ndArray.add(arg).wrap() - } - - public override operator fun INDArrayStructure.minus(arg: Int): INDArrayStructure { - check(this) - return ndArray.sub(arg).wrap() - } - - public override operator fun INDArrayStructure.times(arg: Int): INDArrayStructure { - check(this) - return ndArray.mul(arg).wrap() - } - - public override operator fun Int.minus(arg: INDArrayStructure): INDArrayStructure { - check(arg) - return arg.ndArray.rsub(this).wrap() - } -} - -/** - * Represents [NDRing] over [INDArrayStructure] of [Long]. - */ -public class LongINDArrayRing(public override val shape: IntArray) : INDArrayRing { - public override val elementContext: LongRing - get() = LongRing - - public override fun INDArray.wrap(): INDArrayStructure = check(asLongStructure()) - - public override operator fun INDArrayStructure.plus(arg: Long): INDArrayStructure { - check(this) - return ndArray.add(arg).wrap() - } - - public override operator fun INDArrayStructure.minus(arg: Long): INDArrayStructure { - check(this) - return ndArray.sub(arg).wrap() - } - - public override operator fun INDArrayStructure.times(arg: Long): INDArrayStructure { - check(this) - return ndArray.mul(arg).wrap() - } - - public override operator fun Long.minus(arg: INDArrayStructure): INDArrayStructure { - check(arg) - return arg.ndArray.rsub(this).wrap() - } -} diff --git a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt new file mode 100644 index 000000000..2093a3cb3 --- /dev/null +++ b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt @@ -0,0 +1,288 @@ +package kscience.kmath.nd4j + +import kscience.kmath.operations.* +import kscience.kmath.structures.NDAlgebra +import kscience.kmath.structures.NDField +import kscience.kmath.structures.NDRing +import kscience.kmath.structures.NDSpace +import org.nd4j.linalg.api.ndarray.INDArray +import org.nd4j.linalg.factory.Nd4j + +/** + * Represents [NDAlgebra] over [Nd4jArrayAlgebra]. + * + * @param T the type of ND-structure element. + * @param C the type of the element context. + */ +public interface Nd4jArrayAlgebra : NDAlgebra> { + /** + * Wraps [INDArray] to [N]. + */ + public fun INDArray.wrap(): Nd4jArrayStructure + + public override fun produce(initializer: C.(IntArray) -> T): Nd4jArrayStructure { + val struct = Nd4j.create(*shape)!!.wrap() + struct.indicesIterator().forEach { struct[it] = elementContext.initializer(it) } + return struct + } + + public override fun map(arg: Nd4jArrayStructure, transform: C.(T) -> T): Nd4jArrayStructure { + check(arg) + val newStruct = arg.ndArray.dup().wrap() + newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } + return newStruct + } + + public override fun mapIndexed( + arg: Nd4jArrayStructure, + transform: C.(index: IntArray, T) -> T + ): Nd4jArrayStructure { + check(arg) + val new = Nd4j.create(*shape).wrap() + new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(idx, arg[idx]) } + return new + } + + public override fun combine( + a: Nd4jArrayStructure, + b: Nd4jArrayStructure, + transform: C.(T, T) -> T + ): Nd4jArrayStructure { + check(a, b) + val new = Nd4j.create(*shape).wrap() + new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(a[idx], b[idx]) } + return new + } +} + +/** + * Represents [NDSpace] over [Nd4jArrayStructure]. + * + * @param T the type of the element contained in ND structure. + * @param S the type of space of structure elements. + */ +public interface Nd4jArraySpace : NDSpace>, + Nd4jArrayAlgebra where S : Space { + public override val zero: Nd4jArrayStructure + get() = Nd4j.zeros(*shape).wrap() + + public override fun add(a: Nd4jArrayStructure, b: Nd4jArrayStructure): Nd4jArrayStructure { + check(a, b) + return a.ndArray.add(b.ndArray).wrap() + } + + public override operator fun Nd4jArrayStructure.minus(b: Nd4jArrayStructure): Nd4jArrayStructure { + check(this, b) + return ndArray.sub(b.ndArray).wrap() + } + + public override operator fun Nd4jArrayStructure.unaryMinus(): Nd4jArrayStructure { + check(this) + return ndArray.neg().wrap() + } + + public override fun multiply(a: Nd4jArrayStructure, k: Number): Nd4jArrayStructure { + check(a) + return a.ndArray.mul(k).wrap() + } + + public override operator fun Nd4jArrayStructure.div(k: Number): Nd4jArrayStructure { + check(this) + return ndArray.div(k).wrap() + } + + public override operator fun Nd4jArrayStructure.times(k: Number): Nd4jArrayStructure { + check(this) + return ndArray.mul(k).wrap() + } +} + +/** + * Represents [NDRing] over [Nd4jArrayStructure]. + * + * @param T the type of the element contained in ND structure. + * @param R the type of ring of structure elements. + */ +public interface Nd4jArrayRing : NDRing>, Nd4jArraySpace where R : Ring { + public override val one: Nd4jArrayStructure + get() = Nd4j.ones(*shape).wrap() + + public override fun multiply(a: Nd4jArrayStructure, b: Nd4jArrayStructure): Nd4jArrayStructure { + check(a, b) + return a.ndArray.mul(b.ndArray).wrap() + } + + public override operator fun Nd4jArrayStructure.minus(b: Number): Nd4jArrayStructure { + check(this) + return ndArray.sub(b).wrap() + } + + public override operator fun Nd4jArrayStructure.plus(b: Number): Nd4jArrayStructure { + check(this) + return ndArray.add(b).wrap() + } + + public override operator fun Number.minus(b: Nd4jArrayStructure): Nd4jArrayStructure { + check(b) + return b.ndArray.rsub(this).wrap() + } +} + +/** + * Represents [NDField] over [Nd4jArrayStructure]. + * + * @param T the type of the element contained in ND structure. + * @param N the type of ND structure. + * @param F the type field of structure elements. + */ +public interface Nd4jArrayField : NDField>, Nd4jArrayRing where F : Field { + public override fun divide(a: Nd4jArrayStructure, b: Nd4jArrayStructure): Nd4jArrayStructure { + check(a, b) + return a.ndArray.div(b.ndArray).wrap() + } + + public override operator fun Number.div(b: Nd4jArrayStructure): Nd4jArrayStructure { + check(b) + return b.ndArray.rdiv(this).wrap() + } +} + +/** + * Represents [NDField] over [Nd4jArrayRealStructure]. + */ +public class RealNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { + public override val elementContext: RealField + get() = RealField + + public override fun INDArray.wrap(): Nd4jArrayStructure = check(asRealStructure()) + + public override operator fun Nd4jArrayStructure.div(arg: Double): Nd4jArrayStructure { + check(this) + return ndArray.div(arg).wrap() + } + + public override operator fun Nd4jArrayStructure.plus(arg: Double): Nd4jArrayStructure { + check(this) + return ndArray.add(arg).wrap() + } + + public override operator fun Nd4jArrayStructure.minus(arg: Double): Nd4jArrayStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + public override operator fun Nd4jArrayStructure.times(arg: Double): Nd4jArrayStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + public override operator fun Double.div(arg: Nd4jArrayStructure): Nd4jArrayStructure { + check(arg) + return arg.ndArray.rdiv(this).wrap() + } + + public override operator fun Double.minus(arg: Nd4jArrayStructure): Nd4jArrayStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } +} + +/** + * Represents [NDField] over [Nd4jArrayStructure] of [Float]. + */ +public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { + public override val elementContext: FloatField + get() = FloatField + + public override fun INDArray.wrap(): Nd4jArrayStructure = check(asFloatStructure()) + + public override operator fun Nd4jArrayStructure.div(arg: Float): Nd4jArrayStructure { + check(this) + return ndArray.div(arg).wrap() + } + + public override operator fun Nd4jArrayStructure.plus(arg: Float): Nd4jArrayStructure { + check(this) + return ndArray.add(arg).wrap() + } + + public override operator fun Nd4jArrayStructure.minus(arg: Float): Nd4jArrayStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + public override operator fun Nd4jArrayStructure.times(arg: Float): Nd4jArrayStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + public override operator fun Float.div(arg: Nd4jArrayStructure): Nd4jArrayStructure { + check(arg) + return arg.ndArray.rdiv(this).wrap() + } + + public override operator fun Float.minus(arg: Nd4jArrayStructure): Nd4jArrayStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } +} + +/** + * Represents [NDRing] over [Nd4jArrayIntStructure]. + */ +public class IntNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRing { + public override val elementContext: IntRing + get() = IntRing + + public override fun INDArray.wrap(): Nd4jArrayStructure = check(asIntStructure()) + + public override operator fun Nd4jArrayStructure.plus(arg: Int): Nd4jArrayStructure { + check(this) + return ndArray.add(arg).wrap() + } + + public override operator fun Nd4jArrayStructure.minus(arg: Int): Nd4jArrayStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + public override operator fun Nd4jArrayStructure.times(arg: Int): Nd4jArrayStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + public override operator fun Int.minus(arg: Nd4jArrayStructure): Nd4jArrayStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } +} + +/** + * Represents [NDRing] over [Nd4jArrayStructure] of [Long]. + */ +public class LongNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRing { + public override val elementContext: LongRing + get() = LongRing + + public override fun INDArray.wrap(): Nd4jArrayStructure = check(asLongStructure()) + + public override operator fun Nd4jArrayStructure.plus(arg: Long): Nd4jArrayStructure { + check(this) + return ndArray.add(arg).wrap() + } + + public override operator fun Nd4jArrayStructure.minus(arg: Long): Nd4jArrayStructure { + check(this) + return ndArray.sub(arg).wrap() + } + + public override operator fun Nd4jArrayStructure.times(arg: Long): Nd4jArrayStructure { + check(this) + return ndArray.mul(arg).wrap() + } + + public override operator fun Long.minus(arg: Nd4jArrayStructure): Nd4jArrayStructure { + check(arg) + return arg.ndArray.rsub(this).wrap() + } +} diff --git a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayIterators.kt b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayIterator.kt similarity index 63% rename from kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayIterators.kt rename to kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayIterator.kt index 9e7ef9e16..1463a92fe 100644 --- a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayIterators.kt +++ b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayIterator.kt @@ -3,7 +3,7 @@ package kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray import org.nd4j.linalg.api.shape.Shape -private class INDArrayIndicesIterator(private val iterateOver: INDArray) : Iterator { +private class Nd4jArrayIndicesIterator(private val iterateOver: INDArray) : Iterator { private var i: Int = 0 override fun hasNext(): Boolean = i < iterateOver.length() @@ -18,9 +18,9 @@ private class INDArrayIndicesIterator(private val iterateOver: INDArray) : Itera } } -internal fun INDArray.indicesIterator(): Iterator = INDArrayIndicesIterator(this) +internal fun INDArray.indicesIterator(): Iterator = Nd4jArrayIndicesIterator(this) -private sealed class INDArrayIteratorBase(protected val iterateOver: INDArray) : Iterator> { +private sealed class Nd4jArrayIteratorBase(protected val iterateOver: INDArray) : Iterator> { private var i: Int = 0 final override fun hasNext(): Boolean = i < iterateOver.length() @@ -37,26 +37,26 @@ private sealed class INDArrayIteratorBase(protected val iterateOver: INDArray } } -private class INDArrayRealIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { +private class Nd4jArrayRealIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray): Double = iterateOver.getDouble(*indices) } -internal fun INDArray.realIterator(): Iterator> = INDArrayRealIterator(this) +internal fun INDArray.realIterator(): Iterator> = Nd4jArrayRealIterator(this) -private class INDArrayLongIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { +private class Nd4jArrayLongIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getLong(*indices) } -internal fun INDArray.longIterator(): Iterator> = INDArrayLongIterator(this) +internal fun INDArray.longIterator(): Iterator> = Nd4jArrayLongIterator(this) -private class INDArrayIntIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { +private class Nd4jArrayIntIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getInt(*indices.toIntArray()) } -internal fun INDArray.intIterator(): Iterator> = INDArrayIntIterator(this) +internal fun INDArray.intIterator(): Iterator> = Nd4jArrayIntIterator(this) -private class INDArrayFloatIterator(iterateOver: INDArray) : INDArrayIteratorBase(iterateOver) { +private class Nd4jArrayFloatIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getFloat(*indices) } -internal fun INDArray.floatIterator(): Iterator> = INDArrayFloatIterator(this) +internal fun INDArray.floatIterator(): Iterator> = Nd4jArrayFloatIterator(this) diff --git a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayStructures.kt b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayStructure.kt similarity index 63% rename from kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayStructures.kt rename to kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayStructure.kt index 5d4e1a979..d47a293c3 100644 --- a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/INDArrayStructures.kt +++ b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayStructure.kt @@ -1,15 +1,15 @@ package kscience.kmath.nd4j -import org.nd4j.linalg.api.ndarray.INDArray import kscience.kmath.structures.MutableNDStructure import kscience.kmath.structures.NDStructure +import org.nd4j.linalg.api.ndarray.INDArray /** * Represents a [NDStructure] wrapping an [INDArray] object. * * @param T the type of items. */ -public sealed class INDArrayStructure : MutableNDStructure { +public sealed class Nd4jArrayStructure : MutableNDStructure { /** * The wrapped [INDArray]. */ @@ -23,46 +23,46 @@ public sealed class INDArrayStructure : MutableNDStructure { public override fun elements(): Sequence> = Sequence(::elementsIterator) } -private data class INDArrayIntStructure(override val ndArray: INDArray) : INDArrayStructure() { +private data class Nd4jArrayIntStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.intIterator() override fun get(index: IntArray): Int = ndArray.getInt(*index) override fun set(index: IntArray, value: Int): Unit = run { ndArray.putScalar(index, value) } } /** - * Wraps this [INDArray] to [INDArrayStructure]. + * Wraps this [INDArray] to [Nd4jArrayStructure]. */ -public fun INDArray.asIntStructure(): INDArrayStructure = INDArrayIntStructure(this) +public fun INDArray.asIntStructure(): Nd4jArrayStructure = Nd4jArrayIntStructure(this) -private data class INDArrayLongStructure(override val ndArray: INDArray) : INDArrayStructure() { +private data class Nd4jArrayLongStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.longIterator() override fun get(index: IntArray): Long = ndArray.getLong(*index.toLongArray()) override fun set(index: IntArray, value: Long): Unit = run { ndArray.putScalar(index, value.toDouble()) } } /** - * Wraps this [INDArray] to [INDArrayStructure]. + * Wraps this [INDArray] to [Nd4jArrayStructure]. */ -public fun INDArray.asLongStructure(): INDArrayStructure = INDArrayLongStructure(this) +public fun INDArray.asLongStructure(): Nd4jArrayStructure = Nd4jArrayLongStructure(this) -private data class INDArrayRealStructure(override val ndArray: INDArray) : INDArrayStructure() { +private data class Nd4jArrayRealStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.realIterator() override fun get(index: IntArray): Double = ndArray.getDouble(*index) override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) } } /** - * Wraps this [INDArray] to [INDArrayStructure]. + * Wraps this [INDArray] to [Nd4jArrayStructure]. */ -public fun INDArray.asRealStructure(): INDArrayStructure = INDArrayRealStructure(this) +public fun INDArray.asRealStructure(): Nd4jArrayStructure = Nd4jArrayRealStructure(this) -private data class INDArrayFloatStructure(override val ndArray: INDArray) : INDArrayStructure() { +private data class Nd4jArrayFloatStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.floatIterator() override fun get(index: IntArray): Float = ndArray.getFloat(*index) override fun set(index: IntArray, value: Float): Unit = run { ndArray.putScalar(index, value) } } /** - * Wraps this [INDArray] to [INDArrayStructure]. + * Wraps this [INDArray] to [Nd4jArrayStructure]. */ -public fun INDArray.asFloatStructure(): INDArrayStructure = INDArrayFloatStructure(this) +public fun INDArray.asFloatStructure(): Nd4jArrayStructure = Nd4jArrayFloatStructure(this) diff --git a/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt similarity index 79% rename from kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayAlgebraTest.kt rename to kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index 1a4f4c9f3..650d5670c 100644 --- a/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -6,10 +6,10 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.fail -internal class INDArrayAlgebraTest { +internal class Nd4jArrayAlgebraTest { @Test fun testProduce() { - val res = (RealINDArrayField(intArrayOf(2, 2))) { produce { it.sum().toDouble() } } + val res = (RealNd4jArrayField(intArrayOf(2, 2))) { produce { it.sum().toDouble() } } val expected = (Nd4j.create(2, 2) ?: fail()).asRealStructure() expected[intArrayOf(0, 0)] = 0.0 expected[intArrayOf(0, 1)] = 1.0 @@ -20,7 +20,7 @@ internal class INDArrayAlgebraTest { @Test fun testMap() { - val res = (IntINDArrayRing(intArrayOf(2, 2))) { map(one) { it + it * 2 } } + val res = (IntNd4jArrayRing(intArrayOf(2, 2))) { map(one) { it + it * 2 } } val expected = (Nd4j.create(2, 2) ?: fail()).asIntStructure() expected[intArrayOf(0, 0)] = 3 expected[intArrayOf(0, 1)] = 3 @@ -31,7 +31,7 @@ internal class INDArrayAlgebraTest { @Test fun testAdd() { - val res = (IntINDArrayRing(intArrayOf(2, 2))) { one + 25 } + val res = (IntNd4jArrayRing(intArrayOf(2, 2))) { one + 25 } val expected = (Nd4j.create(2, 2) ?: fail()).asIntStructure() expected[intArrayOf(0, 0)] = 26 expected[intArrayOf(0, 1)] = 26 diff --git a/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt similarity index 98% rename from kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayStructureTest.kt rename to kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt index 63426d7f9..7e46211c1 100644 --- a/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/INDArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt @@ -7,7 +7,7 @@ import kotlin.test.assertEquals import kotlin.test.assertNotEquals import kotlin.test.fail -internal class INDArrayStructureTest { +internal class Nd4jArrayStructureTest { @Test fun testElements() { val nd = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! From 022b8f0fa347aff5bcba3aae6eabae52c60aa390 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 29 Oct 2020 15:44:30 +0700 Subject: [PATCH 121/199] Regenerate readme --- kmath-nd4j/README.md | 40 +++++++++++++++++++------------------ kmath-nd4j/build.gradle.kts | 2 +- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index fac24504a..b071df499 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -2,45 +2,48 @@ This subproject implements the following features: -- NDStructure wrapper for INDArray. -- Optimized NDRing implementations for INDArray storing Ints and Longs. -- Optimized NDField implementations for INDArray storing Floats and Doubles. + - [nd4jarraystrucure](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray + - [nd4jarrayrings](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long + - [nd4jarrayfields](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double + > #### Artifact: -> This module is distributed in the artifact `scientifik:kmath-nd4j:0.1.4-dev-8`. -> +> +> This module artifact: `kscience.kmath:kmath-nd4j:0.2.0-dev-3`. +> +> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-nd4j/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-nd4j/_latestVersion) +> +> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-nd4j/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-nd4j/_latestVersion) +> > **Gradle:** > > ```gradle > repositories { -> mavenCentral() -> maven { url 'https://dl.bintray.com/mipt-npm/scientifik' } +> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } +> maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } +> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + > } > > dependencies { -> implementation 'scientifik:kmath-nd4j:0.1.4-dev-8' -> implementation 'org.nd4j:nd4j-native-platform:1.0.0-beta7' +> implementation 'kscience.kmath:kmath-nd4j:0.2.0-dev-3' > } > ``` > **Gradle Kotlin DSL:** > > ```kotlin > repositories { -> mavenCentral() -> maven("https://dl.bintray.com/mipt-npm/scientifik") +> maven("https://dl.bintray.com/kotlin/kotlin-eap") +> maven("https://dl.bintray.com/mipt-npm/kscience") > maven("https://dl.bintray.com/mipt-npm/dev") +> maven("https://dl.bintray.com/hotkeytlt/maven") > } > > dependencies { -> implementation("scientifik:kmath-nd4j:0.1.4-dev-8") -> implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") +> implementation("kscience.kmath:kmath-nd4j:0.2.0-dev-3") > } > ``` -> -> This distribution also needs an implementation of ND4J API. The ND4J Native Platform is usually the fastest one, so -> it is included to the snippet. -> ## Examples @@ -64,7 +67,7 @@ import org.nd4j.linalg.factory.* import scientifik.kmath.nd4j.* import scientifik.kmath.operations.* -val field = RealINDArrayField(intArrayOf(2, 2)) +val field = RealNd4jArrayField(intArrayOf(2, 2)) val array = Nd4j.rand(2, 2).asRealStructure() val res = field { @@ -76,5 +79,4 @@ println(res.ndArray) // [ 269.7913, 202.2077]] ``` - Contributed by [Iaroslav Postovalov](https://github.com/CommanderTvis). diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 953530b01..391727c45 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -18,7 +18,7 @@ readme { propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( - id = "nd4jarraystrucure", + id = "nd4jarraystructure", description = "NDStructure wrapper for INDArray", ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt" ) From fbe1ab94a4127263b09b5182797deaeab5012e2c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 29 Oct 2020 19:35:08 +0300 Subject: [PATCH 122/199] Change DifferentiableExpression API to use ordered symbol list instead of orders map. --- .../DerivativeStructureExpression.kt | 42 +++++++++++-------- .../DerivativeStructureExpressionTest.kt | 22 ++++++---- .../expressions/DifferentiableExpression.kt | 20 ++++----- .../kscience/kmath/expressions/Expression.kt | 2 +- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index c593f5103..e4311a56b 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -12,46 +12,51 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure */ public class DerivativeStructureField( public val order: Int, - private val bindings: Map + bindings: Map, ) : ExtendedField, ExpressionAlgebra { - public override val zero: DerivativeStructure by lazy { DerivativeStructure(bindings.size, order) } - public override val one: DerivativeStructure by lazy { DerivativeStructure(bindings.size, order, 1.0) } + public override val zero: DerivativeStructure by lazy { DerivativeStructure(bindings.size, 0) } + public override val one: DerivativeStructure by lazy { DerivativeStructure(bindings.size, 0, 1.0) } /** * A class that implements both [DerivativeStructure] and a [Symbol] */ - public inner class DerivativeStructureSymbol(symbol: Symbol, value: Double) : - DerivativeStructure(bindings.size, order, bindings.keys.indexOf(symbol), value), Symbol { + public inner class DerivativeStructureSymbol( + size: Int, + index: Int, + symbol: Symbol, + value: Double, + ) : DerivativeStructure(size, order, index, value), Symbol { override val identity: String = symbol.identity override fun toString(): String = identity override fun equals(other: Any?): Boolean = this.identity == (other as? Symbol)?.identity override fun hashCode(): Int = identity.hashCode() } + public val numberOfVariables: Int = bindings.size + /** * Identity-based symbol bindings map */ - private val variables: Map = bindings.entries.associate { (key, value) -> - key.identity to DerivativeStructureSymbol(key, value) - } + private val variables: Map = bindings.entries.mapIndexed { index, (key, value) -> + key.identity to DerivativeStructureSymbol(numberOfVariables, index, key, value) + }.toMap() - override fun const(value: Double): DerivativeStructure = DerivativeStructure(bindings.size, order, value) + override fun const(value: Double): DerivativeStructure = DerivativeStructure(numberOfVariables, 0, value) public override fun bindOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity] public fun bind(symbol: Symbol): DerivativeStructureSymbol = variables.getValue(symbol.identity) - //public fun Number.const(): DerivativeStructure = const(toDouble()) + override fun symbol(value: String): DerivativeStructureSymbol = bind(StringSymbol(value)) - public fun DerivativeStructure.derivative(parameter: Symbol, order: Int = 1): Double { - return derivative(mapOf(parameter to order)) + public fun DerivativeStructure.derivative(symbols: List): Double { + require(symbols.size <= order) { "The order of derivative ${symbols.size} exceeds computed order $order" } + val ordersCount = symbols.map { it.identity }.groupBy { it }.mapValues { it.value.size } + return getPartialDerivative(*variables.keys.map { ordersCount[it] ?: 0 }.toIntArray()) } - public fun DerivativeStructure.derivative(orders: Map): Double { - return getPartialDerivative(*bindings.keys.map { orders[it] ?: 0 }.toIntArray()) - } + public fun DerivativeStructure.derivative(vararg symbols: Symbol): Double = derivative(symbols.toList()) - public fun DerivativeStructure.derivative(vararg orders: Pair): Double = derivative(mapOf(*orders)) public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b) public override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) { @@ -97,6 +102,7 @@ public class DerivativeStructureField( } } + /** * A constructs that creates a derivative structure with required order on-demand */ @@ -109,7 +115,7 @@ public class DerivativeStructureExpression( /** * Get the derivative expression with given orders */ - public override fun derivativeOrNull(orders: Map): Expression = Expression { arguments -> - with(DerivativeStructureField(orders.values.maxOrNull() ?: 0, arguments)) { function().derivative(orders) } + public override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> + with(DerivativeStructureField(symbols.size, arguments)) { function().derivative(symbols) } } } diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt index 8886e123f..7511a38ed 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt @@ -5,14 +5,15 @@ import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFails -internal inline fun diff( +internal inline fun diff( order: Int, vararg parameters: Pair, - block: DerivativeStructureField.() -> R, -): R { + block: DerivativeStructureField.() -> Unit, +): Unit { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return DerivativeStructureField(order, mapOf(*parameters)).run(block) + DerivativeStructureField(order, mapOf(*parameters)).run(block) } internal class AutoDiffTest { @@ -21,13 +22,16 @@ internal class AutoDiffTest { @Test fun derivativeStructureFieldTest() { - val res: Double = diff(3, x to 1.0, y to 1.0) { + diff(2, x to 1.0, y to 1.0) { val x = bind(x)//by binding() val y = symbol("y") - val z = x * (-sin(x * y) + y) - z.derivative(x) + val z = x * (-sin(x * y) + y) + 2.0 + println(z.derivative(x)) + println(z.derivative(y,x)) + assertEquals(z.derivative(x, y), z.derivative(y, x)) + //check that improper order cause failure + assertFails { z.derivative(x,x,y) } } - println(res) } @Test @@ -40,5 +44,7 @@ internal class AutoDiffTest { assertEquals(10.0, f(x to 1.0, y to 2.0)) assertEquals(6.0, f.derivative(x)(x to 1.0, y to 2.0)) + assertEquals(2.0, f.derivative(x, x)(x to 1.234, y to -2.0)) + assertEquals(2.0, f.derivative(x, y)(x to 1.0, y to 2.0)) } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt index 4fe73f283..ac1f4bc20 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt @@ -3,20 +3,18 @@ package kscience.kmath.expressions /** * An expression that provides derivatives */ -public interface DifferentiableExpression : Expression{ - public fun derivativeOrNull(orders: Map): Expression? +public interface DifferentiableExpression : Expression { + public fun derivativeOrNull(symbols: List): Expression? } -public fun DifferentiableExpression.derivative(orders: Map): Expression = - derivativeOrNull(orders) ?: error("Derivative with orders $orders not provided") +public fun DifferentiableExpression.derivative(symbols: List): Expression = + derivativeOrNull(symbols) ?: error("Derivative by symbols $symbols not provided") -public fun DifferentiableExpression.derivative(vararg orders: Pair): Expression = - derivative(mapOf(*orders)) - -public fun DifferentiableExpression.derivative(symbol: Symbol): Expression = derivative(symbol to 1) +public fun DifferentiableExpression.derivative(vararg symbols: Symbol): Expression = + derivative(symbols.toList()) public fun DifferentiableExpression.derivative(name: String): Expression = - derivative(StringSymbol(name) to 1) + derivative(StringSymbol(name)) /** * A [DifferentiableExpression] that defines only first derivatives @@ -25,8 +23,8 @@ public abstract class FirstDerivativeExpression : DifferentiableExpression public abstract fun derivativeOrNull(symbol: Symbol): Expression? - public override fun derivativeOrNull(orders: Map): Expression? { - val dSymbol = orders.entries.singleOrNull { it.value == 1 }?.key ?: return null + public override fun derivativeOrNull(symbols: List): Expression? { + val dSymbol = symbols.firstOrNull() ?: return null return derivativeOrNull(dSymbol) } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index ab9ff0e72..8f408e09e 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -87,7 +87,7 @@ public fun ExpressionAlgebra.bind(symbol: Symbol): E = /** * A delegate to create a symbol with a string identity in this scope */ -public val symbol: ReadOnlyProperty = ReadOnlyProperty { thisRef, property -> +public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> StringSymbol(property.name) } From 6f31ddba301b2cfb2a8ebbc900afb566b510f612 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 29 Oct 2020 19:50:45 +0300 Subject: [PATCH 123/199] Fix CM DerivativeStructureField constants --- .../expressions/DerivativeStructureExpression.kt | 10 +++++----- .../kmath/commons/optimization/OptimizeTest.kt | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index e4311a56b..244dc1314 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -14,8 +14,10 @@ public class DerivativeStructureField( public val order: Int, bindings: Map, ) : ExtendedField, ExpressionAlgebra { - public override val zero: DerivativeStructure by lazy { DerivativeStructure(bindings.size, 0) } - public override val one: DerivativeStructure by lazy { DerivativeStructure(bindings.size, 0, 1.0) } + public val numberOfVariables: Int = bindings.size + + public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) } + public override val one: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order, 1.0) } /** * A class that implements both [DerivativeStructure] and a [Symbol] @@ -32,8 +34,6 @@ public class DerivativeStructureField( override fun hashCode(): Int = identity.hashCode() } - public val numberOfVariables: Int = bindings.size - /** * Identity-based symbol bindings map */ @@ -41,7 +41,7 @@ public class DerivativeStructureField( key.identity to DerivativeStructureSymbol(numberOfVariables, index, key, value) }.toMap() - override fun const(value: Double): DerivativeStructure = DerivativeStructure(numberOfVariables, 0, value) + override fun const(value: Double): DerivativeStructure = DerivativeStructure(numberOfVariables, order, value) public override fun bindOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity] diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index 4384a5124..fa1978f95 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -6,7 +6,6 @@ import kscience.kmath.stat.Distribution import kscience.kmath.stat.Fitting import kscience.kmath.stat.RandomGenerator import kscience.kmath.stat.normal -import kscience.kmath.structures.asBuffer import org.junit.jupiter.api.Test import kotlin.math.pow @@ -53,7 +52,7 @@ internal class OptimizeTest { it.pow(2) + it + 1 + chain.nextDouble() } val yErr = x.map { sigma } - val chi2 = Fitting.chiSquared(x.asBuffer(), y.asBuffer(), yErr.asBuffer()) { x -> + val chi2 = Fitting.chiSquared(x, y, yErr) { x -> val cWithDefault = bindOrNull(c) ?: one bind(a) * x.pow(2) + bind(b) * x + cWithDefault } From 095b165fa47effa6271274b24b953f47761300dc Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 29 Oct 2020 23:59:36 +0700 Subject: [PATCH 124/199] Uncomment expressions benchmark, and add factory methods for Nd4jRing and Nd4jField --- examples/build.gradle.kts | 20 ++- .../ast/ExpressionsInterpretersBenchmark.kt | 138 +++++++++--------- .../kscience/kmath/structures/NDField.kt | 13 ++ .../kscience.kmath.nd4j/Nd4jArrayAlgebra.kt | 61 ++++++++ 4 files changed, 161 insertions(+), 71 deletions(-) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 9ba1ec5be..f35031140 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -19,7 +19,7 @@ repositories { sourceSets.register("benchmarks") dependencies { -// implementation(project(":kmath-ast")) + implementation(project(":kmath-ast")) implementation(project(":kmath-core")) implementation(project(":kmath-coroutines")) implementation(project(":kmath-commons")) @@ -27,6 +27,20 @@ dependencies { implementation(project(":kmath-viktor")) implementation(project(":kmath-dimensions")) implementation(project(":kmath-ejml")) + implementation(project(":kmath-nd4j")) + implementation("org.deeplearning4j:deeplearning4j-core:1.0.0-beta7") + implementation("org.nd4j:nd4j-native:1.0.0-beta7") + +// uncomment if your system supports AVX2 +// val os = System.getProperty("os.name") +// +// if (System.getProperty("os.arch") in arrayOf("x86_64", "amd64")) when { +// os.startsWith("Windows") -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:windows-x86_64-avx2") +// os == "Linux" -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:linux-x86_64-avx2") +// os == "Mac OS X" -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:macosx-x86_64-avx2") +// } else + implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") + implementation("org.jetbrains.kotlinx:kotlinx-io:0.2.0-npm-dev-11") implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20") implementation("org.slf4j:slf4j-simple:1.7.30") @@ -55,4 +69,6 @@ kotlin.sourceSets.all { } } -tasks.withType { kotlinOptions.jvmTarget = "11" } +tasks.withType { + kotlinOptions.jvmTarget = "11" +} diff --git a/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt index f0a32e5bd..35875747c 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt @@ -1,70 +1,70 @@ package kscience.kmath.ast -// -//import kscience.kmath.asm.compile -//import kscience.kmath.expressions.Expression -//import kscience.kmath.expressions.expressionInField -//import kscience.kmath.expressions.invoke -//import kscience.kmath.operations.Field -//import kscience.kmath.operations.RealField -//import kotlin.random.Random -//import kotlin.system.measureTimeMillis -// -//class ExpressionsInterpretersBenchmark { -// private val algebra: Field = RealField -// fun functionalExpression() { -// val expr = algebra.expressionInField { -// variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0) -// } -// -// invokeAndSum(expr) -// } -// -// fun mstExpression() { -// val expr = algebra.mstInField { -// symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) -// } -// -// invokeAndSum(expr) -// } -// -// fun asmExpression() { -// val expr = algebra.mstInField { -// symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) -// }.compile() -// -// invokeAndSum(expr) -// } -// -// private fun invokeAndSum(expr: Expression) { -// val random = Random(0) -// var sum = 0.0 -// -// repeat(1000000) { -// sum += expr("x" to random.nextDouble()) -// } -// -// println(sum) -// } -//} -// -//fun main() { -// val benchmark = ExpressionsInterpretersBenchmark() -// -// val fe = measureTimeMillis { -// benchmark.functionalExpression() -// } -// -// println("fe=$fe") -// -// val mst = measureTimeMillis { -// benchmark.mstExpression() -// } -// -// println("mst=$mst") -// -// val asm = measureTimeMillis { -// benchmark.asmExpression() -// } -// -// println("asm=$asm") -//} + +import kscience.kmath.asm.compile +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.expressionInField +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.Field +import kscience.kmath.operations.RealField +import kotlin.random.Random +import kotlin.system.measureTimeMillis + +class ExpressionsInterpretersBenchmark { + private val algebra: Field = RealField + fun functionalExpression() { + val expr = algebra.expressionInField { + symbol("x") * const(2.0) + const(2.0) / symbol("x") - const(16.0) + } + + invokeAndSum(expr) + } + + fun mstExpression() { + val expr = algebra.mstInField { + symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) + } + + invokeAndSum(expr) + } + + fun asmExpression() { + val expr = algebra.mstInField { + symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) + }.compile() + + invokeAndSum(expr) + } + + private fun invokeAndSum(expr: Expression) { + val random = Random(0) + var sum = 0.0 + + repeat(1000000) { + sum += expr("x" to random.nextDouble()) + } + + println(sum) + } +} + +fun main() { + val benchmark = ExpressionsInterpretersBenchmark() + + val fe = measureTimeMillis { + benchmark.functionalExpression() + } + + println("fe=$fe") + + val mst = measureTimeMillis { + benchmark.mstExpression() + } + + println("mst=$mst") + + val asm = measureTimeMillis { + benchmark.asmExpression() + } + + println("asm=$asm") +} diff --git a/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt index 28bfab779..e53af0dee 100644 --- a/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt @@ -1,8 +1,10 @@ package kscience.kmath.structures import kotlinx.coroutines.GlobalScope +import kscience.kmath.nd4j.Nd4jArrayField import kscience.kmath.operations.RealField import kscience.kmath.operations.invoke +import org.nd4j.linalg.factory.Nd4j import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.system.measureTimeMillis @@ -14,6 +16,8 @@ internal inline fun measureAndPrint(title: String, block: () -> Unit) { } fun main() { + // initializing Nd4j + Nd4j.zeros(0) val dim = 1000 val n = 1000 @@ -23,6 +27,8 @@ fun main() { val specializedField = NDField.real(dim, dim) //A generic boxing field. It should be used for objects, not primitives. val genericField = NDField.boxing(RealField, dim, dim) + // Nd4j specialized field. + val nd4jField = Nd4jArrayField.real(dim, dim) measureAndPrint("Automatic field addition") { autoField { @@ -43,6 +49,13 @@ fun main() { } } + measureAndPrint("Nd4j specialized addition") { + nd4jField { + var res = one + repeat(n) { res += 1.0 as Number } + } + } + measureAndPrint("Lazy addition") { val res = specializedField.one.mapAsync(GlobalScope) { var c = 0.0 diff --git a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt index 2093a3cb3..a8c874fc3 100644 --- a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt @@ -126,6 +126,36 @@ public interface Nd4jArrayRing : NDRing>, Nd4j check(b) return b.ndArray.rsub(this).wrap() } + + public companion object { + private val intNd4jArrayRingCache: ThreadLocal> = + ThreadLocal.withInitial { hashMapOf() } + + private val longNd4jArrayRingCache: ThreadLocal> = + ThreadLocal.withInitial { hashMapOf() } + + /** + * Creates an [NDRing] for [Int] values or pull it from cache if it was created previously. + */ + public fun int(vararg shape: Int): Nd4jArrayRing = + intNd4jArrayRingCache.get().getOrPut(shape) { IntNd4jArrayRing(shape) } + + /** + * Creates an [NDRing] for [Long] values or pull it from cache if it was created previously. + */ + public fun long(vararg shape: Int): Nd4jArrayRing = + longNd4jArrayRingCache.get().getOrPut(shape) { LongNd4jArrayRing(shape) } + + /** + * Creates a most suitable implementation of [NDRing] using reified class. + */ + @Suppress("UNCHECKED_CAST") + public inline fun auto(vararg shape: Int): Nd4jArrayRing> = when { + T::class == Int::class -> int(*shape) as Nd4jArrayRing> + T::class == Long::class -> long(*shape) as Nd4jArrayRing> + else -> throw UnsupportedOperationException("This factory method only supports Int and Long types.") + } + } } /** @@ -145,6 +175,37 @@ public interface Nd4jArrayField : NDField>, Nd check(b) return b.ndArray.rdiv(this).wrap() } + + + public companion object { + private val floatNd4jArrayFieldCache: ThreadLocal> = + ThreadLocal.withInitial { hashMapOf() } + + private val realNd4jArrayFieldCache: ThreadLocal> = + ThreadLocal.withInitial { hashMapOf() } + + /** + * Creates an [NDField] for [Float] values or pull it from cache if it was created previously. + */ + public fun float(vararg shape: Int): Nd4jArrayRing = + floatNd4jArrayFieldCache.get().getOrPut(shape) { FloatNd4jArrayField(shape) } + + /** + * Creates an [NDField] for [Double] values or pull it from cache if it was created previously. + */ + public fun real(vararg shape: Int): Nd4jArrayRing = + realNd4jArrayFieldCache.get().getOrPut(shape) { RealNd4jArrayField(shape) } + + /** + * Creates a most suitable implementation of [NDRing] using reified class. + */ + @Suppress("UNCHECKED_CAST") + public inline fun auto(vararg shape: Int): Nd4jArrayField> = when { + T::class == Float::class -> float(*shape) as Nd4jArrayField> + T::class == Double::class -> real(*shape) as Nd4jArrayField> + else -> throw UnsupportedOperationException("This factory method only supports Float and Double types.") + } + } } /** From 29a670483ba315a3adde3f6fabc2f69c3d1c09e8 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 30 Oct 2020 01:09:11 +0700 Subject: [PATCH 125/199] Update KG and Maven repos, delete symbol delegate provider, implement working differentiable mst expression based on SFun shape to MST conversion --- build.gradle.kts | 7 ++- examples/build.gradle.kts | 8 --- .../ast/ExpressionsInterpretersBenchmark.kt | 2 +- .../kscience/kmath/ast/KotlingradSupport.kt | 16 +++--- .../kscience/kmath/ast/MstExpression.kt | 25 +++++---- .../kotlin/kscience/kmath/ast/extensions.kt | 12 ---- .../jvmMain/kotlin/kscience/kmath/asm/asm.kt | 3 +- kmath-kotlingrad/build.gradle.kts | 3 +- .../kotlingrad/DifferentiableMstExpression.kt | 53 ++++++++++++++++++ .../kscience/kmath/kotlingrad/KMathNumber.kt | 18 ++++++ .../kmath/kotlingrad/ScalarsAdapters.kt | 56 ++++++++----------- 11 files changed, 125 insertions(+), 78 deletions(-) delete mode 100644 kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt create mode 100644 kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt create mode 100644 kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/KMathNumber.kt diff --git a/build.gradle.kts b/build.gradle.kts index 51ce48d84..095697bc4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,10 +9,15 @@ internal val githubProject: String by extra("kmath") 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://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlinx") - maven("https://dl.bintray.com/hotkeytlt/maven") + maven("https://dl.bintray.com/mipt-npm/dev") + maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://jitpack.io") + mavenCentral() } group = "kscience.kmath" diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 3ca9bbb47..33018976d 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -8,14 +8,6 @@ plugins { } allOpen.annotation("org.openjdk.jmh.annotations.State") - -repositories { - maven("https://dl.bintray.com/mipt-npm/kscience") - maven("https://dl.bintray.com/mipt-npm/dev") - maven("https://dl.bintray.com/kotlin/kotlin-dev/") - mavenCentral() -} - sourceSets.register("benchmarks") dependencies { diff --git a/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt index b25a61e96..a4806ed68 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt @@ -13,7 +13,7 @@ internal class ExpressionsInterpretersBenchmark { private val algebra: Field = RealField fun functionalExpression() { val expr = algebra.expressionInField { - variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0) + symbol("x") * const(2.0) + const(2.0) / symbol("x") - const(16.0) } invokeAndSum(expr) diff --git a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt index c8478a631..7b5e1565d 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt @@ -1,11 +1,9 @@ package kscience.kmath.ast -import edu.umontreal.kotlingrad.experimental.DoublePrecision import kscience.kmath.asm.compile import kscience.kmath.expressions.invoke -import kscience.kmath.kotlingrad.toMst -import kscience.kmath.kotlingrad.toSFun -import kscience.kmath.kotlingrad.toSVar +import kscience.kmath.expressions.symbol +import kscience.kmath.kotlingrad.DifferentiableMstExpression import kscience.kmath.operations.RealField /** @@ -13,10 +11,12 @@ import kscience.kmath.operations.RealField * valid derivative. */ fun main() { - val proto = DoublePrecision.prototype - val x by MstAlgebra.symbol("x").toSVar(proto) - val quadratic = "x^2-4*x-44".parseMath().toSFun(proto) - val actualDerivative = MstExpression(RealField, quadratic.d(x).toMst()).compile() + val x by symbol + + val actualDerivative = DifferentiableMstExpression(RealField, "x^2-4*x-44".parseMath()) + .derivativeOrNull(listOf(x)) + .compile() + val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0)) } diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt index 5ca75e993..f68e3f5f8 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt @@ -13,7 +13,7 @@ import kotlin.contracts.contract * @property mst the [MST] node. * @author Alexander Nozik */ -public class MstExpression(public val algebra: Algebra, public val mst: MST) : Expression { +public class MstExpression>(public val algebra: A, public val mst: MST) : Expression { private inner class InnerAlgebra(val arguments: Map) : NumericAlgebra { override fun symbol(value: String): T = arguments[StringSymbol(value)] ?: algebra.symbol(value) override fun unaryOperation(operation: String, arg: T): T = algebra.unaryOperation(operation, arg) @@ -21,8 +21,9 @@ public class MstExpression(public val algebra: Algebra, public val mst: MS override fun binaryOperation(operation: String, left: T, right: T): T = algebra.binaryOperation(operation, left, right) - override fun number(value: Number): T = if (algebra is NumericAlgebra) - algebra.number(value) + @Suppress("UNCHECKED_CAST") + override fun number(value: Number): T = if (algebra is NumericAlgebra<*>) + (algebra as NumericAlgebra).number(value) else error("Numeric nodes are not supported by $this") } @@ -38,14 +39,14 @@ public class MstExpression(public val algebra: Algebra, public val mst: MS public inline fun , E : Algebra> A.mst( mstAlgebra: E, block: E.() -> MST, -): MstExpression = MstExpression(this, mstAlgebra.block()) +): MstExpression = MstExpression(this, mstAlgebra.block()) /** * Builds [MstExpression] over [Space]. * * @author Alexander Nozik */ -public inline fun Space.mstInSpace(block: MstSpace.() -> MST): MstExpression { +public inline fun > A.mstInSpace(block: MstSpace.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return MstExpression(this, MstSpace.block()) } @@ -55,7 +56,7 @@ public inline fun Space.mstInSpace(block: MstSpace.() -> MS * * @author Alexander Nozik */ -public inline fun Ring.mstInRing(block: MstRing.() -> MST): MstExpression { +public inline fun > A.mstInRing(block: MstRing.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return MstExpression(this, MstRing.block()) } @@ -65,7 +66,7 @@ public inline fun Ring.mstInRing(block: MstRing.() -> MST): * * @author Alexander Nozik */ -public inline fun Field.mstInField(block: MstField.() -> MST): MstExpression { +public inline fun > A.mstInField(block: MstField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return MstExpression(this, MstField.block()) } @@ -75,7 +76,7 @@ public inline fun Field.mstInField(block: MstField.() -> MS * * @author Iaroslav Postovalov */ -public inline fun Field.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression { +public inline fun > A.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return MstExpression(this, MstExtendedField.block()) } @@ -85,7 +86,7 @@ public inline fun Field.mstInExtendedField(block: MstExtend * * @author Alexander Nozik */ -public inline fun > FunctionalExpressionSpace.mstInSpace(block: MstSpace.() -> MST): MstExpression { +public inline fun > FunctionalExpressionSpace.mstInSpace(block: MstSpace.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return algebra.mstInSpace(block) } @@ -95,7 +96,7 @@ public inline fun > FunctionalExpressionSpace> FunctionalExpressionRing.mstInRing(block: MstRing.() -> MST): MstExpression { +public inline fun > FunctionalExpressionRing.mstInRing(block: MstRing.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return algebra.mstInRing(block) } @@ -105,7 +106,7 @@ public inline fun > FunctionalExpressionRing. * * @author Alexander Nozik */ -public inline fun > FunctionalExpressionField.mstInField(block: MstField.() -> MST): MstExpression { +public inline fun > FunctionalExpressionField.mstInField(block: MstField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return algebra.mstInField(block) } @@ -117,7 +118,7 @@ public inline fun > FunctionalExpressionField> FunctionalExpressionExtendedField.mstInExtendedField( block: MstExtendedField.() -> MST, -): MstExpression { +): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return algebra.mstInExtendedField(block) } diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt deleted file mode 100644 index b790a3a88..000000000 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/extensions.kt +++ /dev/null @@ -1,12 +0,0 @@ -package kscience.kmath.ast - -import kscience.kmath.operations.Algebra -import kotlin.properties.PropertyDelegateProvider -import kotlin.properties.ReadOnlyProperty - -/** - * Returns [PropertyDelegateProvider] providing [ReadOnlyProperty] of [MST.Symbolic] with its value equal to the name - * of the property. - */ -public val Algebra.symbol: PropertyDelegateProvider, ReadOnlyProperty, MST.Symbolic>> - get() = PropertyDelegateProvider { _, _ -> ReadOnlyProperty { _, p -> MST.Symbolic(p.name) } } diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt index 2b6fa6247..9ccfa464c 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt @@ -69,4 +69,5 @@ public inline fun Algebra.expression(mst: MST): Expression< * * @author Alexander Nozik. */ -public inline fun MstExpression.compile(): Expression = mst.compileWith(T::class.java, algebra) +public inline fun MstExpression>.compile(): Expression = + mst.compileWith(T::class.java, algebra) diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index f2245c3d5..027a03bc9 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -3,6 +3,7 @@ plugins { } dependencies { - api("com.github.breandan:kotlingrad:0.3.7") + implementation("com.github.breandan:kaliningraph:0.1.2") + implementation("com.github.breandan:kotlingrad:0.3.7") api(project(":kmath-ast")) } diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt new file mode 100644 index 000000000..88cc20639 --- /dev/null +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -0,0 +1,53 @@ +package kscience.kmath.kotlingrad + +import edu.umontreal.kotlingrad.experimental.SFun +import kscience.kmath.ast.MST +import kscience.kmath.ast.MstAlgebra +import kscience.kmath.ast.MstExpression +import kscience.kmath.expressions.DifferentiableExpression +import kscience.kmath.expressions.Symbol +import kscience.kmath.operations.NumericAlgebra + +/** + * Represents wrapper of [MstExpression] implementing [DifferentiableExpression]. + * + * The principle of this API is converting the [mst] to an [SFun], differentiating it with Kotlin∇, then converting + * [SFun] back to [MST]. + * + * @param T the type of number. + * @param A the [NumericAlgebra] of [T]. + * @property expr the underlying [MstExpression]. + */ +public inline class DifferentiableMstExpression(public val expr: MstExpression) : + DifferentiableExpression where A : NumericAlgebra, T : Number { + public constructor(algebra: A, mst: MST) : this(MstExpression(algebra, mst)) + + /** + * The [MstExpression.algebra] of [expr]. + */ + public val algebra: A + get() = expr.algebra + + /** + * The [MstExpression.mst] of [expr]. + */ + public val mst: MST + get() = expr.mst + + public override fun invoke(arguments: Map): T = expr(arguments) + + public override fun derivativeOrNull(symbols: List): MstExpression = MstExpression( + algebra, + symbols.map(Symbol::identity) + .map(MstAlgebra::symbol) + .map { it.toSVar>() } + .fold(mst.toSFun(), SFun>::d) + .toMst(), + ) +} + +/** + * Wraps this [MstExpression] into [DifferentiableMstExpression]. + */ +public fun > MstExpression.differentiable(): DifferentiableMstExpression = + DifferentiableMstExpression(this) diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/KMathNumber.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/KMathNumber.kt new file mode 100644 index 000000000..ce5658137 --- /dev/null +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/KMathNumber.kt @@ -0,0 +1,18 @@ +package kscience.kmath.kotlingrad + +import edu.umontreal.kotlingrad.experimental.RealNumber +import edu.umontreal.kotlingrad.experimental.SConst +import kscience.kmath.operations.NumericAlgebra + +/** + * Implements [RealNumber] 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. + */ +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)) +} diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt index 24e8377bd..b6effab4b 100644 --- a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -3,14 +3,26 @@ package kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.experimental.* import kscience.kmath.ast.MST import kscience.kmath.ast.MstAlgebra -import kscience.kmath.ast.MstExpression import kscience.kmath.ast.MstExtendedField import kscience.kmath.ast.MstExtendedField.unaryMinus -import kscience.kmath.expressions.DifferentiableExpression -import kscience.kmath.expressions.Expression -import kscience.kmath.expressions.Symbol import kscience.kmath.operations.* +/** + * Maps [SVar] to [MST.Symbolic] directly. + * + * @receiver the variable. + * @return a node. + */ +public fun > SVar.toMst(): MST.Symbolic = MstAlgebra.symbol(name) + +/** + * Maps [SVar] to [MST.Numeric] directly. + * + * @receiver the constant. + * @return a node. + */ +public fun > SConst.toMst(): MST.Numeric = MstAlgebra.number(doubleValue) + /** * Maps [SFun] objects to [MST]. Some unsupported operations like [Derivative] are bound and converted then. * [Power] operation is limited to constant right-hand side arguments. @@ -37,8 +49,8 @@ import kscience.kmath.operations.* */ public fun > SFun.toMst(): MST = MstExtendedField { when (this@toMst) { - is SVar -> symbol(name) - is SConst -> number(doubleValue) + is SVar -> toMst() + is SConst -> toMst() is Sum -> left.toMst() + right.toMst() is Prod -> left.toMst() * right.toMst() is Power -> left.toMst() pow ((right as? SConst<*>)?.doubleValue ?: (right() as SConst<*>).doubleValue) @@ -69,7 +81,7 @@ public fun > MST.Numeric.toSConst(): SConst = SConst(value) * @param proto the prototype instance. * @return a new variable. */ -public fun > MST.Symbolic.toSVar(): SVar = SVar(value) +internal fun > MST.Symbolic.toSVar(): SVar = SVar(value) /** * Maps [MST] objects to [SFun]. Unsupported operations throw [IllegalStateException]. @@ -90,12 +102,12 @@ public fun > MST.toSFun(): SFun = when (this) { is MST.Symbolic -> toSVar() is MST.Unary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> value.toSFun() - SpaceOperations.MINUS_OPERATION -> (-value).toSFun() + SpaceOperations.PLUS_OPERATION -> +value.toSFun() + SpaceOperations.MINUS_OPERATION -> -value.toSFun() TrigonometricOperations.SIN_OPERATION -> sin(value.toSFun()) TrigonometricOperations.COS_OPERATION -> cos(value.toSFun()) TrigonometricOperations.TAN_OPERATION -> tan(value.toSFun()) - PowerOperations.SQRT_OPERATION -> value.toSFun().sqrt() + PowerOperations.SQRT_OPERATION -> sqrt(value.toSFun()) ExponentialOperations.EXP_OPERATION -> exp(value.toSFun()) ExponentialOperations.LN_OPERATION -> value.toSFun().ln() else -> error("Unary operation $operation not defined in $this") @@ -110,27 +122,3 @@ public fun > MST.toSFun(): SFun = when (this) { else -> error("Binary operation $operation not defined in $this") } } - -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 DifferentiableMstExpression(public val algebra: A, public val mst: MST) : - DifferentiableExpression where A : NumericAlgebra, T : Number { - public val expr by lazy { MstExpression(algebra, mst) } - - public override fun invoke(arguments: Map): T = expr(arguments) - - public override fun derivativeOrNull(orders: Map): Expression { - TODO() - } - - public fun derivativeOrNull(orders: List): Expression { - orders.map { MstAlgebra.symbol(it.identity).toSVar>() } - .fold>, SFun>>(mst.toSFun()) { result, sVar -> result.d(sVar) } - .toMst() - - TODO() - } -} From bc4eb95ae7c05ff957092586d8823d6064dfc21f Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 30 Oct 2020 16:40:43 +0700 Subject: [PATCH 126/199] Add extension functions for DifferentiableMstExpression --- .../kotlin/kscience/kmath/ast/KotlingradSupport.kt | 3 ++- .../kmath/kotlingrad/DifferentiableMstExpression.kt | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt index 7b5e1565d..9b34426f7 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt @@ -4,6 +4,7 @@ import kscience.kmath.asm.compile import kscience.kmath.expressions.invoke import kscience.kmath.expressions.symbol import kscience.kmath.kotlingrad.DifferentiableMstExpression +import kscience.kmath.kotlingrad.derivative import kscience.kmath.operations.RealField /** @@ -14,7 +15,7 @@ fun main() { val x by symbol val actualDerivative = DifferentiableMstExpression(RealField, "x^2-4*x-44".parseMath()) - .derivativeOrNull(listOf(x)) + .derivative(x) .compile() val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index 88cc20639..ddfc7cccb 100644 --- a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -5,6 +5,7 @@ import kscience.kmath.ast.MST import kscience.kmath.ast.MstAlgebra import kscience.kmath.ast.MstExpression import kscience.kmath.expressions.DifferentiableExpression +import kscience.kmath.expressions.StringSymbol import kscience.kmath.expressions.Symbol import kscience.kmath.operations.NumericAlgebra @@ -46,6 +47,15 @@ public inline class DifferentiableMstExpression(public val expr: MstExpres ) } +public fun > DifferentiableMstExpression.derivative(symbols: List): MstExpression = + derivativeOrNull(symbols) + +public fun > DifferentiableMstExpression.derivative(vararg symbols: Symbol): MstExpression = + derivative(symbols.toList()) + +public fun > DifferentiableMstExpression.derivative(name: String): MstExpression = + derivative(StringSymbol(name)) + /** * Wraps this [MstExpression] into [DifferentiableMstExpression]. */ From ef7066b8c94d0c9450d2b1a0f1eeb79ffb27fdc9 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 30 Oct 2020 16:40:58 +0700 Subject: [PATCH 127/199] Update example --- .../src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt index 9b34426f7..5fbb5b86a 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt @@ -5,6 +5,7 @@ import kscience.kmath.expressions.invoke import kscience.kmath.expressions.symbol import kscience.kmath.kotlingrad.DifferentiableMstExpression import kscience.kmath.kotlingrad.derivative +import kscience.kmath.kotlingrad.differentiable import kscience.kmath.operations.RealField /** @@ -14,7 +15,8 @@ import kscience.kmath.operations.RealField fun main() { val x by symbol - val actualDerivative = DifferentiableMstExpression(RealField, "x^2-4*x-44".parseMath()) + val actualDerivative = MstExpression(RealField, "x^2-4*x-44".parseMath()) + .differentiable() .derivative(x) .compile() From d14e4376595670f7ff9148f01d34fccd277f9e2b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 30 Oct 2020 16:57:19 +0700 Subject: [PATCH 128/199] Update DifferentiableExpression by providing second type argument representing the result of differentiation --- .../kscience/kmath/ast/KotlingradSupport.kt | 1 - .../DerivativeStructureExpression.kt | 10 ++-- .../expressions/DifferentiableExpression.kt | 34 ++++++----- .../kscience/kmath/expressions/Expression.kt | 4 +- .../kmath/expressions/SimpleAutoDiff.kt | 56 +++++++++---------- .../kotlingrad/DifferentiableMstExpression.kt | 12 +--- 6 files changed, 57 insertions(+), 60 deletions(-) diff --git a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt index 5fbb5b86a..5acd97e3d 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt @@ -3,7 +3,6 @@ package kscience.kmath.ast import kscience.kmath.asm.compile import kscience.kmath.expressions.invoke import kscience.kmath.expressions.symbol -import kscience.kmath.kotlingrad.DifferentiableMstExpression import kscience.kmath.kotlingrad.derivative import kscience.kmath.kotlingrad.differentiable import kscience.kmath.operations.RealField diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 244dc1314..345babe8b 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -95,10 +95,10 @@ public class DerivativeStructureField( public override operator fun Number.plus(b: DerivativeStructure): DerivativeStructure = b + this public override operator fun Number.minus(b: DerivativeStructure): DerivativeStructure = b - this - public companion object : AutoDiffProcessor { - override fun process(function: DerivativeStructureField.() -> DerivativeStructure): DifferentiableExpression { - return DerivativeStructureExpression(function) - } + public companion object : + AutoDiffProcessor> { + public override fun process(function: DerivativeStructureField.() -> DerivativeStructure): DifferentiableExpression> = + DerivativeStructureExpression(function) } } @@ -108,7 +108,7 @@ public class DerivativeStructureField( */ public class DerivativeStructureExpression( public val function: DerivativeStructureField.() -> DerivativeStructure, -) : DifferentiableExpression { +) : DifferentiableExpression> { public override operator fun invoke(arguments: Map): Double = DerivativeStructureField(0, arguments).function().value diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt index ac1f4bc20..890ad5f71 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt @@ -1,29 +1,37 @@ package kscience.kmath.expressions /** - * An expression that provides derivatives + * Represents expression which structure can be differentiated. + * + * @param T the type this expression takes as argument and returns. + * @param R the type of expression this expression can be differentiated to. */ -public interface DifferentiableExpression : Expression { - public fun derivativeOrNull(symbols: List): Expression? +public interface DifferentiableExpression> : Expression { + /** + * Differentiates this expression by ordered collection of [symbols]. + */ + public fun derivativeOrNull(symbols: List): R? } -public fun DifferentiableExpression.derivative(symbols: List): Expression = +public fun > DifferentiableExpression.derivative(symbols: List): R = derivativeOrNull(symbols) ?: error("Derivative by symbols $symbols not provided") -public fun DifferentiableExpression.derivative(vararg symbols: Symbol): Expression = +public fun > DifferentiableExpression.derivative(vararg symbols: Symbol): R = derivative(symbols.toList()) -public fun DifferentiableExpression.derivative(name: String): Expression = +public fun > DifferentiableExpression.derivative(name: String): R = derivative(StringSymbol(name)) /** * A [DifferentiableExpression] that defines only first derivatives */ -public abstract class FirstDerivativeExpression : DifferentiableExpression { +public abstract class FirstDerivativeExpression> : DifferentiableExpression { + /** + * Returns first derivative of this expression by given [symbol]. + */ + public abstract fun derivativeOrNull(symbol: Symbol): R? - public abstract fun derivativeOrNull(symbol: Symbol): Expression? - - public override fun derivativeOrNull(symbols: List): Expression? { + public final override fun derivativeOrNull(symbols: List): R? { val dSymbol = symbols.firstOrNull() ?: return null return derivativeOrNull(dSymbol) } @@ -32,6 +40,6 @@ public abstract class FirstDerivativeExpression : DifferentiableExpression /** * A factory that converts an expression in autodiff variables to a [DifferentiableExpression] */ -public interface AutoDiffProcessor> { - public fun process(function: A.() -> I): DifferentiableExpression -} \ No newline at end of file +public fun interface AutoDiffProcessor, R : Expression> { + public fun process(function: A.() -> I): DifferentiableExpression +} diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index 568de255e..98940e767 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -22,7 +22,9 @@ public inline class StringSymbol(override val identity: String) : Symbol { } /** - * An elementary function that could be invoked on a map of arguments + * An elementary function that could be invoked on a map of arguments. + * + * @param T the type this expression takes as argument and returns. */ public fun interface Expression { /** diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt index 5a9642690..e8a894d23 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -68,7 +68,7 @@ public fun > F.simpleAutoDiff( ): DerivationResult { contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) } - return SimpleAutoDiffField(this, bindings).derivate(body) + return SimpleAutoDiffField(this, bindings).differentiate(body) } public fun > F.simpleAutoDiff( @@ -83,12 +83,21 @@ public open class SimpleAutoDiffField>( public val context: F, bindings: Map, ) : Field>, ExpressionAlgebra> { + public override val zero: AutoDiffValue + get() = const(context.zero) + + public override val one: AutoDiffValue + get() = const(context.one) // this stack contains pairs of blocks and values to apply them to private var stack: Array = arrayOfNulls(8) private var sp: Int = 0 private val derivatives: MutableMap, T> = hashMapOf() + private val bindings: Map> = bindings.entries.associate { + it.key.identity to AutoDiffVariableWithDerivative(it.key.identity, it.value, context.zero) + } + /** * Differentiable variable with value and derivative of differentiation ([simpleAutoDiff]) result * with respect to this variable. @@ -106,11 +115,7 @@ public open class SimpleAutoDiffField>( override fun hashCode(): Int = identity.hashCode() } - private val bindings: Map> = bindings.entries.associate { - it.key.identity to AutoDiffVariableWithDerivative(it.key.identity, it.value, context.zero) - } - - override fun bindOrNull(symbol: Symbol): AutoDiffValue? = bindings[symbol.identity] + public override fun bindOrNull(symbol: Symbol): AutoDiffValue? = bindings[symbol.identity] private fun getDerivative(variable: AutoDiffValue): T = (variable as? AutoDiffVariableWithDerivative)?.d ?: derivatives[variable] ?: context.zero @@ -119,7 +124,6 @@ public open class SimpleAutoDiffField>( if (variable is AutoDiffVariableWithDerivative) variable.d = value else derivatives[variable] = value } - @Suppress("UNCHECKED_CAST") private fun runBackwardPass() { while (sp > 0) { @@ -129,9 +133,6 @@ public open class SimpleAutoDiffField>( } } - override val zero: AutoDiffValue get() = const(context.zero) - override val one: AutoDiffValue get() = const(context.one) - override fun const(value: T): AutoDiffValue = AutoDiffValue(value) /** @@ -165,7 +166,7 @@ public open class SimpleAutoDiffField>( } - internal fun derivate(function: SimpleAutoDiffField.() -> AutoDiffValue): DerivationResult { + internal fun differentiate(function: SimpleAutoDiffField.() -> AutoDiffValue): DerivationResult { val result = function() result.d = context.one // computing derivative w.r.t result runBackwardPass() @@ -174,41 +175,41 @@ public open class SimpleAutoDiffField>( // Overloads for Double constants - override operator fun Number.plus(b: AutoDiffValue): AutoDiffValue = + public override operator fun Number.plus(b: AutoDiffValue): AutoDiffValue = derive(const { this@plus.toDouble() * one + b.value }) { z -> b.d += z.d } - override operator fun AutoDiffValue.plus(b: Number): AutoDiffValue = b.plus(this) + public override operator fun AutoDiffValue.plus(b: Number): AutoDiffValue = b.plus(this) - override operator fun Number.minus(b: AutoDiffValue): AutoDiffValue = + public override operator fun Number.minus(b: AutoDiffValue): AutoDiffValue = derive(const { this@minus.toDouble() * one - b.value }) { z -> b.d -= z.d } - override operator fun AutoDiffValue.minus(b: Number): AutoDiffValue = + public override operator fun AutoDiffValue.minus(b: Number): AutoDiffValue = derive(const { this@minus.value - one * b.toDouble() }) { z -> this@minus.d += z.d } // Basic math (+, -, *, /) - override fun add(a: AutoDiffValue, b: AutoDiffValue): AutoDiffValue = + public override fun add(a: AutoDiffValue, b: AutoDiffValue): AutoDiffValue = derive(const { a.value + b.value }) { z -> a.d += z.d b.d += z.d } - override fun multiply(a: AutoDiffValue, b: AutoDiffValue): AutoDiffValue = + public override fun multiply(a: AutoDiffValue, b: AutoDiffValue): AutoDiffValue = derive(const { a.value * b.value }) { z -> a.d += z.d * b.value b.d += z.d * a.value } - override fun divide(a: AutoDiffValue, b: AutoDiffValue): AutoDiffValue = + public override fun divide(a: AutoDiffValue, b: AutoDiffValue): AutoDiffValue = derive(const { a.value / b.value }) { z -> a.d += z.d / b.value b.d -= z.d * a.value / (b.value * b.value) } - override fun multiply(a: AutoDiffValue, k: Number): AutoDiffValue = + public override fun multiply(a: AutoDiffValue, k: Number): AutoDiffValue = derive(const { k.toDouble() * a.value }) { z -> a.d += z.d * k.toDouble() } @@ -220,15 +221,15 @@ public open class SimpleAutoDiffField>( public class SimpleAutoDiffExpression>( public val field: F, public val function: SimpleAutoDiffField.() -> AutoDiffValue, -) : FirstDerivativeExpression() { +) : FirstDerivativeExpression>() { public override operator fun invoke(arguments: Map): T { //val bindings = arguments.entries.map { it.key.bind(it.value) } return SimpleAutoDiffField(field, arguments).function().value } - override fun derivativeOrNull(symbol: Symbol): Expression = Expression { arguments -> + public override fun derivativeOrNull(symbol: Symbol): Expression = Expression { arguments -> //val bindings = arguments.entries.map { it.key.bind(it.value) } - val derivationResult = SimpleAutoDiffField(field, arguments).derivate(function) + val derivationResult = SimpleAutoDiffField(field, arguments).differentiate(function) derivationResult.derivative(symbol) } } @@ -236,13 +237,10 @@ public class SimpleAutoDiffExpression>( /** * Generate [AutoDiffProcessor] for [SimpleAutoDiffExpression] */ -public fun > simpleAutoDiff(field: F): AutoDiffProcessor, SimpleAutoDiffField> { - return object : AutoDiffProcessor, SimpleAutoDiffField> { - override fun process(function: SimpleAutoDiffField.() -> AutoDiffValue): DifferentiableExpression { - return SimpleAutoDiffExpression(field, function) - } +public fun > simpleAutoDiff(field: F): AutoDiffProcessor, SimpleAutoDiffField, Expression> = + AutoDiffProcessor { function -> + SimpleAutoDiffExpression(field, function) } -} // Extensions for differentiation of various basic mathematical functions @@ -392,4 +390,4 @@ public class SimpleAutoDiffExtendedField>( public override fun atanh(arg: AutoDiffValue): AutoDiffValue = (this as SimpleAutoDiffField).atanh(arg) -} \ No newline at end of file +} diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index ddfc7cccb..dd5e46f90 100644 --- a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -5,7 +5,6 @@ import kscience.kmath.ast.MST import kscience.kmath.ast.MstAlgebra import kscience.kmath.ast.MstExpression import kscience.kmath.expressions.DifferentiableExpression -import kscience.kmath.expressions.StringSymbol import kscience.kmath.expressions.Symbol import kscience.kmath.operations.NumericAlgebra @@ -20,7 +19,7 @@ import kscience.kmath.operations.NumericAlgebra * @property expr the underlying [MstExpression]. */ public inline class DifferentiableMstExpression(public val expr: MstExpression) : - DifferentiableExpression where A : NumericAlgebra, T : Number { + DifferentiableExpression> where A : NumericAlgebra, T : Number { public constructor(algebra: A, mst: MST) : this(MstExpression(algebra, mst)) /** @@ -47,15 +46,6 @@ public inline class DifferentiableMstExpression(public val expr: MstExpres ) } -public fun > DifferentiableMstExpression.derivative(symbols: List): MstExpression = - derivativeOrNull(symbols) - -public fun > DifferentiableMstExpression.derivative(vararg symbols: Symbol): MstExpression = - derivative(symbols.toList()) - -public fun > DifferentiableMstExpression.derivative(name: String): MstExpression = - derivative(StringSymbol(name)) - /** * Wraps this [MstExpression] into [DifferentiableMstExpression]. */ From 658a1703ed77f82ce19d2f7e7df89782e5307890 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 31 Oct 2020 21:44:52 +0700 Subject: [PATCH 129/199] Add KDoc comment --- .../kscience/kmath/expressions/DifferentiableExpression.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt index 890ad5f71..a15df1ac8 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt @@ -9,6 +9,9 @@ package kscience.kmath.expressions public interface DifferentiableExpression> : Expression { /** * Differentiates this expression by ordered collection of [symbols]. + * + * @param symbols the symbols. + * @return the derivative or `null`. */ public fun derivativeOrNull(symbols: List): R? } From 33d23c8d289784a00707c553f9c33fd7c64186b3 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 2 Nov 2020 01:08:55 +0700 Subject: [PATCH 130/199] Duplicate repositories declared in main build script, fix errors --- README.md | 16 +++++++++++++++ build.gradle.kts | 5 ++++- examples/build.gradle.kts | 14 +++++++++++++ .../kscience/kmath/ast/KotlingradSupport.kt | 2 +- .../optimization/CMOptimizationProblem.kt | 7 +++---- .../kmath/commons/optimization/cmFit.kt | 11 ++++------ .../commons/optimization/OptimizeTest.kt | 13 +++++++----- .../expressions/DifferentiableExpression.kt | 4 ++-- .../kmath/kotlingrad/AdaptingTests.kt | 20 +++++++++---------- .../kotlin/kscience/kmath/stat/Fitting.kt | 10 +++++++--- .../kmath/stat/OptimizationProblem.kt | 13 +++++------- settings.gradle.kts | 3 +-- 12 files changed, 74 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 2df9d3246..c4e3e5374 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,15 @@ Release artifacts are accessible from bintray with following configuration (see ```kotlin repositories { + jcenter() + maven("https://clojars.org/repo") + maven("https://dl.bintray.com/egor-bogomolov/astminer/") + maven("https://dl.bintray.com/hotkeytlt/maven") + maven("https://dl.bintray.com/kotlin/kotlin-eap") + maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/mipt-npm/kscience") + maven("https://jitpack.io") + mavenCentral() } dependencies { @@ -228,7 +236,15 @@ Development builds are uploaded to the separate repository: ```kotlin repositories { + jcenter() + maven("https://clojars.org/repo") + maven("https://dl.bintray.com/egor-bogomolov/astminer/") + maven("https://dl.bintray.com/hotkeytlt/maven") + maven("https://dl.bintray.com/kotlin/kotlin-eap") + maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/mipt-npm/dev") + maven("https://jitpack.io") + mavenCentral() } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 095697bc4..3514c91e6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import ru.mipt.npm.gradle.KSciencePublishPlugin + plugins { id("ru.mipt.npm.project") } @@ -17,6 +19,7 @@ allprojects { maven("https://dl.bintray.com/mipt-npm/dev") maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://jitpack.io") + maven("http://logicrunch.research.it.uu.se/maven/") mavenCentral() } @@ -25,7 +28,7 @@ allprojects { } subprojects { - if (name.startsWith("kmath")) apply() + if (name.startsWith("kmath")) apply() } readme { diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 99828c621..d42627ff0 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -10,6 +10,20 @@ plugins { allOpen.annotation("org.openjdk.jmh.annotations.State") sourceSets.register("benchmarks") +repositories { + jcenter() + maven("https://clojars.org/repo") + maven("https://dl.bintray.com/egor-bogomolov/astminer/") + maven("https://dl.bintray.com/hotkeytlt/maven") + maven("https://dl.bintray.com/kotlin/kotlin-eap") + maven("https://dl.bintray.com/kotlin/kotlinx") + maven("https://dl.bintray.com/mipt-npm/dev") + maven("https://dl.bintray.com/mipt-npm/kscience") + maven("https://jitpack.io") + maven("http://logicrunch.research.it.uu.se/maven/") + mavenCentral() +} + dependencies { implementation(project(":kmath-ast")) implementation(project(":kmath-kotlingrad")) diff --git a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt index 5acd97e3d..b3c827503 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt @@ -1,9 +1,9 @@ package kscience.kmath.ast import kscience.kmath.asm.compile +import kscience.kmath.expressions.derivative import kscience.kmath.expressions.invoke import kscience.kmath.expressions.symbol -import kscience.kmath.kotlingrad.derivative import kscience.kmath.kotlingrad.differentiable import kscience.kmath.operations.RealField diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt index 13f9af7bb..d6f79529a 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt @@ -19,9 +19,8 @@ import kotlin.reflect.KClass public operator fun PointValuePair.component1(): DoubleArray = point public operator fun PointValuePair.component2(): Double = value -public class CMOptimizationProblem( - override val symbols: List, -) : OptimizationProblem, SymbolIndexer, OptimizationFeature { +public class CMOptimizationProblem(override val symbols: List, ) : + OptimizationProblem, SymbolIndexer, OptimizationFeature { private val optimizationData: HashMap, OptimizationData> = HashMap() private var optimizatorBuilder: (() -> MultivariateOptimizer)? = null public var convergenceChecker: ConvergenceChecker = SimpleValueChecker(DEFAULT_RELATIVE_TOLERANCE, @@ -49,7 +48,7 @@ public class CMOptimizationProblem( addOptimizationData(objectiveFunction) } - public override fun diffExpression(expression: DifferentiableExpression): Unit { + public override fun diffExpression(expression: DifferentiableExpression>) { expression(expression) val gradientFunction = ObjectiveFunctionGradient { val args = it.toMap() diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt index 42475db6c..b8e8bfd4b 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt @@ -12,7 +12,6 @@ import kscience.kmath.structures.asBuffer import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import org.apache.commons.math3.optim.nonlinear.scalar.GoalType - /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation */ @@ -21,7 +20,7 @@ public fun Fitting.chiSquared( y: Buffer, yErr: Buffer, model: DerivativeStructureField.(x: DerivativeStructure) -> DerivativeStructure, -): DifferentiableExpression = chiSquared(DerivativeStructureField, x, y, yErr, model) +): DifferentiableExpression> = chiSquared(DerivativeStructureField, x, y, yErr, model) /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation @@ -31,7 +30,7 @@ public fun Fitting.chiSquared( y: Iterable, yErr: Iterable, model: DerivativeStructureField.(x: DerivativeStructure) -> DerivativeStructure, -): DifferentiableExpression = chiSquared( +): DifferentiableExpression> = chiSquared( DerivativeStructureField, x.toList().asBuffer(), y.toList().asBuffer(), @@ -39,7 +38,6 @@ public fun Fitting.chiSquared( model ) - /** * Optimize expression without derivatives */ @@ -48,16 +46,15 @@ public fun Expression.optimize( configuration: CMOptimizationProblem.() -> Unit, ): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) - /** * Optimize differentiable expression */ -public fun DifferentiableExpression.optimize( +public fun DifferentiableExpression>.optimize( vararg symbols: Symbol, configuration: CMOptimizationProblem.() -> Unit, ): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) -public fun DifferentiableExpression.minimize( +public fun DifferentiableExpression>.minimize( vararg startPoint: Pair, configuration: CMOptimizationProblem.() -> Unit = {}, ): OptimizationResult { diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index fa1978f95..3290c8f32 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -47,14 +47,17 @@ internal class OptimizeTest { val sigma = 1.0 val generator = Distribution.normal(0.0, sigma) val chain = generator.sample(RandomGenerator.default(112667)) - val x = (1..100).map { it.toDouble() } - val y = x.map { it -> + val x = (1..100).map(Int::toDouble) + + val y = x.map { it.pow(2) + it + 1 + chain.nextDouble() } - val yErr = x.map { sigma } - val chi2 = Fitting.chiSquared(x, y, yErr) { x -> + + val yErr = List(x.size) { sigma } + + val chi2 = Fitting.chiSquared(x, y, yErr) { x1 -> val cWithDefault = bindOrNull(c) ?: one - bind(a) * x.pow(2) + bind(b) * x + cWithDefault + bind(a) * x1.pow(2) + bind(b) * x1 + cWithDefault } val result = chi2.minimize(a to 1.5, b to 0.9, c to 1.0) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt index a15df1ac8..abce9c4ec 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt @@ -6,7 +6,7 @@ package kscience.kmath.expressions * @param T the type this expression takes as argument and returns. * @param R the type of expression this expression can be differentiated to. */ -public interface DifferentiableExpression> : Expression { +public interface DifferentiableExpression> : Expression { /** * Differentiates this expression by ordered collection of [symbols]. * @@ -43,6 +43,6 @@ public abstract class FirstDerivativeExpression> : Differen /** * A factory that converts an expression in autodiff variables to a [DifferentiableExpression] */ -public fun interface AutoDiffProcessor, R : Expression> { +public fun interface AutoDiffProcessor, out R : Expression> { public fun process(function: A.() -> I): DifferentiableExpression } diff --git a/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt index 682b0cf2e..77902211b 100644 --- a/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -13,13 +13,11 @@ import kotlin.test.assertTrue import kotlin.test.fail internal class AdaptingTests { - private val proto: DReal = DoublePrecision.prototype - @Test fun symbol() { val c1 = MstAlgebra.symbol("x") - assertTrue(c1.toSVar(proto).name == "x") - val c2 = "kitten".parseMath().toSFun(proto) + assertTrue(c1.toSVar>().name == "x") + val c2 = "kitten".parseMath().toSFun>() if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() } @@ -27,15 +25,15 @@ internal class AdaptingTests { fun number() { val c1 = MstAlgebra.number(12354324) assertTrue(c1.toSConst().doubleValue == 12354324.0) - val c2 = "0.234".parseMath().toSFun(proto) + val c2 = "0.234".parseMath().toSFun>() if (c2 is SConst) assertTrue(c2.doubleValue == 0.234) else fail() - val c3 = "1e-3".parseMath().toSFun(proto) + val c3 = "1e-3".parseMath().toSFun>() if (c3 is SConst) assertEquals(0.001, c3.value) else fail() } @Test fun simpleFunctionShape() { - val linear = "2*x+16".parseMath().toSFun(proto) + val linear = "2*x+16".parseMath().toSFun>() if (linear !is Sum) fail() if (linear.left !is Prod) fail() if (linear.right !is SConst) fail() @@ -43,8 +41,8 @@ internal class AdaptingTests { @Test fun simpleFunctionDerivative() { - val x = MstAlgebra.symbol("x").toSVar(proto) - val quadratic = "x^2-4*x-44".parseMath().toSFun(proto) + val x = MstAlgebra.symbol("x").toSVar>() + val quadratic = "x^2-4*x-44".parseMath().toSFun>() val actualDerivative = MstExpression(RealField, quadratic.d(x).toMst()).compile() val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0)) @@ -52,8 +50,8 @@ internal class AdaptingTests { @Test fun moreComplexDerivative() { - val x = MstAlgebra.symbol("x").toSVar(proto) - val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun(proto) + val x = MstAlgebra.symbol("x").toSVar>() + val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun>() val actualDerivative = MstExpression(RealField, composition.d(x).toMst()).compile() val expectedDerivative = MstExpression( diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt index 01fdf4c5e..9d4655df2 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt @@ -12,16 +12,18 @@ public object Fitting { * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation */ public fun chiSquared( - autoDiff: AutoDiffProcessor, + autoDiff: AutoDiffProcessor>, x: Buffer, y: Buffer, yErr: Buffer, model: A.(I) -> I, - ): DifferentiableExpression where A : ExtendedField, A : ExpressionAlgebra { + ): DifferentiableExpression> where A : ExtendedField, A : ExpressionAlgebra { require(x.size == y.size) { "X and y buffers should be of the same size" } require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + return autoDiff.process { var sum = zero + x.indices.forEach { val xValue = const(x[it]) val yValue = const(y[it]) @@ -29,6 +31,7 @@ public object Fitting { val modelValue = model(xValue) sum += ((yValue - modelValue) / yErrValue).pow(2) } + sum } } @@ -45,6 +48,7 @@ public object Fitting { ): Expression { require(x.size == y.size) { "X and y buffers should be of the same size" } require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + return Expression { arguments -> x.indices.sumByDouble { val xValue = x[it] @@ -56,4 +60,4 @@ public object Fitting { } } } -} \ No newline at end of file +} diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt index ea522bff9..0f3cd9dd9 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt @@ -27,17 +27,17 @@ public interface OptimizationProblem { /** * Define the initial guess for the optimization problem */ - public fun initialGuess(map: Map): Unit + public fun initialGuess(map: Map) /** * Set an objective function expression */ - public fun expression(expression: Expression): Unit + public fun expression(expression: Expression) /** * Set a differentiable expression as objective function as function and gradient provider */ - public fun diffExpression(expression: DifferentiableExpression): Unit + public fun diffExpression(expression: DifferentiableExpression>) /** * Update the problem from previous optimization run @@ -50,9 +50,8 @@ public interface OptimizationProblem { public fun optimize(): OptimizationResult } -public interface OptimizationProblemFactory> { +public fun interface OptimizationProblemFactory> { public fun build(symbols: List): P - } public operator fun > OptimizationProblemFactory.invoke( @@ -60,7 +59,6 @@ public operator fun > OptimizationProblemFac block: P.() -> Unit, ): P = build(symbols).apply(block) - /** * Optimize expression without derivatives using specific [OptimizationProblemFactory] */ @@ -78,7 +76,7 @@ public fun > Expression.optimizeWith( /** * Optimize differentiable expression using specific [OptimizationProblemFactory] */ -public fun > DifferentiableExpression.optimizeWith( +public fun > DifferentiableExpression>.optimizeWith( factory: OptimizationProblemFactory, vararg symbols: Symbol, configuration: F.() -> Unit, @@ -88,4 +86,3 @@ public fun > DifferentiableExpression.op problem.diffExpression(this) return problem.optimize() } - diff --git a/settings.gradle.kts b/settings.gradle.kts index e825ddbdf..97dfe1b96 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,8 +1,7 @@ pluginManagement { repositories { - mavenLocal() - jcenter() gradlePluginPortal() + jcenter() maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://dl.bintray.com/mipt-npm/dev") From 434229a43aa3751430e37c42978fa79ad71d7b3a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 22 Nov 2020 19:06:38 +0300 Subject: [PATCH 131/199] Implementation for #65 --- CHANGELOG.md | 1 + .../kotlin/kscience/kmath/stat/MCScope.kt | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/MCScope.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 435d958d9..80b0c3cec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Chi squared optimization for array-like data in CM - `Fitting` utility object in prob/stat - ND4J support module submitting `NDStructure` and `NDAlgebra` over `INDArray`. +- Coroutine-deterministic Monte-Carlo scope with a random number generator. ### Changed - Package changed from `scientifik` to `kscience.kmath`. diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/MCScope.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/MCScope.kt new file mode 100644 index 000000000..5dc567db8 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/MCScope.kt @@ -0,0 +1,58 @@ +package kscience.kmath.stat + +import kotlinx.coroutines.* +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext +import kotlin.coroutines.coroutineContext + +/** + * A scope for a Monte-Carlo computations or multi-coroutine random number generation. + * The scope preserves the order of random generator calls as long as all concurrency calls is done via [launch] and [async] + * functions. + */ +public class MCScope( + public val coroutineContext: CoroutineContext, + public val random: RandomGenerator, +) + +/** + * Launches a supervised Monte-Carlo scope + */ +public suspend inline fun mcScope(generator: RandomGenerator, block: MCScope.() -> T): T = + MCScope(coroutineContext, generator).block() + +/** + * Launch mc scope with a given seed + */ +public suspend inline fun mcScope(seed: Long, block: MCScope.() -> T): T = + mcScope(RandomGenerator.default(seed), block) + +/** + * Specialized launch for [MCScope]. Behaves the same way as regular [CoroutineScope.launch], but also stores the generator fork. + * The method itself is not thread safe. + */ +public inline fun MCScope.launch( + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + crossinline block: suspend MCScope.() -> Unit, +): Job { + val newRandom = random.fork() + return CoroutineScope(coroutineContext).launch(context, start) { + MCScope(coroutineContext, newRandom).block() + } +} + +/** + * Specialized async for [MCScope]. Behaves the same way as regular [CoroutineScope.async], but also stores the generator fork. + * The method itself is not thread safe. + */ +public inline fun MCScope.async( + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + crossinline block: suspend MCScope.() -> T, +): Deferred { + val newRandom = random.fork() + return CoroutineScope(coroutineContext).async(context, start) { + MCScope(coroutineContext, newRandom).block() + } +} \ No newline at end of file From af306084cfbcf793b032fd852b9b895a42936975 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 22 Nov 2020 19:16:08 +0300 Subject: [PATCH 132/199] Test for #65 --- .../kotlin/kscience/kmath/stat/MCScopeTest.kt | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/MCScopeTest.kt diff --git a/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/MCScopeTest.kt b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/MCScopeTest.kt new file mode 100644 index 000000000..c2304070f --- /dev/null +++ b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/MCScopeTest.kt @@ -0,0 +1,85 @@ +package kscience.kmath.stat + +import kotlinx.coroutines.* +import java.util.* +import kotlin.collections.HashSet +import kotlin.test.Test +import kotlin.test.assertEquals + +data class RandomResult(val branch: String, val order: Int, val value: Int) + +typealias ATest = suspend CoroutineScope.() -> Set + +class MCScopeTest { + val simpleTest: ATest = { + mcScope(1111) { + val res = Collections.synchronizedSet(HashSet()) + + launch { + //println(random) + repeat(10) { + delay(10) + res.add(RandomResult("first", it, random.nextInt())) + } + launch { + //empty fork + } + } + + launch { + //println(random) + repeat(10) { + delay(10) + res.add(RandomResult("second", it, random.nextInt())) + } + } + + + res + } + } + + val testWithJoin: ATest = { + mcScope(1111) { + val res = Collections.synchronizedSet(HashSet()) + + val job = launch { + repeat(10) { + delay(10) + res.add(RandomResult("first", it, random.nextInt())) + } + } + launch { + repeat(10) { + delay(10) + if (it == 4) job.join() + res.add(RandomResult("second", it, random.nextInt())) + } + } + + res + } + } + + + fun compareResult(test: ATest) { + val res1 = runBlocking(Dispatchers.Default) { test() } + val res2 = runBlocking(newSingleThreadContext("test")) { test() } + assertEquals( + res1.find { it.branch == "first" && it.order == 7 }?.value, + res2.find { it.branch == "first" && it.order == 7 }?.value + ) + assertEquals(res1, res2) + } + + @Test + fun testParallel() { + compareResult(simpleTest) + } + + + @Test + fun testConditionalJoin() { + compareResult(testWithJoin) + } +} \ No newline at end of file From 3e7c9d8dce15fd5c17747aba953147e05c13c4f4 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 28 Nov 2020 13:33:05 +0700 Subject: [PATCH 133/199] Rework unary/binary operation API --- .../kotlin/kscience/kmath/ast/MST.kt | 19 ++- .../kotlin/kscience/kmath/ast/MstAlgebra.kt | 126 +++++++++--------- .../kscience/kmath/ast/MstExpression.kt | 6 +- .../kmath/asm/TestAsmSpecialization.kt | 15 +-- .../kotlin/kscience/kmath/ast/ParserTest.kt | 16 +-- .../FunctionalExpressionAlgebra.kt | 76 +++++------ .../kscience/kmath/linear/MatrixContext.kt | 9 +- .../kscience/kmath/operations/Algebra.kt | 72 +++++----- .../kmath/operations/NumberAlgebra.kt | 58 ++++---- 9 files changed, 194 insertions(+), 203 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt index f312323b9..cc3d38f9c 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt @@ -55,24 +55,23 @@ public sealed class MST { public fun Algebra.evaluate(node: MST): T = when (node) { is MST.Numeric -> (this as? NumericAlgebra)?.number(node.value) ?: error("Numeric nodes are not supported by $this") + is MST.Symbolic -> symbol(node.value) - is MST.Unary -> unaryOperation(node.operation, evaluate(node.value)) + is MST.Unary -> unaryOperation(node.operation)(evaluate(node.value)) + is MST.Binary -> when { - this !is NumericAlgebra -> binaryOperation(node.operation, evaluate(node.left), evaluate(node.right)) + this !is NumericAlgebra -> binaryOperation(node.operation)(evaluate(node.left), evaluate(node.right)) node.left is MST.Numeric && node.right is MST.Numeric -> { - val number = RealField.binaryOperation( - node.operation, - node.left.value.toDouble(), - node.right.value.toDouble() - ) + val number = RealField + .binaryOperation(node.operation)(node.left.value.toDouble(), node.right.value.toDouble()) number(number) } - node.left is MST.Numeric -> leftSideNumberOperation(node.operation, node.left.value, evaluate(node.right)) - node.right is MST.Numeric -> rightSideNumberOperation(node.operation, evaluate(node.left), node.right.value) - else -> binaryOperation(node.operation, evaluate(node.left), evaluate(node.right)) + node.left is MST.Numeric -> leftSideNumberOperation(node.operation)(node.left.value, evaluate(node.right)) + node.right is MST.Numeric -> rightSideNumberOperation(node.operation)(evaluate(node.left), node.right.value) + else -> binaryOperation(node.operation)(evaluate(node.left), evaluate(node.right)) } } diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt index 6ee6ab9af..cea708342 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt @@ -6,115 +6,111 @@ import kscience.kmath.operations.* * [Algebra] over [MST] nodes. */ public object MstAlgebra : NumericAlgebra { - override fun number(value: Number): MST.Numeric = MST.Numeric(value) + public override fun number(value: Number): MST.Numeric = MST.Numeric(value) - override fun symbol(value: String): MST.Symbolic = MST.Symbolic(value) + public override fun symbol(value: String): MST.Symbolic = MST.Symbolic(value) - override fun unaryOperation(operation: String, arg: MST): MST.Unary = - MST.Unary(operation, arg) + public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = { arg -> MST.Unary(operation, arg) } - override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary = - MST.Binary(operation, left, right) + public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = + { left, right -> MST.Binary(operation, left, right) } } /** * [Space] over [MST] nodes. */ public object MstSpace : Space, NumericAlgebra { - override val zero: MST.Numeric by lazy { number(0.0) } + public override val zero: MST.Numeric by lazy { number(0.0) } - override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) - override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value) - override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) - override fun multiply(a: MST, k: Number): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION, a, number(k)) + public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) + public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value) + override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b) + override fun multiply(a: MST, k: Number): MST = binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k)) - override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary = - MstAlgebra.binaryOperation(operation, left, right) + override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST = + MstAlgebra.binaryOperation(operation) - override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstAlgebra.unaryOperation(operation, arg) + override fun unaryOperation(operation: String): (arg: MST) -> MST = MstAlgebra.unaryOperation(operation) } /** * [Ring] over [MST] nodes. */ public object MstRing : Ring, NumericAlgebra { - override val zero: MST.Numeric + override val zero: MST get() = MstSpace.zero + override val one: MST = number(1.0) - override val one: MST.Numeric by lazy { number(1.0) } + public override fun number(value: Number): MST = MstSpace.number(value) + public override fun symbol(value: String): MST = MstSpace.symbol(value) + public override fun add(a: MST, b: MST): MST = MstSpace.add(a, b) + public override fun multiply(a: MST, k: Number): MST = MstSpace.multiply(a, k) + public override fun multiply(a: MST, b: MST): MST = binaryOperation(RingOperations.TIMES_OPERATION)(a, b) - override fun number(value: Number): MST.Numeric = MstSpace.number(value) - override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value) - override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b) - override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k) - override fun multiply(a: MST, b: MST): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION, a, b) + public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST = + MstSpace.binaryOperation(operation) - override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary = - MstSpace.binaryOperation(operation, left, right) - - override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstSpace.unaryOperation(operation, arg) + public override fun unaryOperation(operation: String): (arg: MST) -> MST = MstAlgebra.unaryOperation(operation) } /** * [Field] over [MST] nodes. */ public object MstField : Field { - public override val zero: MST.Numeric + public override val zero: MST get() = MstRing.zero - public override val one: MST.Numeric + public override val one: MST get() = MstRing.one - public override fun symbol(value: String): MST.Symbolic = MstRing.symbol(value) - public override fun number(value: Number): MST.Numeric = MstRing.number(value) - public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) - public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k) - public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) - public override fun divide(a: MST, b: MST): MST.Binary = binaryOperation(FieldOperations.DIV_OPERATION, a, b) + public override fun symbol(value: String): MST = MstRing.symbol(value) + public override fun number(value: Number): MST = MstRing.number(value) + public override fun add(a: MST, b: MST): MST = MstRing.add(a, b) + public override fun multiply(a: MST, k: Number): MST = MstRing.multiply(a, k) + public override fun multiply(a: MST, b: MST): MST = MstRing.multiply(a, b) + public override fun divide(a: MST, b: MST): MST = binaryOperation(FieldOperations.DIV_OPERATION)(a, b) - public override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary = - MstRing.binaryOperation(operation, left, right) + public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST = + MstRing.binaryOperation(operation) - override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstRing.unaryOperation(operation, arg) + public override fun unaryOperation(operation: String): (arg: MST) -> MST = MstRing.unaryOperation(operation) } /** * [ExtendedField] over [MST] nodes. */ public object MstExtendedField : ExtendedField { - override val zero: MST.Numeric + public override val zero: MST get() = MstField.zero - override val one: MST.Numeric + public override val one: MST get() = MstField.one - override fun symbol(value: String): MST.Symbolic = MstField.symbol(value) - override fun number(value: Number): MST.Numeric = MstField.number(value) - override fun sin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) - override fun cos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.COS_OPERATION, arg) - override fun tan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.TAN_OPERATION, arg) - override fun asin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg) - override fun acos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg) - override fun atan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg) - override fun sinh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.SINH_OPERATION, arg) - override fun cosh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.COSH_OPERATION, arg) - override fun tanh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.TANH_OPERATION, arg) - override fun asinh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ASINH_OPERATION, arg) - override fun acosh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ACOSH_OPERATION, arg) - override fun atanh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ATANH_OPERATION, arg) - override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) - override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k) - override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) - override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b) + public override fun symbol(value: String): MST = MstField.symbol(value) + public override fun sin(arg: MST): MST = unaryOperation(TrigonometricOperations.SIN_OPERATION)(arg) + public override fun cos(arg: MST): MST = unaryOperation(TrigonometricOperations.COS_OPERATION)(arg) + public override fun tan(arg: MST): MST = unaryOperation(TrigonometricOperations.TAN_OPERATION)(arg) + public override fun asin(arg: MST): MST = unaryOperation(TrigonometricOperations.ASIN_OPERATION)(arg) + public override fun acos(arg: MST): MST = unaryOperation(TrigonometricOperations.ACOS_OPERATION)(arg) + public override fun atan(arg: MST): MST = unaryOperation(TrigonometricOperations.ATAN_OPERATION)(arg) + public override fun sinh(arg: MST): MST = unaryOperation(HyperbolicOperations.SINH_OPERATION)(arg) + public override fun cosh(arg: MST): MST = unaryOperation(HyperbolicOperations.COSH_OPERATION)(arg) + public override fun tanh(arg: MST): MST = unaryOperation(HyperbolicOperations.TANH_OPERATION)(arg) + public override fun asinh(arg: MST): MST = unaryOperation(HyperbolicOperations.ASINH_OPERATION)(arg) + public override fun acosh(arg: MST): MST = unaryOperation(HyperbolicOperations.ACOSH_OPERATION)(arg) + public override fun atanh(arg: MST): MST = unaryOperation(HyperbolicOperations.ATANH_OPERATION)(arg) + public override fun add(a: MST, b: MST): MST = MstField.add(a, b) + public override fun multiply(a: MST, k: Number): MST = MstField.multiply(a, k) + public override fun multiply(a: MST, b: MST): MST = MstField.multiply(a, b) + public override fun divide(a: MST, b: MST): MST = MstField.divide(a, b) + public override fun power(arg: MST, pow: Number): MST = binaryOperation(PowerOperations.POW_OPERATION)(arg, number(pow)) + public override fun exp(arg: MST): MST = unaryOperation(ExponentialOperations.EXP_OPERATION)(arg) + public override fun ln(arg: MST): MST = unaryOperation(ExponentialOperations.LN_OPERATION)(arg) - override fun power(arg: MST, pow: Number): MST.Binary = - binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow)) + public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST = + MstField.binaryOperation(operation) - override fun exp(arg: MST): MST.Unary = unaryOperation(ExponentialOperations.EXP_OPERATION, arg) - override fun ln(arg: MST): MST.Unary = unaryOperation(ExponentialOperations.LN_OPERATION, arg) - - override fun binaryOperation(operation: String, left: MST, right: MST): MST.Binary = - MstField.binaryOperation(operation, left, right) - - override fun unaryOperation(operation: String, arg: MST): MST.Unary = MstField.unaryOperation(operation, arg) + public override fun unaryOperation(operation: String): (arg: MST) -> MST = MstField.unaryOperation(operation) + override fun unaryOperation(operation: String, arg: MST): MST.Unary = + MST.Unary(operation, arg) } diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt index f68e3f5f8..8a99fd2f4 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt @@ -16,10 +16,8 @@ import kotlin.contracts.contract public class MstExpression>(public val algebra: A, public val mst: MST) : Expression { private inner class InnerAlgebra(val arguments: Map) : NumericAlgebra { override fun symbol(value: String): T = arguments[StringSymbol(value)] ?: algebra.symbol(value) - override fun unaryOperation(operation: String, arg: T): T = algebra.unaryOperation(operation, arg) - - override fun binaryOperation(operation: String, left: T, right: T): T = - algebra.binaryOperation(operation, left, right) + override fun unaryOperation(operation: String): (arg: T) -> T = algebra.unaryOperation(operation) + override fun binaryOperation(operation: String): (left: T, right: T) -> T = algebra.binaryOperation(operation) @Suppress("UNCHECKED_CAST") override fun number(value: Number): T = if (algebra is NumericAlgebra<*>) diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt index 8f8175acd..eb5a1c8f3 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt @@ -1,6 +1,5 @@ package kscience.kmath.asm -import kscience.kmath.asm.compile import kscience.kmath.ast.mstInField import kscience.kmath.expressions.invoke import kscience.kmath.operations.RealField @@ -10,44 +9,44 @@ import kotlin.test.assertEquals internal class TestAsmSpecialization { @Test fun testUnaryPlus() { - val expr = RealField.mstInField { unaryOperation("+", symbol("x")) }.compile() + val expr = RealField.mstInField { unaryOperation("+")(symbol("x")) }.compile() assertEquals(2.0, expr("x" to 2.0)) } @Test fun testUnaryMinus() { - val expr = RealField.mstInField { unaryOperation("-", symbol("x")) }.compile() + val expr = RealField.mstInField { unaryOperation("-")(symbol("x")) }.compile() assertEquals(-2.0, expr("x" to 2.0)) } @Test fun testAdd() { - val expr = RealField.mstInField { binaryOperation("+", symbol("x"), symbol("x")) }.compile() + val expr = RealField.mstInField { binaryOperation("+")(symbol("x"), symbol("x")) }.compile() assertEquals(4.0, expr("x" to 2.0)) } @Test fun testSine() { - val expr = RealField.mstInField { unaryOperation("sin", symbol("x")) }.compile() + val expr = RealField.mstInField { unaryOperation("sin")(symbol("x")) }.compile() assertEquals(0.0, expr("x" to 0.0)) } @Test fun testMinus() { - val expr = RealField.mstInField { binaryOperation("-", symbol("x"), symbol("x")) }.compile() + val expr = RealField.mstInField { binaryOperation("-")(symbol("x"), symbol("x")) }.compile() assertEquals(0.0, expr("x" to 2.0)) } @Test fun testDivide() { - val expr = RealField.mstInField { binaryOperation("/", symbol("x"), symbol("x")) }.compile() + val expr = RealField.mstInField { binaryOperation("/")(symbol("x"), symbol("x")) }.compile() assertEquals(1.0, expr("x" to 2.0)) } @Test fun testPower() { val expr = RealField - .mstInField { binaryOperation("power", symbol("x"), number(2)) } + .mstInField { binaryOperation("power")(symbol("x"), number(2)) } .compile() assertEquals(4.0, expr("x" to 2.0)) diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt index 2dc24597e..e2029ce19 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt @@ -1,8 +1,5 @@ package kscience.kmath.ast -import kscience.kmath.ast.evaluate -import kscience.kmath.ast.mstInField -import kscience.kmath.ast.parseMath import kscience.kmath.expressions.invoke import kscience.kmath.operations.Algebra import kscience.kmath.operations.Complex @@ -45,12 +42,15 @@ internal class ParserTest { val magicalAlgebra = object : Algebra { override fun symbol(value: String): String = value - override fun unaryOperation(operation: String, arg: String): String = throw NotImplementedError() - - override fun binaryOperation(operation: String, left: String, right: String): String = when (operation) { - "magic" -> "$left ★ $right" - else -> throw NotImplementedError() + override fun unaryOperation(operation: String): (arg: String) -> String { + throw NotImplementedError() } + + override fun binaryOperation(operation: String): (left: String, right: String) -> String = + when (operation) { + "magic" -> { left, right -> "$left ★ $right" } + else -> throw NotImplementedError() + } } val mst = "magic(a, b)".parseMath() 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 0630e8e4b..e2413dea8 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -7,9 +7,8 @@ import kscience.kmath.operations.* * * @param algebra The algebra to provide for Expressions built. */ -public abstract class FunctionalExpressionAlgebra>( - public val algebra: A, -) : ExpressionAlgebra> { +public abstract class FunctionalExpressionAlgebra>(public val algebra: A) : + ExpressionAlgebra> { /** * Builds an Expression of constant expression which does not depend on arguments. */ @@ -25,19 +24,18 @@ public abstract class FunctionalExpressionAlgebra>( /** * Builds an Expression of dynamic call of binary operation [operation] on [left] and [right]. */ - public override fun binaryOperation( - operation: String, - left: Expression, - right: Expression, - ): Expression = Expression { arguments -> - algebra.binaryOperation(operation, left.invoke(arguments), right.invoke(arguments)) - } + public override fun binaryOperation(operation: String): (left: Expression, right: Expression) -> Expression = + { left, right -> + Expression { arguments -> + algebra.binaryOperation(operation)(left.invoke(arguments), right.invoke(arguments)) + } + } /** * Builds an Expression of dynamic call of unary operation with name [operation] on [arg]. */ - public override fun unaryOperation(operation: String, arg: Expression): Expression = Expression { arguments -> - algebra.unaryOperation(operation, arg.invoke(arguments)) + public override fun unaryOperation(operation: String): (arg: Expression) -> Expression = { arg -> + Expression { arguments -> algebra.unaryOperation(operation)(arg.invoke(arguments)) } } } @@ -52,7 +50,7 @@ public open class FunctionalExpressionSpace>(algebra: A) : * Builds an Expression of addition of two another expressions. */ public override fun add(a: Expression, b: Expression): Expression = - binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) + binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b) /** * Builds an Expression of multiplication of expression by number. @@ -66,11 +64,11 @@ public open class FunctionalExpressionSpace>(algebra: A) : public operator fun T.plus(arg: Expression): Expression = arg + this public operator fun T.minus(arg: Expression): Expression = arg - this - public override fun unaryOperation(operation: String, arg: Expression): Expression = - super.unaryOperation(operation, arg) + public override fun unaryOperation(operation: String): (arg: Expression) -> Expression = + super.unaryOperation(operation) - public override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = - super.binaryOperation(operation, left, right) + public override fun binaryOperation(operation: String): (left: Expression, right: Expression) -> Expression = + super.binaryOperation(operation) } public open class FunctionalExpressionRing(algebra: A) : FunctionalExpressionSpace(algebra), @@ -82,16 +80,16 @@ public open class FunctionalExpressionRing(algebra: A) : FunctionalExpress * Builds an Expression of multiplication of two expressions. */ public override fun multiply(a: Expression, b: Expression): Expression = - binaryOperation(RingOperations.TIMES_OPERATION, a, b) + binaryOperation(RingOperations.TIMES_OPERATION)(a, b) public operator fun Expression.times(arg: T): Expression = this * const(arg) public operator fun T.times(arg: Expression): Expression = arg * this - public override fun unaryOperation(operation: String, arg: Expression): Expression = - super.unaryOperation(operation, arg) + public override fun unaryOperation(operation: String): (arg: Expression) -> Expression = + super.unaryOperation(operation) - public override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = - super.binaryOperation(operation, left, right) + public override fun binaryOperation(operation: String): (left: Expression, right: Expression) -> Expression = + super.binaryOperation(operation) } public open class FunctionalExpressionField(algebra: A) : @@ -101,49 +99,49 @@ public open class FunctionalExpressionField(algebra: A) : * Builds an Expression of division an expression by another one. */ public override fun divide(a: Expression, b: Expression): Expression = - binaryOperation(FieldOperations.DIV_OPERATION, a, b) + binaryOperation(FieldOperations.DIV_OPERATION)(a, b) public operator fun Expression.div(arg: T): Expression = this / const(arg) public operator fun T.div(arg: Expression): Expression = arg / this - public override fun unaryOperation(operation: String, arg: Expression): Expression = - super.unaryOperation(operation, arg) + public override fun unaryOperation(operation: String): (arg: Expression) -> Expression = + super.unaryOperation(operation) - public override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = - super.binaryOperation(operation, left, right) + public override fun binaryOperation(operation: String): (left: Expression, right: Expression) -> Expression = + super.binaryOperation(operation) } public open class FunctionalExpressionExtendedField(algebra: A) : FunctionalExpressionField(algebra), ExtendedField> where A : ExtendedField, A : NumericAlgebra { public override fun sin(arg: Expression): Expression = - unaryOperation(TrigonometricOperations.SIN_OPERATION, arg) + unaryOperation(TrigonometricOperations.SIN_OPERATION)(arg) public override fun cos(arg: Expression): Expression = - unaryOperation(TrigonometricOperations.COS_OPERATION, arg) + unaryOperation(TrigonometricOperations.COS_OPERATION)(arg) public override fun asin(arg: Expression): Expression = - unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg) + unaryOperation(TrigonometricOperations.ASIN_OPERATION)(arg) public override fun acos(arg: Expression): Expression = - unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg) + unaryOperation(TrigonometricOperations.ACOS_OPERATION)(arg) public override fun atan(arg: Expression): Expression = - unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg) + unaryOperation(TrigonometricOperations.ATAN_OPERATION)(arg) public override fun power(arg: Expression, pow: Number): Expression = - binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow)) + binaryOperation(PowerOperations.POW_OPERATION)(arg, number(pow)) public override fun exp(arg: Expression): Expression = - unaryOperation(ExponentialOperations.EXP_OPERATION, arg) + unaryOperation(ExponentialOperations.EXP_OPERATION)(arg) - public override fun ln(arg: Expression): Expression = unaryOperation(ExponentialOperations.LN_OPERATION, arg) + public override fun ln(arg: Expression): Expression = unaryOperation(ExponentialOperations.LN_OPERATION)(arg) - public override fun unaryOperation(operation: String, arg: Expression): Expression = - super.unaryOperation(operation, arg) + public override fun unaryOperation(operation: String): (arg: Expression) -> Expression = + super.unaryOperation(operation) - public override fun binaryOperation(operation: String, left: Expression, right: Expression): Expression = - super.binaryOperation(operation, left, right) + public override fun binaryOperation(operation: String): (left: Expression, right: Expression) -> Expression = + super.binaryOperation(operation) } public inline fun > A.expressionInSpace(block: FunctionalExpressionSpace.() -> Expression): Expression = diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt index f4dbce89a..174f62c12 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt @@ -18,10 +18,11 @@ public interface MatrixContext : SpaceOperations> { */ public fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): Matrix - public override fun binaryOperation(operation: String, left: Matrix, right: Matrix): Matrix = when (operation) { - "dot" -> left dot right - else -> super.binaryOperation(operation, left, right) - } + public override fun binaryOperation(operation: String): (left: Matrix, right: Matrix) -> Matrix = + when (operation) { + "dot" -> { left, right -> left dot right } + else -> super.binaryOperation(operation) + } /** * Computes the dot product of this matrix and another one. diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index 12a45615a..19ca1a4cc 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -13,19 +13,19 @@ public annotation class KMathContext */ public interface Algebra { /** - * Wrap raw string or variable + * Wraps raw string or variable. */ public fun symbol(value: String): T = error("Wrapping of '$value' is not supported in $this") /** - * Dynamic call of unary operation with name [operation] on [arg] + * Dynamically dispatches an unary operation with name [operation]. */ - public fun unaryOperation(operation: String, arg: T): T + public fun unaryOperation(operation: String): (arg: T) -> T /** - * Dynamic call of binary operation [operation] on [left] and [right] + * Dynamically dispatches a binary operation with name [operation]. */ - public fun binaryOperation(operation: String, left: T, right: T): T + public fun binaryOperation(operation: String): (left: T, right: T) -> T } /** @@ -40,16 +40,28 @@ public interface NumericAlgebra : Algebra { public fun number(value: Number): T /** - * Dynamic call of binary operation [operation] on [left] and [right] where left element is [Number]. + * Dynamically dispatches a binary operation with name [operation] where the left argument is [Number]. */ - public fun leftSideNumberOperation(operation: String, left: Number, right: T): T = - binaryOperation(operation, number(left), right) + public fun leftSideNumberOperation(operation: String): (left: Number, right: T) -> T = + { l, r -> binaryOperation(operation)(number(l), r) } + +// /** +// * Dynamically calls a binary operation with name [operation] where the left argument is [Number]. +// */ +// public fun leftSideNumberOperation(operation: String, left: Number, right: T): T = +// leftSideNumberOperation(operation)(left, right) /** - * Dynamic call of binary operation [operation] on [left] and [right] where right element is [Number]. + * Dynamically dispatches a binary operation with name [operation] where the right argument is [Number]. */ - public fun rightSideNumberOperation(operation: String, left: T, right: Number): T = - leftSideNumberOperation(operation, right, left) + public fun rightSideNumberOperation(operation: String): (left: T, right: Number) -> T = + { l, r -> binaryOperation(operation)(l, number(r)) } + +// /** +// * Dynamically calls a binary operation with name [operation] where the right argument is [Number]. +// */ +// public fun rightSideNumberOperation(operation: String, left: T, right: Number): T = +// rightSideNumberOperation(operation)(left, right) } /** @@ -146,15 +158,15 @@ public interface SpaceOperations : Algebra { */ public operator fun Number.times(b: T): T = b * this - override fun unaryOperation(operation: String, arg: T): T = when (operation) { - PLUS_OPERATION -> arg - MINUS_OPERATION -> -arg + override fun unaryOperation(operation: String): (arg: T) -> T = when (operation) { + PLUS_OPERATION -> { arg -> arg } + MINUS_OPERATION -> { arg -> -arg } else -> error("Unary operation $operation not defined in $this") } - override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) { - PLUS_OPERATION -> add(left, right) - MINUS_OPERATION -> left - right + override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { + PLUS_OPERATION -> ::add + MINUS_OPERATION -> { left, right -> left - right } else -> error("Binary operation $operation not defined in $this") } @@ -207,9 +219,9 @@ public interface RingOperations : SpaceOperations { */ public operator fun T.times(b: T): T = multiply(this, b) - override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) { - TIMES_OPERATION -> multiply(left, right) - else -> super.binaryOperation(operation, left, right) + override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { + TIMES_OPERATION -> ::multiply + else -> super.binaryOperation(operation) } public companion object { @@ -234,20 +246,6 @@ public interface Ring : Space, RingOperations, NumericAlgebra { override fun number(value: Number): T = one * value.toDouble() - override fun leftSideNumberOperation(operation: String, left: Number, right: T): T = when (operation) { - SpaceOperations.PLUS_OPERATION -> left + right - SpaceOperations.MINUS_OPERATION -> left - right - RingOperations.TIMES_OPERATION -> left * right - else -> super.leftSideNumberOperation(operation, left, right) - } - - override fun rightSideNumberOperation(operation: String, left: T, right: Number): T = when (operation) { - SpaceOperations.PLUS_OPERATION -> left + right - SpaceOperations.MINUS_OPERATION -> left - right - RingOperations.TIMES_OPERATION -> left * right - else -> super.rightSideNumberOperation(operation, left, right) - } - /** * Addition of element and scalar. * @@ -308,9 +306,9 @@ public interface FieldOperations : RingOperations { */ public operator fun T.div(b: T): T = divide(this, b) - override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) { - DIV_OPERATION -> divide(left, right) - else -> super.binaryOperation(operation, left, right) + override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { + DIV_OPERATION -> ::divide + else -> super.binaryOperation(operation) } public companion object { diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt index a2b33a0c4..611222d34 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt @@ -15,23 +15,23 @@ public interface ExtendedFieldOperations : public override fun tan(arg: T): T = sin(arg) / cos(arg) public override fun tanh(arg: T): T = sinh(arg) / cosh(arg) - public override fun unaryOperation(operation: String, arg: T): T = when (operation) { - TrigonometricOperations.COS_OPERATION -> cos(arg) - TrigonometricOperations.SIN_OPERATION -> sin(arg) - TrigonometricOperations.TAN_OPERATION -> tan(arg) - TrigonometricOperations.ACOS_OPERATION -> acos(arg) - TrigonometricOperations.ASIN_OPERATION -> asin(arg) - TrigonometricOperations.ATAN_OPERATION -> atan(arg) - HyperbolicOperations.COSH_OPERATION -> cosh(arg) - HyperbolicOperations.SINH_OPERATION -> sinh(arg) - HyperbolicOperations.TANH_OPERATION -> tanh(arg) - HyperbolicOperations.ACOSH_OPERATION -> acosh(arg) - HyperbolicOperations.ASINH_OPERATION -> asinh(arg) - HyperbolicOperations.ATANH_OPERATION -> atanh(arg) - PowerOperations.SQRT_OPERATION -> sqrt(arg) - ExponentialOperations.EXP_OPERATION -> exp(arg) - ExponentialOperations.LN_OPERATION -> ln(arg) - else -> super.unaryOperation(operation, arg) + public override fun unaryOperation(operation: String): (arg: T) -> T = when (operation) { + TrigonometricOperations.COS_OPERATION -> ::cos + TrigonometricOperations.SIN_OPERATION -> ::sin + TrigonometricOperations.TAN_OPERATION -> ::tan + TrigonometricOperations.ACOS_OPERATION -> ::acos + TrigonometricOperations.ASIN_OPERATION -> ::asin + TrigonometricOperations.ATAN_OPERATION -> ::atan + HyperbolicOperations.COSH_OPERATION -> ::cosh + HyperbolicOperations.SINH_OPERATION -> ::sinh + HyperbolicOperations.TANH_OPERATION -> ::tanh + HyperbolicOperations.ACOSH_OPERATION -> ::acosh + HyperbolicOperations.ASINH_OPERATION -> ::asinh + HyperbolicOperations.ATANH_OPERATION -> ::atanh + PowerOperations.SQRT_OPERATION -> ::sqrt + ExponentialOperations.EXP_OPERATION -> ::exp + ExponentialOperations.LN_OPERATION -> ::ln + else -> super.unaryOperation(operation) } } @@ -46,10 +46,11 @@ public interface ExtendedField : ExtendedFieldOperations, Field { 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 - public override fun rightSideNumberOperation(operation: String, left: T, right: Number): T = when (operation) { - PowerOperations.POW_OPERATION -> power(left, right) - else -> super.rightSideNumberOperation(operation, left, right) - } + public override fun rightSideNumberOperation(operation: String): (left: T, right: Number) -> T = + when (operation) { + PowerOperations.POW_OPERATION -> ::power + else -> super.rightSideNumberOperation(operation) + } } /** @@ -80,10 +81,11 @@ public object RealField : ExtendedField, Norm { public override val one: Double get() = 1.0 - public override fun binaryOperation(operation: String, left: Double, right: Double): Double = when (operation) { - PowerOperations.POW_OPERATION -> left pow right - else -> super.binaryOperation(operation, left, right) - } + public override fun binaryOperation(operation: String): (left: Double, right: Double) -> Double = + when (operation) { + PowerOperations.POW_OPERATION -> ::power + else -> super.binaryOperation(operation) + } public override inline fun add(a: Double, b: Double): Double = a + b public override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble() @@ -130,9 +132,9 @@ public object FloatField : ExtendedField, Norm { public override val one: Float get() = 1.0f - public override fun binaryOperation(operation: String, left: Float, right: Float): Float = when (operation) { - PowerOperations.POW_OPERATION -> left pow right - else -> super.binaryOperation(operation, left, right) + public override fun binaryOperation(operation: String): (left: Float, right: Float) -> Float = when (operation) { + PowerOperations.POW_OPERATION -> ::power + else -> super.binaryOperation(operation) } public override inline fun add(a: Float, b: Float): Float = a + b From e447a15304f2c1b7df9ad00c48a721db9f92edc6 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 28 Nov 2020 13:42:18 +0700 Subject: [PATCH 134/199] Make MstAlgebra operations return specific types --- .../kotlin/kscience/kmath/ast/MstAlgebra.kt | 101 +++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt index cea708342..44a7f20b9 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt @@ -7,10 +7,10 @@ import kscience.kmath.operations.* */ public object MstAlgebra : NumericAlgebra { public override fun number(value: Number): MST.Numeric = MST.Numeric(value) - public override fun symbol(value: String): MST.Symbolic = MST.Symbolic(value) - public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = { arg -> MST.Unary(operation, arg) } + public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = + { arg -> MST.Unary(operation, arg) } public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = { left, right -> MST.Binary(operation, left, right) } @@ -25,92 +25,95 @@ public object MstSpace : Space, NumericAlgebra { public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value) override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b) - override fun multiply(a: MST, k: Number): MST = binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k)) + override fun multiply(a: MST, k: Number): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k)) - override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST = + override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstAlgebra.binaryOperation(operation) - override fun unaryOperation(operation: String): (arg: MST) -> MST = MstAlgebra.unaryOperation(operation) + override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = MstAlgebra.unaryOperation(operation) } /** * [Ring] over [MST] nodes. */ public object MstRing : Ring, NumericAlgebra { - override val zero: MST + override val zero: MST.Numeric get() = MstSpace.zero - override val one: MST = number(1.0) - public override fun number(value: Number): MST = MstSpace.number(value) - public override fun symbol(value: String): MST = MstSpace.symbol(value) - public override fun add(a: MST, b: MST): MST = MstSpace.add(a, b) - public override fun multiply(a: MST, k: Number): MST = MstSpace.multiply(a, k) - public override fun multiply(a: MST, b: MST): MST = binaryOperation(RingOperations.TIMES_OPERATION)(a, b) + override val one: MST.Numeric by lazy { number(1.0) } - public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST = + public override fun number(value: Number): MST.Numeric = MstSpace.number(value) + public override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value) + public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b) + public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k) + public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION)(a, b) + + public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstSpace.binaryOperation(operation) - public override fun unaryOperation(operation: String): (arg: MST) -> MST = MstAlgebra.unaryOperation(operation) + public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = + MstAlgebra.unaryOperation(operation) } /** * [Field] over [MST] nodes. */ public object MstField : Field { - public override val zero: MST + public override val zero: MST.Numeric get() = MstRing.zero - public override val one: MST + public override val one: MST.Numeric get() = MstRing.one - public override fun symbol(value: String): MST = MstRing.symbol(value) - public override fun number(value: Number): MST = MstRing.number(value) - public override fun add(a: MST, b: MST): MST = MstRing.add(a, b) - public override fun multiply(a: MST, k: Number): MST = MstRing.multiply(a, k) - public override fun multiply(a: MST, b: MST): MST = MstRing.multiply(a, b) - public override fun divide(a: MST, b: MST): MST = binaryOperation(FieldOperations.DIV_OPERATION)(a, b) + public override fun symbol(value: String): MST.Symbolic = MstRing.symbol(value) + public override fun number(value: Number): MST.Numeric = MstRing.number(value) + public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) + public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k) + public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) + public override fun divide(a: MST, b: MST): MST.Binary = binaryOperation(FieldOperations.DIV_OPERATION)(a, b) - public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST = + public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstRing.binaryOperation(operation) - public override fun unaryOperation(operation: String): (arg: MST) -> MST = MstRing.unaryOperation(operation) + public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = MstRing.unaryOperation(operation) } /** * [ExtendedField] over [MST] nodes. */ public object MstExtendedField : ExtendedField { - public override val zero: MST + public override val zero: MST.Numeric get() = MstField.zero - public override val one: MST + public override val one: MST.Numeric get() = MstField.one public override fun symbol(value: String): MST = MstField.symbol(value) - public override fun sin(arg: MST): MST = unaryOperation(TrigonometricOperations.SIN_OPERATION)(arg) - public override fun cos(arg: MST): MST = unaryOperation(TrigonometricOperations.COS_OPERATION)(arg) - public override fun tan(arg: MST): MST = unaryOperation(TrigonometricOperations.TAN_OPERATION)(arg) - public override fun asin(arg: MST): MST = unaryOperation(TrigonometricOperations.ASIN_OPERATION)(arg) - public override fun acos(arg: MST): MST = unaryOperation(TrigonometricOperations.ACOS_OPERATION)(arg) - public override fun atan(arg: MST): MST = unaryOperation(TrigonometricOperations.ATAN_OPERATION)(arg) - public override fun sinh(arg: MST): MST = unaryOperation(HyperbolicOperations.SINH_OPERATION)(arg) - public override fun cosh(arg: MST): MST = unaryOperation(HyperbolicOperations.COSH_OPERATION)(arg) - public override fun tanh(arg: MST): MST = unaryOperation(HyperbolicOperations.TANH_OPERATION)(arg) - public override fun asinh(arg: MST): MST = unaryOperation(HyperbolicOperations.ASINH_OPERATION)(arg) - public override fun acosh(arg: MST): MST = unaryOperation(HyperbolicOperations.ACOSH_OPERATION)(arg) - public override fun atanh(arg: MST): MST = unaryOperation(HyperbolicOperations.ATANH_OPERATION)(arg) - public override fun add(a: MST, b: MST): MST = MstField.add(a, b) - public override fun multiply(a: MST, k: Number): MST = MstField.multiply(a, k) - public override fun multiply(a: MST, b: MST): MST = MstField.multiply(a, b) - public override fun divide(a: MST, b: MST): MST = MstField.divide(a, b) - public override fun power(arg: MST, pow: Number): MST = binaryOperation(PowerOperations.POW_OPERATION)(arg, number(pow)) - public override fun exp(arg: MST): MST = unaryOperation(ExponentialOperations.EXP_OPERATION)(arg) - public override fun ln(arg: MST): MST = unaryOperation(ExponentialOperations.LN_OPERATION)(arg) + public override fun sin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.SIN_OPERATION)(arg) + public override fun cos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.COS_OPERATION)(arg) + public override fun tan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.TAN_OPERATION)(arg) + public override fun asin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ASIN_OPERATION)(arg) + public override fun acos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ACOS_OPERATION)(arg) + public override fun atan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ATAN_OPERATION)(arg) + public override fun sinh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.SINH_OPERATION)(arg) + public override fun cosh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.COSH_OPERATION)(arg) + public override fun tanh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.TANH_OPERATION)(arg) + public override fun asinh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ASINH_OPERATION)(arg) + public override fun acosh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ACOSH_OPERATION)(arg) + public override fun atanh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ATANH_OPERATION)(arg) + public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) + public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k) + public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) + public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b) - public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST = + public override fun power(arg: MST, pow: Number): MST.Binary = + binaryOperation(PowerOperations.POW_OPERATION)(arg, number(pow)) + + public override fun exp(arg: MST): MST.Unary = unaryOperation(ExponentialOperations.EXP_OPERATION)(arg) + public override fun ln(arg: MST): MST.Unary = unaryOperation(ExponentialOperations.LN_OPERATION)(arg) + + public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstField.binaryOperation(operation) - public override fun unaryOperation(operation: String): (arg: MST) -> MST = MstField.unaryOperation(operation) - override fun unaryOperation(operation: String, arg: MST): MST.Unary = - MST.Unary(operation, arg) + public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = MstField.unaryOperation(operation) } From a8329b2ed25155ad6089da5603218f6aba53ea64 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 28 Nov 2020 18:43:35 +0300 Subject: [PATCH 135/199] Grid generators moved to kmath-for-real --- CHANGELOG.md | 3 +++ build.gradle.kts | 2 +- .../kscience/kmath/structures/RealBuffer.kt | 13 +++++++++---- .../kmath/real/{realMatrix.kt => RealMatrix.kt} | 0 .../kotlin/kscience/kmath/real/RealVector.kt | 5 +++-- .../kotlin/kscience/kmath/real/grids.kt | 16 ++++++---------- .../kotlin/kscience/kmath/real/realBuffer.kt | 8 -------- .../kotlin/kaceince/kmath/real/GridTest.kt | 13 +++++++++++++ .../kmath/real}/RealMatrixTest.kt | 3 ++- .../kmath/real/RealVectorTest.kt} | 7 +++++-- settings.gradle.kts | 6 +++--- 11 files changed, 45 insertions(+), 31 deletions(-) rename kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/{realMatrix.kt => RealMatrix.kt} (100%) rename kmath-core/src/commonMain/kotlin/kscience/kmath/misc/Grids.kt => kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/grids.kt (72%) delete mode 100644 kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realBuffer.kt create mode 100644 kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt rename kmath-for-real/src/commonTest/kotlin/{scientific.kmath.real => kaceince/kmath/real}/RealMatrixTest.kt (98%) rename kmath-for-real/src/commonTest/kotlin/{kscience/kmath/linear/VectorTest.kt => kaceince/kmath/real/RealVectorTest.kt} (83%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80b0c3cec..259c56c34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - `Fitting` utility object in prob/stat - ND4J support module submitting `NDStructure` and `NDAlgebra` over `INDArray`. - Coroutine-deterministic Monte-Carlo scope with a random number generator. +- Some minor utilities to `kmath-for-real`. ### Changed - Package changed from `scientifik` to `kscience.kmath`. @@ -25,12 +26,14 @@ - `kmath-ast` doesn't depend on heavy `kotlin-reflect` library. - Full autodiff refactoring based on `Symbol` - `kmath-prob` renamed to `kmath-stat` +- Grid generators moved to `kmath-for-real` ### Deprecated ### Removed - `kmath-koma` module because it doesn't support Kotlin 1.4. - Support of `legacy` JS backend (we will support only IR) +- `toGrid` method. ### Fixed - `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) diff --git a/build.gradle.kts b/build.gradle.kts index 3514c91e6..561a2212b 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-3") +internal val kmathVersion: String by extra("0.2.0-dev-4") internal val bintrayRepo: String by extra("kscience") internal val githubProject: String by extra("kmath") diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBuffer.kt index 2a03e2dd3..769c445d6 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBuffer.kt @@ -5,19 +5,19 @@ package kscience.kmath.structures * * @property array the underlying array. */ +@Suppress("OVERRIDE_BY_INLINE") public inline class RealBuffer(public val array: DoubleArray) : MutableBuffer { override val size: Int get() = array.size - override operator fun get(index: Int): Double = array[index] + override inline operator fun get(index: Int): Double = array[index] - override operator fun set(index: Int, value: Double) { + override inline operator fun set(index: Int, value: Double) { array[index] = value } override operator fun iterator(): DoubleIterator = array.iterator() - override fun copy(): MutableBuffer = - RealBuffer(array.copyOf()) + override fun copy(): RealBuffer = RealBuffer(array.copyOf()) } /** @@ -34,6 +34,11 @@ public inline fun RealBuffer(size: Int, init: (Int) -> Double): RealBuffer = Rea */ public fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles) +/** + * Simplified [RealBuffer] to array comparison + */ +public fun RealBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles) + /** * Returns a [DoubleArray] containing all of the elements of this [MutableBuffer]. */ diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realMatrix.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt similarity index 100% rename from kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realMatrix.kt rename to kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt index ba5f8444b..1ee33ee32 100644 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt @@ -14,8 +14,9 @@ import kotlin.math.sqrt public typealias RealPoint = Point -public fun DoubleArray.asVector(): RealVector = RealVector(asBuffer()) -public fun List.asVector(): RealVector = RealVector(asBuffer()) +public fun RealPoint.asVector(): RealVector = RealVector(this) +public fun DoubleArray.asVector(): RealVector = asBuffer().asVector() +public fun List.asVector(): RealVector = asBuffer().asVector() public object VectorL2Norm : Norm, Double> { override fun norm(arg: Point): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble)) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/Grids.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/grids.kt similarity index 72% rename from kmath-core/src/commonMain/kotlin/kscience/kmath/misc/Grids.kt rename to kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/grids.kt index 4d058c366..bd0e092e0 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/Grids.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/grids.kt @@ -1,5 +1,7 @@ -package kscience.kmath.misc +package kscience.kmath.real +import kscience.kmath.linear.Point +import kscience.kmath.structures.asBuffer import kotlin.math.abs /** @@ -32,6 +34,9 @@ public fun ClosedFloatingPointRange.toSequenceWithStep(step: Double): Se } } +public infix fun ClosedFloatingPointRange.step(step: Double): Point = + toSequenceWithStep(step).toList().asBuffer() + /** * Convert double range to sequence with the fixed number of points */ @@ -39,12 +44,3 @@ public fun ClosedFloatingPointRange.toSequenceWithPoints(numPoints: Int) require(numPoints > 1) { "The number of points should be more than 2" } return toSequenceWithStep(abs(endInclusive - start) / (numPoints - 1)) } - -/** - * Convert double range to array of evenly spaced doubles, where the size of array equals [numPoints] - */ -@Deprecated("Replace by 'toSequenceWithPoints'") -public fun ClosedFloatingPointRange.toGrid(numPoints: Int): DoubleArray { - require(numPoints >= 2) { "Can't create generic grid with less than two points" } - return DoubleArray(numPoints) { i -> start + (endInclusive - start) / (numPoints - 1) * i } -} diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realBuffer.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realBuffer.kt deleted file mode 100644 index 0a2119b0d..000000000 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/realBuffer.kt +++ /dev/null @@ -1,8 +0,0 @@ -package kscience.kmath.real - -import kscience.kmath.structures.RealBuffer - -/** - * Simplified [RealBuffer] to array comparison - */ -public fun RealBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles) diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt new file mode 100644 index 000000000..5f19e94b7 --- /dev/null +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt @@ -0,0 +1,13 @@ +package kaceince.kmath.real + +import kscience.kmath.real.step +import kotlin.test.Test +import kotlin.test.assertEquals + +class GridTest { + @Test + fun testStepGrid(){ + val grid = 0.0..1.0 step 0.2 + assertEquals(6, grid.size) + } +} \ No newline at end of file diff --git a/kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt similarity index 98% rename from kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt rename to kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt index 859938481..5c33b76a9 100644 --- a/kmath-for-real/src/commonTest/kotlin/scientific.kmath.real/RealMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt @@ -1,9 +1,10 @@ -package scientific.kmath.real +package kaceince.kmath.real import kscience.kmath.linear.VirtualMatrix import kscience.kmath.linear.build import kscience.kmath.real.* import kscience.kmath.structures.Matrix +import kscience.kmath.structures.contentEquals import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-for-real/src/commonTest/kotlin/kscience/kmath/linear/VectorTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt similarity index 83% rename from kmath-for-real/src/commonTest/kotlin/kscience/kmath/linear/VectorTest.kt rename to kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt index 17ff4ef20..8a9f7a443 100644 --- a/kmath-for-real/src/commonTest/kotlin/kscience/kmath/linear/VectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt @@ -1,11 +1,14 @@ -package kscience.kmath.linear +package kaceince.kmath.real +import kscience.kmath.linear.MatrixContext +import kscience.kmath.linear.asMatrix +import kscience.kmath.linear.transpose import kscience.kmath.operations.invoke import kscience.kmath.real.RealVector import kotlin.test.Test import kotlin.test.assertEquals -internal class VectorTest { +internal class RealVectorTest { @Test fun testSum() { val vector1 = RealVector(5) { it.toDouble() } diff --git a/settings.gradle.kts b/settings.gradle.kts index 97dfe1b96..10e4d9577 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,8 +8,8 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlinx") } - val toolsVersion = "0.6.4-dev-1.4.20-M2" - val kotlinVersion = "1.4.20-M2" + val toolsVersion = "0.7.0" + val kotlinVersion = "1.4.20" plugins { id("kotlinx.benchmark") version "0.2.0-dev-20" @@ -17,7 +17,7 @@ pluginManagement { id("ru.mipt.npm.mpp") version toolsVersion id("ru.mipt.npm.jvm") version toolsVersion id("ru.mipt.npm.publish") version toolsVersion - kotlin("jvm") version kotlinVersion + kotlin("jvm") version kotlinVersion kotlin("plugin.allopen") version kotlinVersion } } From c21e761a76f79128469bb2162b5cfd7d5fe3b837 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 28 Nov 2020 19:46:51 +0300 Subject: [PATCH 136/199] Workaround for https://youtrack.jetbrains.com/issue/KT-40121 --- .../kscience/kmath/expressions/Expression.kt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt index 98940e767..63bbc9312 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/Expression.kt @@ -3,6 +3,7 @@ package kscience.kmath.expressions import kscience.kmath.operations.Algebra import kotlin.jvm.JvmName import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty /** * A marker interface for a symbol. A symbol mus have an identity @@ -12,6 +13,13 @@ public interface Symbol { * Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol. */ public val identity: String + + public companion object : ReadOnlyProperty { + //TODO deprecate and replace by top level function after fix of https://youtrack.jetbrains.com/issue/KT-40121 + override fun getValue(thisRef: Any?, property: KProperty<*>): Symbol { + return StringSymbol(property.name) + } + } } /** @@ -95,9 +103,9 @@ public fun ExpressionAlgebra.bind(symbol: Symbol): E = /** * A delegate to create a symbol with a string identity in this scope */ -public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> - StringSymbol(property.name) -} +public val symbol: ReadOnlyProperty get() = Symbol +//TODO does not work directly on native due to https://youtrack.jetbrains.com/issue/KT-40121 + /** * Bind a symbol by name inside the [ExpressionAlgebra] From 5b653f10d7298e361b8d8f69f11b63f0902dfb82 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 29 Nov 2020 13:32:20 +0300 Subject: [PATCH 137/199] kmath-for-real refactoring --- CHANGELOG.md | 1 + README.md | 38 ++++--- examples/build.gradle.kts | 9 +- .../kmath/commons/fit/fitWithAutoDiff.kt | 101 ++++++++++++++++++ .../prob => stat}/DistributionBenchmark.kt | 0 .../prob => stat}/DistributionDemo.kt | 11 +- kmath-core/README.md | 6 +- .../kscience/kmath/linear/VectorSpace.kt | 8 +- .../kotlin/kscience/kmath/misc/annotations.kt | 4 + .../kscience/kmath/structures/Buffers.kt | 5 + .../kotlin/kscience/kmath/chains/Chain.kt | 2 +- kmath-for-real/README.md | 44 ++++++++ kmath-for-real/build.gradle.kts | 28 +++++ kmath-for-real/docs/README-TEMPLATE.md | 5 + .../kotlin/kscience/kmath/real/RealMatrix.kt | 52 ++++----- .../kotlin/kscience/kmath/real/RealVector.kt | 74 ++++++++----- .../kotlin/kscience/kmath/real/grids.kt | 3 +- kmath-nd4j/README.md | 8 +- .../kscience/kmath/stat/distributions.kt | 5 +- 19 files changed, 310 insertions(+), 94 deletions(-) create mode 100644 examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt rename examples/src/main/kotlin/kscience/kmath/{commons/prob => stat}/DistributionBenchmark.kt (100%) rename examples/src/main/kotlin/kscience/kmath/{commons/prob => stat}/DistributionDemo.kt (83%) create mode 100644 kmath-core/src/commonMain/kotlin/kscience/kmath/misc/annotations.kt create mode 100644 kmath-for-real/README.md create mode 100644 kmath-for-real/docs/README-TEMPLATE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 259c56c34..99511a161 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - Full autodiff refactoring based on `Symbol` - `kmath-prob` renamed to `kmath-stat` - Grid generators moved to `kmath-for-real` +- Use `Point` instead of specialized type in `kmath-for-real` ### Deprecated diff --git a/README.md b/README.md index c4e3e5374..50a916d2c 100644 --- a/README.md +++ b/README.md @@ -132,9 +132,17 @@ submit a feature request if you want something to be implemented first.
* ### [kmath-for-real](kmath-for-real) -> +> Extension module that should be used to achieve numpy-like behavior. +All operations are specialized to work with `Double` numbers without declaring algebraic contexts. +One can still use generic algebras though. > > **Maturity**: EXPERIMENTAL +> +> **Features:** +> - [RealVector](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt) : Numpy-like operations for Buffers/Points +> - [RealMatrix](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt) : Numpy-like operations for 2d real structures +> - [grids](kmath-for-real/src/commonMain/kotlin/kscience/kmath/structures/grids.kt) : Uniform grid generators +
* ### [kmath-functions](kmath-functions) @@ -155,6 +163,12 @@ submit a feature request if you want something to be implemented first. > **Maturity**: EXPERIMENTAL
+* ### [kmath-kotlingrad](kmath-kotlingrad) +> +> +> **Maturity**: EXPERIMENTAL +
+ * ### [kmath-memory](kmath-memory) > > @@ -167,7 +181,7 @@ submit a feature request if you want something to be implemented first. > **Maturity**: EXPERIMENTAL > > **Features:** -> - [nd4jarraystrucure](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray +> - [nd4jarraystructure](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray > - [nd4jarrayrings](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long > - [nd4jarrayfields](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double @@ -211,20 +225,12 @@ Release artifacts are accessible from bintray with following configuration (see ```kotlin repositories { - jcenter() - maven("https://clojars.org/repo") - maven("https://dl.bintray.com/egor-bogomolov/astminer/") - maven("https://dl.bintray.com/hotkeytlt/maven") - maven("https://dl.bintray.com/kotlin/kotlin-eap") - maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/mipt-npm/kscience") - maven("https://jitpack.io") - mavenCentral() } dependencies { - api("kscience.kmath:kmath-core:0.2.0-dev-3") - // api("kscience.kmath:kmath-core-jvm:0.2.0-dev-3") for jvm-specific version + api("kscience.kmath:kmath-core:0.2.0-dev-4") + // api("kscience.kmath:kmath-core-jvm:0.2.0-dev-4") for jvm-specific version } ``` @@ -236,15 +242,7 @@ Development builds are uploaded to the separate repository: ```kotlin repositories { - jcenter() - maven("https://clojars.org/repo") - maven("https://dl.bintray.com/egor-bogomolov/astminer/") - maven("https://dl.bintray.com/hotkeytlt/maven") - maven("https://dl.bintray.com/kotlin/kotlin-eap") - maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/mipt-npm/dev") - maven("https://jitpack.io") - mavenCentral() } ``` diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index d42627ff0..eead68a9d 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -35,6 +35,9 @@ dependencies { implementation(project(":kmath-dimensions")) implementation(project(":kmath-ejml")) implementation(project(":kmath-nd4j")) + + implementation(project(":kmath-for-real")) + implementation("org.deeplearning4j:deeplearning4j-core:1.0.0-beta7") implementation("org.nd4j:nd4j-native:1.0.0-beta7") @@ -51,7 +54,11 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-io:0.2.0-npm-dev-11") implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20") implementation("org.slf4j:slf4j-simple:1.7.30") - "benchmarksImplementation"("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-8") + + // plotting + implementation("kscience.plotlykt:plotlykt-server:0.3.1-dev") + + "benchmarksImplementation"("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-20") "benchmarksImplementation"(sourceSets.main.get().output + sourceSets.main.get().runtimeClasspath) } diff --git a/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt new file mode 100644 index 000000000..6cfa1961b --- /dev/null +++ b/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -0,0 +1,101 @@ +package kscience.kmath.commons.fit + +import kotlinx.html.br +import kotlinx.html.h3 +import kscience.kmath.commons.optimization.chiSquared +import kscience.kmath.commons.optimization.minimize +import kscience.kmath.expressions.symbol +import kscience.kmath.real.RealVector +import kscience.kmath.real.map +import kscience.kmath.real.step +import kscience.kmath.stat.* +import kscience.kmath.structures.asIterable +import kscience.kmath.structures.toList +import kscience.plotly.* +import kscience.plotly.models.ScatterMode +import kscience.plotly.models.TraceValues +import kotlin.math.pow +import kotlin.math.sqrt + +//Forward declaration of symbols that will be used in expressions. +// This declaration is required for +private val a by symbol +private val b by symbol +private val c by symbol + +/** + * Shortcut to use buffers in plotly + */ +operator fun TraceValues.invoke(vector: RealVector) { + numbers = vector.asIterable() +} + +/** + * Least squares fie with auto-differentiation. Uses `kmath-commons` and `kmath-for-real` modules. + */ +fun main() { + + //A generator for a normally distributed values + val generator = Distribution.normal() + + //A chain/flow of random values with the given seed + val chain = generator.sample(RandomGenerator.default(112667)) + + + //Create a uniformly distributed x values like numpy.arrange + val x = 1.0..100.0 step 1.0 + + + //Perform an operation on each x value (much more effective, than numpy) + val y = x.map { + val value = it.pow(2) + it + 1 + value + chain.nextDouble() * sqrt(value) + } + // this will also work, but less effective: + // val y = x.pow(2)+ x + 1 + chain.nextDouble() + + // create same errors for all xs + val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma) + + // compute differentiable chi^2 sum for given model ax^2 + bx + c + val chi2 = Fitting.chiSquared(x, y, yErr) { x1 -> + //bind variables to autodiff context + val a = bind(a) + val b = bind(b) + //Include default value for c if it is not provided as a parameter + val c = bindOrNull(c) ?: one + a * x1.pow(2) + b * x1 + c + } + + //minimize the chi^2 in given starting point. Derivatives are not required, they are already included. + val result: OptimizationResult = chi2.minimize(a to 1.5, b to 0.9, c to 1.0) + + val page = Plotly.page { + plot { + scatter { + mode = ScatterMode.markers + x(x) + y(y) + error_y { + array = yErr.toList() + } + name = "data" + } + scatter { + mode = ScatterMode.lines + x(x) + y(x.map { result.point[a]!! * it.pow(2) + result.point[b]!! * it + 1 }) + name = "fit" + } + } + br() + h3{ + +"Fit result: $result" + } + h3{ + +"Chi2/dof = ${result.value / (x.size - 3)}" + } + } + + page.makeFile() +} \ No newline at end of file diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt similarity index 100% rename from examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt rename to examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt b/examples/src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt similarity index 83% rename from examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt rename to examples/src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt index 6146e17af..24a4cb1a7 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt @@ -1,14 +1,17 @@ -package kscience.kmath.commons.prob +package kscience.kmath.stat import kotlinx.coroutines.runBlocking import kscience.kmath.chains.Chain import kscience.kmath.chains.collectWithState -import kscience.kmath.stat.Distribution -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.normal +/** + * The state of distribution averager + */ private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0) +/** + * Averaging + */ private fun Chain.mean(): Chain = collectWithState(AveragingChainState(), { it.copy() }) { chain -> val next = chain.next() num++ diff --git a/kmath-core/README.md b/kmath-core/README.md index 42a513a10..3a919e85a 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -12,7 +12,7 @@ The core features of KMath: > #### Artifact: > -> This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-3`. +> This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-4`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) > @@ -30,7 +30,7 @@ The core features of KMath: > } > > dependencies { -> implementation 'kscience.kmath:kmath-core:0.2.0-dev-3' +> implementation 'kscience.kmath:kmath-core:0.2.0-dev-4' > } > ``` > **Gradle Kotlin DSL:** @@ -44,6 +44,6 @@ The core features of KMath: > } > > dependencies { -> implementation("kscience.kmath:kmath-core:0.2.0-dev-3") +> implementation("kscience.kmath:kmath-core:0.2.0-dev-4") > } > ``` diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VectorSpace.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VectorSpace.kt index 67056c6b2..2a3b8f5d1 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VectorSpace.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VectorSpace.kt @@ -15,7 +15,7 @@ public interface VectorSpace> : Space> { public val space: S override val zero: Point get() = produce { space.zero } - public fun produce(initializer: (Int) -> T): Point + public fun produce(initializer: S.(Int) -> T): Point /** * Produce a space-element of this vector space for expressions @@ -48,7 +48,7 @@ public interface VectorSpace> : Space> { public fun > buffered( size: Int, space: S, - bufferFactory: BufferFactory = Buffer.Companion::boxing + bufferFactory: BufferFactory = Buffer.Companion::boxing, ): BufferVectorSpace = BufferVectorSpace(size, space, bufferFactory) /** @@ -63,8 +63,8 @@ public interface VectorSpace> : Space> { public class BufferVectorSpace>( override val size: Int, override val space: S, - public val bufferFactory: BufferFactory + public val bufferFactory: BufferFactory, ) : VectorSpace { - override fun produce(initializer: (Int) -> T): Buffer = bufferFactory(size, initializer) + override fun produce(initializer: S.(Int) -> T): Buffer = bufferFactory(size) { space.initializer(it) } //override fun produceElement(initializer: (Int) -> T): Vector = BufferVector(this, produce(initializer)) } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/annotations.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/annotations.kt new file mode 100644 index 000000000..d70ac7b39 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/misc/annotations.kt @@ -0,0 +1,4 @@ +package kscience.kmath.misc + +@RequiresOptIn("This API is unstable and could change in future", RequiresOptIn.Level.WARNING) +public annotation class UnstableKMathAPI \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt index 5174eb314..bfec6f871 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt @@ -102,6 +102,11 @@ public fun Buffer.asSequence(): Sequence = Sequence(::iterator) */ public fun Buffer.asIterable(): Iterable = Iterable(::iterator) +/** + * Converts this [Buffer] to a new [List] + */ +public fun Buffer.toList(): List = asSequence().toList() + /** * Returns an [IntRange] of the valid indices for this [Buffer]. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt index 8c15e52c7..7ff7b7aae 100644 --- a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt @@ -47,7 +47,7 @@ public fun Iterator.asChain(): Chain = SimpleChain { next() } public fun Sequence.asChain(): Chain = iterator().asChain() /** - * A simple chain of independent tokens + * A simple chain of independent tokens. [fork] returns the same chain. */ public class SimpleChain(private val gen: suspend () -> R) : Chain { public override suspend fun next(): R = gen() diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md new file mode 100644 index 000000000..2ddf78e57 --- /dev/null +++ b/kmath-for-real/README.md @@ -0,0 +1,44 @@ +# Real number specialization module (`kmath-for-real`) + + - [RealVector](src/commonMain/kotlin/kscience/kmath/real/RealVector.kt) : Numpy-like operations for Buffers/Points + - [RealMatrix](src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt) : Numpy-like operations for 2d real structures + - [grids](src/commonMain/kotlin/kscience/kmath/structures/grids.kt) : Uniform grid generators + + +> #### Artifact: +> +> This module artifact: `kscience.kmath:kmath-for-real:0.2.0-dev-4`. +> +> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-for-real/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-for-real/_latestVersion) +> +> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-for-real/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-for-real/_latestVersion) +> +> **Gradle:** +> +> ```gradle +> repositories { +> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } +> maven { url 'https://dl.bintray.com/mipt-npm/kscience' } +> maven { url 'https://dl.bintray.com/mipt-npm/dev' } +> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + +> } +> +> dependencies { +> implementation 'kscience.kmath:kmath-for-real:0.2.0-dev-4' +> } +> ``` +> **Gradle Kotlin DSL:** +> +> ```kotlin +> repositories { +> maven("https://dl.bintray.com/kotlin/kotlin-eap") +> maven("https://dl.bintray.com/mipt-npm/kscience") +> maven("https://dl.bintray.com/mipt-npm/dev") +> maven("https://dl.bintray.com/hotkeytlt/maven") +> } +> +> dependencies { +> implementation("kscience.kmath:kmath-for-real:0.2.0-dev-4") +> } +> ``` diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 2a4539c10..f26f98c2c 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -7,3 +7,31 @@ kotlin.sourceSets.commonMain { api(project(":kmath-core")) } } + +readme { + description = """ + Extension module that should be used to achieve numpy-like behavior. + All operations are specialized to work with `Double` numbers without declaring algebraic contexts. + One can still use generic algebras though. + """.trimIndent() + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + + feature( + id = "RealVector", + description = "Numpy-like operations for Buffers/Points", + ref = "src/commonMain/kotlin/kscience/kmath/real/RealVector.kt" + ) + + feature( + id = "RealMatrix", + description = "Numpy-like operations for 2d real structures", + ref = "src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt" + ) + + feature( + id = "grids", + description = "Uniform grid generators", + ref = "src/commonMain/kotlin/kscience/kmath/structures/grids.kt" + ) +} diff --git a/kmath-for-real/docs/README-TEMPLATE.md b/kmath-for-real/docs/README-TEMPLATE.md new file mode 100644 index 000000000..670844bd0 --- /dev/null +++ b/kmath-for-real/docs/README-TEMPLATE.md @@ -0,0 +1,5 @@ +# Real number specialization module (`kmath-for-real`) + +${features} + +${artifact} diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt index 1860b5870..784b27f9d 100644 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt @@ -3,6 +3,7 @@ package kscience.kmath.real import kscience.kmath.linear.MatrixContext import kscience.kmath.linear.RealMatrixContext.elementContext import kscience.kmath.linear.VirtualMatrix +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.invoke import kscience.kmath.operations.sum import kscience.kmath.structures.Buffer @@ -36,7 +37,7 @@ public fun Sequence.toMatrix(): RealMatrix = toList().let { MatrixContext.real.produce(it.size, it[0].size) { row, col -> it[row][col] } } -public fun Matrix.repeatStackVertical(n: Int): RealMatrix = +public fun RealMatrix.repeatStackVertical(n: Int): RealMatrix = VirtualMatrix(rowNum * n, colNum) { row, col -> get(if (row == 0) 0 else row % rowNum, col) } @@ -45,43 +46,43 @@ public fun Matrix.repeatStackVertical(n: Int): RealMatrix = * Operations for matrix and real number */ -public operator fun Matrix.times(double: Double): RealMatrix = +public operator fun RealMatrix.times(double: Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] * double } -public operator fun Matrix.plus(double: Double): RealMatrix = +public operator fun RealMatrix.plus(double: Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] + double } -public operator fun Matrix.minus(double: Double): RealMatrix = +public operator fun RealMatrix.minus(double: Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] - double } -public operator fun Matrix.div(double: Double): RealMatrix = +public operator fun RealMatrix.div(double: Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] / double } -public operator fun Double.times(matrix: Matrix): RealMatrix = +public operator fun Double.times(matrix: RealMatrix): RealMatrix = MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col -> this * matrix[row, col] } -public operator fun Double.plus(matrix: Matrix): RealMatrix = +public operator fun Double.plus(matrix: RealMatrix): RealMatrix = MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col -> this + matrix[row, col] } -public operator fun Double.minus(matrix: Matrix): RealMatrix = +public operator fun Double.minus(matrix: RealMatrix): RealMatrix = MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col -> this - matrix[row, col] } // TODO: does this operation make sense? Should it be 'this/matrix[row, col]'? -//operator fun Double.div(matrix: Matrix) = MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { +//operator fun Double.div(matrix: RealMatrix) = MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { // row, col -> matrix[row, col] / this //} @@ -89,11 +90,11 @@ public operator fun Double.minus(matrix: Matrix): RealMatrix = * Per-element (!) square and power operations */ -public fun Matrix.square(): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> +public fun RealMatrix.square(): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col].pow(2) } -public fun Matrix.pow(n: Int): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { i, j -> +public fun RealMatrix.pow(n: Int): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { i, j -> this[i, j].pow(n) } @@ -101,20 +102,21 @@ public fun Matrix.pow(n: Int): RealMatrix = MatrixContext.real.produce(r * Operations on two matrices (per-element!) */ -public operator fun Matrix.times(other: Matrix): RealMatrix = +@UnstableKMathAPI +public operator fun RealMatrix.times(other: RealMatrix): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] * other[row, col] } -public operator fun Matrix.plus(other: Matrix): RealMatrix = +public operator fun RealMatrix.plus(other: RealMatrix): RealMatrix = MatrixContext.real.add(this, other) -public operator fun Matrix.minus(other: Matrix): RealMatrix = +public operator fun RealMatrix.minus(other: RealMatrix): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] - other[row, col] } /* * Operations on columns */ -public inline fun Matrix.appendColumn(crossinline mapper: (Buffer) -> Double): Matrix = +public inline fun RealMatrix.appendColumn(crossinline mapper: (Buffer) -> Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum + 1) { row, col -> if (col < colNum) this[row, col] @@ -122,28 +124,28 @@ public inline fun Matrix.appendColumn(crossinline mapper: (Buffer.extractColumns(columnRange: IntRange): RealMatrix = +public fun RealMatrix.extractColumns(columnRange: IntRange): RealMatrix = MatrixContext.real.produce(rowNum, columnRange.count()) { row, col -> this[row, columnRange.first + col] } -public fun Matrix.extractColumn(columnIndex: Int): RealMatrix = +public fun RealMatrix.extractColumn(columnIndex: Int): RealMatrix = extractColumns(columnIndex..columnIndex) -public fun Matrix.sumByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun RealMatrix.sumByColumn(): RealBuffer = RealBuffer(colNum) { j -> val column = columns[j] elementContext { sum(column.asIterable()) } } -public fun Matrix.minByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun RealMatrix.minByColumn(): RealBuffer = RealBuffer(colNum) { j -> columns[j].asIterable().minOrNull() ?: error("Cannot produce min on empty column") } -public fun Matrix.maxByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun RealMatrix.maxByColumn(): RealBuffer = RealBuffer(colNum) { j -> columns[j].asIterable().maxOrNull() ?: error("Cannot produce min on empty column") } -public fun Matrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun RealMatrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j -> columns[j].asIterable().average() } @@ -151,7 +153,7 @@ public fun Matrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j * Operations processing all elements */ -public fun Matrix.sum(): Double = elements().map { (_, value) -> value }.sum() -public fun Matrix.min(): Double? = elements().map { (_, value) -> value }.minOrNull() -public fun Matrix.max(): Double? = elements().map { (_, value) -> value }.maxOrNull() -public fun Matrix.average(): Double = elements().map { (_, value) -> value }.average() +public fun RealMatrix.sum(): Double = elements().map { (_, value) -> value }.sum() +public fun RealMatrix.min(): Double? = elements().map { (_, value) -> value }.minOrNull() +public fun RealMatrix.max(): Double? = elements().map { (_, value) -> value }.maxOrNull() +public fun RealMatrix.average(): Double = elements().map { (_, value) -> value }.average() diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt index 1ee33ee32..33684fc8c 100644 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt @@ -1,47 +1,63 @@ package kscience.kmath.real -import kscience.kmath.linear.BufferVectorSpace import kscience.kmath.linear.Point -import kscience.kmath.linear.VectorSpace import kscience.kmath.operations.Norm -import kscience.kmath.operations.RealField -import kscience.kmath.operations.SpaceElement import kscience.kmath.structures.Buffer -import kscience.kmath.structures.RealBuffer -import kscience.kmath.structures.asBuffer import kscience.kmath.structures.asIterable +import kotlin.math.pow import kotlin.math.sqrt -public typealias RealPoint = Point - -public fun RealPoint.asVector(): RealVector = RealVector(this) -public fun DoubleArray.asVector(): RealVector = asBuffer().asVector() -public fun List.asVector(): RealVector = asBuffer().asVector() +public typealias RealVector = Point public object VectorL2Norm : Norm, Double> { override fun norm(arg: Point): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble)) } -public inline class RealVector(private val point: Point) : - SpaceElement>, RealPoint { - public override val size: Int get() = point.size - public override val context: VectorSpace get() = space(point.size) +/** + * Fill the vector of given [size] with given [value] + */ +public fun Buffer.Companion.same(size: Int, value: Number): RealVector = real(size) { value.toDouble() } - public override fun unwrap(): RealPoint = point - public override fun RealPoint.wrap(): RealVector = RealVector(this) - public override operator fun get(index: Int): Double = point[index] - public override operator fun iterator(): Iterator = point.iterator() +// Transformation methods - public companion object { - private val spaceCache: MutableMap> = hashMapOf() +public inline fun RealVector.map(transform: (Double) -> Double): RealVector = + Buffer.real(size) { transform(get(it)) } - public inline operator fun invoke(dim: Int, initializer: (Int) -> Double): RealVector = - RealVector(RealBuffer(dim, initializer)) +public inline fun RealVector.mapIndexed(transform: (index: Int, value: Double) -> Double): RealVector = + Buffer.real(size) { transform(it, get(it)) } - public operator fun invoke(vararg values: Double): RealVector = values.asVector() +public fun RealVector.pow(p: Double): RealVector = map { it.pow(p) } - public fun space(dim: Int): BufferVectorSpace = spaceCache.getOrPut(dim) { - BufferVectorSpace(dim, RealField) { size, init -> Buffer.real(size, init) } - } - } -} +public fun RealVector.pow(p: Int): RealVector = map { it.pow(p) } + +public fun exp(vector: RealVector): RealVector = vector.map { kotlin.math.exp(it) } + +public operator fun RealVector.plus(other: RealVector): RealVector = + mapIndexed { index, value -> value + other[index] } + +public operator fun RealVector.plus(number: Number): RealVector = map { it + number.toDouble() } + +public operator fun Number.plus(vector: RealVector): RealVector = vector + this + +public operator fun RealVector.unaryMinus(): Buffer = map { -it } + +public operator fun RealVector.minus(other: RealVector): RealVector = + mapIndexed { index, value -> value - other[index] } + +public operator fun RealVector.minus(number: Number): RealVector = map { it - number.toDouble() } + +public operator fun Number.minus(vector: RealVector): RealVector = vector.map { toDouble() - it } + +public operator fun RealVector.times(other: RealVector): RealVector = + mapIndexed { index, value -> value * other[index] } + +public operator fun RealVector.times(number: Number): RealVector = map { it * number.toDouble() } + +public operator fun Number.times(vector: RealVector): RealVector = vector * this + +public operator fun RealVector.div(other: RealVector): RealVector = + mapIndexed { index, value -> value / other[index] } + +public operator fun RealVector.div(number: Number): RealVector = map { it / number.toDouble() } + +public operator fun Number.div(vector: RealVector): RealVector = vector.map { toDouble() / it } diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/grids.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/grids.kt index bd0e092e0..69a149fb8 100644 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/grids.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/grids.kt @@ -1,6 +1,5 @@ package kscience.kmath.real -import kscience.kmath.linear.Point import kscience.kmath.structures.asBuffer import kotlin.math.abs @@ -34,7 +33,7 @@ public fun ClosedFloatingPointRange.toSequenceWithStep(step: Double): Se } } -public infix fun ClosedFloatingPointRange.step(step: Double): Point = +public infix fun ClosedFloatingPointRange.step(step: Double): RealVector = toSequenceWithStep(step).toList().asBuffer() /** diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index b071df499..176dfc09d 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -2,14 +2,14 @@ This subproject implements the following features: - - [nd4jarraystrucure](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray + - [nd4jarraystructure](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray - [nd4jarrayrings](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long - [nd4jarrayfields](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double > #### Artifact: > -> This module artifact: `kscience.kmath:kmath-nd4j:0.2.0-dev-3`. +> This module artifact: `kscience.kmath:kmath-nd4j:0.2.0-dev-4`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-nd4j/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-nd4j/_latestVersion) > @@ -27,7 +27,7 @@ This subproject implements the following features: > } > > dependencies { -> implementation 'kscience.kmath:kmath-nd4j:0.2.0-dev-3' +> implementation 'kscience.kmath:kmath-nd4j:0.2.0-dev-4' > } > ``` > **Gradle Kotlin DSL:** @@ -41,7 +41,7 @@ This subproject implements the following features: > } > > dependencies { -> implementation("kscience.kmath:kmath-nd4j:0.2.0-dev-3") +> implementation("kscience.kmath:kmath-nd4j:0.2.0-dev-4") > } > ``` diff --git a/kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat/distributions.kt b/kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat/distributions.kt index 9a77b0bd2..6cc18a37c 100644 --- a/kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat/distributions.kt +++ b/kmath-stat/src/jvmMain/kotlin/kscience/kmath/stat/distributions.kt @@ -51,7 +51,7 @@ private fun normalSampler(method: NormalSamplerMethod, provider: UniformRandomPr public fun Distribution.Companion.normal( method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat -): Distribution = object : ContinuousSamplerDistribution() { +): ContinuousSamplerDistribution = object : ContinuousSamplerDistribution() { override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { val provider = generator.asUniformRandomProvider() return normalSampler(method, provider) @@ -60,6 +60,9 @@ public fun Distribution.Companion.normal( override fun probability(arg: Double): Double = exp(-arg.pow(2) / 2) / sqrt(PI * 2) } +/** + * A univariate normal distribution with given [mean] and [sigma]. [method] defines commons-rng generation method + */ public fun Distribution.Companion.normal( mean: Double, sigma: Double, From b10ba4c62a568573a81d8ca3410fd4fc766bd45d Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 30 Nov 2020 00:55:42 +0700 Subject: [PATCH 138/199] Update KotlinGrad --- kmath-kotlingrad/build.gradle.kts | 4 ++-- .../kscience/kmath/kotlingrad/DifferentiableMstExpression.kt | 2 +- .../src/main/kotlin/kscience/kmath/kotlingrad/KMathNumber.kt | 4 ++-- .../main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt | 2 +- .../test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index 027a03bc9..3925a744c 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -3,7 +3,7 @@ plugins { } dependencies { - implementation("com.github.breandan:kaliningraph:0.1.2") - implementation("com.github.breandan:kotlingrad:0.3.7") + implementation("com.github.breandan:kaliningraph:0.1.4") + implementation("com.github.breandan:kotlingrad:0.4.0") api(project(":kmath-ast")) } diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index dd5e46f90..abde9e54d 100644 --- a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -1,6 +1,6 @@ package kscience.kmath.kotlingrad -import edu.umontreal.kotlingrad.experimental.SFun +import edu.umontreal.kotlingrad.api.SFun import kscience.kmath.ast.MST import kscience.kmath.ast.MstAlgebra import kscience.kmath.ast.MstExpression diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/KMathNumber.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/KMathNumber.kt index ce5658137..2a4db4258 100644 --- a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/KMathNumber.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/KMathNumber.kt @@ -1,7 +1,7 @@ package kscience.kmath.kotlingrad -import edu.umontreal.kotlingrad.experimental.RealNumber -import edu.umontreal.kotlingrad.experimental.SConst +import edu.umontreal.kotlingrad.api.RealNumber +import edu.umontreal.kotlingrad.api.SConst import kscience.kmath.operations.NumericAlgebra /** diff --git a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt index b6effab4b..8dc1d3958 100644 --- a/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -1,6 +1,6 @@ package kscience.kmath.kotlingrad -import edu.umontreal.kotlingrad.experimental.* +import edu.umontreal.kotlingrad.api.* import kscience.kmath.ast.MST import kscience.kmath.ast.MstAlgebra import kscience.kmath.ast.MstExtendedField diff --git a/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt index 77902211b..aa4ddd703 100644 --- a/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -1,6 +1,6 @@ package kscience.kmath.kotlingrad -import edu.umontreal.kotlingrad.experimental.* +import edu.umontreal.kotlingrad.api.* import kscience.kmath.asm.compile import kscience.kmath.ast.MstAlgebra import kscience.kmath.ast.MstExpression From 6fb3c03e87bb272bb09de237df3bf25491fb1054 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 30 Nov 2020 01:19:27 +0700 Subject: [PATCH 139/199] Fix broken APIs in kmath-for-real --- .../kotlin/kscience/kmath/real/RealVector.kt | 10 ++++++++++ .../kotlin/kaceince/kmath/real/RealVectorTest.kt | 1 + 2 files changed, 11 insertions(+) diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt index 33684fc8c..1182d871c 100644 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt @@ -3,16 +3,26 @@ package kscience.kmath.real import kscience.kmath.linear.Point import kscience.kmath.operations.Norm import kscience.kmath.structures.Buffer +import kscience.kmath.structures.RealBuffer +import kscience.kmath.structures.asBuffer import kscience.kmath.structures.asIterable import kotlin.math.pow import kotlin.math.sqrt public typealias RealVector = Point +public inline fun RealVector(size: Int, init: (Int) -> Double): RealVector = RealBuffer(size, init) +public fun RealVector(vararg doubles: Double): RealVector = RealBuffer(doubles) + +public fun DoubleArray.asVector(): RealVector = asBuffer() +public fun List.asVector(): RealVector = asBuffer() + + public object VectorL2Norm : Norm, Double> { override fun norm(arg: Point): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble)) } + /** * Fill the vector of given [size] with given [value] */ diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt index 8a9f7a443..002db935c 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt @@ -5,6 +5,7 @@ import kscience.kmath.linear.asMatrix import kscience.kmath.linear.transpose import kscience.kmath.operations.invoke import kscience.kmath.real.RealVector +import kscience.kmath.real.plus import kotlin.test.Test import kotlin.test.assertEquals From 625e624cabacae0281313eff1c9f08baeeb5eaff Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 29 Nov 2020 21:38:12 +0300 Subject: [PATCH 140/199] kmath-for-real refactoring --- CHANGELOG.md | 2 + .../structures/MultiplicationBenchmark.kt | 51 +++++++++++++++++++ .../kmath/commons/fit/fitWithAutoDiff.kt | 1 + .../kmath/linear/LinearAlgebraBenchmark.kt | 4 +- .../kmath/linear/MultiplicationBenchmark.kt | 38 -------------- .../kscience/kmath/linear/BufferMatrix.kt | 37 +++----------- .../kscience/kmath/linear/FeaturedMatrix.kt | 7 +-- .../kscience/kmath/linear/MatrixTest.kt | 3 +- .../kscience/kmath/ejml/EjmlMatrixContext.kt | 20 ++++---- .../kotlin/kscience/kmath/real/RealMatrix.kt | 44 ++++++++++------ .../kotlin/kscience/kmath/real/RealVector.kt | 37 +++++++++----- .../kotlin/kscience/kmath/real/dot.kt | 31 +++++++++++ .../kaceince/kmath/real/RealVectorTest.kt | 15 +++--- .../kscience/kmath/histogram/RealHistogram.kt | 5 +- .../histogram/MultivariateHistogramTest.kt | 2 + .../kmath/histogram/UnivariateHistogram.kt | 4 +- 16 files changed, 172 insertions(+), 129 deletions(-) create mode 100644 examples/src/benchmarks/kotlin/kscience/kmath/structures/MultiplicationBenchmark.kt delete mode 100644 examples/src/main/kotlin/kscience/kmath/linear/MultiplicationBenchmark.kt create mode 100644 kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/dot.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 99511a161..1fd169b10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ - `kmath-prob` renamed to `kmath-stat` - Grid generators moved to `kmath-for-real` - Use `Point` instead of specialized type in `kmath-for-real` +- Optimized dot product for buffer matrices moved to `kmath-for-real` +- EjmlMatrix context is an object ### Deprecated diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/MultiplicationBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/MultiplicationBenchmark.kt new file mode 100644 index 000000000..3c2c12c0b --- /dev/null +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/MultiplicationBenchmark.kt @@ -0,0 +1,51 @@ +package kscience.kmath.structures + +import kotlinx.benchmark.Benchmark +import kscience.kmath.commons.linear.CMMatrixContext +import kscience.kmath.commons.linear.CMMatrixContext.dot +import kscience.kmath.commons.linear.toCM +import kscience.kmath.ejml.EjmlMatrixContext +import kscience.kmath.ejml.toEjml +import kscience.kmath.linear.real +import kscience.kmath.operations.RealField +import kscience.kmath.operations.invoke +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.State +import kotlin.random.Random + +@State(Scope.Benchmark) +class MultiplicationBenchmark { + companion object { + val random = Random(12224) + val dim = 1000 + + //creating invertible matrix + 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 ejmlMatrix1 = matrix1.toEjml() + val ejmlMatrix2 = matrix2.toEjml() + } + + @Benchmark + fun commonsMathMultiplication() { + CMMatrixContext.invoke { + cmMatrix1 dot cmMatrix2 + } + } + + @Benchmark + fun ejmlMultiplication() { + EjmlMatrixContext.invoke { + ejmlMatrix1 dot ejmlMatrix2 + } + } + + @Benchmark + fun bufferedMultiplication() { + matrix1 dot matrix2 + } +} \ No newline at end of file diff --git a/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt index 6cfa1961b..c0cd9dc5c 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -70,6 +70,7 @@ fun main() { //minimize the chi^2 in given starting point. Derivatives are not required, they are already included. val result: OptimizationResult = chi2.minimize(a to 1.5, b to 0.9, c to 1.0) + //display a page with plot and numerical results val page = Plotly.page { plot { scatter { diff --git a/examples/src/main/kotlin/kscience/kmath/linear/LinearAlgebraBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/linear/LinearAlgebraBenchmark.kt index 3316f3236..5b1fc9bc7 100644 --- a/examples/src/main/kotlin/kscience/kmath/linear/LinearAlgebraBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/linear/LinearAlgebraBenchmark.kt @@ -1,10 +1,12 @@ package kscience.kmath.linear 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.RealField import kscience.kmath.operations.invoke import kscience.kmath.structures.Matrix @@ -40,7 +42,7 @@ fun main() { println("[commons-math] Inversion of $n matrices $dim x $dim finished in $commonsTime millis") val ejmlTime = measureTimeMillis { - (EjmlMatrixContext(RealField)) { + EjmlMatrixContext { val km = matrix.toEjml() //avoid overhead on conversion repeat(n) { inverse(km) } } diff --git a/examples/src/main/kotlin/kscience/kmath/linear/MultiplicationBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/linear/MultiplicationBenchmark.kt deleted file mode 100644 index d1011e8f5..000000000 --- a/examples/src/main/kotlin/kscience/kmath/linear/MultiplicationBenchmark.kt +++ /dev/null @@ -1,38 +0,0 @@ -package kscience.kmath.linear - -import kscience.kmath.commons.linear.CMMatrixContext -import kscience.kmath.commons.linear.toCM -import kscience.kmath.ejml.EjmlMatrixContext -import kscience.kmath.operations.RealField -import kscience.kmath.operations.invoke -import kscience.kmath.structures.Matrix -import kotlin.random.Random -import kotlin.system.measureTimeMillis - -fun main() { - val random = Random(12224) - val dim = 1000 - //creating invertible matrix - 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 } - -// //warmup -// matrix1 dot matrix2 - - CMMatrixContext { - val cmMatrix1 = matrix1.toCM() - val cmMatrix2 = matrix2.toCM() - val cmTime = measureTimeMillis { cmMatrix1 dot cmMatrix2 } - println("CM implementation time: $cmTime") - } - - (EjmlMatrixContext(RealField)) { - val ejmlMatrix1 = matrix1.toEjml() - val ejmlMatrix2 = matrix2.toEjml() - val ejmlTime = measureTimeMillis { ejmlMatrix1 dot ejmlMatrix2 } - println("EJML implementation time: $ejmlTime") - } - - val genericTime = measureTimeMillis { val res = matrix1 dot matrix2 } - println("Generic implementation time: $genericTime") -} diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt index d51f40890..f6ed34be0 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt @@ -9,7 +9,7 @@ import kscience.kmath.structures.* */ public class BufferMatrixContext>( public override val elementContext: R, - private val bufferFactory: BufferFactory + private val bufferFactory: BufferFactory, ) : GenericMatrixContext { public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix { val buffer = bufferFactory(rows * columns) { offset -> initializer(offset / columns, offset % columns) } @@ -29,8 +29,8 @@ public object RealMatrixContext : GenericMatrixContext { public override inline fun produce( rows: Int, columns: Int, - initializer: (i: Int, j: Int) -> Double - ): Matrix { + initializer: (i: Int, j: Int) -> Double, + ): BufferMatrix { val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) } return BufferMatrix(rows, columns, buffer) } @@ -43,15 +43,15 @@ public class BufferMatrix( public override val rowNum: Int, public override val colNum: Int, public val buffer: Buffer, - public override val features: Set = emptySet() + public override val features: Set = emptySet(), ) : FeaturedMatrix { - override val shape: IntArray - get() = intArrayOf(rowNum, colNum) init { require(buffer.size == rowNum * colNum) { "Dimension mismatch for matrix structure" } } + override val shape: IntArray get() = intArrayOf(rowNum, colNum) + public override fun suggestFeature(vararg features: MatrixFeature): BufferMatrix = BufferMatrix(rowNum, colNum, buffer, this.features + features) @@ -86,28 +86,3 @@ public class BufferMatrix( else "Matrix(rowsNum = $rowNum, colNum = $colNum, features=$features)" } } - -/** - * Optimized dot product for real matrices - */ -public infix fun BufferMatrix.dot(other: BufferMatrix): BufferMatrix { - require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } - val array = DoubleArray(this.rowNum * other.colNum) - - //convert to array to insure there is not memory indirection - fun Buffer.unsafeArray() = if (this is RealBuffer) - array - else - DoubleArray(size) { get(it) } - - val a = this.buffer.unsafeArray() - val b = other.buffer.unsafeArray() - - for (i in (0 until rowNum)) - for (j in (0 until other.colNum)) - for (k in (0 until colNum)) - array[i * other.colNum + j] += a[i * colNum + k] * b[k * other.colNum + j] - - val buffer = RealBuffer(array) - return BufferMatrix(rowNum, other.colNum, buffer) -} diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt index 5d9af8608..003741979 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt @@ -27,9 +27,8 @@ public interface FeaturedMatrix : Matrix { public inline fun Structure2D.Companion.real( rows: Int, columns: Int, - initializer: (Int, Int) -> Double -): Matrix = - MatrixContext.real.produce(rows, columns, initializer) + initializer: (Int, Int) -> Double, +): BufferMatrix = MatrixContext.real.produce(rows, columns, initializer) /** * Build a square matrix from given elements. @@ -82,5 +81,3 @@ public fun Matrix.transpose(): Matrix { setOf(TransposedFeature(this)) ) { i, j -> get(j, i) } } - -public infix fun Matrix.dot(other: Matrix): Matrix = with(MatrixContext.real) { dot(other) } 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 7cfa25a66..0a582e339 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/MatrixTest.kt @@ -1,5 +1,6 @@ package kscience.kmath.linear +import kscience.kmath.operations.invoke import kscience.kmath.structures.Matrix import kscience.kmath.structures.NDStructure import kscience.kmath.structures.as2D @@ -38,7 +39,7 @@ class MatrixTest { infix fun Matrix.pow(power: Int): Matrix { var res = this repeat(power - 1) { - res = res dot this + res = RealMatrixContext.invoke { res dot this@pow } } return res } diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt index 52826a7b1..1ed57fcb3 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt @@ -7,17 +7,18 @@ import kscience.kmath.operations.Space import kscience.kmath.operations.invoke import kscience.kmath.structures.Matrix +/** + * Converts this matrix to EJML one. + */ +public fun Matrix.toEjml(): EjmlMatrix = + if (this is EjmlMatrix) this else EjmlMatrixContext.produce(rowNum, colNum) { i, j -> get(i, j) } + /** * Represents context of basic operations operating with [EjmlMatrix]. * * @author Iaroslav Postovalov */ -public class EjmlMatrixContext(private val space: Space) : MatrixContext { - /** - * Converts this matrix to EJML one. - */ - public fun Matrix.toEjml(): EjmlMatrix = - if (this is EjmlMatrix) this else produce(rowNum, colNum) { i, j -> get(i, j) } +public object EjmlMatrixContext : MatrixContext { /** * Converts this vector to EJML one. @@ -47,11 +48,10 @@ public class EjmlMatrixContext(private val space: Space) : MatrixContext EjmlMatrix(toEjml().origin - b.toEjml().origin) public override fun multiply(a: Matrix, k: Number): EjmlMatrix = - produce(a.rowNum, a.colNum) { i, j -> space { a[i, j] * k } } + produce(a.rowNum, a.colNum) { i, j -> a[i, j] * k.toDouble() } - public override operator fun Matrix.times(value: Double): EjmlMatrix = EjmlMatrix(toEjml().origin.scale(value)) - - public companion object + public override operator fun Matrix.times(value: Double): EjmlMatrix = + EjmlMatrix(toEjml().origin.scale(value)) } /** diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt index 784b27f9d..c0657c0bf 100644 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt @@ -6,10 +6,7 @@ import kscience.kmath.linear.VirtualMatrix import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.invoke import kscience.kmath.operations.sum -import kscience.kmath.structures.Buffer -import kscience.kmath.structures.Matrix -import kscience.kmath.structures.RealBuffer -import kscience.kmath.structures.asIterable +import kscience.kmath.structures.* import kotlin.math.pow /* @@ -86,18 +83,6 @@ public operator fun Double.minus(matrix: RealMatrix): RealMatrix = // row, col -> matrix[row, col] / this //} -/* - * Per-element (!) square and power operations - */ - -public fun RealMatrix.square(): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col -> - this[row, col].pow(2) -} - -public fun RealMatrix.pow(n: Int): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { i, j -> - this[i, j].pow(n) -} - /* * Operations on two matrices (per-element!) */ @@ -157,3 +142,30 @@ public fun RealMatrix.sum(): Double = elements().map { (_, value) -> value }.sum public fun RealMatrix.min(): Double? = elements().map { (_, value) -> value }.minOrNull() public fun RealMatrix.max(): Double? = elements().map { (_, value) -> value }.maxOrNull() public fun RealMatrix.average(): Double = elements().map { (_, value) -> value }.average() + +public inline fun RealMatrix.map(transform: (Double) -> Double): RealMatrix = + MatrixContext.real.produce(rowNum, colNum) { i, j -> + transform(get(i, j)) + } + +//extended operations + +public fun RealMatrix.pow(p: Double): RealMatrix = map { it.pow(p) } + +public fun RealMatrix.pow(p: Int): RealMatrix = map { it.pow(p) } + +public fun exp(arg: RealMatrix): RealMatrix = arg.map { kotlin.math.exp(it) } + +public fun sqrt(arg: RealMatrix): RealMatrix = arg.map { kotlin.math.sqrt(it) } + +public fun RealMatrix.square(): RealMatrix = map { it.pow(2) } + +public fun sin(arg: RealMatrix): RealMatrix = arg.map { kotlin.math.sin(it) } + +public fun cos(arg: RealMatrix): RealMatrix = arg.map { kotlin.math.cos(it) } + +public fun tan(arg: RealMatrix): RealMatrix = arg.map { kotlin.math.tan(it) } + +public fun ln(arg: RealMatrix): RealMatrix = arg.map { kotlin.math.ln(it) } + +public fun log10(arg: RealMatrix): RealMatrix = arg.map { kotlin.math.log10(it) } \ No newline at end of file diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt index 1182d871c..596692782 100644 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt @@ -3,7 +3,6 @@ package kscience.kmath.real import kscience.kmath.linear.Point import kscience.kmath.operations.Norm import kscience.kmath.structures.Buffer -import kscience.kmath.structures.RealBuffer import kscience.kmath.structures.asBuffer import kscience.kmath.structures.asIterable import kotlin.math.pow @@ -11,17 +10,11 @@ import kotlin.math.sqrt public typealias RealVector = Point -public inline fun RealVector(size: Int, init: (Int) -> Double): RealVector = RealBuffer(size, init) -public fun RealVector(vararg doubles: Double): RealVector = RealBuffer(doubles) - -public fun DoubleArray.asVector(): RealVector = asBuffer() -public fun List.asVector(): RealVector = asBuffer() - - public object VectorL2Norm : Norm, Double> { override fun norm(arg: Point): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble)) } +public operator fun Buffer.Companion.invoke(vararg doubles: Double): RealVector = doubles.asBuffer() /** * Fill the vector of given [size] with given [value] @@ -36,12 +29,6 @@ public inline fun RealVector.map(transform: (Double) -> Double): RealVector = public inline fun RealVector.mapIndexed(transform: (index: Int, value: Double) -> Double): RealVector = Buffer.real(size) { transform(it, get(it)) } -public fun RealVector.pow(p: Double): RealVector = map { it.pow(p) } - -public fun RealVector.pow(p: Int): RealVector = map { it.pow(p) } - -public fun exp(vector: RealVector): RealVector = vector.map { kotlin.math.exp(it) } - public operator fun RealVector.plus(other: RealVector): RealVector = mapIndexed { index, value -> value + other[index] } @@ -71,3 +58,25 @@ public operator fun RealVector.div(other: RealVector): RealVector = public operator fun RealVector.div(number: Number): RealVector = map { it / number.toDouble() } public operator fun Number.div(vector: RealVector): RealVector = vector.map { toDouble() / it } + +//extended operations + +public fun RealVector.pow(p: Double): RealVector = map { it.pow(p) } + +public fun RealVector.pow(p: Int): RealVector = map { it.pow(p) } + +public fun exp(vector: RealVector): RealVector = vector.map { kotlin.math.exp(it) } + +public fun sqrt(vector: RealVector): RealVector = vector.map { kotlin.math.sqrt(it) } + +public fun RealVector.square(): RealVector = map { it.pow(2) } + +public fun sin(vector: RealVector): RealVector = vector.map { kotlin.math.sin(it) } + +public fun cos(vector: RealVector): RealVector = vector.map { kotlin.math.cos(it) } + +public fun tan(vector: RealVector): RealVector = vector.map { kotlin.math.tan(it) } + +public fun ln(vector: RealVector): RealVector = vector.map { kotlin.math.ln(it) } + +public fun log10(vector: RealVector): RealVector = vector.map { kotlin.math.log10(it) } diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/dot.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/dot.kt new file mode 100644 index 000000000..9beffe6bb --- /dev/null +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/dot.kt @@ -0,0 +1,31 @@ +package kscience.kmath.real + +import kscience.kmath.linear.BufferMatrix +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.RealBuffer + + +/** + * Optimized dot product for real matrices + */ +public infix fun BufferMatrix.dot(other: BufferMatrix): BufferMatrix { + require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } + val resultArray = DoubleArray(this.rowNum * other.colNum) + + //convert to array to insure there is no memory indirection + fun Buffer.unsafeArray() = if (this is RealBuffer) + this.array + else + DoubleArray(size) { get(it) } + + val a = this.buffer.unsafeArray() + val b = other.buffer.unsafeArray() + + for (i in (0 until rowNum)) + for (j in (0 until other.colNum)) + for (k in (0 until colNum)) + resultArray[i * other.colNum + j] += a[i * colNum + k] * b[k * other.colNum + j] + + val buffer = RealBuffer(resultArray) + return BufferMatrix(rowNum, other.colNum, buffer) +} \ No newline at end of file diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt index 002db935c..6215ba5e8 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt @@ -1,34 +1,33 @@ package kaceince.kmath.real -import kscience.kmath.linear.MatrixContext -import kscience.kmath.linear.asMatrix -import kscience.kmath.linear.transpose +import kscience.kmath.linear.* import kscience.kmath.operations.invoke import kscience.kmath.real.RealVector import kscience.kmath.real.plus +import kscience.kmath.structures.Buffer import kotlin.test.Test import kotlin.test.assertEquals internal class RealVectorTest { @Test fun testSum() { - val vector1 = RealVector(5) { it.toDouble() } - val vector2 = RealVector(5) { 5 - it.toDouble() } + val vector1 = Buffer.real(5) { it.toDouble() } + val vector2 = Buffer.real(5) { 5 - it.toDouble() } val sum = vector1 + vector2 assertEquals(5.0, sum[2]) } @Test fun testVectorToMatrix() { - val vector = RealVector(5) { it.toDouble() } + val vector = Buffer.real(5) { it.toDouble() } val matrix = vector.asMatrix() assertEquals(4.0, matrix[4, 0]) } @Test fun testDot() { - val vector1 = RealVector(5) { it.toDouble() } - val vector2 = RealVector(5) { 5 - it.toDouble() } + val vector1 = Buffer.real(5) { it.toDouble() } + val vector2 = Buffer.real(5) { 5 - it.toDouble() } val matrix1 = vector1.asMatrix() val matrix2 = vector2.asMatrix().transpose() val product = MatrixContext.real { matrix1 dot matrix2 } diff --git a/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/RealHistogram.kt b/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/RealHistogram.kt index c58952ab4..f95264ee1 100644 --- a/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/RealHistogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/kscience/kmath/histogram/RealHistogram.kt @@ -3,7 +3,6 @@ package kscience.kmath.histogram import kscience.kmath.linear.Point import kscience.kmath.operations.SpaceOperations import kscience.kmath.operations.invoke -import kscience.kmath.real.asVector import kscience.kmath.structures.* import kotlin.math.floor @@ -123,8 +122,8 @@ public class RealHistogram( *``` */ public fun fromRanges(vararg ranges: ClosedFloatingPointRange): RealHistogram = RealHistogram( - ranges.map(ClosedFloatingPointRange::start).asVector(), - ranges.map(ClosedFloatingPointRange::endInclusive).asVector() + ranges.map(ClosedFloatingPointRange::start).asBuffer(), + ranges.map(ClosedFloatingPointRange::endInclusive).asBuffer() ) /** diff --git a/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt index eebb41019..af22afc6b 100644 --- a/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/scietifik/kmath/histogram/MultivariateHistogramTest.kt @@ -4,6 +4,8 @@ import kscience.kmath.histogram.RealHistogram import kscience.kmath.histogram.fill import kscience.kmath.histogram.put import kscience.kmath.real.RealVector +import kscience.kmath.real.invoke +import kscience.kmath.structures.Buffer import kotlin.random.Random import kotlin.test.* diff --git a/kmath-histograms/src/jvmMain/kotlin/kscience/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/kscience/kmath/histogram/UnivariateHistogram.kt index 5fada1302..2f3855892 100644 --- a/kmath-histograms/src/jvmMain/kotlin/kscience/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/kscience/kmath/histogram/UnivariateHistogram.kt @@ -1,8 +1,8 @@ package kscience.kmath.histogram import kscience.kmath.real.RealVector -import kscience.kmath.real.asVector import kscience.kmath.structures.Buffer +import kscience.kmath.structures.asBuffer import java.util.* import kotlin.math.floor @@ -16,7 +16,7 @@ public class UnivariateBin( //TODO add weighting public override val value: Number get() = counter.sum() - public override val center: RealVector get() = doubleArrayOf(position).asVector() + public override val center: RealVector get() = doubleArrayOf(position).asBuffer() public override val dimension: Int get() = 1 public operator fun contains(value: Double): Boolean = value in (position - size / 2)..(position + size / 2) From 89c0d863d2ddc7ae71f60c7b6d4b28cb30b7a660 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 29 Nov 2020 22:26:05 +0300 Subject: [PATCH 141/199] Benchmark refactoring --- examples/build.gradle.kts | 2 +- .../ArrayBenchmark.kt | 2 +- .../BufferBenchmark.kt | 4 +- .../benchmarks/LinearAlgebraBenchmark.kt | 50 ++++++++++++++++++ .../MultiplicationBenchmark.kt | 13 ++++- .../NDFieldBenchmark.kt | 3 +- .../ViktorBenchmark.kt | 7 ++- .../kotlin/kscience/kmath/utils/utils.kt | 11 ---- .../kmath/linear/LinearAlgebraBenchmark.kt | 52 ------------------- .../kscience/kmath/linear/FeaturedMatrix.kt | 2 +- 10 files changed, 74 insertions(+), 72 deletions(-) rename examples/src/benchmarks/kotlin/kscience/kmath/{structures => benchmarks}/ArrayBenchmark.kt (96%) rename examples/src/benchmarks/kotlin/kscience/kmath/{structures => benchmarks}/BufferBenchmark.kt (85%) create mode 100644 examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt rename examples/src/benchmarks/kotlin/kscience/kmath/{structures => benchmarks}/MultiplicationBenchmark.kt (81%) rename examples/src/benchmarks/kotlin/kscience/kmath/{structures => benchmarks}/NDFieldBenchmark.kt (94%) rename examples/src/benchmarks/kotlin/kscience/kmath/{structures => benchmarks}/ViktorBenchmark.kt (86%) delete mode 100644 examples/src/benchmarks/kotlin/kscience/kmath/utils/utils.kt delete mode 100644 examples/src/main/kotlin/kscience/kmath/linear/LinearAlgebraBenchmark.kt diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index eead68a9d..c079eaa84 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -69,7 +69,7 @@ benchmark { // This one matches sourceSet name above configurations.register("fast") { - warmups = 5 // number of warmup iterations + 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 diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/ArrayBenchmark.kt similarity index 96% rename from examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/ArrayBenchmark.kt index a91d02253..8c44135fb 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/ArrayBenchmark.kt @@ -1,4 +1,4 @@ -package kscience.kmath.structures +package kscience.kmath.benchmarks import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/BufferBenchmark.kt similarity index 85% rename from examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/BufferBenchmark.kt index 8b6fd4a51..4c64517f1 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/BufferBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/BufferBenchmark.kt @@ -1,7 +1,9 @@ -package kscience.kmath.structures +package kscience.kmath.benchmarks import kscience.kmath.operations.Complex import kscience.kmath.operations.complex +import kscience.kmath.structures.MutableBuffer +import kscience.kmath.structures.RealBuffer import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt new file mode 100644 index 000000000..0ac6ea5f0 --- /dev/null +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt @@ -0,0 +1,50 @@ +package kscience.kmath.linear + + +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 +import org.openjdk.jmh.annotations.State +import kotlin.random.Random + +@State(Scope.Benchmark) +class LinearAlgebraBenchmark { + companion object { + val random = Random(1224) + val dim = 100 + + //creating invertible matrix + val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } + val l = Matrix.real(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 } + val matrix = l dot u + } + + @Benchmark + fun kmathLUPInversion() { + MatrixContext.real.inverse(matrix) + } + + @Benchmark + fun cmLUPInversion() { + CMMatrixContext { + val cm = matrix.toCM() //avoid overhead on conversion + inverse(cm) + } + } + + @Benchmark + fun ejmlInverse() { + EjmlMatrixContext { + val km = matrix.toEjml() //avoid overhead on conversion + inverse(km) + } + } +} \ No newline at end of file diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/MultiplicationBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/MultiplicationBenchmark.kt similarity index 81% rename from examples/src/benchmarks/kotlin/kscience/kmath/structures/MultiplicationBenchmark.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/MultiplicationBenchmark.kt index 3c2c12c0b..9d2b02245 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/MultiplicationBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/MultiplicationBenchmark.kt @@ -1,4 +1,4 @@ -package kscience.kmath.structures +package kscience.kmath.benchmarks import kotlinx.benchmark.Benchmark import kscience.kmath.commons.linear.CMMatrixContext @@ -7,8 +7,8 @@ import kscience.kmath.commons.linear.toCM import kscience.kmath.ejml.EjmlMatrixContext import kscience.kmath.ejml.toEjml import kscience.kmath.linear.real -import kscience.kmath.operations.RealField import kscience.kmath.operations.invoke +import kscience.kmath.structures.Matrix import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State import kotlin.random.Random @@ -44,6 +44,15 @@ class MultiplicationBenchmark { } } + @Benchmark + fun ejmlMultiplicationwithConversion() { + val ejmlMatrix1 = matrix1.toEjml() + val ejmlMatrix2 = matrix2.toEjml() + EjmlMatrixContext.invoke { + ejmlMatrix1 dot ejmlMatrix2 + } + } + @Benchmark fun bufferedMultiplication() { matrix1 dot matrix2 diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/NDFieldBenchmark.kt similarity index 94% rename from examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/NDFieldBenchmark.kt index 8ec47ae81..1be8e7236 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/NDFieldBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -1,7 +1,8 @@ -package kscience.kmath.structures +package kscience.kmath.benchmarks import kscience.kmath.operations.RealField import kscience.kmath.operations.invoke +import kscience.kmath.structures.* import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/ViktorBenchmark.kt similarity index 86% rename from examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/ViktorBenchmark.kt index 464925ca0..8663e353c 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/ViktorBenchmark.kt @@ -1,7 +1,10 @@ -package kscience.kmath.structures +package kscience.kmath.benchmarks import kscience.kmath.operations.RealField import kscience.kmath.operations.invoke +import kscience.kmath.structures.BufferedNDField +import kscience.kmath.structures.NDField +import kscience.kmath.structures.RealNDField import kscience.kmath.viktor.ViktorNDField import org.jetbrains.bio.viktor.F64Array import org.openjdk.jmh.annotations.Benchmark @@ -36,7 +39,7 @@ internal class ViktorBenchmark { @Benchmark fun rawViktor() { - val one = F64Array.full(init = 1.0, shape = *intArrayOf(dim, dim)) + val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim)) var res = one repeat(n) { res = res + one } } diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/utils/utils.kt b/examples/src/benchmarks/kotlin/kscience/kmath/utils/utils.kt deleted file mode 100644 index 329b7b17b..000000000 --- a/examples/src/benchmarks/kotlin/kscience/kmath/utils/utils.kt +++ /dev/null @@ -1,11 +0,0 @@ -package kscience.kmath.utils - -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.system.measureTimeMillis - -internal inline fun measureAndPrint(title: String, block: () -> Unit) { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - val time = measureTimeMillis(block) - println("$title completed in $time millis") -} diff --git a/examples/src/main/kotlin/kscience/kmath/linear/LinearAlgebraBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/linear/LinearAlgebraBenchmark.kt deleted file mode 100644 index 5b1fc9bc7..000000000 --- a/examples/src/main/kotlin/kscience/kmath/linear/LinearAlgebraBenchmark.kt +++ /dev/null @@ -1,52 +0,0 @@ -package kscience.kmath.linear - -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.RealField -import kscience.kmath.operations.invoke -import kscience.kmath.structures.Matrix -import kotlin.random.Random -import kotlin.system.measureTimeMillis - -fun main() { - val random = Random(1224) - val dim = 100 - //creating invertible matrix - val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } - val l = Matrix.real(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 } - val matrix = l dot u - - val n = 5000 // iterations - - MatrixContext.real { - repeat(50) { inverse(matrix) } - val inverseTime = measureTimeMillis { repeat(n) { inverse(matrix) } } - println("[kmath] Inversion of $n matrices $dim x $dim finished in $inverseTime millis") - } - - //commons-math - - val commonsTime = measureTimeMillis { - CMMatrixContext { - val cm = matrix.toCM() //avoid overhead on conversion - repeat(n) { inverse(cm) } - } - } - - - println("[commons-math] Inversion of $n matrices $dim x $dim finished in $commonsTime millis") - - val ejmlTime = measureTimeMillis { - EjmlMatrixContext { - val km = matrix.toEjml() //avoid overhead on conversion - repeat(n) { inverse(km) } - } - } - - println("[ejml] Inversion of $n matrices $dim x $dim finished in $ejmlTime millis") -} diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt index 003741979..350379717 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt @@ -80,4 +80,4 @@ public fun Matrix.transpose(): Matrix { rowNum, setOf(TransposedFeature(this)) ) { i, j -> get(j, i) } -} +} \ No newline at end of file From 5368bb5d4a19363d4448e9f985ae04a1e15a799a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 30 Nov 2020 11:25:21 +0300 Subject: [PATCH 142/199] Readme update --- kmath-ast/build.gradle.kts | 4 ++++ kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt | 4 +--- kmath-core/build.gradle.kts | 4 +--- kmath-dimensions/build.gradle.kts | 4 ++++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 2f95d427d..3e3c0475f 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -17,3 +17,7 @@ kotlin.sourceSets { } } } + +readme{ + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE +} \ No newline at end of file diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt index 94cd3b321..79cf77a6a 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt @@ -83,11 +83,10 @@ public object ArithmeticsEvaluator : Grammar() { } /** - * Tries to parse the string into [MST]. + * Tries to parse the string into [MST]. Returns [ParseResult] representing expression or error. * * @receiver the string to parse. * @return the [MST] node. - * @author Alexander Nozik */ public fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryParseToEnd(this) @@ -96,6 +95,5 @@ public fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryPar * * @receiver the string to parse. * @return the [MST] node. - * @author Alexander Nozik */ public fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this) diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 7f889d9b4..9ed7e690b 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,5 +1,3 @@ -import ru.mipt.npm.gradle.Maturity - plugins { id("ru.mipt.npm.mpp") id("ru.mipt.npm.native") @@ -13,7 +11,7 @@ kotlin.sourceSets.commonMain { 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-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index 412d7162f..9bf89fc43 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -18,3 +18,7 @@ kotlin.sourceSets { } } } + +readme{ + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE +} From 712df041704cf6194610eb76009aa028c93dc331 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 1 Dec 2020 21:21:56 +0300 Subject: [PATCH 143/199] Implemented #131 --- CHANGELOG.md | 7 +- .../benchmarks/LinearAlgebraBenchmark.kt | 2 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 7 +- .../kscience/kmath/linear/BufferMatrix.kt | 4 +- .../kscience/kmath/linear/FeaturedMatrix.kt | 4 +- .../kscience/kmath/linear/LUPDecomposition.kt | 86 ++++++++++--------- .../kscience/kmath/linear/MatrixContext.kt | 37 ++++---- .../kmath/operations/AlgebraExtensions.kt | 5 ++ .../kmath/structures/BufferAccessor2D.kt | 22 +++-- .../kscience/kmath/linear/RealLUSolverTest.kt | 4 +- .../kscience/kmath/dimensions/Wrappers.kt | 4 +- .../kscience/kmath/ejml/EjmlMatrixContext.kt | 6 +- .../kotlin/kscience/kmath/real/RealMatrix.kt | 13 ++- 13 files changed, 112 insertions(+), 89 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fd169b10..e542d210c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,13 +16,14 @@ - ND4J support module submitting `NDStructure` and `NDAlgebra` over `INDArray`. - Coroutine-deterministic Monte-Carlo scope with a random number generator. - Some minor utilities to `kmath-for-real`. +- Generic operation result parameter to `MatrixContext` ### Changed - Package changed from `scientifik` to `kscience.kmath`. -- Gradle version: 6.6 -> 6.7 +- Gradle version: 6.6 -> 6.7.1 - Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`) - `Polynomial` secondary constructor made function. -- Kotlin version: 1.3.72 -> 1.4.20-M1 +- Kotlin version: 1.3.72 -> 1.4.20 - `kmath-ast` doesn't depend on heavy `kotlin-reflect` library. - Full autodiff refactoring based on `Symbol` - `kmath-prob` renamed to `kmath-stat` @@ -30,6 +31,7 @@ - Use `Point` instead of specialized type in `kmath-for-real` - Optimized dot product for buffer matrices moved to `kmath-for-real` - EjmlMatrix context is an object +- Matrix LUP `inverse` renamed to `inverseWithLUP` ### Deprecated @@ -37,6 +39,7 @@ - `kmath-koma` module because it doesn't support Kotlin 1.4. - Support of `legacy` JS backend (we will support only IR) - `toGrid` method. +- Public visibility of `BufferAccessor2D` ### Fixed - `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt index 0ac6ea5f0..ec8714617 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt @@ -29,7 +29,7 @@ class LinearAlgebraBenchmark { @Benchmark fun kmathLUPInversion() { - MatrixContext.real.inverse(matrix) + MatrixContext.real.inverseWithLUP(matrix) } @Benchmark diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt index 377d167bc..712927400 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt @@ -5,8 +5,7 @@ import kscience.kmath.structures.Matrix import kscience.kmath.structures.NDStructure import org.apache.commons.math3.linear.* -public class CMMatrix(public val origin: RealMatrix, features: Set? = null) : - FeaturedMatrix { +public class CMMatrix(public val origin: RealMatrix, features: Set? = null) : FeaturedMatrix { public override val rowNum: Int get() = origin.rowDimension public override val colNum: Int get() = origin.columnDimension @@ -55,7 +54,7 @@ public fun Point.toCM(): CMVector = if (this is CMVector) this else { public fun RealVector.toPoint(): CMVector = CMVector(this) -public object CMMatrixContext : MatrixContext { +public object CMMatrixContext : MatrixContext { public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): CMMatrix { val array = Array(rows) { i -> DoubleArray(columns) { j -> initializer(i, j) } } return CMMatrix(Array2DRowRealMatrix(array)) @@ -79,7 +78,7 @@ public object CMMatrixContext : MatrixContext { public override fun multiply(a: Matrix, k: Number): CMMatrix = CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble())) - public override operator fun Matrix.times(value: Double): Matrix = + public override operator fun Matrix.times(value: Double): CMMatrix = produce(rowNum, colNum) { i, j -> get(i, j) * value } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt index f6ed34be0..8b50bbe33 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt @@ -10,7 +10,7 @@ import kscience.kmath.structures.* public class BufferMatrixContext>( public override val elementContext: R, private val bufferFactory: BufferFactory, -) : GenericMatrixContext { +) : GenericMatrixContext> { public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix { val buffer = bufferFactory(rows * columns) { offset -> initializer(offset / columns, offset % columns) } return BufferMatrix(rows, columns, buffer) @@ -22,7 +22,7 @@ public class BufferMatrixContext>( } @Suppress("OVERRIDE_BY_INLINE") -public object RealMatrixContext : GenericMatrixContext { +public object RealMatrixContext : GenericMatrixContext> { public override val elementContext: RealField get() = RealField diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt index 350379717..68272203c 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt @@ -57,7 +57,7 @@ public inline fun Matrix<*>.getFeature(): T? = /** * Diagonal matrix of ones. The matrix is virtual no actual matrix is created */ -public fun > GenericMatrixContext.one(rows: Int, columns: Int): FeaturedMatrix = +public fun > GenericMatrixContext.one(rows: Int, columns: Int): FeaturedMatrix = VirtualMatrix(rows, columns, DiagonalFeature) { i, j -> if (i == j) elementContext.one else elementContext.zero } @@ -66,7 +66,7 @@ public fun > GenericMatrixContext.one(rows: Int, colu /** * A virtual matrix of zeroes */ -public fun > GenericMatrixContext.zero(rows: Int, columns: Int): FeaturedMatrix = +public fun > GenericMatrixContext.zero(rows: Int, columns: Int): FeaturedMatrix = VirtualMatrix(rows, columns) { _, _ -> elementContext.zero } public class TransposedFeature(public val original: Matrix) : MatrixFeature 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 bb80bcafd..099fa1909 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt @@ -1,25 +1,18 @@ package kscience.kmath.linear -import kscience.kmath.operations.Field -import kscience.kmath.operations.RealField -import kscience.kmath.operations.Ring -import kscience.kmath.operations.invoke -import kscience.kmath.structures.BufferAccessor2D -import kscience.kmath.structures.Matrix -import kscience.kmath.structures.Structure2D -import kotlin.reflect.KClass +import kscience.kmath.operations.* +import kscience.kmath.structures.* /** * Common implementation of [LUPDecompositionFeature] */ public class LUPDecomposition( - public val context: GenericMatrixContext>, + public val context: MatrixContext>, + public val elementContext: Field, public val lu: Structure2D, public val pivot: IntArray, - private val even: Boolean + private val even: Boolean, ) : LUPDecompositionFeature, DeterminantFeature { - public val elementContext: Field - get() = context.elementContext /** * Returns the matrix L of the decomposition. @@ -64,23 +57,25 @@ public class LUPDecomposition( } -public fun , F : Field> GenericMatrixContext.abs(value: T): T = +@PublishedApi +internal fun , F : Field> GenericMatrixContext.abs(value: T): T = if (value > elementContext.zero) value else elementContext { -value } /** - * Create a lup decomposition of generic matrix + * Create a lup decomposition of generic matrix. */ -public inline fun , F : Field> GenericMatrixContext.lup( - type: KClass, +public fun > MatrixContext>.lup( + factory: MutableBufferFactory, + elementContext: Field, matrix: Matrix, - checkSingular: (T) -> Boolean + checkSingular: (T) -> Boolean, ): LUPDecomposition { require(matrix.rowNum == matrix.colNum) { "LU decomposition supports only square matrices" } val m = matrix.colNum val pivot = IntArray(matrix.rowNum) //TODO just waits for KEEP-176 - BufferAccessor2D(type, matrix.rowNum, matrix.colNum).run { + BufferAccessor2D(matrix.rowNum, matrix.colNum, factory).run { elementContext { val lu = create(matrix) @@ -112,14 +107,14 @@ public inline fun , F : Field> GenericMatrixContext.l luRow[col] = sum // maintain best permutation choice - if (this@lup.abs(sum) > largest) { - largest = this@lup.abs(sum) + if (abs(sum) > largest) { + largest = abs(sum) max = row } } // Singularity check - check(!checkSingular(this@lup.abs(lu[max, col]))) { "The matrix is singular" } + check(!checkSingular(abs(lu[max, col]))) { "The matrix is singular" } // Pivot if necessary if (max != col) { @@ -143,23 +138,23 @@ public inline fun , F : Field> GenericMatrixContext.l for (row in col + 1 until m) lu[row, col] /= luDiag } - return LUPDecomposition(this@lup, lu.collect(), pivot, even) + return LUPDecomposition(this@lup, elementContext, lu.collect(), pivot, even) } } } -public inline fun , F : Field> GenericMatrixContext.lup( +public inline fun , F : Field> GenericMatrixContext>.lup( matrix: Matrix, - checkSingular: (T) -> Boolean -): LUPDecomposition = lup(T::class, matrix, checkSingular) + noinline checkSingular: (T) -> Boolean, +): LUPDecomposition = lup(MutableBuffer.Companion::auto, elementContext, matrix, checkSingular) -public fun GenericMatrixContext.lup(matrix: Matrix): LUPDecomposition = - lup(Double::class, matrix) { it < 1e-11 } +public fun MatrixContext>.lup(matrix: Matrix): LUPDecomposition = + lup(Buffer.Companion::real, RealField, matrix) { it < 1e-11 } -public fun LUPDecomposition.solve(type: KClass, matrix: Matrix): Matrix { +public fun LUPDecomposition.solveWithLUP(factory: MutableBufferFactory, matrix: Matrix): FeaturedMatrix { require(matrix.rowNum == pivot.size) { "Matrix dimension mismatch. Expected ${pivot.size}, but got ${matrix.colNum}" } - BufferAccessor2D(type, matrix.rowNum, matrix.colNum).run { + BufferAccessor2D(matrix.rowNum, matrix.colNum, factory).run { elementContext { // Apply permutations to b val bp = create { _, _ -> zero } @@ -201,27 +196,34 @@ public fun LUPDecomposition.solve(type: KClass, matrix: Matrix LUPDecomposition.solve(matrix: Matrix): Matrix = solve(T::class, matrix) +public inline fun LUPDecomposition.solveWithLUP(matrix: Matrix): Matrix = + solveWithLUP(MutableBuffer.Companion::auto, matrix) /** - * Solve a linear equation **a*x = b** + * Solve a linear equation **a*x = b** using LUP decomposition */ -public inline fun , F : Field> GenericMatrixContext.solve( +public inline fun , F : Field> GenericMatrixContext>.solveWithLUP( a: Matrix, b: Matrix, - checkSingular: (T) -> Boolean -): Matrix { + noinline bufferFactory: MutableBufferFactory = MutableBuffer.Companion::auto, + noinline checkSingular: (T) -> Boolean, +): FeaturedMatrix { // Use existing decomposition if it is provided by matrix - val decomposition = a.getFeature() ?: lup(T::class, a, checkSingular) - return decomposition.solve(T::class, b) + val decomposition = a.getFeature() ?: lup(bufferFactory, elementContext, a, checkSingular) + return decomposition.solveWithLUP(bufferFactory, b) } -public fun RealMatrixContext.solve(a: Matrix, b: Matrix): Matrix = solve(a, b) { it < 1e-11 } +public fun RealMatrixContext.solveWithLUP(a: Matrix, b: Matrix): FeaturedMatrix = + solveWithLUP(a, b) { it < 1e-11 } -public inline fun , F : Field> GenericMatrixContext.inverse( +public inline fun , F : Field> GenericMatrixContext>.inverseWithLUP( matrix: Matrix, - checkSingular: (T) -> Boolean -): Matrix = solve(matrix, one(matrix.rowNum, matrix.colNum), checkSingular) + noinline bufferFactory: MutableBufferFactory = MutableBuffer.Companion::auto, + noinline checkSingular: (T) -> Boolean, +): FeaturedMatrix = solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum), bufferFactory, checkSingular) -public fun RealMatrixContext.inverse(matrix: Matrix): Matrix = - solve(matrix, one(matrix.rowNum, matrix.colNum)) { it < 1e-11 } +/** + * Inverses a square matrix using LUP decomposition. Non square matrix will throw a error. + */ +public fun RealMatrixContext.inverseWithLUP(matrix: Matrix): FeaturedMatrix = + solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum), Buffer.Companion::real) { it < 1e-11 } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt index f4dbce89a..d9dc57b0f 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt @@ -12,15 +12,16 @@ import kscience.kmath.structures.asSequence /** * Basic operations on matrices. Operates on [Matrix] */ -public interface MatrixContext : SpaceOperations> { +public interface MatrixContext> : SpaceOperations> { /** * Produce a matrix with this context and given dimensions */ - public fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): Matrix + public fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): M - public override fun binaryOperation(operation: String, left: Matrix, right: Matrix): Matrix = when (operation) { + @Suppress("UNCHECKED_CAST") + public override fun binaryOperation(operation: String, left: Matrix, right: Matrix): M = when (operation) { "dot" -> left dot right - else -> super.binaryOperation(operation, left, right) + else -> super.binaryOperation(operation, left, right) as M } /** @@ -30,7 +31,7 @@ public interface MatrixContext : SpaceOperations> { * @param other the multiplier. * @return the dot product. */ - public infix fun Matrix.dot(other: Matrix): Matrix + public infix fun Matrix.dot(other: Matrix): M /** * Computes the dot product of this matrix and a vector. @@ -48,7 +49,7 @@ public interface MatrixContext : SpaceOperations> { * @param value the multiplier. * @receiver the product. */ - public operator fun Matrix.times(value: T): Matrix + public operator fun Matrix.times(value: T): M /** * Multiplies an element by a matrix of it. @@ -57,7 +58,7 @@ public interface MatrixContext : SpaceOperations> { * @param value the multiplier. * @receiver the product. */ - public operator fun T.times(m: Matrix): Matrix = m * this + public operator fun T.times(m: Matrix): M = m * this public companion object { /** @@ -70,18 +71,18 @@ public interface MatrixContext : SpaceOperations> { */ public fun > buffered( ring: R, - bufferFactory: BufferFactory = Buffer.Companion::boxing - ): GenericMatrixContext = BufferMatrixContext(ring, bufferFactory) + bufferFactory: BufferFactory = Buffer.Companion::boxing, + ): GenericMatrixContext> = BufferMatrixContext(ring, bufferFactory) /** * Automatic buffered matrix, unboxed if it is possible */ - public inline fun > auto(ring: R): GenericMatrixContext = + public inline fun > auto(ring: R): GenericMatrixContext> = buffered(ring, Buffer.Companion::auto) } } -public interface GenericMatrixContext> : MatrixContext { +public interface GenericMatrixContext, out M : Matrix> : MatrixContext { /** * The ring context for matrix elements */ @@ -92,7 +93,7 @@ public interface GenericMatrixContext> : MatrixContext { */ public fun point(size: Int, initializer: (Int) -> T): Point - public override infix fun Matrix.dot(other: Matrix): Matrix { + public override infix fun Matrix.dot(other: Matrix): M { //TODO add typed error require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } @@ -113,10 +114,10 @@ public interface GenericMatrixContext> : MatrixContext { } } - public override operator fun Matrix.unaryMinus(): Matrix = + public override operator fun Matrix.unaryMinus(): M = produce(rowNum, colNum) { i, j -> elementContext { -get(i, j) } } - public override fun add(a: Matrix, b: Matrix): Matrix { + public override fun add(a: Matrix, b: Matrix): M { require(a.rowNum == b.rowNum && a.colNum == b.colNum) { "Matrix operation dimension mismatch. [${a.rowNum},${a.colNum}] + [${b.rowNum},${b.colNum}]" } @@ -124,7 +125,7 @@ public interface GenericMatrixContext> : MatrixContext { return produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] + b[i, j] } } } - public override operator fun Matrix.minus(b: Matrix): Matrix { + public override operator fun Matrix.minus(b: Matrix): M { require(rowNum == b.rowNum && colNum == b.colNum) { "Matrix operation dimension mismatch. [$rowNum,$colNum] - [${b.rowNum},${b.colNum}]" } @@ -132,11 +133,11 @@ public interface GenericMatrixContext> : MatrixContext { return produce(rowNum, colNum) { i, j -> elementContext { get(i, j) + b[i, j] } } } - public override fun multiply(a: Matrix, k: Number): Matrix = + public override fun multiply(a: Matrix, k: Number): M = produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } } - public operator fun Number.times(matrix: FeaturedMatrix): Matrix = matrix * this + public operator fun Number.times(matrix: FeaturedMatrix): M = multiply(matrix, this) - public override operator fun Matrix.times(value: T): Matrix = + public override operator fun Matrix.times(value: T): M = produce(rowNum, colNum) { i, j -> elementContext { get(i, j) * value } } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/AlgebraExtensions.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/AlgebraExtensions.kt index 657da6b4e..4527a2a42 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/AlgebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/AlgebraExtensions.kt @@ -38,6 +38,11 @@ public fun Space.average(data: Iterable): T = sum(data) / data.count() */ public fun Space.average(data: Sequence): T = sum(data) / data.count() +/** + * Absolute of the comparable [value] + */ +public fun > Space.abs(value: T): T = if (value > zero) value else -value + /** * Returns the sum of all elements in the iterable in provided space. * diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferAccessor2D.kt index 00fc4aef0..5d7ba611f 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/BufferAccessor2D.kt @@ -1,25 +1,31 @@ package kscience.kmath.structures -import kotlin.reflect.KClass - /** * A context that allows to operate on a [MutableBuffer] as on 2d array */ -public class BufferAccessor2D(public val type: KClass, public val rowNum: Int, public val colNum: Int) { +internal class BufferAccessor2D( + public val rowNum: Int, + public val colNum: Int, + val factory: MutableBufferFactory, +) { public operator fun Buffer.get(i: Int, j: Int): T = get(i + colNum * j) public operator fun MutableBuffer.set(i: Int, j: Int, value: T) { set(i + colNum * j, value) } - public inline fun create(init: (i: Int, j: Int) -> T): MutableBuffer = - MutableBuffer.auto(type, rowNum * colNum) { offset -> init(offset / colNum, offset % colNum) } + public inline fun create(crossinline init: (i: Int, j: Int) -> T): MutableBuffer = + factory(rowNum * colNum) { offset -> init(offset / colNum, offset % colNum) } public fun create(mat: Structure2D): MutableBuffer = create { i, j -> mat[i, j] } //TODO optimize wrapper - public fun MutableBuffer.collect(): Structure2D = - NDStructure.auto(type, rowNum, colNum) { (i, j) -> get(i, j) }.as2D() + public fun MutableBuffer.collect(): Structure2D = NDStructure.build( + DefaultStrides(intArrayOf(rowNum, colNum)), + factory + ) { (i, j) -> + get(i, j) + }.as2D() public inner class Row(public val buffer: MutableBuffer, public val rowIndex: Int) : MutableBuffer { override val size: Int get() = colNum @@ -30,7 +36,7 @@ public class BufferAccessor2D(public val type: KClass, public val ro buffer[rowIndex, index] = value } - override fun copy(): MutableBuffer = MutableBuffer.auto(type, colNum) { get(it) } + override fun copy(): MutableBuffer = factory(colNum) { get(it) } override operator fun iterator(): Iterator = (0 until colNum).map(::get).iterator() } diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/RealLUSolverTest.kt index de07d3639..28dfe46ec 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/linear/RealLUSolverTest.kt @@ -9,7 +9,7 @@ class RealLUSolverTest { @Test fun testInvertOne() { val matrix = MatrixContext.real.one(2, 2) - val inverted = MatrixContext.real.inverse(matrix) + val inverted = MatrixContext.real.inverseWithLUP(matrix) assertEquals(matrix, inverted) } @@ -37,7 +37,7 @@ class RealLUSolverTest { 1.0, 3.0 ) - val inverted = MatrixContext.real.inverse(matrix) + val inverted = MatrixContext.real.inverseWithLUP(matrix) val expected = Matrix.square( 0.375, -0.125, diff --git a/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt index 4111cb78d..68a5dc262 100644 --- a/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt @@ -42,7 +42,7 @@ public interface DMatrix : Structure2D { * An inline wrapper for a Matrix */ public inline class DMatrixWrapper( - public val structure: Structure2D + private val structure: Structure2D ) : DMatrix { override val shape: IntArray get() = structure.shape override operator fun get(i: Int, j: Int): T = structure[i, j] @@ -81,7 +81,7 @@ public inline class DPointWrapper(public val point: Point) /** * Basic operations on dimension-safe matrices. Operates on [Matrix] */ -public inline class DMatrixContext>(public val context: GenericMatrixContext) { +public inline class DMatrixContext>(public val context: GenericMatrixContext>) { public inline fun Matrix.coerce(): DMatrix { require(rowNum == Dimension.dim().toInt()) { "Row number mismatch: expected ${Dimension.dim()} but found $rowNum" diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt index 1ed57fcb3..31792e39c 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt @@ -1,11 +1,9 @@ package kscience.kmath.ejml -import org.ejml.simple.SimpleMatrix import kscience.kmath.linear.MatrixContext import kscience.kmath.linear.Point -import kscience.kmath.operations.Space -import kscience.kmath.operations.invoke import kscience.kmath.structures.Matrix +import org.ejml.simple.SimpleMatrix /** * Converts this matrix to EJML one. @@ -18,7 +16,7 @@ public fun Matrix.toEjml(): EjmlMatrix = * * @author Iaroslav Postovalov */ -public object EjmlMatrixContext : MatrixContext { +public object EjmlMatrixContext : MatrixContext { /** * Converts this vector to EJML one. diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt index c0657c0bf..e8ad835e5 100644 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt @@ -1,12 +1,16 @@ package kscience.kmath.real +import kscience.kmath.linear.FeaturedMatrix import kscience.kmath.linear.MatrixContext import kscience.kmath.linear.RealMatrixContext.elementContext import kscience.kmath.linear.VirtualMatrix +import kscience.kmath.linear.inverseWithLUP import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.invoke import kscience.kmath.operations.sum -import kscience.kmath.structures.* +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.RealBuffer +import kscience.kmath.structures.asIterable import kotlin.math.pow /* @@ -21,7 +25,7 @@ import kotlin.math.pow * Functions that help create a real (Double) matrix */ -public typealias RealMatrix = Matrix +public typealias RealMatrix = FeaturedMatrix public fun realMatrix(rowNum: Int, colNum: Int, initializer: (i: Int, j: Int) -> Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum, initializer) @@ -148,6 +152,11 @@ public inline fun RealMatrix.map(transform: (Double) -> Double): RealMatrix = transform(get(i, j)) } +/** + * Inverse a square real matrix using LUP decomposition + */ +public fun RealMatrix.inverseWithLUP(): RealMatrix = MatrixContext.real.inverseWithLUP(this) + //extended operations public fun RealMatrix.pow(p: Double): RealMatrix = map { it.pow(p) } From 1064a2494052d3f210979127f77706aa81845bdf Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 7 Dec 2020 04:28:54 +0700 Subject: [PATCH 144/199] Make gradle GA run cross-platform --- .github/workflows/gradle.yml | 103 +++++++++++++++++++++++++++++++---- 1 file changed, 92 insertions(+), 11 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index adc74adfe..d66d68ad5 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,17 +1,98 @@ name: Gradle build -on: [push] +on: [ push ] jobs: - build: - - runs-on: ubuntu-latest + build-ubuntu: + runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v1 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - name: Build with Gradle - run: ./gradlew build + - uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Install Chrome + run: | + sudo apt install -y libappindicator1 fonts-liberation + wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb + sudo dpkg -i google-chrome*.deb + - name: Cache gradle + uses: actions/cache@v2 + with: + path: | + **/.gradle + **/build + key: gradle_6_6_1 + restore-keys: gradle_6_6_1 + + - name: Cache konan + uses: actions/cache@v2 + with: + path: | + ~/.konan/dependencies + ~/.konan/kotlin-native-prebuilt-linux-1.4.20 + key: ${{ runner.os }}-konan-1.4.20 + restore-keys: ${{ runner.os }}-konan-1.4.20 + - name: Build with Gradle + run: ./gradlew -Dorg.gradle.daemon=false --build-cache build + + build-osx: + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Cache gradle + uses: actions/cache@v2 + with: + path: | + **/.gradle + **/build + key: gradle_6_6_1 + restore-keys: gradle_6_6_1 + + - name: Cache konan + uses: actions/cache@v2 + with: + path: | + ~/.konan/dependencies + ~/.konan/kotlin-native-prebuilt-macos-1.4.20 + key: ${{ runner.os }}-konan-1.4.20 + restore-keys: ${{ runner.os }}-konan-1.4.20 + - name: Build with Gradle + run: sudo ./gradlew -Dorg.gradle.daemon=false --build-cache build + + build-windows: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Add msys to path + run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" + - name: Cache gradle + uses: actions/cache@v2 + with: + path: | + **/.gradle + **/build + key: gradle_6_6_1 + restore-keys: gradle_6_6_1 + + - name: Cache konan + uses: actions/cache@v2 + with: + path: | + ~/.konan/dependencies + ~/.konan/kotlin-native-prebuilt-mingw-1.4.20 + key: ${{ runner.os }}-konan-1.4.20 + restore-keys: ${{ runner.os }}-konan-1.4.20 + - name: Build with Gradle + run: ./gradlew --build-cache build From 8603149d4b6b045f46c4a06f6dc58389cac1f722 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 7 Dec 2020 14:01:46 +0700 Subject: [PATCH 145/199] Update gradle.yml --- .github/workflows/gradle.yml | 45 +++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index d66d68ad5..cb1952bc8 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -21,19 +21,20 @@ jobs: uses: actions/cache@v2 with: path: | - **/.gradle - **/build - key: gradle_6_6_1 - restore-keys: gradle_6_6_1 + .gradle + build + ~/.gradle + key: gradle + restore-keys: gradle - name: Cache konan uses: actions/cache@v2 with: path: | ~/.konan/dependencies - ~/.konan/kotlin-native-prebuilt-linux-1.4.20 - key: ${{ runner.os }}-konan-1.4.20 - restore-keys: ${{ runner.os }}-konan-1.4.20 + ~/.konan/kotlin-native-prebuilt-linux-* + key: ${{ runner.os }}-konan + restore-keys: ${{ runner.os }}-konan - name: Build with Gradle run: ./gradlew -Dorg.gradle.daemon=false --build-cache build @@ -50,19 +51,20 @@ jobs: uses: actions/cache@v2 with: path: | - **/.gradle - **/build - key: gradle_6_6_1 - restore-keys: gradle_6_6_1 + .gradle + build + ~/.gradle + key: gradle + restore-keys: gradle - name: Cache konan uses: actions/cache@v2 with: path: | ~/.konan/dependencies - ~/.konan/kotlin-native-prebuilt-macos-1.4.20 - key: ${{ runner.os }}-konan-1.4.20 - restore-keys: ${{ runner.os }}-konan-1.4.20 + ~/.konan/kotlin-native-prebuilt-macos-* + key: ${{ runner.os }}-konan + restore-keys: ${{ runner.os }}-konan - name: Build with Gradle run: sudo ./gradlew -Dorg.gradle.daemon=false --build-cache build @@ -81,18 +83,19 @@ jobs: uses: actions/cache@v2 with: path: | - **/.gradle - **/build - key: gradle_6_6_1 - restore-keys: gradle_6_6_1 + .gradle + build + ~/.gradle + key: {{ runner.os }}-gradle + restore-keys: {{ runner.os }}-gradle - name: Cache konan uses: actions/cache@v2 with: path: | ~/.konan/dependencies - ~/.konan/kotlin-native-prebuilt-mingw-1.4.20 - key: ${{ runner.os }}-konan-1.4.20 - restore-keys: ${{ runner.os }}-konan-1.4.20 + ~/.konan/kotlin-native-prebuilt-mingw-* + key: ${{ runner.os }}-konan + restore-keys: ${{ runner.os }}-konan - name: Build with Gradle run: ./gradlew --build-cache build From e62cf4fc6586643f6a5adddd2e1f25deb1b756cc Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 8 Dec 2020 14:42:42 +0700 Subject: [PATCH 146/199] Rewrite ASM codegen to use curried operators, fix bugs, update benchmarks --- .../ast/ExpressionsInterpretersBenchmark.kt | 49 +-- .../kmath/structures/ArrayBenchmark.kt | 8 +- .../kmath/structures/ViktorBenchmark.kt | 2 +- .../kotlin/kscience/kmath/ast/MST.kt | 3 +- .../kotlin/kscience/kmath/ast/MstAlgebra.kt | 15 +- .../kscience/kmath/ast/MstExpression.kt | 7 +- .../jvmMain/kotlin/kscience/kmath/asm/asm.kt | 49 +-- .../kscience/kmath/asm/internal/AsmBuilder.kt | 300 ++++-------------- .../kscience/kmath/asm/internal/MstType.kt | 20 -- .../kmath/asm/internal/codegenUtils.kt | 120 ------- .../kscience/kmath/asm/TestAsmAlgebras.kt | 36 +-- .../kscience/kmath/asm/TestAsmExpressions.kt | 12 +- .../kmath/asm/TestAsmSpecialization.kt | 2 +- .../kscience/kmath/asm/TestAsmVariables.kt | 2 +- .../kscience/kmath/operations/Algebra.kt | 10 +- .../kmath/operations/NumberAlgebra.kt | 2 +- 16 files changed, 158 insertions(+), 479 deletions(-) rename examples/src/{main => benchmarks}/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt (66%) delete mode 100644 kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/MstType.kt diff --git a/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt similarity index 66% rename from examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt index a4806ed68..6acaca84d 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/ast/ExpressionsInterpretersBenchmark.kt @@ -4,13 +4,19 @@ import kscience.kmath.asm.compile import kscience.kmath.expressions.Expression import kscience.kmath.expressions.expressionInField import kscience.kmath.expressions.invoke +import kscience.kmath.expressions.symbol import kscience.kmath.operations.Field import kscience.kmath.operations.RealField +import org.openjdk.jmh.annotations.Benchmark +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.State import kotlin.random.Random -import kotlin.system.measureTimeMillis +@State(Scope.Benchmark) internal class ExpressionsInterpretersBenchmark { private val algebra: Field = RealField + + @Benchmark fun functionalExpression() { val expr = algebra.expressionInField { symbol("x") * const(2.0) + const(2.0) / symbol("x") - const(16.0) @@ -19,6 +25,7 @@ internal class ExpressionsInterpretersBenchmark { invokeAndSum(expr) } + @Benchmark fun mstExpression() { val expr = algebra.mstInField { symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) @@ -27,6 +34,7 @@ internal class ExpressionsInterpretersBenchmark { invokeAndSum(expr) } + @Benchmark fun asmExpression() { val expr = algebra.mstInField { symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0) @@ -35,6 +43,13 @@ internal class ExpressionsInterpretersBenchmark { invokeAndSum(expr) } + @Benchmark + fun rawExpression() { + val x by symbol + val expr = Expression { args -> args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 } + invokeAndSum(expr) + } + private fun invokeAndSum(expr: Expression) { val random = Random(0) var sum = 0.0 @@ -46,35 +61,3 @@ internal class ExpressionsInterpretersBenchmark { println(sum) } } - -/** - * This benchmark compares basically evaluation of simple function with MstExpression interpreter, ASM backend and - * core FunctionalExpressions API. - * - * The expected rating is: - * - * 1. ASM. - * 2. MST. - * 3. FE. - */ -fun main() { - val benchmark = ExpressionsInterpretersBenchmark() - - val fe = measureTimeMillis { - benchmark.functionalExpression() - } - - println("fe=$fe") - - val mst = measureTimeMillis { - benchmark.mstExpression() - } - - println("mst=$mst") - - val asm = measureTimeMillis { - benchmark.asmExpression() - } - - println("asm=$asm") -} diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt index a91d02253..f7e0d05c6 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ArrayBenchmark.kt @@ -16,17 +16,13 @@ internal class ArrayBenchmark { @Benchmark fun benchmarkBufferRead() { var res = 0 - for (i in 1..size) res += arrayBuffer.get( - size - i - ) + for (i in 1..size) res += arrayBuffer[size - i] } @Benchmark fun nativeBufferRead() { var res = 0 - for (i in 1..size) res += nativeBuffer.get( - size - i - ) + for (i in 1..size) res += nativeBuffer[size - i] } companion object { diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt index 464925ca0..df35b0b78 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt @@ -36,7 +36,7 @@ internal class ViktorBenchmark { @Benchmark fun rawViktor() { - val one = F64Array.full(init = 1.0, shape = *intArrayOf(dim, dim)) + val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim)) var res = one repeat(n) { res = res + one } } diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt index cc3d38f9c..4ff4d7354 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt @@ -64,7 +64,8 @@ public fun Algebra.evaluate(node: MST): T = when (node) { node.left is MST.Numeric && node.right is MST.Numeric -> { val number = RealField - .binaryOperation(node.operation)(node.left.value.toDouble(), node.right.value.toDouble()) + .binaryOperation(node.operation) + .invoke(node.left.value.toDouble(), node.right.value.toDouble()) number(number) } diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt index 44a7f20b9..96703ffb8 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt @@ -24,13 +24,17 @@ public object MstSpace : Space, NumericAlgebra { public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value) - override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b) - override fun multiply(a: MST, k: Number): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k)) + public override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b) + public override fun MST.unaryMinus(): MST = unaryOperation(SpaceOperations.MINUS_OPERATION)(this) - override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = + public override fun multiply(a: MST, k: Number): MST.Binary = + binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k)) + + public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstAlgebra.binaryOperation(operation) - override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = MstAlgebra.unaryOperation(operation) + public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = + MstAlgebra.unaryOperation(operation) } /** @@ -47,6 +51,7 @@ public object MstRing : Ring, NumericAlgebra { public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b) public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION)(a, b) + public override fun MST.unaryMinus(): MST = MstSpace.unaryOperation(SpaceOperations.MINUS_OPERATION)(this) public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstSpace.binaryOperation(operation) @@ -71,6 +76,7 @@ public object MstField : Field { public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) public override fun divide(a: MST, b: MST): MST.Binary = binaryOperation(FieldOperations.DIV_OPERATION)(a, b) + public override fun MST.unaryMinus(): MST = MstSpace.unaryOperation(SpaceOperations.MINUS_OPERATION)(this) public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstRing.binaryOperation(operation) @@ -105,6 +111,7 @@ public object MstExtendedField : ExtendedField { public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b) + public override fun MST.unaryMinus(): MST = MstSpace.unaryOperation(SpaceOperations.MINUS_OPERATION)(this) public override fun power(arg: MST, pow: Number): MST.Binary = binaryOperation(PowerOperations.POW_OPERATION)(arg, number(pow)) diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt index 8a99fd2f4..4d1b65621 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt @@ -15,7 +15,12 @@ import kotlin.contracts.contract */ public class MstExpression>(public val algebra: A, public val mst: MST) : Expression { private inner class InnerAlgebra(val arguments: Map) : NumericAlgebra { - override fun symbol(value: String): T = arguments[StringSymbol(value)] ?: algebra.symbol(value) + override fun symbol(value: String): T = try { + algebra.symbol(value) + } catch (ignored: IllegalStateException) { + null + } ?: arguments.getValue(StringSymbol(value)) + override fun unaryOperation(operation: String): (arg: T) -> T = algebra.unaryOperation(operation) override fun binaryOperation(operation: String): (left: T, right: T) -> T = algebra.binaryOperation(operation) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt index 9ccfa464c..932813182 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt @@ -1,13 +1,13 @@ package kscience.kmath.asm import kscience.kmath.asm.internal.AsmBuilder -import kscience.kmath.asm.internal.MstType -import kscience.kmath.asm.internal.buildAlgebraOperationCall import kscience.kmath.asm.internal.buildName import kscience.kmath.ast.MST import kscience.kmath.ast.MstExpression import kscience.kmath.expressions.Expression import kscience.kmath.operations.Algebra +import kscience.kmath.operations.NumericAlgebra +import kscience.kmath.operations.RealField /** * Compiles given MST to an Expression using AST compiler. @@ -23,37 +23,46 @@ internal fun MST.compileWith(type: Class, algebra: Algebra): Exp is MST.Symbolic -> { val symbol = try { algebra.symbol(node.value) - } catch (ignored: Throwable) { + } catch (ignored: IllegalStateException) { null } if (symbol != null) - loadTConstant(symbol) + loadObjectConstant(symbol as Any) else loadVariable(node.value) } - is MST.Numeric -> loadNumeric(node.value) + is MST.Numeric -> loadNumberConstant(node.value) + is MST.Unary -> buildCall(algebra.unaryOperation(node.operation)) { visit(node.value) } - is MST.Unary -> buildAlgebraOperationCall( - context = algebra, - name = node.operation, - fallbackMethodName = "unaryOperation", - parameterTypes = arrayOf(MstType.fromMst(node.value)) - ) { visit(node.value) } + is MST.Binary -> when { + algebra is NumericAlgebra && node.left is MST.Numeric && node.right is MST.Numeric -> loadObjectConstant( + algebra.number( + RealField + .binaryOperation(node.operation) + .invoke(node.left.value.toDouble(), node.right.value.toDouble()) + ) + ) - is MST.Binary -> buildAlgebraOperationCall( - context = algebra, - name = node.operation, - fallbackMethodName = "binaryOperation", - parameterTypes = arrayOf(MstType.fromMst(node.left), MstType.fromMst(node.right)) - ) { - visit(node.left) - visit(node.right) + algebra is NumericAlgebra && node.left is MST.Numeric -> buildCall(algebra.leftSideNumberOperation(node.operation)) { + visit(node.left) + visit(node.right) + } + + algebra is NumericAlgebra && node.right is MST.Numeric -> buildCall(algebra.rightSideNumberOperation(node.operation)) { + visit(node.left) + visit(node.right) + } + + else -> buildCall(algebra.binaryOperation(node.operation)) { + visit(node.left) + visit(node.right) + } } } - return AsmBuilder(type, algebra, buildName(this)) { visit(this@compileWith) }.getInstance() + return AsmBuilder(type, buildName(this)) { visit(this@compileWith) }.instance } /** diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index a1e482103..792034232 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -4,26 +4,24 @@ import kscience.kmath.asm.internal.AsmBuilder.ClassLoader import kscience.kmath.ast.MST import kscience.kmath.expressions.Expression import kscience.kmath.operations.Algebra -import kscience.kmath.operations.NumericAlgebra import org.objectweb.asm.* import org.objectweb.asm.Opcodes.* import org.objectweb.asm.commons.InstructionAdapter -import java.util.* -import java.util.stream.Collectors +import java.util.stream.Collectors.toMap +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract /** * ASM Builder is a structure that abstracts building a class designated to unwrap [MST] to plain Java expression. * This class uses [ClassLoader] for loading the generated class, then it is able to instantiate the new class. * * @property T the type of AsmExpression to unwrap. - * @property algebra the algebra the applied AsmExpressions use. * @property className the unique class name of new loaded class. * @property invokeLabel0Visitor the function to apply to this object when generating invoke method, label 0. * @author Iaroslav Postovalov */ internal class AsmBuilder internal constructor( - private val classOfT: Class<*>, - private val algebra: Algebra, + classOfT: Class<*>, private val className: String, private val invokeLabel0Visitor: AsmBuilder.() -> Unit, ) { @@ -39,15 +37,10 @@ internal class AsmBuilder internal constructor( */ private val classLoader: ClassLoader = ClassLoader(javaClass.classLoader) - /** - * ASM Type for [algebra]. - */ - private val tAlgebraType: Type = algebra.javaClass.asm - /** * ASM type for [T]. */ - internal val tType: Type = classOfT.asm + private val tType: Type = classOfT.asm /** * ASM type for new class. @@ -69,51 +62,13 @@ internal class AsmBuilder internal constructor( */ private var hasConstants: Boolean = true - /** - * States whether [T] a primitive type, so [AsmBuilder] may generate direct primitive calls. - */ - internal var primitiveMode: Boolean = false - - /** - * Primitive type to apply for specific primitive calls. Use [OBJECT_TYPE], if not in [primitiveMode]. - */ - internal var primitiveMask: Type = OBJECT_TYPE - - /** - * Boxed primitive type to apply for specific primitive calls. Use [OBJECT_TYPE], if not in [primitiveMode]. - */ - internal var primitiveMaskBoxed: Type = OBJECT_TYPE - - /** - * Stack of useful objects types on stack to verify types. - */ - private val typeStack: ArrayDeque = ArrayDeque() - - /** - * Stack of useful objects types on stack expected by algebra calls. - */ - internal val expectationStack: ArrayDeque = ArrayDeque(1).also { it.push(tType) } - - /** - * The cache for instance built by this builder. - */ - private var generatedInstance: Expression? = null - /** * Subclasses, loads and instantiates [Expression] for given parameters. * * The built instance is cached. */ @Suppress("UNCHECKED_CAST") - internal fun getInstance(): Expression { - generatedInstance?.let { return it } - - if (SIGNATURE_LETTERS.containsKey(classOfT)) { - primitiveMode = true - primitiveMask = SIGNATURE_LETTERS.getValue(classOfT) - primitiveMaskBoxed = tType - } - + val instance: Expression by lazy { val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) { visit( V1_8, @@ -192,15 +147,6 @@ internal class AsmBuilder internal constructor( hasConstants = constants.isNotEmpty() - visitField( - access = ACC_PRIVATE or ACC_FINAL, - name = "algebra", - descriptor = tAlgebraType.descriptor, - signature = null, - value = null, - block = FieldVisitor::visitEnd - ) - if (hasConstants) visitField( access = ACC_PRIVATE or ACC_FINAL, @@ -214,25 +160,17 @@ internal class AsmBuilder internal constructor( visitMethod( ACC_PUBLIC, "", - - Type.getMethodDescriptor( - Type.VOID_TYPE, - tAlgebraType, - *OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }), - + Type.getMethodDescriptor(Type.VOID_TYPE, *OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }), null, null ).instructionAdapter { val thisVar = 0 - val algebraVar = 1 - val constantsVar = 2 + val constantsVar = 1 val l0 = label() load(thisVar, classType) invokespecial(OBJECT_TYPE.internalName, "", Type.getMethodDescriptor(Type.VOID_TYPE), false) label() load(thisVar, classType) - load(algebraVar, tAlgebraType) - putfield(classType.internalName, "algebra", tAlgebraType.descriptor) if (hasConstants) { label() @@ -246,15 +184,6 @@ internal class AsmBuilder internal constructor( val l4 = label() visitLocalVariable("this", classType.descriptor, null, l0, l4, thisVar) - visitLocalVariable( - "algebra", - tAlgebraType.descriptor, - null, - l0, - l4, - algebraVar - ) - if (hasConstants) visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l4, constantsVar) @@ -265,33 +194,55 @@ internal class AsmBuilder internal constructor( visitEnd() } - val new = classLoader +// java.io.File("dump.class").writeBytes(classWriter.toByteArray()) + + classLoader .defineClass(className, classWriter.toByteArray()) .constructors .first() - .newInstance(algebra, *(constants.toTypedArray().wrapToArrayIf { hasConstants })) as Expression - - generatedInstance = new - return new + .newInstance(*(constants.toTypedArray().wrapToArrayIf { hasConstants })) as Expression } /** - * Loads a [T] constant from [constants]. + * Loads [java.lang.Object] constant from constants. */ - internal fun loadTConstant(value: T) { - if (classOfT in INLINABLE_NUMBERS) { - val expectedType = expectationStack.pop() - val mustBeBoxed = expectedType.sort == Type.OBJECT - loadNumberConstant(value as Number, mustBeBoxed) + fun loadObjectConstant(value: Any, type: Type = tType): Unit = invokeMethodVisitor.run { + val idx = if (value in constants) constants.indexOf(value) else constants.also { it += value }.lastIndex + loadThis() + getfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor) + iconst(idx) + visitInsn(AALOAD) + checkcast(type) + } - if (mustBeBoxed) - invokeMethodVisitor.checkcast(tType) + /** + * Loads `this` variable. + */ + private fun loadThis(): Unit = invokeMethodVisitor.load(invokeThisVar, classType) - if (mustBeBoxed) typeStack.push(tType) else typeStack.push(primitiveMask) + /** + * Either loads a numeric constant [value] from the class's constants field or boxes a primitive + * constant from the constant pool. + */ + fun loadNumberConstant(value: Number) { + val boxed = value.javaClass.asm + val primitive = BOXED_TO_PRIMITIVES[boxed] + + if (primitive != null) { + when (primitive) { + Type.BYTE_TYPE -> invokeMethodVisitor.iconst(value.toInt()) + Type.DOUBLE_TYPE -> invokeMethodVisitor.dconst(value.toDouble()) + Type.FLOAT_TYPE -> invokeMethodVisitor.fconst(value.toFloat()) + Type.LONG_TYPE -> invokeMethodVisitor.lconst(value.toLong()) + Type.INT_TYPE -> invokeMethodVisitor.iconst(value.toInt()) + Type.SHORT_TYPE -> invokeMethodVisitor.iconst(value.toInt()) + } + + box(primitive) return } - loadObjectConstant(value as Any, tType) + loadObjectConstant(value, boxed) } /** @@ -309,77 +260,9 @@ internal class AsmBuilder internal constructor( } /** - * Unboxes the current boxed value and pushes it. + * Loads a variable [name] from arguments [Map] parameter of [Expression.invoke]. */ - private fun unboxTo(primitive: Type) = invokeMethodVisitor.invokevirtual( - NUMBER_TYPE.internalName, - NUMBER_CONVERTER_METHODS.getValue(primitive), - Type.getMethodDescriptor(primitive), - false - ) - - /** - * Loads [java.lang.Object] constant from constants. - */ - private fun loadObjectConstant(value: Any, type: Type): Unit = invokeMethodVisitor.run { - val idx = if (value in constants) constants.indexOf(value) else constants.apply { add(value) }.lastIndex - loadThis() - getfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor) - iconst(idx) - visitInsn(AALOAD) - checkcast(type) - } - - internal fun loadNumeric(value: Number) { - if (expectationStack.peek() == NUMBER_TYPE) { - loadNumberConstant(value, true) - expectationStack.pop() - typeStack.push(NUMBER_TYPE) - } else (algebra as? NumericAlgebra)?.number(value)?.let { loadTConstant(it) } - ?: error("Cannot resolve numeric $value since target algebra is not numeric, and the current operation doesn't accept numbers.") - } - - /** - * Loads this variable. - */ - private fun loadThis(): Unit = invokeMethodVisitor.load(invokeThisVar, classType) - - /** - * Either loads a numeric constant [value] from the class's constants field or boxes a primitive - * constant from the constant pool (some numbers with special opcodes like [Opcodes.ICONST_0] aren't even loaded - * from it). - */ - private fun loadNumberConstant(value: Number, mustBeBoxed: Boolean) { - val boxed = value.javaClass.asm - val primitive = BOXED_TO_PRIMITIVES[boxed] - - if (primitive != null) { - when (primitive) { - Type.BYTE_TYPE -> invokeMethodVisitor.iconst(value.toInt()) - Type.DOUBLE_TYPE -> invokeMethodVisitor.dconst(value.toDouble()) - Type.FLOAT_TYPE -> invokeMethodVisitor.fconst(value.toFloat()) - Type.LONG_TYPE -> invokeMethodVisitor.lconst(value.toLong()) - Type.INT_TYPE -> invokeMethodVisitor.iconst(value.toInt()) - Type.SHORT_TYPE -> invokeMethodVisitor.iconst(value.toInt()) - } - - if (mustBeBoxed) - box(primitive) - - return - } - - loadObjectConstant(value, boxed) - - if (!mustBeBoxed) - unboxTo(primitiveMask) - } - - /** - * Loads a variable [name] from arguments [Map] parameter of [Expression.invoke]. The [defaultValue] may be - * provided. - */ - internal fun loadVariable(name: String): Unit = invokeMethodVisitor.run { + fun loadVariable(name: String): Unit = invokeMethodVisitor.run { load(invokeArgumentsVar, MAP_TYPE) aconst(name) @@ -391,70 +274,28 @@ internal class AsmBuilder internal constructor( ) checkcast(tType) - val expectedType = expectationStack.pop() - - if (expectedType.sort == Type.OBJECT) - typeStack.push(tType) - else { - unboxTo(primitiveMask) - typeStack.push(primitiveMask) - } } - /** - * Loads algebra from according field of the class and casts it to class of [algebra] provided. - */ - internal fun loadAlgebra() { - loadThis() - invokeMethodVisitor.getfield(classType.internalName, "algebra", tAlgebraType.descriptor) - } + inline fun buildCall(function: Function, parameters: AsmBuilder.() -> Unit) { + contract { callsInPlace(parameters, InvocationKind.EXACTLY_ONCE) } + val `interface` = function.javaClass.interfaces.first { it.interfaces.contains(Function::class.java) } - /** - * Writes a method instruction of opcode with its [owner], [method] and its [descriptor]. The default opcode is - * [Opcodes.INVOKEINTERFACE], since most Algebra functions are declared in interfaces. [loadAlgebra] should be - * called before the arguments and this operation. - * - * The result is casted to [T] automatically. - */ - internal fun invokeAlgebraOperation( - owner: String, - method: String, - descriptor: String, - expectedArity: Int, - opcode: Int = INVOKEINTERFACE, - ) { - run loop@{ - repeat(expectedArity) { - if (typeStack.isEmpty()) return@loop - typeStack.pop() - } - } + val arity = `interface`.methods.find { it.name == "invoke" }?.parameterCount + ?: error("Provided function object doesn't contain invoke method") - invokeMethodVisitor.visitMethodInsn( - opcode, - owner, - method, - descriptor, - opcode == INVOKEINTERFACE + val type = Type.getType(`interface`) + loadObjectConstant(function, type) + parameters(this) + + invokeMethodVisitor.invokeinterface( + type.internalName, + "invoke", + Type.getMethodDescriptor(OBJECT_TYPE, *Array(arity) { OBJECT_TYPE}), ) invokeMethodVisitor.checkcast(tType) - val isLastExpr = expectationStack.size == 1 - val expectedType = expectationStack.pop() - - if (expectedType.sort == Type.OBJECT || isLastExpr) - typeStack.push(tType) - else { - unboxTo(primitiveMask) - typeStack.push(primitiveMask) - } } - /** - * Writes a LDC Instruction with string constant provided. - */ - internal fun loadStringConstant(string: String): Unit = invokeMethodVisitor.aconst(string) - internal companion object { /** * Index of `this` variable in invoke method of the built subclass. @@ -490,32 +331,13 @@ internal class AsmBuilder internal constructor( */ private val PRIMITIVES_TO_BOXED: Map by lazy { BOXED_TO_PRIMITIVES.entries.stream().collect( - Collectors.toMap( + toMap( Map.Entry::value, Map.Entry::key ) ) } - /** - * Maps primitive ASM types to [Number] functions unboxing them. - */ - private val NUMBER_CONVERTER_METHODS: Map by lazy { - hashMapOf( - Type.BYTE_TYPE to "byteValue", - Type.SHORT_TYPE to "shortValue", - Type.INT_TYPE to "intValue", - Type.LONG_TYPE to "longValue", - Type.FLOAT_TYPE to "floatValue", - Type.DOUBLE_TYPE to "doubleValue" - ) - } - - /** - * Provides boxed number types values of which can be stored in JVM bytecode constant pool. - */ - private val INLINABLE_NUMBERS: Set> by lazy { SIGNATURE_LETTERS.keys } - /** * ASM type for [Expression]. */ diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/MstType.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/MstType.kt deleted file mode 100644 index 526c27305..000000000 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/MstType.kt +++ /dev/null @@ -1,20 +0,0 @@ -package kscience.kmath.asm.internal - -import kscience.kmath.ast.MST - -/** - * Represents types known in [MST], numbers and general values. - */ -internal enum class MstType { - GENERAL, - NUMBER; - - companion object { - fun fromMst(mst: MST): MstType { - if (mst is MST.Numeric) - return NUMBER - - return GENERAL - } - } -} diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt index ef9751502..d301ddf15 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt @@ -2,29 +2,11 @@ package kscience.kmath.asm.internal import kscience.kmath.ast.MST import kscience.kmath.expressions.Expression -import kscience.kmath.operations.Algebra -import kscience.kmath.operations.FieldOperations -import kscience.kmath.operations.RingOperations -import kscience.kmath.operations.SpaceOperations import org.objectweb.asm.* -import org.objectweb.asm.Opcodes.INVOKEVIRTUAL import org.objectweb.asm.commons.InstructionAdapter -import java.lang.reflect.Method -import java.util.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract -private val methodNameAdapters: Map, String> by lazy { - hashMapOf( - SpaceOperations.PLUS_OPERATION to 2 to "add", - RingOperations.TIMES_OPERATION to 2 to "multiply", - FieldOperations.DIV_OPERATION to 2 to "divide", - SpaceOperations.PLUS_OPERATION to 1 to "unaryPlus", - SpaceOperations.MINUS_OPERATION to 1 to "unaryMinus", - SpaceOperations.MINUS_OPERATION to 2 to "minus" - ) -} - /** * Returns ASM [Type] for given [Class]. * @@ -110,106 +92,4 @@ internal inline fun ClassWriter.visitField( return visitField(access, name, descriptor, signature, value).apply(block) } -private fun AsmBuilder.findSpecific(context: Algebra, name: String, parameterTypes: Array): Method? = - context.javaClass.methods.find { method -> - val nameValid = method.name == name - val arityValid = method.parameters.size == parameterTypes.size - val notBridgeInPrimitive = !(primitiveMode && method.isBridge) - val paramsValid = method.parameterTypes.zip(parameterTypes).all { (type, mstType) -> - !(mstType != MstType.NUMBER && type == java.lang.Number::class.java) - } - - nameValid && arityValid && notBridgeInPrimitive && paramsValid - } - -/** - * Checks if the target [context] for code generation contains a method with needed [name] and arity, also builds - * type expectation stack for needed arity. - * - * @author Iaroslav Postovalov - */ -private fun AsmBuilder.buildExpectationStack( - context: Algebra, - name: String, - parameterTypes: Array -): Boolean { - val arity = parameterTypes.size - val specific = findSpecific(context, methodNameAdapters[name to arity] ?: name, parameterTypes) - - if (specific != null) - mapTypes(specific, parameterTypes).reversed().forEach { expectationStack.push(it) } - else - expectationStack.addAll(Collections.nCopies(arity, tType)) - - return specific != null -} - -private fun AsmBuilder.mapTypes(method: Method, parameterTypes: Array): List = method - .parameterTypes - .zip(parameterTypes) - .map { (type, mstType) -> - when { - type == java.lang.Number::class.java && mstType == MstType.NUMBER -> AsmBuilder.NUMBER_TYPE - else -> if (primitiveMode) primitiveMask else primitiveMaskBoxed - } - } - -/** - * Checks if the target [context] for code generation contains a method with needed [name] and arity and inserts - * [AsmBuilder.invokeAlgebraOperation] of this method. - * - * @author Iaroslav Postovalov - */ -private fun AsmBuilder.tryInvokeSpecific( - context: Algebra, - name: String, - parameterTypes: Array -): Boolean { - val arity = parameterTypes.size - val theName = methodNameAdapters[name to arity] ?: name - val spec = findSpecific(context, theName, parameterTypes) ?: return false - val owner = context.javaClass.asm - - invokeAlgebraOperation( - owner = owner.internalName, - method = theName, - descriptor = Type.getMethodDescriptor(primitiveMaskBoxed, *mapTypes(spec, parameterTypes).toTypedArray()), - expectedArity = arity, - opcode = INVOKEVIRTUAL - ) - - return true -} - -/** - * Builds specialized [context] call with option to fallback to generic algebra operation accepting [String]. - * - * @author Iaroslav Postovalov - */ -internal inline fun AsmBuilder.buildAlgebraOperationCall( - context: Algebra, - name: String, - fallbackMethodName: String, - parameterTypes: Array, - parameters: AsmBuilder.() -> Unit -) { - contract { callsInPlace(parameters, InvocationKind.EXACTLY_ONCE) } - val arity = parameterTypes.size - loadAlgebra() - if (!buildExpectationStack(context, name, parameterTypes)) loadStringConstant(name) - parameters() - - if (!tryInvokeSpecific(context, name, parameterTypes)) invokeAlgebraOperation( - owner = AsmBuilder.ALGEBRA_TYPE.internalName, - method = fallbackMethodName, - - descriptor = Type.getMethodDescriptor( - AsmBuilder.OBJECT_TYPE, - AsmBuilder.STRING_TYPE, - *Array(arity) { AsmBuilder.OBJECT_TYPE } - ), - - expectedArity = arity - ) -} diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt index 5eebfe43d..a1687c1c7 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt @@ -10,15 +10,11 @@ import kotlin.test.Test import kotlin.test.assertEquals internal class TestAsmAlgebras { - @Test fun space() { val res1 = ByteRing.mstInSpace { - binaryOperation( - "+", - - unaryOperation( - "+", + binaryOperation("+")( + unaryOperation("+")( number(3.toByte()) - (number(2.toByte()) + (multiply( add(number(1), number(1)), 2 @@ -30,11 +26,8 @@ internal class TestAsmAlgebras { }("x" to 2.toByte()) val res2 = ByteRing.mstInSpace { - binaryOperation( - "+", - - unaryOperation( - "+", + binaryOperation("+")( + unaryOperation("+")( number(3.toByte()) - (number(2.toByte()) + (multiply( add(number(1), number(1)), 2 @@ -51,11 +44,8 @@ internal class TestAsmAlgebras { @Test fun ring() { val res1 = ByteRing.mstInRing { - binaryOperation( - "+", - - unaryOperation( - "+", + binaryOperation("+")( + unaryOperation("+")( (symbol("x") - (2.toByte() + (multiply( add(number(1), number(1)), 2 @@ -67,17 +57,13 @@ internal class TestAsmAlgebras { }("x" to 3.toByte()) val res2 = ByteRing.mstInRing { - binaryOperation( - "+", - - unaryOperation( - "+", + binaryOperation("+")( + unaryOperation("+")( (symbol("x") - (2.toByte() + (multiply( add(number(1), number(1)), 2 ) + 1.toByte()))) * 3.0 - 1.toByte() ), - number(1) ) * number(2) }.compile()("x" to 3.toByte()) @@ -88,8 +74,7 @@ internal class TestAsmAlgebras { @Test fun field() { val res1 = RealField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation( - "+", + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one @@ -97,8 +82,7 @@ internal class TestAsmAlgebras { }("x" to 2.0) val res2 = RealField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation( - "+", + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmExpressions.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmExpressions.kt index 7f4d453f7..acd9e21ea 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmExpressions.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmExpressions.kt @@ -1,10 +1,11 @@ package kscience.kmath.asm -import kscience.kmath.asm.compile +import kscience.kmath.ast.mstInExtendedField import kscience.kmath.ast.mstInField import kscience.kmath.ast.mstInSpace import kscience.kmath.expressions.invoke import kscience.kmath.operations.RealField +import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals @@ -28,4 +29,13 @@ internal class TestAsmExpressions { val res = RealField.mstInField { symbol("x") * 2 }("x" to 2.0) assertEquals(4.0, res) } + + @Test + fun testMultipleCalls() { + val e = RealField.mstInExtendedField { sin(symbol("x")).pow(4) - 6 * symbol("x") / tanh(symbol("x")) }.compile() + val r = Random(0) + var s = 0.0 + repeat(1000000) { s += e("x" to r.nextDouble()) } + println(s) + } } diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt index eb5a1c8f3..ce9e602d3 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt @@ -46,7 +46,7 @@ internal class TestAsmSpecialization { @Test fun testPower() { val expr = RealField - .mstInField { binaryOperation("power")(symbol("x"), number(2)) } + .mstInField { binaryOperation("pow")(symbol("x"), number(2)) } .compile() assertEquals(4.0, expr("x" to 2.0)) diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt index 7b89c74fa..1011515c8 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt @@ -17,6 +17,6 @@ internal class TestAsmVariables { @Test fun testVariableWithoutDefaultFails() { val expr = ByteRing.mstInRing { symbol("x") } - assertFailsWith { expr() } + assertFailsWith { expr() } } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index 19ca1a4cc..2661525fb 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -20,12 +20,14 @@ public interface Algebra { /** * Dynamically dispatches an unary operation with name [operation]. */ - public fun unaryOperation(operation: String): (arg: T) -> T + public fun unaryOperation(operation: String): (arg: T) -> T = + error("Unary operation $operation not defined in $this") /** * Dynamically dispatches a binary operation with name [operation]. */ - public fun binaryOperation(operation: String): (left: T, right: T) -> T + public fun binaryOperation(operation: String): (left: T, right: T) -> T = + error("Binary operation $operation not defined in $this") } /** @@ -161,13 +163,13 @@ public interface SpaceOperations : Algebra { override fun unaryOperation(operation: String): (arg: T) -> T = when (operation) { PLUS_OPERATION -> { arg -> arg } MINUS_OPERATION -> { arg -> -arg } - else -> error("Unary operation $operation not defined in $this") + else -> super.unaryOperation(operation) } override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { PLUS_OPERATION -> ::add MINUS_OPERATION -> { left, right -> left - right } - else -> error("Binary operation $operation not defined in $this") + else -> super.binaryOperation(operation) } public companion object { diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt index 611222d34..cd2bd0417 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt @@ -31,7 +31,7 @@ public interface ExtendedFieldOperations : PowerOperations.SQRT_OPERATION -> ::sqrt ExponentialOperations.EXP_OPERATION -> ::exp ExponentialOperations.LN_OPERATION -> ::ln - else -> super.unaryOperation(operation) + else -> super.unaryOperation(operation) } } From cc45e3683b702b8c8e637af66d7cf07d67dcbd24 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 8 Dec 2020 16:16:32 +0700 Subject: [PATCH 147/199] Refactor ASM builder --- .../kscience/kmath/asm/internal/AsmBuilder.kt | 129 +++++++----------- .../kmath/asm/internal/codegenUtils.kt | 2 - 2 files changed, 53 insertions(+), 78 deletions(-) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index 792034232..46051e158 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -6,6 +6,7 @@ import kscience.kmath.expressions.Expression import kscience.kmath.operations.Algebra import org.objectweb.asm.* import org.objectweb.asm.Opcodes.* +import org.objectweb.asm.Type.* import org.objectweb.asm.commons.InstructionAdapter import java.util.stream.Collectors.toMap import kotlin.contracts.InvocationKind @@ -17,13 +18,13 @@ import kotlin.contracts.contract * * @property T the type of AsmExpression to unwrap. * @property className the unique class name of new loaded class. - * @property invokeLabel0Visitor the function to apply to this object when generating invoke method, label 0. + * @property callbackAtInvokeL0 the function to apply to this object when generating invoke method, label 0. * @author Iaroslav Postovalov */ -internal class AsmBuilder internal constructor( +internal class AsmBuilder( classOfT: Class<*>, private val className: String, - private val invokeLabel0Visitor: AsmBuilder.() -> Unit, + private val callbackAtInvokeL0: AsmBuilder.() -> Unit, ) { /** * Internal classloader of [AsmBuilder] with alias to define class from byte array. @@ -45,7 +46,7 @@ internal class AsmBuilder internal constructor( /** * ASM type for new class. */ - private val classType: Type = Type.getObjectType(className.replace(oldChar = '.', newChar = '/'))!! + private val classType: Type = getObjectType(className.replace(oldChar = '.', newChar = '/')) /** * List of constants to provide to the subclass. @@ -57,11 +58,6 @@ internal class AsmBuilder internal constructor( */ private lateinit var invokeMethodVisitor: InstructionAdapter - /** - * States whether this [AsmBuilder] needs to generate constants field. - */ - private var hasConstants: Boolean = true - /** * Subclasses, loads and instantiates [Expression] for given parameters. * @@ -69,6 +65,8 @@ internal class AsmBuilder internal constructor( */ @Suppress("UNCHECKED_CAST") val instance: Expression by lazy { + val hasConstants: Boolean + val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) { visit( V1_8, @@ -82,14 +80,14 @@ internal class AsmBuilder internal constructor( visitMethod( ACC_PUBLIC or ACC_FINAL, "invoke", - Type.getMethodDescriptor(tType, MAP_TYPE), + getMethodDescriptor(tType, MAP_TYPE), "(L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;)${tType.descriptor}", null ).instructionAdapter { invokeMethodVisitor = this visitCode() val l0 = label() - invokeLabel0Visitor() + callbackAtInvokeL0() areturn(tType) val l1 = label() @@ -99,7 +97,7 @@ internal class AsmBuilder internal constructor( null, l0, l1, - invokeThisVar + 0 ) visitLocalVariable( @@ -108,7 +106,7 @@ internal class AsmBuilder internal constructor( "L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;", l0, l1, - invokeArgumentsVar + 1 ) visitMaxs(0, 2) @@ -118,7 +116,7 @@ internal class AsmBuilder internal constructor( visitMethod( ACC_PUBLIC or ACC_FINAL or ACC_BRIDGE or ACC_SYNTHETIC, "invoke", - Type.getMethodDescriptor(OBJECT_TYPE, MAP_TYPE), + getMethodDescriptor(OBJECT_TYPE, MAP_TYPE), null, null ).instructionAdapter { @@ -128,7 +126,7 @@ internal class AsmBuilder internal constructor( val l0 = label() load(thisVar, OBJECT_TYPE) load(argumentsVar, MAP_TYPE) - invokevirtual(classType.internalName, "invoke", Type.getMethodDescriptor(tType, MAP_TYPE), false) + invokevirtual(classType.internalName, "invoke", getMethodDescriptor(tType, MAP_TYPE), false) areturn(tType) val l1 = label() @@ -160,32 +158,30 @@ internal class AsmBuilder internal constructor( visitMethod( ACC_PUBLIC, "", - Type.getMethodDescriptor(Type.VOID_TYPE, *OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }), + getMethodDescriptor(VOID_TYPE, *OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }), null, null ).instructionAdapter { - val thisVar = 0 - val constantsVar = 1 val l0 = label() - load(thisVar, classType) - invokespecial(OBJECT_TYPE.internalName, "", Type.getMethodDescriptor(Type.VOID_TYPE), false) + load(0, classType) + invokespecial(OBJECT_TYPE.internalName, "", getMethodDescriptor(VOID_TYPE), false) label() - load(thisVar, classType) + load(0, classType) if (hasConstants) { label() - load(thisVar, classType) - load(constantsVar, OBJECT_ARRAY_TYPE) + load(0, classType) + load(1, OBJECT_ARRAY_TYPE) putfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor) } label() visitInsn(RETURN) val l4 = label() - visitLocalVariable("this", classType.descriptor, null, l0, l4, thisVar) + visitLocalVariable("this", classType.descriptor, null, l0, l4, 0) if (hasConstants) - visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l4, constantsVar) + visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l4, 1) visitMaxs(0, 3) visitEnd() @@ -218,7 +214,7 @@ internal class AsmBuilder internal constructor( /** * Loads `this` variable. */ - private fun loadThis(): Unit = invokeMethodVisitor.load(invokeThisVar, classType) + private fun loadThis(): Unit = invokeMethodVisitor.load(0, classType) /** * Either loads a numeric constant [value] from the class's constants field or boxes a primitive @@ -230,12 +226,12 @@ internal class AsmBuilder internal constructor( if (primitive != null) { when (primitive) { - Type.BYTE_TYPE -> invokeMethodVisitor.iconst(value.toInt()) - Type.DOUBLE_TYPE -> invokeMethodVisitor.dconst(value.toDouble()) - Type.FLOAT_TYPE -> invokeMethodVisitor.fconst(value.toFloat()) - Type.LONG_TYPE -> invokeMethodVisitor.lconst(value.toLong()) - Type.INT_TYPE -> invokeMethodVisitor.iconst(value.toInt()) - Type.SHORT_TYPE -> invokeMethodVisitor.iconst(value.toInt()) + BYTE_TYPE -> invokeMethodVisitor.iconst(value.toInt()) + DOUBLE_TYPE -> invokeMethodVisitor.dconst(value.toDouble()) + FLOAT_TYPE -> invokeMethodVisitor.fconst(value.toFloat()) + LONG_TYPE -> invokeMethodVisitor.lconst(value.toLong()) + INT_TYPE -> invokeMethodVisitor.iconst(value.toInt()) + SHORT_TYPE -> invokeMethodVisitor.iconst(value.toInt()) } box(primitive) @@ -254,7 +250,7 @@ internal class AsmBuilder internal constructor( invokeMethodVisitor.invokestatic( r.internalName, "valueOf", - Type.getMethodDescriptor(r, primitive), + getMethodDescriptor(r, primitive), false ) } @@ -263,13 +259,13 @@ internal class AsmBuilder internal constructor( * Loads a variable [name] from arguments [Map] parameter of [Expression.invoke]. */ fun loadVariable(name: String): Unit = invokeMethodVisitor.run { - load(invokeArgumentsVar, MAP_TYPE) + load(1, MAP_TYPE) aconst(name) invokestatic( MAP_INTRINSICS_TYPE.internalName, "getOrFail", - Type.getMethodDescriptor(OBJECT_TYPE, MAP_TYPE, STRING_TYPE), + getMethodDescriptor(OBJECT_TYPE, MAP_TYPE, STRING_TYPE), false ) @@ -283,100 +279,81 @@ internal class AsmBuilder internal constructor( val arity = `interface`.methods.find { it.name == "invoke" }?.parameterCount ?: error("Provided function object doesn't contain invoke method") - val type = Type.getType(`interface`) + val type = getType(`interface`) loadObjectConstant(function, type) parameters(this) invokeMethodVisitor.invokeinterface( type.internalName, "invoke", - Type.getMethodDescriptor(OBJECT_TYPE, *Array(arity) { OBJECT_TYPE}), + getMethodDescriptor(OBJECT_TYPE, *Array(arity) { OBJECT_TYPE }), ) invokeMethodVisitor.checkcast(tType) } - internal companion object { - /** - * Index of `this` variable in invoke method of the built subclass. - */ - private const val invokeThisVar: Int = 0 - - /** - * Index of `arguments` variable in invoke method of the built subclass. - */ - private const val invokeArgumentsVar: Int = 1 - - /** - * Maps JVM primitive numbers boxed types to their primitive ASM types. - */ - private val SIGNATURE_LETTERS: Map, Type> by lazy { - hashMapOf( - java.lang.Byte::class.java to Type.BYTE_TYPE, - java.lang.Short::class.java to Type.SHORT_TYPE, - java.lang.Integer::class.java to Type.INT_TYPE, - java.lang.Long::class.java to Type.LONG_TYPE, - java.lang.Float::class.java to Type.FLOAT_TYPE, - java.lang.Double::class.java to Type.DOUBLE_TYPE - ) - } - + companion object { /** * Maps JVM primitive numbers boxed ASM types to their primitive ASM types. */ - private val BOXED_TO_PRIMITIVES: Map by lazy { SIGNATURE_LETTERS.mapKeys { (k, _) -> k.asm } } + private val BOXED_TO_PRIMITIVES: Map by lazy { + hashMapOf( + Byte::class.java.asm to BYTE_TYPE, + Short::class.java.asm to SHORT_TYPE, + Integer::class.java.asm to INT_TYPE, + Long::class.java.asm to LONG_TYPE, + Float::class.java.asm to FLOAT_TYPE, + Double::class.java.asm to DOUBLE_TYPE, + ) + } /** * Maps JVM primitive numbers boxed ASM types to their primitive ASM types. */ private val PRIMITIVES_TO_BOXED: Map by lazy { BOXED_TO_PRIMITIVES.entries.stream().collect( - toMap( - Map.Entry::value, - Map.Entry::key - ) + toMap(Map.Entry::value, Map.Entry::key), ) } /** * ASM type for [Expression]. */ - internal val EXPRESSION_TYPE: Type by lazy { Type.getObjectType("kscience/kmath/expressions/Expression") } + val EXPRESSION_TYPE: Type by lazy { getObjectType("kscience/kmath/expressions/Expression") } /** * ASM type for [java.lang.Number]. */ - internal val NUMBER_TYPE: Type by lazy { Type.getObjectType("java/lang/Number") } + val NUMBER_TYPE: Type by lazy { getObjectType("java/lang/Number") } /** * ASM type for [java.util.Map]. */ - internal val MAP_TYPE: Type by lazy { Type.getObjectType("java/util/Map") } + val MAP_TYPE: Type by lazy { getObjectType("java/util/Map") } /** * ASM type for [java.lang.Object]. */ - internal val OBJECT_TYPE: Type by lazy { Type.getObjectType("java/lang/Object") } + val OBJECT_TYPE: Type by lazy { getObjectType("java/lang/Object") } /** * ASM type for array of [java.lang.Object]. */ - @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "RemoveRedundantQualifierName") - internal val OBJECT_ARRAY_TYPE: Type by lazy { Type.getType("[Ljava/lang/Object;") } + val OBJECT_ARRAY_TYPE: Type by lazy { getType("[Ljava/lang/Object;") } /** * ASM type for [Algebra]. */ - internal val ALGEBRA_TYPE: Type by lazy { Type.getObjectType("kscience/kmath/operations/Algebra") } + val ALGEBRA_TYPE: Type by lazy { getObjectType("kscience/kmath/operations/Algebra") } /** * ASM type for [java.lang.String]. */ - internal val STRING_TYPE: Type by lazy { Type.getObjectType("java/lang/String") } + val STRING_TYPE: Type by lazy { getObjectType("java/lang/String") } /** * ASM type for MapIntrinsics. */ - internal val MAP_INTRINSICS_TYPE: Type by lazy { Type.getObjectType("kscience/kmath/asm/internal/MapIntrinsics") } + val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("kscience/kmath/asm/internal/MapIntrinsics") } } } diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt index d301ddf15..6d5d19d42 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/codegenUtils.kt @@ -91,5 +91,3 @@ internal inline fun ClassWriter.visitField( contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return visitField(access, name, descriptor, signature, value).apply(block) } - - From 6d96bba101b068b773c68e4853a72e9012b5168a Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 8 Dec 2020 16:35:30 +0700 Subject: [PATCH 148/199] Fix variable name --- .github/workflows/gradle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index cb1952bc8..467a867bc 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -86,8 +86,8 @@ jobs: .gradle build ~/.gradle - key: {{ runner.os }}-gradle - restore-keys: {{ runner.os }}-gradle + key: ${{ runner.os }}-gradle + restore-keys: ${{ runner.os }}-gradle - name: Cache konan uses: actions/cache@v2 From 95c1504c00006eb4f5096b569cede64788032f93 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 9 Dec 2020 11:41:37 +0700 Subject: [PATCH 149/199] Add cast microoptimization to AsmBuilder --- .../kscience/kmath/asm/internal/AsmBuilder.kt | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index 46051e158..eb0f60f4d 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -3,7 +3,6 @@ package kscience.kmath.asm.internal import kscience.kmath.asm.internal.AsmBuilder.ClassLoader import kscience.kmath.ast.MST import kscience.kmath.expressions.Expression -import kscience.kmath.operations.Algebra import org.objectweb.asm.* import org.objectweb.asm.Opcodes.* import org.objectweb.asm.Type.* @@ -74,7 +73,7 @@ internal class AsmBuilder( classType.internalName, "${OBJECT_TYPE.descriptor}L${EXPRESSION_TYPE.internalName}<${tType.descriptor}>;", OBJECT_TYPE.internalName, - arrayOf(EXPRESSION_TYPE.internalName) + arrayOf(EXPRESSION_TYPE.internalName), ) visitMethod( @@ -82,7 +81,7 @@ internal class AsmBuilder( "invoke", getMethodDescriptor(tType, MAP_TYPE), "(L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;)${tType.descriptor}", - null + null, ).instructionAdapter { invokeMethodVisitor = this visitCode() @@ -97,7 +96,7 @@ internal class AsmBuilder( null, l0, l1, - 0 + 0, ) visitLocalVariable( @@ -106,7 +105,7 @@ internal class AsmBuilder( "L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;", l0, l1, - 1 + 1, ) visitMaxs(0, 2) @@ -118,14 +117,12 @@ internal class AsmBuilder( "invoke", getMethodDescriptor(OBJECT_TYPE, MAP_TYPE), null, - null + null, ).instructionAdapter { - val thisVar = 0 - val argumentsVar = 1 visitCode() val l0 = label() - load(thisVar, OBJECT_TYPE) - load(argumentsVar, MAP_TYPE) + load(0, OBJECT_TYPE) + load(1, MAP_TYPE) invokevirtual(classType.internalName, "invoke", getMethodDescriptor(tType, MAP_TYPE), false) areturn(tType) val l1 = label() @@ -136,7 +133,7 @@ internal class AsmBuilder( null, l0, l1, - thisVar + 0, ) visitMaxs(0, 2) @@ -152,7 +149,7 @@ internal class AsmBuilder( descriptor = OBJECT_ARRAY_TYPE.descriptor, signature = null, value = null, - block = FieldVisitor::visitEnd + block = FieldVisitor::visitEnd, ) visitMethod( @@ -208,7 +205,7 @@ internal class AsmBuilder( getfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor) iconst(idx) visitInsn(AALOAD) - checkcast(type) + if (type != OBJECT_TYPE) checkcast(type) } /** @@ -266,7 +263,7 @@ internal class AsmBuilder( MAP_INTRINSICS_TYPE.internalName, "getOrFail", getMethodDescriptor(OBJECT_TYPE, MAP_TYPE, STRING_TYPE), - false + false, ) checkcast(tType) @@ -321,11 +318,6 @@ internal class AsmBuilder( */ val EXPRESSION_TYPE: Type by lazy { getObjectType("kscience/kmath/expressions/Expression") } - /** - * ASM type for [java.lang.Number]. - */ - val NUMBER_TYPE: Type by lazy { getObjectType("java/lang/Number") } - /** * ASM type for [java.util.Map]. */ @@ -341,11 +333,6 @@ internal class AsmBuilder( */ val OBJECT_ARRAY_TYPE: Type by lazy { getType("[Ljava/lang/Object;") } - /** - * ASM type for [Algebra]. - */ - val ALGEBRA_TYPE: Type by lazy { getObjectType("kscience/kmath/operations/Algebra") } - /** * ASM type for [java.lang.String]. */ From 07d6d891928d89d3eb14917cfbf78d790e4883b8 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 9 Dec 2020 14:43:37 +0700 Subject: [PATCH 150/199] Replace reflective constructor invocation with method handle --- .../kscience/kmath/asm/internal/AsmBuilder.kt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index eb0f60f4d..d146afeee 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -7,6 +7,8 @@ import org.objectweb.asm.* import org.objectweb.asm.Opcodes.* import org.objectweb.asm.Type.* import org.objectweb.asm.commons.InstructionAdapter +import java.lang.invoke.MethodHandles +import java.lang.invoke.MethodType import java.util.stream.Collectors.toMap import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -187,13 +189,14 @@ internal class AsmBuilder( visitEnd() } -// java.io.File("dump.class").writeBytes(classWriter.toByteArray()) + val cls = classLoader.defineClass(className, classWriter.toByteArray()) + val l = MethodHandles.publicLookup() - classLoader - .defineClass(className, classWriter.toByteArray()) - .constructors - .first() - .newInstance(*(constants.toTypedArray().wrapToArrayIf { hasConstants })) as Expression + if (hasConstants) + l.findConstructor(cls, MethodType.methodType(Void.TYPE, Array::class.java)) + .invoke(constants.toTypedArray()) as Expression + else + l.findConstructor(cls, MethodType.methodType(Void.TYPE)).invoke() as Expression } /** @@ -248,7 +251,7 @@ internal class AsmBuilder( r.internalName, "valueOf", getMethodDescriptor(r, primitive), - false + false, ) } From bdd33ca6ca608663882616f1b8147fe0f65d070c Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 00:40:18 +0700 Subject: [PATCH 151/199] Add dependencies needed for ESTree codegen --- kmath-ast/build.gradle.kts | 6 + kmath-ast/src/jsMain/kotlin/Codegen.kt | 0 kmath-ast/src/jsMain/kotlin/astring.d.ts | 50 ++ kmath-ast/src/jsMain/kotlin/astring.global.kt | 17 + kmath-ast/src/jsMain/kotlin/astring.kt | 32 + kmath-ast/src/jsMain/kotlin/emitter.d.ts | 19 + kmath-ast/src/jsMain/kotlin/emitter.kt | 18 + kmath-ast/src/jsMain/kotlin/estree.d.ts | 569 +++++++++++++++ kmath-ast/src/jsMain/kotlin/estree.kt | 647 ++++++++++++++++++ .../src/jsMain/kotlin/lib.es2015.iterable.kt | 40 ++ kmath-ast/src/jsMain/kotlin/lib.es5.kt | 86 +++ kmath-ast/src/jsMain/kotlin/stream.d.ts | 5 + kmath-ast/src/jsMain/kotlin/stream.kt | 9 + 13 files changed, 1498 insertions(+) create mode 100644 kmath-ast/src/jsMain/kotlin/Codegen.kt create mode 100644 kmath-ast/src/jsMain/kotlin/astring.d.ts create mode 100644 kmath-ast/src/jsMain/kotlin/astring.global.kt create mode 100644 kmath-ast/src/jsMain/kotlin/astring.kt create mode 100644 kmath-ast/src/jsMain/kotlin/emitter.d.ts create mode 100644 kmath-ast/src/jsMain/kotlin/emitter.kt create mode 100644 kmath-ast/src/jsMain/kotlin/estree.d.ts create mode 100644 kmath-ast/src/jsMain/kotlin/estree.kt create mode 100644 kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt create mode 100644 kmath-ast/src/jsMain/kotlin/lib.es5.kt create mode 100644 kmath-ast/src/jsMain/kotlin/stream.d.ts create mode 100644 kmath-ast/src/jsMain/kotlin/stream.kt diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 3e3c0475f..e3884025d 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -9,6 +9,12 @@ kotlin.sourceSets { } } + jsMain { + dependencies { + implementation(npm("astring", "1.4.3")) + } + } + jvmMain { dependencies { api("com.github.h0tk3y.betterParse:better-parse:0.4.0") diff --git a/kmath-ast/src/jsMain/kotlin/Codegen.kt b/kmath-ast/src/jsMain/kotlin/Codegen.kt new file mode 100644 index 000000000..e69de29bb diff --git a/kmath-ast/src/jsMain/kotlin/astring.d.ts b/kmath-ast/src/jsMain/kotlin/astring.d.ts new file mode 100644 index 000000000..22cd7e980 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/astring.d.ts @@ -0,0 +1,50 @@ +// Type definitions for astring 1.3 +// Project: https://github.com/davidbonnet/astring +// Definitions by: Nikolaj Kappler +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +import * as ESTree from 'estree'; +import 'node'; +import { Stream } from 'stream'; + +export interface Options { + /** string to use for indentation (defaults to " ") */ + indent?: string; + /** string to use for line endings (defaults to "\n") */ + lineEnd?: string; + /** indent level to start from (defaults to 0) */ + startingIndentLevel?: number; + /** generate comments if true (defaults to false) */ + comments?: boolean; + /** custom code generator (defaults to astring.baseGenerator) */ + generator?: object; + /** source map generator (defaults to null), see https://github.com/mozilla/source-map#sourcemapgenerator */ + sourceMap?: any; +} + +/** Returns a string representing the rendered code of the provided AST `node`. However, if an `output` stream is provided in the options, it writes to that stream and returns it. */ +export function generate(node: ESTree.Node, options?: Options): string; +/** Returns a string representing the rendered code of the provided AST `node`. However, if an `output` stream is provided in the options, it writes to that stream and returns it. */ +export function generate(node: ESTree.Node, options: Options & { + /** output stream to write the rendered code to (defaults to null) */ + output: Stream; +}): Stream; + +/** + * A code generator consists of a mapping of node names and functions that take two arguments: `node` and `state`. + * The `node` points to the node from which to generate the code and the `state` exposes the `write` method that takes generated code strings. + */ +export type Generator = { [key in ESTree.Node["type"]]: (node: Extract, state: { write(s: string): void }) => void }; + +/** Base generator that can be used to extend Astring. See https://github.com/davidbonnet/astring#extending */ +export const baseGenerator: Generator; + +declare global { + interface astring { + generate: typeof generate; + /** Base generator that can be used to extend Astring. See https://github.com/davidbonnet/astring#extending */ + baseGenerator: Generator; + } + const astring: astring; +} \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/astring.global.kt b/kmath-ast/src/jsMain/kotlin/astring.global.kt new file mode 100644 index 000000000..78c771f26 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/astring.global.kt @@ -0,0 +1,17 @@ +@file:JsQualifier("global") +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "PackageDirectoryMismatch", "ClassName" +) + +package global + +import Generator + +@Suppress("EXTERNAL_DELEGATION", "NESTED_CLASS_IN_EXTERNAL_INTERFACE") +external interface astring { + var generate: Any + var baseGenerator: Generator + + companion object : astring by definedExternally +} \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/astring.kt b/kmath-ast/src/jsMain/kotlin/astring.kt new file mode 100644 index 000000000..e9ab6f627 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/astring.kt @@ -0,0 +1,32 @@ +@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation" +) + +external interface Options { + var indent: String? + get() = definedExternally + set(value) = definedExternally + var lineEnd: String? + get() = definedExternally + set(value) = definedExternally + var startingIndentLevel: Number? + get() = definedExternally + set(value) = definedExternally + var comments: Boolean? + get() = definedExternally + set(value) = definedExternally + var generator: Any? + get() = definedExternally + set(value) = definedExternally + var sourceMap: Any? + get() = definedExternally + set(value) = definedExternally +} + +external fun generate(node: BaseNode, options: Options /* Options & `T$0` */ = definedExternally): String + +external fun generate(node: BaseNode): String + +typealias Generator = Any + +external var baseGenerator: Generator \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/emitter.d.ts b/kmath-ast/src/jsMain/kotlin/emitter.d.ts new file mode 100644 index 000000000..ea0319cd6 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/emitter.d.ts @@ -0,0 +1,19 @@ +export class Emitter { + constructor(obj: any) + constructor() + + on(event: string, fn: () => void) + + off(event: string, fn: () => void) + + once(event: string, fn: () => void) + + emit(event: string, ...any: any[]) + + listeners(event: string): (() => void)[] + + hasListeners(event: string): boolean +} + + +function mixin(obj: any): any diff --git a/kmath-ast/src/jsMain/kotlin/emitter.kt b/kmath-ast/src/jsMain/kotlin/emitter.kt new file mode 100644 index 000000000..ad0a16bf7 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/emitter.kt @@ -0,0 +1,18 @@ +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", + "OVERRIDING_FINAL_MEMBER", + "RETURN_TYPE_MISMATCH_ON_OVERRIDE", + "CONFLICTING_OVERLOADS", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "SortModifiers" +) + +external open class Emitter { + constructor(obj: Any) + constructor() + + open fun on(event: String, fn: () -> Unit) + open fun off(event: String, fn: () -> Unit) + open fun once(event: String, fn: () -> Unit) + open fun emit(event: String, vararg any: Any) + open fun listeners(event: String): Array<() -> Unit> + open fun hasListeners(event: String): Boolean +} \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/estree.d.ts b/kmath-ast/src/jsMain/kotlin/estree.d.ts new file mode 100644 index 000000000..927477c66 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/estree.d.ts @@ -0,0 +1,569 @@ +// Type definitions for ESTree AST specification +// Project: https://github.com/estree/estree +// Definitions by: RReverser +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +// This definition file follows a somewhat unusual format. ESTree allows +// runtime type checks based on the `type` parameter. In order to explain this +// to typescript we want to use discriminated union types: +// https://github.com/Microsoft/TypeScript/pull/9163 +// +// For ESTree this is a bit tricky because the high level interfaces like +// Node or Function are pulling double duty. We want to pass common fields down +// to the interfaces that extend them (like Identifier or +// ArrowFunctionExpression), but you can't extend a type union or enforce +// common fields on them. So we've split the high level interfaces into two +// types, a base type which passes down inhereted fields, and a type union of +// all types which extend the base type. Only the type union is exported, and +// the union is how other types refer to the collection of inheriting types. +// +// This makes the definitions file here somewhat more difficult to maintain, +// but it has the notable advantage of making ESTree much easier to use as +// an end user. + +interface BaseNodeWithoutComments { + // Every leaf interface that extends BaseNode must specify a type property. + // The type property should be a string literal. For example, Identifier + // has: `type: "Identifier"` + type: string; + loc?: SourceLocation | null; + range?: [number, number]; +} + +interface BaseNode extends BaseNodeWithoutComments { + leadingComments?: Array; + trailingComments?: Array; +} + +export type Node = + Identifier | Literal | Program | Function | SwitchCase | CatchClause | + VariableDeclarator | Statement | Expression | Property | + AssignmentProperty | Super | TemplateElement | SpreadElement | Pattern | + ClassBody | Class | MethodDefinition | ModuleDeclaration | ModuleSpecifier; + +export interface Comment extends BaseNodeWithoutComments { + type: "Line" | "Block"; + value: string; +} + +interface SourceLocation { + source?: string | null; + start: Position; + end: Position; +} + +export interface Position { + /** >= 1 */ + line: number; + /** >= 0 */ + column: number; +} + +export interface Program extends BaseNode { + type: "Program"; + sourceType: "script" | "module"; + body: Array; + comments?: Array; +} + +export interface Directive extends BaseNode { + type: "ExpressionStatement"; + expression: Literal; + directive: string; +} + +interface BaseFunction extends BaseNode { + params: Array; + generator?: boolean; + async?: boolean; + // The body is either BlockStatement or Expression because arrow functions + // can have a body that's either. FunctionDeclarations and + // FunctionExpressions have only BlockStatement bodies. + body: BlockStatement | Expression; +} + +export type Function = + FunctionDeclaration | FunctionExpression | ArrowFunctionExpression; + +export type Statement = + ExpressionStatement | BlockStatement | EmptyStatement | + DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | + BreakStatement | ContinueStatement | IfStatement | SwitchStatement | + ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | + ForStatement | ForInStatement | ForOfStatement | Declaration; + +interface BaseStatement extends BaseNode { } + +export interface EmptyStatement extends BaseStatement { + type: "EmptyStatement"; +} + +export interface BlockStatement extends BaseStatement { + type: "BlockStatement"; + body: Array; + innerComments?: Array; +} + +export interface ExpressionStatement extends BaseStatement { + type: "ExpressionStatement"; + expression: Expression; +} + +export interface IfStatement extends BaseStatement { + type: "IfStatement"; + test: Expression; + consequent: Statement; + alternate?: Statement | null; +} + +export interface LabeledStatement extends BaseStatement { + type: "LabeledStatement"; + label: Identifier; + body: Statement; +} + +export interface BreakStatement extends BaseStatement { + type: "BreakStatement"; + label?: Identifier | null; +} + +export interface ContinueStatement extends BaseStatement { + type: "ContinueStatement"; + label?: Identifier | null; +} + +export interface WithStatement extends BaseStatement { + type: "WithStatement"; + object: Expression; + body: Statement; +} + +export interface SwitchStatement extends BaseStatement { + type: "SwitchStatement"; + discriminant: Expression; + cases: Array; +} + +export interface ReturnStatement extends BaseStatement { + type: "ReturnStatement"; + argument?: Expression | null; +} + +export interface ThrowStatement extends BaseStatement { + type: "ThrowStatement"; + argument: Expression; +} + +export interface TryStatement extends BaseStatement { + type: "TryStatement"; + block: BlockStatement; + handler?: CatchClause | null; + finalizer?: BlockStatement | null; +} + +export interface WhileStatement extends BaseStatement { + type: "WhileStatement"; + test: Expression; + body: Statement; +} + +export interface DoWhileStatement extends BaseStatement { + type: "DoWhileStatement"; + body: Statement; + test: Expression; +} + +export interface ForStatement extends BaseStatement { + type: "ForStatement"; + init?: VariableDeclaration | Expression | null; + test?: Expression | null; + update?: Expression | null; + body: Statement; +} + +interface BaseForXStatement extends BaseStatement { + left: VariableDeclaration | Pattern; + right: Expression; + body: Statement; +} + +export interface ForInStatement extends BaseForXStatement { + type: "ForInStatement"; +} + +export interface DebuggerStatement extends BaseStatement { + type: "DebuggerStatement"; +} + +export type Declaration = + FunctionDeclaration | VariableDeclaration | ClassDeclaration; + +interface BaseDeclaration extends BaseStatement { } + +export interface FunctionDeclaration extends BaseFunction, BaseDeclaration { + type: "FunctionDeclaration"; + /** It is null when a function declaration is a part of the `export default function` statement */ + id: Identifier | null; + body: BlockStatement; +} + +export interface VariableDeclaration extends BaseDeclaration { + type: "VariableDeclaration"; + declarations: Array; + kind: "var" | "let" | "const"; +} + +export interface VariableDeclarator extends BaseNode { + type: "VariableDeclarator"; + id: Pattern; + init?: Expression | null; +} + +type Expression = + ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | + ArrowFunctionExpression | YieldExpression | Literal | UnaryExpression | + UpdateExpression | BinaryExpression | AssignmentExpression | + LogicalExpression | MemberExpression | ConditionalExpression | + CallExpression | NewExpression | SequenceExpression | TemplateLiteral | + TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | + AwaitExpression | ImportExpression | ChainExpression; + +export interface BaseExpression extends BaseNode { } + +type ChainElement = SimpleCallExpression | MemberExpression; + +export interface ChainExpression extends BaseExpression { + type: "ChainExpression"; + expression: ChainElement; +} + +export interface ThisExpression extends BaseExpression { + type: "ThisExpression"; +} + +export interface ArrayExpression extends BaseExpression { + type: "ArrayExpression"; + elements: Array; +} + +export interface ObjectExpression extends BaseExpression { + type: "ObjectExpression"; + properties: Array; +} + +export interface Property extends BaseNode { + type: "Property"; + key: Expression; + value: Expression | Pattern; // Could be an AssignmentProperty + kind: "init" | "get" | "set"; + method: boolean; + shorthand: boolean; + computed: boolean; +} + +export interface FunctionExpression extends BaseFunction, BaseExpression { + id?: Identifier | null; + type: "FunctionExpression"; + body: BlockStatement; +} + +export interface SequenceExpression extends BaseExpression { + type: "SequenceExpression"; + expressions: Array; +} + +export interface UnaryExpression extends BaseExpression { + type: "UnaryExpression"; + operator: UnaryOperator; + prefix: true; + argument: Expression; +} + +export interface BinaryExpression extends BaseExpression { + type: "BinaryExpression"; + operator: BinaryOperator; + left: Expression; + right: Expression; +} + +export interface AssignmentExpression extends BaseExpression { + type: "AssignmentExpression"; + operator: AssignmentOperator; + left: Pattern | MemberExpression; + right: Expression; +} + +export interface UpdateExpression extends BaseExpression { + type: "UpdateExpression"; + operator: UpdateOperator; + argument: Expression; + prefix: boolean; +} + +export interface LogicalExpression extends BaseExpression { + type: "LogicalExpression"; + operator: LogicalOperator; + left: Expression; + right: Expression; +} + +export interface ConditionalExpression extends BaseExpression { + type: "ConditionalExpression"; + test: Expression; + alternate: Expression; + consequent: Expression; +} + +interface BaseCallExpression extends BaseExpression { + callee: Expression | Super; + arguments: Array; +} +export type CallExpression = SimpleCallExpression | NewExpression; + +export interface SimpleCallExpression extends BaseCallExpression { + type: "CallExpression"; + optional: boolean; +} + +export interface NewExpression extends BaseCallExpression { + type: "NewExpression"; +} + +export interface MemberExpression extends BaseExpression, BasePattern { + type: "MemberExpression"; + object: Expression | Super; + property: Expression; + computed: boolean; + optional: boolean; +} + +export type Pattern = + Identifier | ObjectPattern | ArrayPattern | RestElement | + AssignmentPattern | MemberExpression; + +interface BasePattern extends BaseNode { } + +export interface SwitchCase extends BaseNode { + type: "SwitchCase"; + test?: Expression | null; + consequent: Array; +} + +export interface CatchClause extends BaseNode { + type: "CatchClause"; + param: Pattern | null; + body: BlockStatement; +} + +export interface Identifier extends BaseNode, BaseExpression, BasePattern { + type: "Identifier"; + name: string; +} + +export type Literal = SimpleLiteral | RegExpLiteral; + +export interface SimpleLiteral extends BaseNode, BaseExpression { + type: "Literal"; + value: string | boolean | number | null; + raw?: string; +} + +export interface RegExpLiteral extends BaseNode, BaseExpression { + type: "Literal"; + value?: RegExp | null; + regex: { + pattern: string; + flags: string; + }; + raw?: string; +} + +export type UnaryOperator = + "-" | "+" | "!" | "~" | "typeof" | "void" | "delete"; + +export type BinaryOperator = + "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | + ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "**" | "|" | "^" | "&" | "in" | + "instanceof"; + +export type LogicalOperator = "||" | "&&" | "??"; + +export type AssignmentOperator = + "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "**=" | "<<=" | ">>=" | ">>>=" | + "|=" | "^=" | "&="; + +export type UpdateOperator = "++" | "--"; + +export interface ForOfStatement extends BaseForXStatement { + type: "ForOfStatement"; + await: boolean; +} + +export interface Super extends BaseNode { + type: "Super"; +} + +export interface SpreadElement extends BaseNode { + type: "SpreadElement"; + argument: Expression; +} + +export interface ArrowFunctionExpression extends BaseExpression, BaseFunction { + type: "ArrowFunctionExpression"; + expression: boolean; + body: BlockStatement | Expression; +} + +export interface YieldExpression extends BaseExpression { + type: "YieldExpression"; + argument?: Expression | null; + delegate: boolean; +} + +export interface TemplateLiteral extends BaseExpression { + type: "TemplateLiteral"; + quasis: Array; + expressions: Array; +} + +export interface TaggedTemplateExpression extends BaseExpression { + type: "TaggedTemplateExpression"; + tag: Expression; + quasi: TemplateLiteral; +} + +export interface TemplateElement extends BaseNode { + type: "TemplateElement"; + tail: boolean; + value: { + cooked: string; + raw: string; + }; +} + +export interface AssignmentProperty extends Property { + value: Pattern; + kind: "init"; + method: boolean; // false +} + +export interface ObjectPattern extends BasePattern { + type: "ObjectPattern"; + properties: Array; +} + +export interface ArrayPattern extends BasePattern { + type: "ArrayPattern"; + elements: Array; +} + +export interface RestElement extends BasePattern { + type: "RestElement"; + argument: Pattern; +} + +export interface AssignmentPattern extends BasePattern { + type: "AssignmentPattern"; + left: Pattern; + right: Expression; +} + +export type Class = ClassDeclaration | ClassExpression; +interface BaseClass extends BaseNode { + superClass?: Expression | null; + body: ClassBody; +} + +export interface ClassBody extends BaseNode { + type: "ClassBody"; + body: Array; +} + +export interface MethodDefinition extends BaseNode { + type: "MethodDefinition"; + key: Expression; + value: FunctionExpression; + kind: "constructor" | "method" | "get" | "set"; + computed: boolean; + static: boolean; +} + +export interface ClassDeclaration extends BaseClass, BaseDeclaration { + type: "ClassDeclaration"; + /** It is null when a class declaration is a part of the `export default class` statement */ + id: Identifier | null; +} + +export interface ClassExpression extends BaseClass, BaseExpression { + type: "ClassExpression"; + id?: Identifier | null; +} + +export interface MetaProperty extends BaseExpression { + type: "MetaProperty"; + meta: Identifier; + property: Identifier; +} + +export type ModuleDeclaration = + ImportDeclaration | ExportNamedDeclaration | ExportDefaultDeclaration | + ExportAllDeclaration; +interface BaseModuleDeclaration extends BaseNode { } + +export type ModuleSpecifier = + ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | + ExportSpecifier; +interface BaseModuleSpecifier extends BaseNode { + local: Identifier; +} + +export interface ImportDeclaration extends BaseModuleDeclaration { + type: "ImportDeclaration"; + specifiers: Array; + source: Literal; +} + +export interface ImportSpecifier extends BaseModuleSpecifier { + type: "ImportSpecifier"; + imported: Identifier; +} + +export interface ImportExpression extends BaseExpression { + type: "ImportExpression"; + source: Expression; +} + +export interface ImportDefaultSpecifier extends BaseModuleSpecifier { + type: "ImportDefaultSpecifier"; +} + +export interface ImportNamespaceSpecifier extends BaseModuleSpecifier { + type: "ImportNamespaceSpecifier"; +} + +export interface ExportNamedDeclaration extends BaseModuleDeclaration { + type: "ExportNamedDeclaration"; + declaration?: Declaration | null; + specifiers: Array; + source?: Literal | null; +} + +export interface ExportSpecifier extends BaseModuleSpecifier { + type: "ExportSpecifier"; + exported: Identifier; +} + +export interface ExportDefaultDeclaration extends BaseModuleDeclaration { + type: "ExportDefaultDeclaration"; + declaration: Declaration | Expression; +} + +export interface ExportAllDeclaration extends BaseModuleDeclaration { + type: "ExportAllDeclaration"; + source: Literal; +} + +export interface AwaitExpression extends BaseExpression { + type: "AwaitExpression"; + argument: Expression; +} \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/estree.kt b/kmath-ast/src/jsMain/kotlin/estree.kt new file mode 100644 index 000000000..841688f6d --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/estree.kt @@ -0,0 +1,647 @@ +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "ClassName", +) + +import kotlin.js.RegExp + +external interface BaseNodeWithoutComments { + var type: String + var loc: SourceLocation? + get() = definedExternally + set(value) = definedExternally + var range: dynamic /* JsTuple */ + get() = definedExternally + set(value) = definedExternally +} + +external interface BaseNode : BaseNodeWithoutComments { + var leadingComments: Array? + get() = definedExternally + set(value) = definedExternally + var trailingComments: Array? + get() = definedExternally + set(value) = definedExternally +} + +external interface Comment : BaseNodeWithoutComments { + override var type: String /* "Line" | "Block" */ + var value: String +} + +external interface SourceLocation { + var source: String? + get() = definedExternally + set(value) = definedExternally + var start: Position + var end: Position +} + +external interface Position { + var line: Number + var column: Number +} + +external interface Program : BaseNode { + override var type: String /* "Program" */ + var sourceType: String /* "script" | "module" */ + var body: Array + var comments: Array? + get() = definedExternally + set(value) = definedExternally +} + +external interface Directive : BaseNode { + override var type: String /* "ExpressionStatement" */ + var expression: dynamic /* SimpleLiteral | RegExpLiteral */ + get() = definedExternally + set(value) = definedExternally + var directive: String +} + +external interface BaseFunction : BaseNode { + var params: Array + var generator: Boolean? + get() = definedExternally + set(value) = definedExternally + var async: Boolean? + get() = definedExternally + set(value) = definedExternally + var body: dynamic /* BlockStatement | ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface BaseStatement : BaseNode + +external interface EmptyStatement : BaseStatement { + override var type: String /* "EmptyStatement" */ +} + +external interface BlockStatement : BaseStatement { + override var type: String /* "BlockStatement" */ + var body: Array + var innerComments: Array? + get() = definedExternally + set(value) = definedExternally +} + +external interface ExpressionStatement : BaseStatement { + override var type: String /* "ExpressionStatement" */ + var expression: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface IfStatement : BaseStatement { + override var type: String /* "IfStatement" */ + var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var consequent: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */ + get() = definedExternally + set(value) = definedExternally + var alternate: dynamic /* ExpressionStatement? | BlockStatement? | EmptyStatement? | DebuggerStatement? | WithStatement? | ReturnStatement? | LabeledStatement? | BreakStatement? | ContinueStatement? | IfStatement? | SwitchStatement? | ThrowStatement? | TryStatement? | WhileStatement? | DoWhileStatement? | ForStatement? | ForInStatement? | ForOfStatement? | FunctionDeclaration? | VariableDeclaration? | ClassDeclaration? */ + get() = definedExternally + set(value) = definedExternally +} + +external interface LabeledStatement : BaseStatement { + override var type: String /* "LabeledStatement" */ + var label: Identifier + var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */ + get() = definedExternally + set(value) = definedExternally +} + +external interface BreakStatement : BaseStatement { + override var type: String /* "BreakStatement" */ + var label: Identifier? + get() = definedExternally + set(value) = definedExternally +} + +external interface ContinueStatement : BaseStatement { + override var type: String /* "ContinueStatement" */ + var label: Identifier? + get() = definedExternally + set(value) = definedExternally +} + +external interface WithStatement : BaseStatement { + override var type: String /* "WithStatement" */ + var `object`: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */ + get() = definedExternally + set(value) = definedExternally +} + +external interface SwitchStatement : BaseStatement { + override var type: String /* "SwitchStatement" */ + var discriminant: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var cases: Array +} + +external interface ReturnStatement : BaseStatement { + override var type: String /* "ReturnStatement" */ + var argument: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ + get() = definedExternally + set(value) = definedExternally +} + +external interface ThrowStatement : BaseStatement { + override var type: String /* "ThrowStatement" */ + var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface TryStatement : BaseStatement { + override var type: String /* "TryStatement" */ + var block: BlockStatement + var handler: CatchClause? + get() = definedExternally + set(value) = definedExternally + var finalizer: BlockStatement? + get() = definedExternally + set(value) = definedExternally +} + +external interface WhileStatement : BaseStatement { + override var type: String /* "WhileStatement" */ + var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */ + get() = definedExternally + set(value) = definedExternally +} + +external interface DoWhileStatement : BaseStatement { + override var type: String /* "DoWhileStatement" */ + var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */ + get() = definedExternally + set(value) = definedExternally + var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface ForStatement : BaseStatement { + override var type: String /* "ForStatement" */ + var init: dynamic /* VariableDeclaration? | ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ + get() = definedExternally + set(value) = definedExternally + var test: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ + get() = definedExternally + set(value) = definedExternally + var update: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ + get() = definedExternally + set(value) = definedExternally + var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */ + get() = definedExternally + set(value) = definedExternally +} + +external interface BaseForXStatement : BaseStatement { + var left: dynamic /* VariableDeclaration | Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ + get() = definedExternally + set(value) = definedExternally + var right: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */ + get() = definedExternally + set(value) = definedExternally +} + +external interface ForInStatement : BaseForXStatement { + override var type: String /* "ForInStatement" */ +} + +external interface DebuggerStatement : BaseStatement { + override var type: String /* "DebuggerStatement" */ +} + +external interface BaseDeclaration : BaseStatement + +external interface FunctionDeclaration : BaseFunction, BaseDeclaration { + override var type: String /* "FunctionDeclaration" */ + var id: Identifier? + override var body: BlockStatement +} + +external interface VariableDeclaration : BaseDeclaration { + override var type: String /* "VariableDeclaration" */ + var declarations: Array + var kind: String /* "var" | "let" | "const" */ +} + +external interface VariableDeclarator : BaseNode { + override var type: String /* "VariableDeclarator" */ + var id: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ + get() = definedExternally + set(value) = definedExternally + var init: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ + get() = definedExternally + set(value) = definedExternally +} + +external interface BaseExpression : BaseNode + +external interface ChainExpression : BaseExpression { + override var type: String /* "ChainExpression" */ + var expression: dynamic /* SimpleCallExpression | MemberExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface ThisExpression : BaseExpression { + override var type: String /* "ThisExpression" */ +} + +external interface ArrayExpression : BaseExpression { + override var type: String /* "ArrayExpression" */ + var elements: Array +} + +external interface ObjectExpression : BaseExpression { + override var type: String /* "ObjectExpression" */ + var properties: Array +} + +external interface Property : BaseNode { + override var type: String /* "Property" */ + var key: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var value: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern */ + get() = definedExternally + set(value) = definedExternally + var kind: String /* "init" | "get" | "set" */ + var method: Boolean + var shorthand: Boolean + var computed: Boolean +} + +external interface FunctionExpression : BaseFunction, BaseExpression { + var id: Identifier? + get() = definedExternally + set(value) = definedExternally + override var type: String /* "FunctionExpression" */ + override var body: BlockStatement +} + +external interface SequenceExpression : BaseExpression { + override var type: String /* "SequenceExpression" */ + var expressions: Array +} + +external interface UnaryExpression : BaseExpression { + override var type: String /* "UnaryExpression" */ + var operator: String /* "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" */ + var prefix: Boolean + var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface BinaryExpression : BaseExpression { + override var type: String /* "BinaryExpression" */ + var operator: String /* "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "**" | "|" | "^" | "&" | "in" | "instanceof" */ + var left: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var right: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface AssignmentExpression : BaseExpression { + override var type: String /* "AssignmentExpression" */ + var operator: String /* "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "**=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" */ + var left: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ + get() = definedExternally + set(value) = definedExternally + var right: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface UpdateExpression : BaseExpression { + override var type: String /* "UpdateExpression" */ + var operator: String /* "++" | "--" */ + var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var prefix: Boolean +} + +external interface LogicalExpression : BaseExpression { + override var type: String /* "LogicalExpression" */ + var operator: String /* "||" | "&&" | "??" */ + var left: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var right: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface ConditionalExpression : BaseExpression { + override var type: String /* "ConditionalExpression" */ + var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var alternate: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var consequent: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface BaseCallExpression : BaseExpression { + var callee: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression | Super */ + get() = definedExternally + set(value) = definedExternally + var arguments: Array +} + +external interface SimpleCallExpression : BaseCallExpression { + override var type: String /* "CallExpression" */ + var optional: Boolean +} + +external interface NewExpression : BaseCallExpression { + override var type: String /* "NewExpression" */ +} + +external interface MemberExpression : BaseExpression, BasePattern { + override var type: String /* "MemberExpression" */ + var `object`: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression | Super */ + get() = definedExternally + set(value) = definedExternally + var property: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var computed: Boolean + var optional: Boolean +} + +external interface BasePattern : BaseNode + +external interface SwitchCase : BaseNode { + override var type: String /* "SwitchCase" */ + var test: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ + get() = definedExternally + set(value) = definedExternally + var consequent: Array +} + +external interface CatchClause : BaseNode { + override var type: String /* "CatchClause" */ + var param: dynamic /* Identifier? | ObjectPattern? | ArrayPattern? | RestElement? | AssignmentPattern? | MemberExpression? */ + get() = definedExternally + set(value) = definedExternally + var body: BlockStatement +} + +external interface Identifier : BaseNode, BaseExpression, BasePattern { + override var type: String /* "Identifier" */ + var name: String +} + +external interface SimpleLiteral : BaseNode, BaseExpression { + override var type: String /* "Literal" */ + var value: dynamic /* String? | Boolean? | Number? */ + get() = definedExternally + set(value) = definedExternally + var raw: String? + get() = definedExternally + set(value) = definedExternally +} + +external interface `T$1` { + var pattern: String + var flags: String +} + +external interface RegExpLiteral : BaseNode, BaseExpression { + override var type: String /* "Literal" */ + var value: RegExp? + get() = definedExternally + set(value) = definedExternally + var regex: `T$1` + var raw: String? + get() = definedExternally + set(value) = definedExternally +} + +external interface ForOfStatement : BaseForXStatement { + override var type: String /* "ForOfStatement" */ + var await: Boolean +} + +external interface Super : BaseNode { + override var type: String /* "Super" */ +} + +external interface SpreadElement : BaseNode { + override var type: String /* "SpreadElement" */ + var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface ArrowFunctionExpression : BaseExpression, BaseFunction { + override var type: String /* "ArrowFunctionExpression" */ + var expression: Boolean + override var body: dynamic /* BlockStatement | ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface YieldExpression : BaseExpression { + override var type: String /* "YieldExpression" */ + var argument: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ + get() = definedExternally + set(value) = definedExternally + var delegate: Boolean +} + +external interface TemplateLiteral : BaseExpression { + override var type: String /* "TemplateLiteral" */ + var quasis: Array + var expressions: Array +} + +external interface TaggedTemplateExpression : BaseExpression { + override var type: String /* "TaggedTemplateExpression" */ + var tag: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var quasi: TemplateLiteral +} + +external interface `T$2` { + var cooked: String + var raw: String +} + +external interface TemplateElement : BaseNode { + override var type: String /* "TemplateElement" */ + var tail: Boolean + var value: `T$2` +} + +external interface AssignmentProperty : Property { + override var value: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ + get() = definedExternally + set(value) = definedExternally + override var kind: String /* "init" */ + override var method: Boolean +} + +external interface ObjectPattern : BasePattern { + override var type: String /* "ObjectPattern" */ + var properties: Array +} + +external interface ArrayPattern : BasePattern { + override var type: String /* "ArrayPattern" */ + var elements: Array +} + +external interface RestElement : BasePattern { + override var type: String /* "RestElement" */ + var argument: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface AssignmentPattern : BasePattern { + override var type: String /* "AssignmentPattern" */ + var left: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ + get() = definedExternally + set(value) = definedExternally + var right: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface BaseClass : BaseNode { + var superClass: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ + get() = definedExternally + set(value) = definedExternally + var body: ClassBody +} + +external interface ClassBody : BaseNode { + override var type: String /* "ClassBody" */ + var body: Array +} + +external interface MethodDefinition : BaseNode { + override var type: String /* "MethodDefinition" */ + var key: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally + var value: FunctionExpression + var kind: String /* "constructor" | "method" | "get" | "set" */ + var computed: Boolean + var static: Boolean +} + +external interface ClassDeclaration : BaseClass, BaseDeclaration { + override var type: String /* "ClassDeclaration" */ + var id: Identifier? +} + +external interface ClassExpression : BaseClass, BaseExpression { + override var type: String /* "ClassExpression" */ + var id: Identifier? + get() = definedExternally + set(value) = definedExternally +} + +external interface MetaProperty : BaseExpression { + override var type: String /* "MetaProperty" */ + var meta: Identifier + var property: Identifier +} + +external interface BaseModuleDeclaration : BaseNode + +external interface BaseModuleSpecifier : BaseNode { + var local: Identifier +} + +external interface ImportDeclaration : BaseModuleDeclaration { + override var type: String /* "ImportDeclaration" */ + var specifiers: Array + var source: dynamic /* SimpleLiteral | RegExpLiteral */ + get() = definedExternally + set(value) = definedExternally +} + +external interface ImportSpecifier : BaseModuleSpecifier { + override var type: String /* "ImportSpecifier" */ + var imported: Identifier +} + +external interface ImportExpression : BaseExpression { + override var type: String /* "ImportExpression" */ + var source: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface ImportDefaultSpecifier : BaseModuleSpecifier { + override var type: String /* "ImportDefaultSpecifier" */ +} + +external interface ImportNamespaceSpecifier : BaseModuleSpecifier { + override var type: String /* "ImportNamespaceSpecifier" */ +} + +external interface ExportNamedDeclaration : BaseModuleDeclaration { + override var type: String /* "ExportNamedDeclaration" */ + var declaration: dynamic /* FunctionDeclaration? | VariableDeclaration? | ClassDeclaration? */ + get() = definedExternally + set(value) = definedExternally + var specifiers: Array + var source: dynamic /* SimpleLiteral? | RegExpLiteral? */ + get() = definedExternally + set(value) = definedExternally +} + +external interface ExportSpecifier : BaseModuleSpecifier { + override var type: String /* "ExportSpecifier" */ + var exported: Identifier +} + +external interface ExportDefaultDeclaration : BaseModuleDeclaration { + override var type: String /* "ExportDefaultDeclaration" */ + var declaration: dynamic /* FunctionDeclaration | VariableDeclaration | ClassDeclaration | ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} + +external interface ExportAllDeclaration : BaseModuleDeclaration { + override var type: String /* "ExportAllDeclaration" */ + var source: dynamic /* SimpleLiteral | RegExpLiteral */ + get() = definedExternally + set(value) = definedExternally +} + +external interface AwaitExpression : BaseExpression { + override var type: String /* "AwaitExpression" */ + var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ + get() = definedExternally + set(value) = definedExternally +} \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt b/kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt new file mode 100644 index 000000000..fd548b72b --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt @@ -0,0 +1,40 @@ +@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS") +package tsstdlib + +import kotlin.js.* +import org.khronos.webgl.* +import org.w3c.dom.* +import org.w3c.dom.events.* +import org.w3c.dom.parsing.* +import org.w3c.dom.svg.* +import org.w3c.dom.url.* +import org.w3c.fetch.* +import org.w3c.files.* +import org.w3c.notifications.* +import org.w3c.performance.* +import org.w3c.workers.* +import org.w3c.xhr.* + +external interface IteratorYieldResult { + var done: Boolean? + get() = definedExternally + set(value) = definedExternally + var value: TYield +} + +external interface IteratorReturnResult { + var done: Boolean + var value: TReturn +} + +external interface Iterator { + fun next(vararg args: Any /* JsTuple<> | JsTuple */): dynamic /* IteratorYieldResult | IteratorReturnResult */ + val `return`: ((value: TReturn) -> dynamic)? + val `throw`: ((e: Any) -> dynamic)? +} + +typealias Iterator__1 = Iterator + +external interface Iterable + +external interface IterableIterator : Iterator__1 \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/lib.es5.kt b/kmath-ast/src/jsMain/kotlin/lib.es5.kt new file mode 100644 index 000000000..fe3847232 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/lib.es5.kt @@ -0,0 +1,86 @@ +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "DEPRECATION", "PackageDirectoryMismatch", "KDocMissingDocumentation", + "PropertyName" +) + +package tsstdlib + +import kotlin.js.RegExp + +typealias RegExpMatchArray = Array + +typealias RegExpExecArray = Array + +external interface RegExpConstructor { + @nativeInvoke + operator fun invoke(pattern: RegExp, flags: String = definedExternally): RegExp + + @nativeInvoke + operator fun invoke(pattern: RegExp): RegExp + + @nativeInvoke + operator fun invoke(pattern: String, flags: String = definedExternally): RegExp + + @nativeInvoke + operator fun invoke(pattern: String): RegExp + var prototype: RegExp + var `$1`: String + var `$2`: String + var `$3`: String + var `$4`: String + var `$5`: String + var `$6`: String + var `$7`: String + var `$8`: String + var `$9`: String + var lastMatch: String +} + +external interface ConcatArray { + var length: Number + + @nativeGetter + operator fun get(n: Number): T? + + @nativeSetter + operator fun set(n: Number, value: T) + fun join(separator: String = definedExternally): String + fun slice(start: Number = definedExternally, end: Number = definedExternally): Array +} + +external interface ArrayConstructor { + fun from(iterable: Iterable): Array + fun from(iterable: ArrayLike): Array + fun from(iterable: Iterable, mapfn: (v: T, k: Number) -> U, thisArg: Any = definedExternally): Array + fun from(iterable: Iterable, mapfn: (v: T, k: Number) -> U): Array + fun from(iterable: ArrayLike, mapfn: (v: T, k: Number) -> U, thisArg: Any = definedExternally): Array + fun from(iterable: ArrayLike, mapfn: (v: T, k: Number) -> U): Array + fun of(vararg items: T): Array + + @nativeInvoke + operator fun invoke(arrayLength: Number = definedExternally): Array + + @nativeInvoke + operator fun invoke(): Array + + @nativeInvoke + operator fun invoke(arrayLength: Number): Array + + @nativeInvoke + operator fun invoke(vararg items: T): Array + fun isArray(arg: Any): Boolean + var prototype: Array +} + +external interface ArrayLike { + var length: Number + + @nativeGetter + operator fun get(n: Number): T? + + @nativeSetter + operator fun set(n: Number, value: T) +} + +typealias Extract = Any \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/stream.d.ts b/kmath-ast/src/jsMain/kotlin/stream.d.ts new file mode 100644 index 000000000..f98fcab8c --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/stream.d.ts @@ -0,0 +1,5 @@ +import {Emitter} from 'emitter' + +export class Stream extends Emitter { + pipe(dest: any, options: any): any +} diff --git a/kmath-ast/src/jsMain/kotlin/stream.kt b/kmath-ast/src/jsMain/kotlin/stream.kt new file mode 100644 index 000000000..d76f43f71 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/stream.kt @@ -0,0 +1,9 @@ +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "SortModifiers", + "KDocMissingDocumentation" +) + +external open class Stream : Emitter { + open fun pipe(dest: Any, options: Any): Any +} \ No newline at end of file From d66fb4be750e92c3f022e32be1338c743fdb1ac4 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 00:56:08 +0700 Subject: [PATCH 152/199] Delete empty file --- kmath-ast/src/jsMain/kotlin/Codegen.kt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 kmath-ast/src/jsMain/kotlin/Codegen.kt diff --git a/kmath-ast/src/jsMain/kotlin/Codegen.kt b/kmath-ast/src/jsMain/kotlin/Codegen.kt deleted file mode 100644 index e69de29bb..000000000 From 32d77c0e7f4868725c54d05fd99da783ffb8dec5 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 17:42:57 +0700 Subject: [PATCH 153/199] Implement ESTree based code generation for the MST --- kmath-ast/build.gradle.kts | 14 +++ kmath-ast/src/jsMain/kotlin/astring.global.kt | 2 +- kmath-ast/src/jsMain/kotlin/astring.kt | 16 +++- .../src/jsMain/kotlin/astring.typealises.kt | 3 + kmath-ast/src/jsMain/kotlin/emitter.d.ts | 3 - kmath-ast/src/jsMain/kotlin/emitter.kt | 5 +- .../src/jsMain/kotlin/estree.extensions.kt | 67 +++++++++++++ kmath-ast/src/jsMain/kotlin/estree.kt | 4 +- .../kotlin/kscience/kmath/estree/Codegen.kt | 78 +++++++++++++++ .../kmath/estree/internal/JSBuilder.kt | 73 ++++++++++++++ .../src/jsMain/kotlin/lib.es2015.iterable.kt | 18 +--- kmath-ast/src/jsMain/kotlin/stream.kt | 6 +- .../kmath/estree/TestESTreeAlgebras.kt | 94 +++++++++++++++++++ .../kmath/estree/TestESTreeExpressions.kt | 56 +++++++++++ .../kmath/estree/TestESTreeSpecialization.kt | 54 +++++++++++ .../kmath/estree/TestESTreeVariables.kt | 22 +++++ .../kscience/kmath/asm/internal/AsmBuilder.kt | 2 +- .../kscience/kmath/asm/TestAsmVariables.kt | 4 +- 18 files changed, 491 insertions(+), 30 deletions(-) create mode 100644 kmath-ast/src/jsMain/kotlin/astring.typealises.kt create mode 100644 kmath-ast/src/jsMain/kotlin/estree.extensions.kt create mode 100644 kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt create mode 100644 kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt create mode 100644 kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeAlgebras.kt create mode 100644 kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeExpressions.kt create mode 100644 kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeSpecialization.kt create mode 100644 kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeVariables.kt diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index e3884025d..1f4a87b12 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -2,6 +2,20 @@ plugins { id("ru.mipt.npm.mpp") } +kotlin.js { + nodejs { + testTask { + useMocha().timeout = "0" + } + } + + browser { + testTask { + useMocha().timeout = "0" + } + } +} + kotlin.sourceSets { commonMain { dependencies { diff --git a/kmath-ast/src/jsMain/kotlin/astring.global.kt b/kmath-ast/src/jsMain/kotlin/astring.global.kt index 78c771f26..c69c26caf 100644 --- a/kmath-ast/src/jsMain/kotlin/astring.global.kt +++ b/kmath-ast/src/jsMain/kotlin/astring.global.kt @@ -10,7 +10,7 @@ import Generator @Suppress("EXTERNAL_DELEGATION", "NESTED_CLASS_IN_EXTERNAL_INTERFACE") external interface astring { - var generate: Any + var generate: (dynamic, dynamic) -> dynamic var baseGenerator: Generator companion object : astring by definedExternally diff --git a/kmath-ast/src/jsMain/kotlin/astring.kt b/kmath-ast/src/jsMain/kotlin/astring.kt index e9ab6f627..fe2b2da0a 100644 --- a/kmath-ast/src/jsMain/kotlin/astring.kt +++ b/kmath-ast/src/jsMain/kotlin/astring.kt @@ -1,7 +1,15 @@ -@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", - "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation" +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "PackageDirectoryMismatch" ) +@file:JsModule("astring") +@file:JsNonModule +package astring + +import Generator +import estree.BaseNode + external interface Options { var indent: String? get() = definedExternally @@ -27,6 +35,4 @@ external fun generate(node: BaseNode, options: Options /* Options & `T$0` */ = d external fun generate(node: BaseNode): String -typealias Generator = Any - -external var baseGenerator: Generator \ No newline at end of file +external var baseGenerator: Generator diff --git a/kmath-ast/src/jsMain/kotlin/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/astring.typealises.kt new file mode 100644 index 000000000..9b74e2d04 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/astring.typealises.kt @@ -0,0 +1,3 @@ +@file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation") + +typealias Generator = Any diff --git a/kmath-ast/src/jsMain/kotlin/emitter.d.ts b/kmath-ast/src/jsMain/kotlin/emitter.d.ts index ea0319cd6..4970529d4 100644 --- a/kmath-ast/src/jsMain/kotlin/emitter.d.ts +++ b/kmath-ast/src/jsMain/kotlin/emitter.d.ts @@ -14,6 +14,3 @@ export class Emitter { hasListeners(event: string): boolean } - - -function mixin(obj: any): any diff --git a/kmath-ast/src/jsMain/kotlin/emitter.kt b/kmath-ast/src/jsMain/kotlin/emitter.kt index ad0a16bf7..94398397f 100644 --- a/kmath-ast/src/jsMain/kotlin/emitter.kt +++ b/kmath-ast/src/jsMain/kotlin/emitter.kt @@ -2,9 +2,12 @@ "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", - "CONFLICTING_OVERLOADS", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "SortModifiers" + "CONFLICTING_OVERLOADS", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "SortModifiers", + "PackageDirectoryMismatch" ) +package emitter + external open class Emitter { constructor(obj: Any) constructor() diff --git a/kmath-ast/src/jsMain/kotlin/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/estree.extensions.kt new file mode 100644 index 000000000..d4fc4baa1 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/estree.extensions.kt @@ -0,0 +1,67 @@ +@file:Suppress( + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", + "NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING", "PackageDirectoryMismatch" +) + +package estree + +fun Program(sourceType: String, vararg body: dynamic) = object : Program { + override var type = "Program" + override var sourceType = sourceType + override var body = body +} + +fun VariableDeclaration(kind: String, vararg declarations: VariableDeclarator) = object : VariableDeclaration { + override var type = "VariableDeclaration" + override var declarations = declarations.toList().toTypedArray() + override var kind = kind +} + +fun VariableDeclarator(id: dynamic, init: dynamic) = object : VariableDeclarator { + override var type = "VariableDeclarator" + override var id = id + override var init = init +} + +fun Identifier(name: String) = object : Identifier { + override var type = "Identifier" + override var name = name +} + +fun FunctionExpression(params: Array, body: BlockStatement) = object : FunctionExpression { + override var params = params + override var type = "FunctionExpression" + override var body = body +} + +fun BlockStatement(vararg body: dynamic) = object : BlockStatement { + override var type = "BlockStatement" + override var body = body +} + +fun ReturnStatement(argument: dynamic) = object : ReturnStatement { + override var type = "ReturnStatement" + override var argument = argument +} + +fun SimpleLiteral(value: dynamic) = object : SimpleLiteral { + override var type = "Literal" + override var value = value +} + +fun MemberExpression(computed: Boolean, optional: Boolean, `object`: dynamic, property: dynamic) = + object : MemberExpression { + override var type = "MemberExpression" + override var computed = computed + override var optional = optional + override var `object` = `object` + override var property = property + } + +fun SimpleCallExpression(optional: Boolean, callee: dynamic, vararg arguments: dynamic) = + object : SimpleCallExpression { + override var type = "CallExpression" + override var optional = optional + override var callee = callee + override var arguments = arguments + } diff --git a/kmath-ast/src/jsMain/kotlin/estree.kt b/kmath-ast/src/jsMain/kotlin/estree.kt index 841688f6d..79d043eae 100644 --- a/kmath-ast/src/jsMain/kotlin/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/estree.kt @@ -1,8 +1,10 @@ @file:Suppress( "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", - "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "ClassName", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "ClassName", "PackageDirectoryMismatch", ) +package estree + import kotlin.js.RegExp external interface BaseNodeWithoutComments { diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt new file mode 100644 index 000000000..d10c9c0cf --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt @@ -0,0 +1,78 @@ +package kscience.kmath.estree + +import estree.* +import kscience.kmath.ast.MST +import kscience.kmath.ast.MstExpression +import kscience.kmath.estree.internal.JSBuilder +import kscience.kmath.expressions.Expression +import kscience.kmath.operations.Algebra +import kscience.kmath.operations.NumericAlgebra +import kscience.kmath.operations.RealField + +@PublishedApi +internal fun MST.compileWith(algebra: Algebra): Expression { + fun JSBuilder.visit(node: MST): BaseExpression = when (node) { + is MST.Symbolic -> { + val symbol = try { + algebra.symbol(node.value) + } catch (ignored: IllegalStateException) { + null + } + + if (symbol != null) + constant(symbol) + else + variable(node.value) + } + + is MST.Numeric -> constant(node.value) + is MST.Unary -> call(algebra.unaryOperation(node.operation), visit(node.value)) + + is MST.Binary -> when { + algebra is NumericAlgebra && node.left is MST.Numeric && node.right is MST.Numeric -> constant( + algebra.number( + RealField + .binaryOperation(node.operation) + .invoke(node.left.value.toDouble(), node.right.value.toDouble()) + ) + ) + + algebra is NumericAlgebra && node.left is MST.Numeric -> call( + algebra.leftSideNumberOperation(node.operation), + visit(node.left), + visit(node.right), + ) + + algebra is NumericAlgebra && node.right is MST.Numeric -> call( + algebra.rightSideNumberOperation(node.operation), + visit(node.left), + visit(node.right), + ) + + else -> call( + algebra.binaryOperation(node.operation), + visit(node.left), + visit(node.right), + ) + } + } + + return JSBuilder { visit(this@compileWith) }.instance +} + + +/** + * Compiles an [MST] to ASM using given algebra. + * + * @author Alexander Nozik. + */ +public fun Algebra.expression(mst: MST): Expression = + mst.compileWith(this) + +/** + * Optimizes performance of an [MstExpression] using ASM codegen. + * + * @author Alexander Nozik. + */ +public fun MstExpression>.compile(): Expression = + mst.compileWith(algebra) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt new file mode 100644 index 000000000..7b3f02616 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt @@ -0,0 +1,73 @@ +package kscience.kmath.estree.internal + +import astring.generate +import estree.* +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.Symbol + +internal class JSBuilder(val bodyCallback: JSBuilder.() -> BaseExpression) { + private class GeneratedExpression(val executable: dynamic, val constants: Array) : Expression { + @Suppress("UNUSED_VARIABLE", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") + override fun invoke(map: Map): T { + val e = executable + val c = constants + val a = js("{}") + map.forEach { (key, value) -> a[key.identity] = value } + return js("e(c, a)").unsafeCast() + } + } + + val instance: Expression by lazy { + val node = Program( + sourceType = "script", + VariableDeclaration( + kind = "var", + VariableDeclarator( + id = Identifier("executable"), + init = FunctionExpression( + params = arrayOf(Identifier("constants"), Identifier("arguments")), + body = BlockStatement(ReturnStatement(bodyCallback())), + ), + ), + ), + ) + + eval(generate(node)) + GeneratedExpression(js("executable"), constants.toTypedArray()) + } + + private val constants = mutableListOf() + private val keys = mutableListOf() + + fun constant(value: Any?) = when { + value == null || jsTypeOf(value) == "number" || jsTypeOf(value) == "string" || jsTypeOf(value) == "boolean" -> { + SimpleLiteral(value) + } + + else -> { + val idx = if (value in constants) constants.indexOf(value) else constants.also { it += value }.lastIndex + + MemberExpression( + computed = true, + optional = false, + `object` = Identifier("constants"),я + property = SimpleLiteral(idx), + ) + } + } + + fun variable(name: String): BaseExpression { + return MemberExpression( + computed = true, + optional = false, + `object` = Identifier("arguments"), + property = SimpleLiteral(name), + ) + } + + fun call(function: Function, vararg args: BaseExpression): BaseExpression = SimpleCallExpression( + optional = false, + callee = constant(function), + *args, + ) +} diff --git a/kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt b/kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt index fd548b72b..b55785a8e 100644 --- a/kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt +++ b/kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt @@ -1,20 +1,8 @@ -@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS") +@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "PackageDirectoryMismatch" +) package tsstdlib -import kotlin.js.* -import org.khronos.webgl.* -import org.w3c.dom.* -import org.w3c.dom.events.* -import org.w3c.dom.parsing.* -import org.w3c.dom.svg.* -import org.w3c.dom.url.* -import org.w3c.fetch.* -import org.w3c.files.* -import org.w3c.notifications.* -import org.w3c.performance.* -import org.w3c.workers.* -import org.w3c.xhr.* - external interface IteratorYieldResult { var done: Boolean? get() = definedExternally diff --git a/kmath-ast/src/jsMain/kotlin/stream.kt b/kmath-ast/src/jsMain/kotlin/stream.kt index d76f43f71..c6c30446c 100644 --- a/kmath-ast/src/jsMain/kotlin/stream.kt +++ b/kmath-ast/src/jsMain/kotlin/stream.kt @@ -1,9 +1,13 @@ @file:Suppress( "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "SortModifiers", - "KDocMissingDocumentation" + "KDocMissingDocumentation", "PackageDirectoryMismatch" ) +package stream + +import emitter.Emitter + external open class Stream : Emitter { open fun pipe(dest: Any, options: Any): Any } \ No newline at end of file diff --git a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeAlgebras.kt b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeAlgebras.kt new file mode 100644 index 000000000..09a8ab3e5 --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeAlgebras.kt @@ -0,0 +1,94 @@ +package kscience.kmath.estree + +import kscience.kmath.ast.mstInField +import kscience.kmath.ast.mstInRing +import kscience.kmath.ast.mstInSpace +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.ByteRing +import kscience.kmath.operations.RealField +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestESTreeAlgebras { + @Test + fun space() { + val res1 = ByteRing.mstInSpace { + binaryOperation("+")( + unaryOperation("+")( + number(3.toByte()) - (number(2.toByte()) + (multiply( + add(number(1), number(1)), + 2 + ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) + ), + + number(1) + ) + symbol("x") + zero + }("x" to 2.toByte()) + + val res2 = ByteRing.mstInSpace { + binaryOperation("+")( + unaryOperation("+")( + number(3.toByte()) - (number(2.toByte()) + (multiply( + add(number(1), number(1)), + 2 + ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) + ), + + number(1) + ) + symbol("x") + zero + }.compile()("x" to 2.toByte()) + + assertEquals(res1, res2) + } + + @Test + fun ring() { + val res1 = ByteRing.mstInRing { + binaryOperation("+")( + unaryOperation("+")( + (symbol("x") - (2.toByte() + (multiply( + add(number(1), number(1)), + 2 + ) + 1.toByte()))) * 3.0 - 1.toByte() + ), + + number(1) + ) * number(2) + }("x" to 3.toByte()) + + val res2 = ByteRing.mstInRing { + binaryOperation("+")( + unaryOperation("+")( + (symbol("x") - (2.toByte() + (multiply( + add(number(1), number(1)), + 2 + ) + 1.toByte()))) * 3.0 - 1.toByte() + ), + number(1) + ) * number(2) + }.compile()("x" to 3.toByte()) + + assertEquals(res1, res2) + } + + @Test + fun field() { + val res1 = RealField.mstInField { + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + + number(1), + number(1) / 2 + number(2.0) * one + ) + zero + }("x" to 2.0) + + val res2 = RealField.mstInField { + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + + number(1), + number(1) / 2 + number(2.0) * one + ) + zero + }.compile()("x" to 2.0) + + assertEquals(res1, res2) + } +} diff --git a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeExpressions.kt b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeExpressions.kt new file mode 100644 index 000000000..3dc259cb3 --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeExpressions.kt @@ -0,0 +1,56 @@ +package kscience.kmath.estree + +import kscience.kmath.ast.mstInExtendedField +import kscience.kmath.ast.mstInField +import kscience.kmath.ast.mstInSpace +import kscience.kmath.expressions.Expression +import kscience.kmath.expressions.StringSymbol +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.RealField +import kotlin.math.pow +import kotlin.random.Random +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.time.measureTime + +internal class TestESTreeExpressions { + @Test + fun testUnaryOperationInvocation() { + val expression = RealField.mstInSpace { -symbol("x") }.compile() + val res = expression("x" to 2.0) + assertEquals(-2.0, res) + } + + @Test + fun testBinaryOperationInvocation() { + val expression = RealField.mstInSpace { -symbol("x") + number(1.0) }.compile() + val res = expression("x" to 2.0) + assertEquals(-1.0, res) + } + + @Test + fun testConstProductInvocation() { + val res = RealField.mstInField { symbol("x") * 2 }("x" to 2.0) + assertEquals(4.0, res) + } + + @Test + fun testMultipleCalls() { + val e1 = + RealField.mstInExtendedField { sin(symbol("x")).pow(4) - 6 * symbol("x") / tanh(symbol("x")) }.compile() + + val e2 = Expression { a -> + val x = a.getValue(StringSymbol("x")) + kotlin.math.sin(x).pow(4) - 6 * x / kotlin.math.tanh(x) + } + + var r = Random(0) + var s = 0.0 + measureTime { repeat(1000000) { s += e1("x" to r.nextDouble()) } }.also(::println) + println(s) + s = 0.0 + r = Random(0) + measureTime { repeat(1000000) { s += e2("x" to r.nextDouble()) } }.also(::println) + println(s) + } +} diff --git a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeSpecialization.kt new file mode 100644 index 000000000..0821686fc --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeSpecialization.kt @@ -0,0 +1,54 @@ +package kscience.kmath.estree + +import kscience.kmath.ast.mstInField +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.RealField +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestESTreeSpecialization { + @Test + fun testUnaryPlus() { + val expr = RealField.mstInField { unaryOperation("+")(symbol("x")) }.compile() + assertEquals(2.0, expr("x" to 2.0)) + } + + @Test + fun testUnaryMinus() { + val expr = RealField.mstInField { unaryOperation("-")(symbol("x")) }.compile() + assertEquals(-2.0, expr("x" to 2.0)) + } + + @Test + fun testAdd() { + val expr = RealField.mstInField { binaryOperation("+")(symbol("x"), symbol("x")) }.compile() + assertEquals(4.0, expr("x" to 2.0)) + } + + @Test + fun testSine() { + val expr = RealField.mstInField { unaryOperation("sin")(symbol("x")) }.compile() + assertEquals(0.0, expr("x" to 0.0)) + } + + @Test + fun testMinus() { + val expr = RealField.mstInField { binaryOperation("-")(symbol("x"), symbol("x")) }.compile() + assertEquals(0.0, expr("x" to 2.0)) + } + + @Test + fun testDivide() { + val expr = RealField.mstInField { binaryOperation("/")(symbol("x"), symbol("x")) }.compile() + assertEquals(1.0, expr("x" to 2.0)) + } + + @Test + fun testPower() { + val expr = RealField + .mstInField { binaryOperation("pow")(symbol("x"), number(2)) } + .compile() + + assertEquals(4.0, expr("x" to 2.0)) + } +} diff --git a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeVariables.kt b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeVariables.kt new file mode 100644 index 000000000..b6f59247d --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeVariables.kt @@ -0,0 +1,22 @@ +package kscience.kmath.estree + +import kscience.kmath.ast.mstInRing +import kscience.kmath.expressions.invoke +import kscience.kmath.operations.ByteRing +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +internal class TestESTreeVariables { + @Test + fun testVariableWithoutDefault() { + val expr = ByteRing.mstInRing { symbol("x") }.compile() + assertEquals(1.toByte(), expr("x" to 1.toByte())) + } + + @Test + fun testVariableWithoutDefaultFails() { + val expr = ByteRing.mstInRing { symbol("x") }.compile() + assertFailsWith { expr() } + } +} diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index d146afeee..20e42ed25 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -274,7 +274,7 @@ internal class AsmBuilder( inline fun buildCall(function: Function, parameters: AsmBuilder.() -> Unit) { contract { callsInPlace(parameters, InvocationKind.EXACTLY_ONCE) } - val `interface` = function.javaClass.interfaces.first { it.interfaces.contains(Function::class.java) } + val `interface` = function.javaClass.interfaces.first { Function::class.java in it.interfaces } val arity = `interface`.methods.find { it.name == "invoke" }?.parameterCount ?: error("Provided function object doesn't contain invoke method") diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt index 1011515c8..0ebc31be4 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt @@ -10,13 +10,13 @@ import kotlin.test.assertFailsWith internal class TestAsmVariables { @Test fun testVariableWithoutDefault() { - val expr = ByteRing.mstInRing { symbol("x") } + val expr = ByteRing.mstInRing { symbol("x") }.compile() assertEquals(1.toByte(), expr("x" to 1.toByte())) } @Test fun testVariableWithoutDefaultFails() { - val expr = ByteRing.mstInRing { symbol("x") } + val expr = ByteRing.mstInRing { symbol("x") }.compile() assertFailsWith { expr() } } } From a655404486d5cebef9e8c52c2a0c0e69e394dda3 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 17:43:21 +0700 Subject: [PATCH 154/199] Fix typo --- .../jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt index 7b3f02616..b6b58179b 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt @@ -50,7 +50,7 @@ internal class JSBuilder(val bodyCallback: JSBuilder.() -> BaseExpression) MemberExpression( computed = true, optional = false, - `object` = Identifier("constants"),я + `object` = Identifier("constants"), property = SimpleLiteral(idx), ) } From de3c2a1b5ad902c1b6bba70a4983b033ae822924 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 20 Dec 2020 14:18:12 +0300 Subject: [PATCH 155/199] Add curring and update kotlin --- .../kscience/kmath/operations/Algebra.kt | 28 +++++++++++++++++++ settings.gradle.kts | 4 +-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index 12a45615a..ed10901df 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -22,10 +22,22 @@ public interface Algebra { */ public fun unaryOperation(operation: String, arg: T): T + /** + * Currying version of [unaryOperation] + */ + public fun unaryOperationFunction(operation: String): (T) -> T = { unaryOperation(operation, it) } + /** * Dynamic call of binary operation [operation] on [left] and [right] */ public fun binaryOperation(operation: String, left: T, right: T): T + + /** + * Curring version of [binaryOperation] + */ + public fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = { left, right -> + binaryOperation(operation, left, right) + } } /** @@ -45,11 +57,27 @@ public interface NumericAlgebra : Algebra { public fun leftSideNumberOperation(operation: String, left: Number, right: T): T = binaryOperation(operation, number(left), right) + /** + * Curring version of [leftSideNumberOperation] + */ + public fun leftSideNumberOperationFunction(operation: String): (left: Number, right: T) -> T = + { left: Number, right: T -> + leftSideNumberOperation(operation, left, right) + } + /** * Dynamic call of binary operation [operation] on [left] and [right] where right element is [Number]. */ public fun rightSideNumberOperation(operation: String, left: T, right: Number): T = leftSideNumberOperation(operation, right, left) + + /** + * Curring version of [rightSideNumberOperation] + */ + public fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = + { left: T, right: Number -> + rightSideNumberOperation(operation, left, right) + } } /** diff --git a/settings.gradle.kts b/settings.gradle.kts index 10e4d9577..da33fea59 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,8 +8,8 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlinx") } - val toolsVersion = "0.7.0" - val kotlinVersion = "1.4.20" + val toolsVersion = "0.7.1" + val kotlinVersion = "1.4.21" plugins { id("kotlinx.benchmark") version "0.2.0-dev-20" From 484b35cb4fcb363053512baf3e619410d8ba03cc Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 18:34:35 +0700 Subject: [PATCH 156/199] Fix failing tests --- .../kmath/estree/internal/JSBuilder.kt | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt index b6b58179b..c77f0c9ef 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt @@ -56,18 +56,25 @@ internal class JSBuilder(val bodyCallback: JSBuilder.() -> BaseExpression) } } - fun variable(name: String): BaseExpression { - return MemberExpression( - computed = true, - optional = false, - `object` = Identifier("arguments"), - property = SimpleLiteral(name), - ) - } + fun variable(name: String): BaseExpression = call(getOrFail, Identifier("arguments"), SimpleLiteral(name)) fun call(function: Function, vararg args: BaseExpression): BaseExpression = SimpleCallExpression( optional = false, callee = constant(function), *args, ) + + private companion object { + @Suppress("UNUSED_VARIABLE") + val getOrFail: (`object`: dynamic, key: String) -> dynamic = { `object`, key -> + val k = key + val o = `object` + + if (!(js("k in o") as Boolean)) { + throw NoSuchElementException() + } + + js("o[k]") + } + } } From 3cd00b9df60343767b81d5116196b441cbb5207a Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 18:55:59 +0700 Subject: [PATCH 157/199] Inline internal functions with one usage --- .../kscience/kmath/asm/internal/AsmBuilder.kt | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index 20e42ed25..882b95bf0 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -204,18 +204,13 @@ internal class AsmBuilder( */ fun loadObjectConstant(value: Any, type: Type = tType): Unit = invokeMethodVisitor.run { val idx = if (value in constants) constants.indexOf(value) else constants.also { it += value }.lastIndex - loadThis() + invokeMethodVisitor.load(0, classType) getfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor) iconst(idx) visitInsn(AALOAD) if (type != OBJECT_TYPE) checkcast(type) } - /** - * Loads `this` variable. - */ - private fun loadThis(): Unit = invokeMethodVisitor.load(0, classType) - /** * Either loads a numeric constant [value] from the class's constants field or boxes a primitive * constant from the constant pool. @@ -234,27 +229,21 @@ internal class AsmBuilder( SHORT_TYPE -> invokeMethodVisitor.iconst(value.toInt()) } - box(primitive) + val r = PRIMITIVES_TO_BOXED.getValue(primitive) + + invokeMethodVisitor.invokestatic( + r.internalName, + "valueOf", + getMethodDescriptor(r, primitive), + false, + ) + return } loadObjectConstant(value, boxed) } - /** - * Boxes the current value and pushes it. - */ - private fun box(primitive: Type) { - val r = PRIMITIVES_TO_BOXED.getValue(primitive) - - invokeMethodVisitor.invokestatic( - r.internalName, - "valueOf", - getMethodDescriptor(r, primitive), - false, - ) - } - /** * Loads a variable [name] from arguments [Map] parameter of [Expression.invoke]. */ From 95701bec1b36759242f2c05a06e8dc0ed01c0b8f Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 19:02:36 +0700 Subject: [PATCH 158/199] Add informative NoSuchElementException message --- .../kotlin/kscience/kmath/estree/internal/JSBuilder.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt index c77f0c9ef..c6a36b538 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt @@ -70,9 +70,8 @@ internal class JSBuilder(val bodyCallback: JSBuilder.() -> BaseExpression) val k = key val o = `object` - if (!(js("k in o") as Boolean)) { - throw NoSuchElementException() - } + if (!(js("k in o") as Boolean)) + throw NoSuchElementException("Key $key is missing in the map.") js("o[k]") } From 9a875bc7db3a3e1b5707c2cfdc4dfaec048bc1b2 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 19:04:09 +0700 Subject: [PATCH 159/199] Add missing newline --- kmath-ast/src/jsMain/kotlin/astring.global.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-ast/src/jsMain/kotlin/astring.global.kt b/kmath-ast/src/jsMain/kotlin/astring.global.kt index c69c26caf..d8514c310 100644 --- a/kmath-ast/src/jsMain/kotlin/astring.global.kt +++ b/kmath-ast/src/jsMain/kotlin/astring.global.kt @@ -14,4 +14,4 @@ external interface astring { var baseGenerator: Generator companion object : astring by definedExternally -} \ No newline at end of file +} From d9932042e84ccd1b36274619225fd9fcb5f390ff Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 19:04:43 +0700 Subject: [PATCH 160/199] Delete TS bindings --- kmath-ast/src/jsMain/kotlin/astring.d.ts | 50 -- kmath-ast/src/jsMain/kotlin/emitter.d.ts | 16 - kmath-ast/src/jsMain/kotlin/estree.d.ts | 569 ----------------------- kmath-ast/src/jsMain/kotlin/stream.d.ts | 5 - 4 files changed, 640 deletions(-) delete mode 100644 kmath-ast/src/jsMain/kotlin/astring.d.ts delete mode 100644 kmath-ast/src/jsMain/kotlin/emitter.d.ts delete mode 100644 kmath-ast/src/jsMain/kotlin/estree.d.ts delete mode 100644 kmath-ast/src/jsMain/kotlin/stream.d.ts diff --git a/kmath-ast/src/jsMain/kotlin/astring.d.ts b/kmath-ast/src/jsMain/kotlin/astring.d.ts deleted file mode 100644 index 22cd7e980..000000000 --- a/kmath-ast/src/jsMain/kotlin/astring.d.ts +++ /dev/null @@ -1,50 +0,0 @@ -// Type definitions for astring 1.3 -// Project: https://github.com/davidbonnet/astring -// Definitions by: Nikolaj Kappler -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 - -import * as ESTree from 'estree'; -import 'node'; -import { Stream } from 'stream'; - -export interface Options { - /** string to use for indentation (defaults to " ") */ - indent?: string; - /** string to use for line endings (defaults to "\n") */ - lineEnd?: string; - /** indent level to start from (defaults to 0) */ - startingIndentLevel?: number; - /** generate comments if true (defaults to false) */ - comments?: boolean; - /** custom code generator (defaults to astring.baseGenerator) */ - generator?: object; - /** source map generator (defaults to null), see https://github.com/mozilla/source-map#sourcemapgenerator */ - sourceMap?: any; -} - -/** Returns a string representing the rendered code of the provided AST `node`. However, if an `output` stream is provided in the options, it writes to that stream and returns it. */ -export function generate(node: ESTree.Node, options?: Options): string; -/** Returns a string representing the rendered code of the provided AST `node`. However, if an `output` stream is provided in the options, it writes to that stream and returns it. */ -export function generate(node: ESTree.Node, options: Options & { - /** output stream to write the rendered code to (defaults to null) */ - output: Stream; -}): Stream; - -/** - * A code generator consists of a mapping of node names and functions that take two arguments: `node` and `state`. - * The `node` points to the node from which to generate the code and the `state` exposes the `write` method that takes generated code strings. - */ -export type Generator = { [key in ESTree.Node["type"]]: (node: Extract, state: { write(s: string): void }) => void }; - -/** Base generator that can be used to extend Astring. See https://github.com/davidbonnet/astring#extending */ -export const baseGenerator: Generator; - -declare global { - interface astring { - generate: typeof generate; - /** Base generator that can be used to extend Astring. See https://github.com/davidbonnet/astring#extending */ - baseGenerator: Generator; - } - const astring: astring; -} \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/emitter.d.ts b/kmath-ast/src/jsMain/kotlin/emitter.d.ts deleted file mode 100644 index 4970529d4..000000000 --- a/kmath-ast/src/jsMain/kotlin/emitter.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -export class Emitter { - constructor(obj: any) - constructor() - - on(event: string, fn: () => void) - - off(event: string, fn: () => void) - - once(event: string, fn: () => void) - - emit(event: string, ...any: any[]) - - listeners(event: string): (() => void)[] - - hasListeners(event: string): boolean -} diff --git a/kmath-ast/src/jsMain/kotlin/estree.d.ts b/kmath-ast/src/jsMain/kotlin/estree.d.ts deleted file mode 100644 index 927477c66..000000000 --- a/kmath-ast/src/jsMain/kotlin/estree.d.ts +++ /dev/null @@ -1,569 +0,0 @@ -// Type definitions for ESTree AST specification -// Project: https://github.com/estree/estree -// Definitions by: RReverser -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped - -// This definition file follows a somewhat unusual format. ESTree allows -// runtime type checks based on the `type` parameter. In order to explain this -// to typescript we want to use discriminated union types: -// https://github.com/Microsoft/TypeScript/pull/9163 -// -// For ESTree this is a bit tricky because the high level interfaces like -// Node or Function are pulling double duty. We want to pass common fields down -// to the interfaces that extend them (like Identifier or -// ArrowFunctionExpression), but you can't extend a type union or enforce -// common fields on them. So we've split the high level interfaces into two -// types, a base type which passes down inhereted fields, and a type union of -// all types which extend the base type. Only the type union is exported, and -// the union is how other types refer to the collection of inheriting types. -// -// This makes the definitions file here somewhat more difficult to maintain, -// but it has the notable advantage of making ESTree much easier to use as -// an end user. - -interface BaseNodeWithoutComments { - // Every leaf interface that extends BaseNode must specify a type property. - // The type property should be a string literal. For example, Identifier - // has: `type: "Identifier"` - type: string; - loc?: SourceLocation | null; - range?: [number, number]; -} - -interface BaseNode extends BaseNodeWithoutComments { - leadingComments?: Array; - trailingComments?: Array; -} - -export type Node = - Identifier | Literal | Program | Function | SwitchCase | CatchClause | - VariableDeclarator | Statement | Expression | Property | - AssignmentProperty | Super | TemplateElement | SpreadElement | Pattern | - ClassBody | Class | MethodDefinition | ModuleDeclaration | ModuleSpecifier; - -export interface Comment extends BaseNodeWithoutComments { - type: "Line" | "Block"; - value: string; -} - -interface SourceLocation { - source?: string | null; - start: Position; - end: Position; -} - -export interface Position { - /** >= 1 */ - line: number; - /** >= 0 */ - column: number; -} - -export interface Program extends BaseNode { - type: "Program"; - sourceType: "script" | "module"; - body: Array; - comments?: Array; -} - -export interface Directive extends BaseNode { - type: "ExpressionStatement"; - expression: Literal; - directive: string; -} - -interface BaseFunction extends BaseNode { - params: Array; - generator?: boolean; - async?: boolean; - // The body is either BlockStatement or Expression because arrow functions - // can have a body that's either. FunctionDeclarations and - // FunctionExpressions have only BlockStatement bodies. - body: BlockStatement | Expression; -} - -export type Function = - FunctionDeclaration | FunctionExpression | ArrowFunctionExpression; - -export type Statement = - ExpressionStatement | BlockStatement | EmptyStatement | - DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | - BreakStatement | ContinueStatement | IfStatement | SwitchStatement | - ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | - ForStatement | ForInStatement | ForOfStatement | Declaration; - -interface BaseStatement extends BaseNode { } - -export interface EmptyStatement extends BaseStatement { - type: "EmptyStatement"; -} - -export interface BlockStatement extends BaseStatement { - type: "BlockStatement"; - body: Array; - innerComments?: Array; -} - -export interface ExpressionStatement extends BaseStatement { - type: "ExpressionStatement"; - expression: Expression; -} - -export interface IfStatement extends BaseStatement { - type: "IfStatement"; - test: Expression; - consequent: Statement; - alternate?: Statement | null; -} - -export interface LabeledStatement extends BaseStatement { - type: "LabeledStatement"; - label: Identifier; - body: Statement; -} - -export interface BreakStatement extends BaseStatement { - type: "BreakStatement"; - label?: Identifier | null; -} - -export interface ContinueStatement extends BaseStatement { - type: "ContinueStatement"; - label?: Identifier | null; -} - -export interface WithStatement extends BaseStatement { - type: "WithStatement"; - object: Expression; - body: Statement; -} - -export interface SwitchStatement extends BaseStatement { - type: "SwitchStatement"; - discriminant: Expression; - cases: Array; -} - -export interface ReturnStatement extends BaseStatement { - type: "ReturnStatement"; - argument?: Expression | null; -} - -export interface ThrowStatement extends BaseStatement { - type: "ThrowStatement"; - argument: Expression; -} - -export interface TryStatement extends BaseStatement { - type: "TryStatement"; - block: BlockStatement; - handler?: CatchClause | null; - finalizer?: BlockStatement | null; -} - -export interface WhileStatement extends BaseStatement { - type: "WhileStatement"; - test: Expression; - body: Statement; -} - -export interface DoWhileStatement extends BaseStatement { - type: "DoWhileStatement"; - body: Statement; - test: Expression; -} - -export interface ForStatement extends BaseStatement { - type: "ForStatement"; - init?: VariableDeclaration | Expression | null; - test?: Expression | null; - update?: Expression | null; - body: Statement; -} - -interface BaseForXStatement extends BaseStatement { - left: VariableDeclaration | Pattern; - right: Expression; - body: Statement; -} - -export interface ForInStatement extends BaseForXStatement { - type: "ForInStatement"; -} - -export interface DebuggerStatement extends BaseStatement { - type: "DebuggerStatement"; -} - -export type Declaration = - FunctionDeclaration | VariableDeclaration | ClassDeclaration; - -interface BaseDeclaration extends BaseStatement { } - -export interface FunctionDeclaration extends BaseFunction, BaseDeclaration { - type: "FunctionDeclaration"; - /** It is null when a function declaration is a part of the `export default function` statement */ - id: Identifier | null; - body: BlockStatement; -} - -export interface VariableDeclaration extends BaseDeclaration { - type: "VariableDeclaration"; - declarations: Array; - kind: "var" | "let" | "const"; -} - -export interface VariableDeclarator extends BaseNode { - type: "VariableDeclarator"; - id: Pattern; - init?: Expression | null; -} - -type Expression = - ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | - ArrowFunctionExpression | YieldExpression | Literal | UnaryExpression | - UpdateExpression | BinaryExpression | AssignmentExpression | - LogicalExpression | MemberExpression | ConditionalExpression | - CallExpression | NewExpression | SequenceExpression | TemplateLiteral | - TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | - AwaitExpression | ImportExpression | ChainExpression; - -export interface BaseExpression extends BaseNode { } - -type ChainElement = SimpleCallExpression | MemberExpression; - -export interface ChainExpression extends BaseExpression { - type: "ChainExpression"; - expression: ChainElement; -} - -export interface ThisExpression extends BaseExpression { - type: "ThisExpression"; -} - -export interface ArrayExpression extends BaseExpression { - type: "ArrayExpression"; - elements: Array; -} - -export interface ObjectExpression extends BaseExpression { - type: "ObjectExpression"; - properties: Array; -} - -export interface Property extends BaseNode { - type: "Property"; - key: Expression; - value: Expression | Pattern; // Could be an AssignmentProperty - kind: "init" | "get" | "set"; - method: boolean; - shorthand: boolean; - computed: boolean; -} - -export interface FunctionExpression extends BaseFunction, BaseExpression { - id?: Identifier | null; - type: "FunctionExpression"; - body: BlockStatement; -} - -export interface SequenceExpression extends BaseExpression { - type: "SequenceExpression"; - expressions: Array; -} - -export interface UnaryExpression extends BaseExpression { - type: "UnaryExpression"; - operator: UnaryOperator; - prefix: true; - argument: Expression; -} - -export interface BinaryExpression extends BaseExpression { - type: "BinaryExpression"; - operator: BinaryOperator; - left: Expression; - right: Expression; -} - -export interface AssignmentExpression extends BaseExpression { - type: "AssignmentExpression"; - operator: AssignmentOperator; - left: Pattern | MemberExpression; - right: Expression; -} - -export interface UpdateExpression extends BaseExpression { - type: "UpdateExpression"; - operator: UpdateOperator; - argument: Expression; - prefix: boolean; -} - -export interface LogicalExpression extends BaseExpression { - type: "LogicalExpression"; - operator: LogicalOperator; - left: Expression; - right: Expression; -} - -export interface ConditionalExpression extends BaseExpression { - type: "ConditionalExpression"; - test: Expression; - alternate: Expression; - consequent: Expression; -} - -interface BaseCallExpression extends BaseExpression { - callee: Expression | Super; - arguments: Array; -} -export type CallExpression = SimpleCallExpression | NewExpression; - -export interface SimpleCallExpression extends BaseCallExpression { - type: "CallExpression"; - optional: boolean; -} - -export interface NewExpression extends BaseCallExpression { - type: "NewExpression"; -} - -export interface MemberExpression extends BaseExpression, BasePattern { - type: "MemberExpression"; - object: Expression | Super; - property: Expression; - computed: boolean; - optional: boolean; -} - -export type Pattern = - Identifier | ObjectPattern | ArrayPattern | RestElement | - AssignmentPattern | MemberExpression; - -interface BasePattern extends BaseNode { } - -export interface SwitchCase extends BaseNode { - type: "SwitchCase"; - test?: Expression | null; - consequent: Array; -} - -export interface CatchClause extends BaseNode { - type: "CatchClause"; - param: Pattern | null; - body: BlockStatement; -} - -export interface Identifier extends BaseNode, BaseExpression, BasePattern { - type: "Identifier"; - name: string; -} - -export type Literal = SimpleLiteral | RegExpLiteral; - -export interface SimpleLiteral extends BaseNode, BaseExpression { - type: "Literal"; - value: string | boolean | number | null; - raw?: string; -} - -export interface RegExpLiteral extends BaseNode, BaseExpression { - type: "Literal"; - value?: RegExp | null; - regex: { - pattern: string; - flags: string; - }; - raw?: string; -} - -export type UnaryOperator = - "-" | "+" | "!" | "~" | "typeof" | "void" | "delete"; - -export type BinaryOperator = - "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | - ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "**" | "|" | "^" | "&" | "in" | - "instanceof"; - -export type LogicalOperator = "||" | "&&" | "??"; - -export type AssignmentOperator = - "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "**=" | "<<=" | ">>=" | ">>>=" | - "|=" | "^=" | "&="; - -export type UpdateOperator = "++" | "--"; - -export interface ForOfStatement extends BaseForXStatement { - type: "ForOfStatement"; - await: boolean; -} - -export interface Super extends BaseNode { - type: "Super"; -} - -export interface SpreadElement extends BaseNode { - type: "SpreadElement"; - argument: Expression; -} - -export interface ArrowFunctionExpression extends BaseExpression, BaseFunction { - type: "ArrowFunctionExpression"; - expression: boolean; - body: BlockStatement | Expression; -} - -export interface YieldExpression extends BaseExpression { - type: "YieldExpression"; - argument?: Expression | null; - delegate: boolean; -} - -export interface TemplateLiteral extends BaseExpression { - type: "TemplateLiteral"; - quasis: Array; - expressions: Array; -} - -export interface TaggedTemplateExpression extends BaseExpression { - type: "TaggedTemplateExpression"; - tag: Expression; - quasi: TemplateLiteral; -} - -export interface TemplateElement extends BaseNode { - type: "TemplateElement"; - tail: boolean; - value: { - cooked: string; - raw: string; - }; -} - -export interface AssignmentProperty extends Property { - value: Pattern; - kind: "init"; - method: boolean; // false -} - -export interface ObjectPattern extends BasePattern { - type: "ObjectPattern"; - properties: Array; -} - -export interface ArrayPattern extends BasePattern { - type: "ArrayPattern"; - elements: Array; -} - -export interface RestElement extends BasePattern { - type: "RestElement"; - argument: Pattern; -} - -export interface AssignmentPattern extends BasePattern { - type: "AssignmentPattern"; - left: Pattern; - right: Expression; -} - -export type Class = ClassDeclaration | ClassExpression; -interface BaseClass extends BaseNode { - superClass?: Expression | null; - body: ClassBody; -} - -export interface ClassBody extends BaseNode { - type: "ClassBody"; - body: Array; -} - -export interface MethodDefinition extends BaseNode { - type: "MethodDefinition"; - key: Expression; - value: FunctionExpression; - kind: "constructor" | "method" | "get" | "set"; - computed: boolean; - static: boolean; -} - -export interface ClassDeclaration extends BaseClass, BaseDeclaration { - type: "ClassDeclaration"; - /** It is null when a class declaration is a part of the `export default class` statement */ - id: Identifier | null; -} - -export interface ClassExpression extends BaseClass, BaseExpression { - type: "ClassExpression"; - id?: Identifier | null; -} - -export interface MetaProperty extends BaseExpression { - type: "MetaProperty"; - meta: Identifier; - property: Identifier; -} - -export type ModuleDeclaration = - ImportDeclaration | ExportNamedDeclaration | ExportDefaultDeclaration | - ExportAllDeclaration; -interface BaseModuleDeclaration extends BaseNode { } - -export type ModuleSpecifier = - ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | - ExportSpecifier; -interface BaseModuleSpecifier extends BaseNode { - local: Identifier; -} - -export interface ImportDeclaration extends BaseModuleDeclaration { - type: "ImportDeclaration"; - specifiers: Array; - source: Literal; -} - -export interface ImportSpecifier extends BaseModuleSpecifier { - type: "ImportSpecifier"; - imported: Identifier; -} - -export interface ImportExpression extends BaseExpression { - type: "ImportExpression"; - source: Expression; -} - -export interface ImportDefaultSpecifier extends BaseModuleSpecifier { - type: "ImportDefaultSpecifier"; -} - -export interface ImportNamespaceSpecifier extends BaseModuleSpecifier { - type: "ImportNamespaceSpecifier"; -} - -export interface ExportNamedDeclaration extends BaseModuleDeclaration { - type: "ExportNamedDeclaration"; - declaration?: Declaration | null; - specifiers: Array; - source?: Literal | null; -} - -export interface ExportSpecifier extends BaseModuleSpecifier { - type: "ExportSpecifier"; - exported: Identifier; -} - -export interface ExportDefaultDeclaration extends BaseModuleDeclaration { - type: "ExportDefaultDeclaration"; - declaration: Declaration | Expression; -} - -export interface ExportAllDeclaration extends BaseModuleDeclaration { - type: "ExportAllDeclaration"; - source: Literal; -} - -export interface AwaitExpression extends BaseExpression { - type: "AwaitExpression"; - argument: Expression; -} \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/stream.d.ts b/kmath-ast/src/jsMain/kotlin/stream.d.ts deleted file mode 100644 index f98fcab8c..000000000 --- a/kmath-ast/src/jsMain/kotlin/stream.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {Emitter} from 'emitter' - -export class Stream extends Emitter { - pipe(dest: any, options: any): any -} From 4294bc1b97edbad2f7a6cfe3ea57409aa03bf611 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 19:23:10 +0700 Subject: [PATCH 161/199] Hide bindings from public API --- kmath-ast/src/jsMain/kotlin/astring.global.kt | 17 -- .../src/jsMain/kotlin/astring.typealises.kt | 3 - .../src/jsMain/kotlin/estree.extensions.kt | 67 ------- .../kmath/estree/internal/JSBuilder.kt | 17 +- .../kmath/estree/internal/astring}/astring.kt | 17 +- .../internal/astring/astring.typealises.kt | 3 + .../kmath/estree/internal/emitter}/emitter.kt | 14 +- .../internal/estree/estree.extensions.kt | 74 +++++++ .../kmath/estree/internal/estree}/estree.kt | 183 +++++++++--------- .../kmath/estree/internal/stream/stream.kt | 7 + .../internal/tsstdlib/lib.es2015.iterable.kt | 25 +++ .../estree/internal/tsstdlib}/lib.es5.kt | 22 +-- .../src/jsMain/kotlin/lib.es2015.iterable.kt | 28 --- kmath-ast/src/jsMain/kotlin/stream.kt | 13 -- 14 files changed, 230 insertions(+), 260 deletions(-) delete mode 100644 kmath-ast/src/jsMain/kotlin/astring.global.kt delete mode 100644 kmath-ast/src/jsMain/kotlin/astring.typealises.kt delete mode 100644 kmath-ast/src/jsMain/kotlin/estree.extensions.kt rename kmath-ast/src/jsMain/kotlin/{ => kscience/kmath/estree/internal/astring}/astring.kt (57%) create mode 100644 kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.typealises.kt rename kmath-ast/src/jsMain/kotlin/{ => kscience/kmath/estree/internal/emitter}/emitter.kt (51%) create mode 100644 kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.extensions.kt rename kmath-ast/src/jsMain/kotlin/{ => kscience/kmath/estree/internal/estree}/estree.kt (88%) create mode 100644 kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/stream/stream.kt create mode 100644 kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt rename kmath-ast/src/jsMain/kotlin/{ => kscience/kmath/estree/internal/tsstdlib}/lib.es5.kt (77%) delete mode 100644 kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt delete mode 100644 kmath-ast/src/jsMain/kotlin/stream.kt diff --git a/kmath-ast/src/jsMain/kotlin/astring.global.kt b/kmath-ast/src/jsMain/kotlin/astring.global.kt deleted file mode 100644 index d8514c310..000000000 --- a/kmath-ast/src/jsMain/kotlin/astring.global.kt +++ /dev/null @@ -1,17 +0,0 @@ -@file:JsQualifier("global") -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", - "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "PackageDirectoryMismatch", "ClassName" -) - -package global - -import Generator - -@Suppress("EXTERNAL_DELEGATION", "NESTED_CLASS_IN_EXTERNAL_INTERFACE") -external interface astring { - var generate: (dynamic, dynamic) -> dynamic - var baseGenerator: Generator - - companion object : astring by definedExternally -} diff --git a/kmath-ast/src/jsMain/kotlin/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/astring.typealises.kt deleted file mode 100644 index 9b74e2d04..000000000 --- a/kmath-ast/src/jsMain/kotlin/astring.typealises.kt +++ /dev/null @@ -1,3 +0,0 @@ -@file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation") - -typealias Generator = Any diff --git a/kmath-ast/src/jsMain/kotlin/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/estree.extensions.kt deleted file mode 100644 index d4fc4baa1..000000000 --- a/kmath-ast/src/jsMain/kotlin/estree.extensions.kt +++ /dev/null @@ -1,67 +0,0 @@ -@file:Suppress( - "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", - "NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING", "PackageDirectoryMismatch" -) - -package estree - -fun Program(sourceType: String, vararg body: dynamic) = object : Program { - override var type = "Program" - override var sourceType = sourceType - override var body = body -} - -fun VariableDeclaration(kind: String, vararg declarations: VariableDeclarator) = object : VariableDeclaration { - override var type = "VariableDeclaration" - override var declarations = declarations.toList().toTypedArray() - override var kind = kind -} - -fun VariableDeclarator(id: dynamic, init: dynamic) = object : VariableDeclarator { - override var type = "VariableDeclarator" - override var id = id - override var init = init -} - -fun Identifier(name: String) = object : Identifier { - override var type = "Identifier" - override var name = name -} - -fun FunctionExpression(params: Array, body: BlockStatement) = object : FunctionExpression { - override var params = params - override var type = "FunctionExpression" - override var body = body -} - -fun BlockStatement(vararg body: dynamic) = object : BlockStatement { - override var type = "BlockStatement" - override var body = body -} - -fun ReturnStatement(argument: dynamic) = object : ReturnStatement { - override var type = "ReturnStatement" - override var argument = argument -} - -fun SimpleLiteral(value: dynamic) = object : SimpleLiteral { - override var type = "Literal" - override var value = value -} - -fun MemberExpression(computed: Boolean, optional: Boolean, `object`: dynamic, property: dynamic) = - object : MemberExpression { - override var type = "MemberExpression" - override var computed = computed - override var optional = optional - override var `object` = `object` - override var property = property - } - -fun SimpleCallExpression(optional: Boolean, callee: dynamic, vararg arguments: dynamic) = - object : SimpleCallExpression { - override var type = "CallExpression" - override var optional = optional - override var callee = callee - override var arguments = arguments - } diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt index c6a36b538..b38be085d 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt @@ -1,18 +1,29 @@ package kscience.kmath.estree.internal -import astring.generate +import kscience.kmath.estree.internal.astring.generate import estree.* +import kscience.kmath.estree.internal.estree.* +import kscience.kmath.estree.internal.estree.BlockStatement +import kscience.kmath.estree.internal.estree.FunctionExpression +import kscience.kmath.estree.internal.estree.Identifier +import kscience.kmath.estree.internal.estree.MemberExpression +import kscience.kmath.estree.internal.estree.Program +import kscience.kmath.estree.internal.estree.ReturnStatement +import kscience.kmath.estree.internal.estree.SimpleCallExpression +import kscience.kmath.estree.internal.estree.SimpleLiteral +import kscience.kmath.estree.internal.estree.VariableDeclaration +import kscience.kmath.estree.internal.estree.VariableDeclarator import kscience.kmath.expressions.Expression import kscience.kmath.expressions.Symbol internal class JSBuilder(val bodyCallback: JSBuilder.() -> BaseExpression) { private class GeneratedExpression(val executable: dynamic, val constants: Array) : Expression { @Suppress("UNUSED_VARIABLE", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") - override fun invoke(map: Map): T { + override fun invoke(arguments: Map): T { val e = executable val c = constants val a = js("{}") - map.forEach { (key, value) -> a[key.identity] = value } + arguments.forEach { (key, value) -> a[key.identity] = value } return js("e(c, a)").unsafeCast() } } diff --git a/kmath-ast/src/jsMain/kotlin/astring.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.kt similarity index 57% rename from kmath-ast/src/jsMain/kotlin/astring.kt rename to kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.kt index fe2b2da0a..4ef3acf20 100644 --- a/kmath-ast/src/jsMain/kotlin/astring.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.kt @@ -1,16 +1,11 @@ -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", - "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "PackageDirectoryMismatch" -) - @file:JsModule("astring") @file:JsNonModule -package astring -import Generator +package kscience.kmath.estree.internal.astring + import estree.BaseNode -external interface Options { +internal external interface Options { var indent: String? get() = definedExternally set(value) = definedExternally @@ -31,8 +26,8 @@ external interface Options { set(value) = definedExternally } -external fun generate(node: BaseNode, options: Options /* Options & `T$0` */ = definedExternally): String +internal external fun generate(node: BaseNode, options: Options /* Options & `T$0` */ = definedExternally): String -external fun generate(node: BaseNode): String +internal external fun generate(node: BaseNode): String -external var baseGenerator: Generator +internal external var baseGenerator: Generator diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.typealises.kt new file mode 100644 index 000000000..5a7fe4f16 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.typealises.kt @@ -0,0 +1,3 @@ +package kscience.kmath.estree.internal.astring + +internal typealias Generator = Any diff --git a/kmath-ast/src/jsMain/kotlin/emitter.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/emitter/emitter.kt similarity index 51% rename from kmath-ast/src/jsMain/kotlin/emitter.kt rename to kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/emitter/emitter.kt index 94398397f..1e0a95a16 100644 --- a/kmath-ast/src/jsMain/kotlin/emitter.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/emitter/emitter.kt @@ -1,14 +1,6 @@ -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", - "OVERRIDING_FINAL_MEMBER", - "RETURN_TYPE_MISMATCH_ON_OVERRIDE", - "CONFLICTING_OVERLOADS", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "SortModifiers", - "PackageDirectoryMismatch" -) +package kscience.kmath.estree.internal.emitter -package emitter - -external open class Emitter { +internal open external class Emitter { constructor(obj: Any) constructor() @@ -18,4 +10,4 @@ external open class Emitter { open fun emit(event: String, vararg any: Any) open fun listeners(event: String): Array<() -> Unit> open fun hasListeners(event: String): Boolean -} \ No newline at end of file +} diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.extensions.kt new file mode 100644 index 000000000..951cd9ef8 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.extensions.kt @@ -0,0 +1,74 @@ +package kscience.kmath.estree.internal.estree + +import estree.* +import estree.BlockStatement +import estree.FunctionExpression +import estree.Identifier +import estree.MemberExpression +import estree.Program +import estree.ReturnStatement +import estree.SimpleCallExpression +import estree.SimpleLiteral +import estree.VariableDeclaration +import estree.VariableDeclarator + +internal fun Program(sourceType: String, vararg body: dynamic) = object : Program { + override var type = "Program" + override var sourceType = sourceType + override var body = body +} + +internal fun VariableDeclaration(kind: String, vararg declarations: VariableDeclarator) = object : VariableDeclaration { + override var type = "VariableDeclaration" + override var declarations = declarations.toList().toTypedArray() + override var kind = kind +} + +internal fun VariableDeclarator(id: dynamic, init: dynamic) = object : VariableDeclarator { + override var type = "VariableDeclarator" + override var id = id + override var init = init +} + +internal fun Identifier(name: String) = object : Identifier { + override var type = "Identifier" + override var name = name +} + +internal fun FunctionExpression(params: Array, body: BlockStatement) = object : FunctionExpression { + override var params = params + override var type = "FunctionExpression" + override var body = body +} + +internal fun BlockStatement(vararg body: dynamic) = object : BlockStatement { + override var type = "BlockStatement" + override var body = body +} + +internal fun ReturnStatement(argument: dynamic) = object : ReturnStatement { + override var type = "ReturnStatement" + override var argument = argument +} + +internal fun SimpleLiteral(value: dynamic) = object : SimpleLiteral { + override var type = "Literal" + override var value = value +} + +internal fun MemberExpression(computed: Boolean, optional: Boolean, `object`: dynamic, property: dynamic) = + object : MemberExpression { + override var type = "MemberExpression" + override var computed = computed + override var optional = optional + override var `object` = `object` + override var property = property + } + +internal fun SimpleCallExpression(optional: Boolean, callee: dynamic, vararg arguments: dynamic) = + object : SimpleCallExpression { + override var type = "CallExpression" + override var optional = optional + override var callee = callee + override var arguments = arguments + } diff --git a/kmath-ast/src/jsMain/kotlin/estree.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.kt similarity index 88% rename from kmath-ast/src/jsMain/kotlin/estree.kt rename to kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.kt index 79d043eae..8d894a1b1 100644 --- a/kmath-ast/src/jsMain/kotlin/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.kt @@ -1,13 +1,8 @@ -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", - "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "ClassName", "PackageDirectoryMismatch", -) - package estree import kotlin.js.RegExp -external interface BaseNodeWithoutComments { +internal external interface BaseNodeWithoutComments { var type: String var loc: SourceLocation? get() = definedExternally @@ -17,7 +12,7 @@ external interface BaseNodeWithoutComments { set(value) = definedExternally } -external interface BaseNode : BaseNodeWithoutComments { +internal external interface BaseNode : BaseNodeWithoutComments { var leadingComments: Array? get() = definedExternally set(value) = definedExternally @@ -26,12 +21,12 @@ external interface BaseNode : BaseNodeWithoutComments { set(value) = definedExternally } -external interface Comment : BaseNodeWithoutComments { +internal external interface Comment : BaseNodeWithoutComments { override var type: String /* "Line" | "Block" */ var value: String } -external interface SourceLocation { +internal external interface SourceLocation { var source: String? get() = definedExternally set(value) = definedExternally @@ -39,12 +34,12 @@ external interface SourceLocation { var end: Position } -external interface Position { +internal external interface Position { var line: Number var column: Number } -external interface Program : BaseNode { +internal external interface Program : BaseNode { override var type: String /* "Program" */ var sourceType: String /* "script" | "module" */ var body: Array @@ -53,7 +48,7 @@ external interface Program : BaseNode { set(value) = definedExternally } -external interface Directive : BaseNode { +internal external interface Directive : BaseNode { override var type: String /* "ExpressionStatement" */ var expression: dynamic /* SimpleLiteral | RegExpLiteral */ get() = definedExternally @@ -61,7 +56,7 @@ external interface Directive : BaseNode { var directive: String } -external interface BaseFunction : BaseNode { +internal external interface BaseFunction : BaseNode { var params: Array var generator: Boolean? get() = definedExternally @@ -74,13 +69,13 @@ external interface BaseFunction : BaseNode { set(value) = definedExternally } -external interface BaseStatement : BaseNode +internal external interface BaseStatement : BaseNode -external interface EmptyStatement : BaseStatement { +internal external interface EmptyStatement : BaseStatement { override var type: String /* "EmptyStatement" */ } -external interface BlockStatement : BaseStatement { +internal external interface BlockStatement : BaseStatement { override var type: String /* "BlockStatement" */ var body: Array var innerComments: Array? @@ -88,14 +83,14 @@ external interface BlockStatement : BaseStatement { set(value) = definedExternally } -external interface ExpressionStatement : BaseStatement { +internal external interface ExpressionStatement : BaseStatement { override var type: String /* "ExpressionStatement" */ var expression: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally set(value) = definedExternally } -external interface IfStatement : BaseStatement { +internal external interface IfStatement : BaseStatement { override var type: String /* "IfStatement" */ var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally @@ -108,7 +103,7 @@ external interface IfStatement : BaseStatement { set(value) = definedExternally } -external interface LabeledStatement : BaseStatement { +internal external interface LabeledStatement : BaseStatement { override var type: String /* "LabeledStatement" */ var label: Identifier var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */ @@ -116,21 +111,21 @@ external interface LabeledStatement : BaseStatement { set(value) = definedExternally } -external interface BreakStatement : BaseStatement { +internal external interface BreakStatement : BaseStatement { override var type: String /* "BreakStatement" */ var label: Identifier? get() = definedExternally set(value) = definedExternally } -external interface ContinueStatement : BaseStatement { +internal external interface ContinueStatement : BaseStatement { override var type: String /* "ContinueStatement" */ var label: Identifier? get() = definedExternally set(value) = definedExternally } -external interface WithStatement : BaseStatement { +internal external interface WithStatement : BaseStatement { override var type: String /* "WithStatement" */ var `object`: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally @@ -140,7 +135,7 @@ external interface WithStatement : BaseStatement { set(value) = definedExternally } -external interface SwitchStatement : BaseStatement { +internal external interface SwitchStatement : BaseStatement { override var type: String /* "SwitchStatement" */ var discriminant: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally @@ -148,21 +143,21 @@ external interface SwitchStatement : BaseStatement { var cases: Array } -external interface ReturnStatement : BaseStatement { +internal external interface ReturnStatement : BaseStatement { override var type: String /* "ReturnStatement" */ var argument: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ get() = definedExternally set(value) = definedExternally } -external interface ThrowStatement : BaseStatement { +internal external interface ThrowStatement : BaseStatement { override var type: String /* "ThrowStatement" */ var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally set(value) = definedExternally } -external interface TryStatement : BaseStatement { +internal external interface TryStatement : BaseStatement { override var type: String /* "TryStatement" */ var block: BlockStatement var handler: CatchClause? @@ -173,7 +168,7 @@ external interface TryStatement : BaseStatement { set(value) = definedExternally } -external interface WhileStatement : BaseStatement { +internal external interface WhileStatement : BaseStatement { override var type: String /* "WhileStatement" */ var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally @@ -183,7 +178,7 @@ external interface WhileStatement : BaseStatement { set(value) = definedExternally } -external interface DoWhileStatement : BaseStatement { +internal external interface DoWhileStatement : BaseStatement { override var type: String /* "DoWhileStatement" */ var body: dynamic /* ExpressionStatement | BlockStatement | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | VariableDeclaration | ClassDeclaration */ get() = definedExternally @@ -193,7 +188,7 @@ external interface DoWhileStatement : BaseStatement { set(value) = definedExternally } -external interface ForStatement : BaseStatement { +internal external interface ForStatement : BaseStatement { override var type: String /* "ForStatement" */ var init: dynamic /* VariableDeclaration? | ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ get() = definedExternally @@ -209,7 +204,7 @@ external interface ForStatement : BaseStatement { set(value) = definedExternally } -external interface BaseForXStatement : BaseStatement { +internal external interface BaseForXStatement : BaseStatement { var left: dynamic /* VariableDeclaration | Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ get() = definedExternally set(value) = definedExternally @@ -221,29 +216,29 @@ external interface BaseForXStatement : BaseStatement { set(value) = definedExternally } -external interface ForInStatement : BaseForXStatement { +internal external interface ForInStatement : BaseForXStatement { override var type: String /* "ForInStatement" */ } -external interface DebuggerStatement : BaseStatement { +internal external interface DebuggerStatement : BaseStatement { override var type: String /* "DebuggerStatement" */ } -external interface BaseDeclaration : BaseStatement +internal external interface BaseDeclaration : BaseStatement -external interface FunctionDeclaration : BaseFunction, BaseDeclaration { +internal external interface FunctionDeclaration : BaseFunction, BaseDeclaration { override var type: String /* "FunctionDeclaration" */ var id: Identifier? override var body: BlockStatement } -external interface VariableDeclaration : BaseDeclaration { +internal external interface VariableDeclaration : BaseDeclaration { override var type: String /* "VariableDeclaration" */ var declarations: Array var kind: String /* "var" | "let" | "const" */ } -external interface VariableDeclarator : BaseNode { +internal external interface VariableDeclarator : BaseNode { override var type: String /* "VariableDeclarator" */ var id: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ get() = definedExternally @@ -253,30 +248,30 @@ external interface VariableDeclarator : BaseNode { set(value) = definedExternally } -external interface BaseExpression : BaseNode +internal external interface BaseExpression : BaseNode -external interface ChainExpression : BaseExpression { +internal external interface ChainExpression : BaseExpression { override var type: String /* "ChainExpression" */ var expression: dynamic /* SimpleCallExpression | MemberExpression */ get() = definedExternally set(value) = definedExternally } -external interface ThisExpression : BaseExpression { +internal external interface ThisExpression : BaseExpression { override var type: String /* "ThisExpression" */ } -external interface ArrayExpression : BaseExpression { +internal external interface ArrayExpression : BaseExpression { override var type: String /* "ArrayExpression" */ var elements: Array } -external interface ObjectExpression : BaseExpression { +internal external interface ObjectExpression : BaseExpression { override var type: String /* "ObjectExpression" */ var properties: Array } -external interface Property : BaseNode { +internal external interface Property : BaseNode { override var type: String /* "Property" */ var key: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally @@ -290,7 +285,7 @@ external interface Property : BaseNode { var computed: Boolean } -external interface FunctionExpression : BaseFunction, BaseExpression { +internal external interface FunctionExpression : BaseFunction, BaseExpression { var id: Identifier? get() = definedExternally set(value) = definedExternally @@ -298,12 +293,12 @@ external interface FunctionExpression : BaseFunction, BaseExpression { override var body: BlockStatement } -external interface SequenceExpression : BaseExpression { +internal external interface SequenceExpression : BaseExpression { override var type: String /* "SequenceExpression" */ var expressions: Array } -external interface UnaryExpression : BaseExpression { +internal external interface UnaryExpression : BaseExpression { override var type: String /* "UnaryExpression" */ var operator: String /* "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" */ var prefix: Boolean @@ -312,7 +307,7 @@ external interface UnaryExpression : BaseExpression { set(value) = definedExternally } -external interface BinaryExpression : BaseExpression { +internal external interface BinaryExpression : BaseExpression { override var type: String /* "BinaryExpression" */ var operator: String /* "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "**" | "|" | "^" | "&" | "in" | "instanceof" */ var left: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ @@ -323,7 +318,7 @@ external interface BinaryExpression : BaseExpression { set(value) = definedExternally } -external interface AssignmentExpression : BaseExpression { +internal external interface AssignmentExpression : BaseExpression { override var type: String /* "AssignmentExpression" */ var operator: String /* "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "**=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" */ var left: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ @@ -334,7 +329,7 @@ external interface AssignmentExpression : BaseExpression { set(value) = definedExternally } -external interface UpdateExpression : BaseExpression { +internal external interface UpdateExpression : BaseExpression { override var type: String /* "UpdateExpression" */ var operator: String /* "++" | "--" */ var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ @@ -343,7 +338,7 @@ external interface UpdateExpression : BaseExpression { var prefix: Boolean } -external interface LogicalExpression : BaseExpression { +internal external interface LogicalExpression : BaseExpression { override var type: String /* "LogicalExpression" */ var operator: String /* "||" | "&&" | "??" */ var left: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ @@ -354,7 +349,7 @@ external interface LogicalExpression : BaseExpression { set(value) = definedExternally } -external interface ConditionalExpression : BaseExpression { +internal external interface ConditionalExpression : BaseExpression { override var type: String /* "ConditionalExpression" */ var test: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally @@ -367,23 +362,23 @@ external interface ConditionalExpression : BaseExpression { set(value) = definedExternally } -external interface BaseCallExpression : BaseExpression { +internal external interface BaseCallExpression : BaseExpression { var callee: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression | Super */ get() = definedExternally set(value) = definedExternally var arguments: Array } -external interface SimpleCallExpression : BaseCallExpression { +internal external interface SimpleCallExpression : BaseCallExpression { override var type: String /* "CallExpression" */ var optional: Boolean } -external interface NewExpression : BaseCallExpression { +internal external interface NewExpression : BaseCallExpression { override var type: String /* "NewExpression" */ } -external interface MemberExpression : BaseExpression, BasePattern { +internal external interface MemberExpression : BaseExpression, BasePattern { override var type: String /* "MemberExpression" */ var `object`: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression | Super */ get() = definedExternally @@ -395,9 +390,9 @@ external interface MemberExpression : BaseExpression, BasePattern { var optional: Boolean } -external interface BasePattern : BaseNode +internal external interface BasePattern : BaseNode -external interface SwitchCase : BaseNode { +internal external interface SwitchCase : BaseNode { override var type: String /* "SwitchCase" */ var test: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ get() = definedExternally @@ -405,7 +400,7 @@ external interface SwitchCase : BaseNode { var consequent: Array } -external interface CatchClause : BaseNode { +internal external interface CatchClause : BaseNode { override var type: String /* "CatchClause" */ var param: dynamic /* Identifier? | ObjectPattern? | ArrayPattern? | RestElement? | AssignmentPattern? | MemberExpression? */ get() = definedExternally @@ -413,12 +408,12 @@ external interface CatchClause : BaseNode { var body: BlockStatement } -external interface Identifier : BaseNode, BaseExpression, BasePattern { +internal external interface Identifier : BaseNode, BaseExpression, BasePattern { override var type: String /* "Identifier" */ var name: String } -external interface SimpleLiteral : BaseNode, BaseExpression { +internal external interface SimpleLiteral : BaseNode, BaseExpression { override var type: String /* "Literal" */ var value: dynamic /* String? | Boolean? | Number? */ get() = definedExternally @@ -428,12 +423,12 @@ external interface SimpleLiteral : BaseNode, BaseExpression { set(value) = definedExternally } -external interface `T$1` { +internal external interface `T$1` { var pattern: String var flags: String } -external interface RegExpLiteral : BaseNode, BaseExpression { +internal external interface RegExpLiteral : BaseNode, BaseExpression { override var type: String /* "Literal" */ var value: RegExp? get() = definedExternally @@ -444,23 +439,23 @@ external interface RegExpLiteral : BaseNode, BaseExpression { set(value) = definedExternally } -external interface ForOfStatement : BaseForXStatement { +internal external interface ForOfStatement : BaseForXStatement { override var type: String /* "ForOfStatement" */ var await: Boolean } -external interface Super : BaseNode { +internal external interface Super : BaseNode { override var type: String /* "Super" */ } -external interface SpreadElement : BaseNode { +internal external interface SpreadElement : BaseNode { override var type: String /* "SpreadElement" */ var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally set(value) = definedExternally } -external interface ArrowFunctionExpression : BaseExpression, BaseFunction { +internal external interface ArrowFunctionExpression : BaseExpression, BaseFunction { override var type: String /* "ArrowFunctionExpression" */ var expression: Boolean override var body: dynamic /* BlockStatement | ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ @@ -468,7 +463,7 @@ external interface ArrowFunctionExpression : BaseExpression, BaseFunction { set(value) = definedExternally } -external interface YieldExpression : BaseExpression { +internal external interface YieldExpression : BaseExpression { override var type: String /* "YieldExpression" */ var argument: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ get() = definedExternally @@ -476,13 +471,13 @@ external interface YieldExpression : BaseExpression { var delegate: Boolean } -external interface TemplateLiteral : BaseExpression { +internal external interface TemplateLiteral : BaseExpression { override var type: String /* "TemplateLiteral" */ var quasis: Array var expressions: Array } -external interface TaggedTemplateExpression : BaseExpression { +internal external interface TaggedTemplateExpression : BaseExpression { override var type: String /* "TaggedTemplateExpression" */ var tag: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally @@ -490,18 +485,18 @@ external interface TaggedTemplateExpression : BaseExpression { var quasi: TemplateLiteral } -external interface `T$2` { +internal external interface `T$2` { var cooked: String var raw: String } -external interface TemplateElement : BaseNode { +internal external interface TemplateElement : BaseNode { override var type: String /* "TemplateElement" */ var tail: Boolean var value: `T$2` } -external interface AssignmentProperty : Property { +internal external interface AssignmentProperty : Property { override var value: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ get() = definedExternally set(value) = definedExternally @@ -509,24 +504,24 @@ external interface AssignmentProperty : Property { override var method: Boolean } -external interface ObjectPattern : BasePattern { +internal external interface ObjectPattern : BasePattern { override var type: String /* "ObjectPattern" */ var properties: Array } -external interface ArrayPattern : BasePattern { +internal external interface ArrayPattern : BasePattern { override var type: String /* "ArrayPattern" */ var elements: Array } -external interface RestElement : BasePattern { +internal external interface RestElement : BasePattern { override var type: String /* "RestElement" */ var argument: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ get() = definedExternally set(value) = definedExternally } -external interface AssignmentPattern : BasePattern { +internal external interface AssignmentPattern : BasePattern { override var type: String /* "AssignmentPattern" */ var left: dynamic /* Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression */ get() = definedExternally @@ -536,19 +531,19 @@ external interface AssignmentPattern : BasePattern { set(value) = definedExternally } -external interface BaseClass : BaseNode { +internal external interface BaseClass : BaseNode { var superClass: dynamic /* ThisExpression? | ArrayExpression? | ObjectExpression? | FunctionExpression? | ArrowFunctionExpression? | YieldExpression? | SimpleLiteral? | RegExpLiteral? | UnaryExpression? | UpdateExpression? | BinaryExpression? | AssignmentExpression? | LogicalExpression? | MemberExpression? | ConditionalExpression? | SimpleCallExpression? | NewExpression? | SequenceExpression? | TemplateLiteral? | TaggedTemplateExpression? | ClassExpression? | MetaProperty? | Identifier? | AwaitExpression? | ImportExpression? | ChainExpression? */ get() = definedExternally set(value) = definedExternally var body: ClassBody } -external interface ClassBody : BaseNode { +internal external interface ClassBody : BaseNode { override var type: String /* "ClassBody" */ var body: Array } -external interface MethodDefinition : BaseNode { +internal external interface MethodDefinition : BaseNode { override var type: String /* "MethodDefinition" */ var key: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally @@ -559,31 +554,31 @@ external interface MethodDefinition : BaseNode { var static: Boolean } -external interface ClassDeclaration : BaseClass, BaseDeclaration { +internal external interface ClassDeclaration : BaseClass, BaseDeclaration { override var type: String /* "ClassDeclaration" */ var id: Identifier? } -external interface ClassExpression : BaseClass, BaseExpression { +internal external interface ClassExpression : BaseClass, BaseExpression { override var type: String /* "ClassExpression" */ var id: Identifier? get() = definedExternally set(value) = definedExternally } -external interface MetaProperty : BaseExpression { +internal external interface MetaProperty : BaseExpression { override var type: String /* "MetaProperty" */ var meta: Identifier var property: Identifier } -external interface BaseModuleDeclaration : BaseNode +internal external interface BaseModuleDeclaration : BaseNode -external interface BaseModuleSpecifier : BaseNode { +internal external interface BaseModuleSpecifier : BaseNode { var local: Identifier } -external interface ImportDeclaration : BaseModuleDeclaration { +internal external interface ImportDeclaration : BaseModuleDeclaration { override var type: String /* "ImportDeclaration" */ var specifiers: Array var source: dynamic /* SimpleLiteral | RegExpLiteral */ @@ -591,27 +586,27 @@ external interface ImportDeclaration : BaseModuleDeclaration { set(value) = definedExternally } -external interface ImportSpecifier : BaseModuleSpecifier { +internal external interface ImportSpecifier : BaseModuleSpecifier { override var type: String /* "ImportSpecifier" */ var imported: Identifier } -external interface ImportExpression : BaseExpression { +internal external interface ImportExpression : BaseExpression { override var type: String /* "ImportExpression" */ var source: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally set(value) = definedExternally } -external interface ImportDefaultSpecifier : BaseModuleSpecifier { +internal external interface ImportDefaultSpecifier : BaseModuleSpecifier { override var type: String /* "ImportDefaultSpecifier" */ } -external interface ImportNamespaceSpecifier : BaseModuleSpecifier { +internal external interface ImportNamespaceSpecifier : BaseModuleSpecifier { override var type: String /* "ImportNamespaceSpecifier" */ } -external interface ExportNamedDeclaration : BaseModuleDeclaration { +internal external interface ExportNamedDeclaration : BaseModuleDeclaration { override var type: String /* "ExportNamedDeclaration" */ var declaration: dynamic /* FunctionDeclaration? | VariableDeclaration? | ClassDeclaration? */ get() = definedExternally @@ -622,28 +617,28 @@ external interface ExportNamedDeclaration : BaseModuleDeclaration { set(value) = definedExternally } -external interface ExportSpecifier : BaseModuleSpecifier { +internal external interface ExportSpecifier : BaseModuleSpecifier { override var type: String /* "ExportSpecifier" */ var exported: Identifier } -external interface ExportDefaultDeclaration : BaseModuleDeclaration { +internal external interface ExportDefaultDeclaration : BaseModuleDeclaration { override var type: String /* "ExportDefaultDeclaration" */ var declaration: dynamic /* FunctionDeclaration | VariableDeclaration | ClassDeclaration | ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally set(value) = definedExternally } -external interface ExportAllDeclaration : BaseModuleDeclaration { +internal external interface ExportAllDeclaration : BaseModuleDeclaration { override var type: String /* "ExportAllDeclaration" */ var source: dynamic /* SimpleLiteral | RegExpLiteral */ get() = definedExternally set(value) = definedExternally } -external interface AwaitExpression : BaseExpression { +internal external interface AwaitExpression : BaseExpression { override var type: String /* "AwaitExpression" */ var argument: dynamic /* ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | YieldExpression | SimpleLiteral | RegExpLiteral | UnaryExpression | UpdateExpression | BinaryExpression | AssignmentExpression | LogicalExpression | MemberExpression | ConditionalExpression | SimpleCallExpression | NewExpression | SequenceExpression | TemplateLiteral | TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier | AwaitExpression | ImportExpression | ChainExpression */ get() = definedExternally set(value) = definedExternally -} \ No newline at end of file +} diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/stream/stream.kt new file mode 100644 index 000000000..b3c65a758 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/stream/stream.kt @@ -0,0 +1,7 @@ +package kscience.kmath.estree.internal.stream + +import 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/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt new file mode 100644 index 000000000..22d4dd8e0 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt @@ -0,0 +1,25 @@ +package kscience.kmath.estree.internal.tsstdlib + +internal external interface IteratorYieldResult { + var done: Boolean? + get() = definedExternally + set(value) = definedExternally + var value: TYield +} + +internal external interface IteratorReturnResult { + var done: Boolean + var value: TReturn +} + +internal external interface Iterator { + fun next(vararg args: Any /* JsTuple<> | JsTuple */): dynamic /* IteratorYieldResult | IteratorReturnResult */ + val `return`: ((value: TReturn) -> dynamic)? + val `throw`: ((e: Any) -> dynamic)? +} + +internal typealias Iterator__1 = Iterator + +internal external interface Iterable + +internal external interface IterableIterator : Iterator__1 diff --git a/kmath-ast/src/jsMain/kotlin/lib.es5.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt similarity index 77% rename from kmath-ast/src/jsMain/kotlin/lib.es5.kt rename to kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt index fe3847232..70f6d9702 100644 --- a/kmath-ast/src/jsMain/kotlin/lib.es5.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt @@ -1,18 +1,14 @@ -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", - "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "DEPRECATION", "PackageDirectoryMismatch", "KDocMissingDocumentation", - "PropertyName" -) +@file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION") -package tsstdlib +package kscience.kmath.estree.internal.tsstdlib import kotlin.js.RegExp -typealias RegExpMatchArray = Array +internal typealias RegExpMatchArray = Array -typealias RegExpExecArray = Array +internal typealias RegExpExecArray = Array -external interface RegExpConstructor { +internal external interface RegExpConstructor { @nativeInvoke operator fun invoke(pattern: RegExp, flags: String = definedExternally): RegExp @@ -37,7 +33,7 @@ external interface RegExpConstructor { var lastMatch: String } -external interface ConcatArray { +internal external interface ConcatArray { var length: Number @nativeGetter @@ -49,7 +45,7 @@ external interface ConcatArray { fun slice(start: Number = definedExternally, end: Number = definedExternally): Array } -external interface ArrayConstructor { +internal external interface ArrayConstructor { fun from(iterable: Iterable): Array fun from(iterable: ArrayLike): Array fun from(iterable: Iterable, mapfn: (v: T, k: Number) -> U, thisArg: Any = definedExternally): Array @@ -73,7 +69,7 @@ external interface ArrayConstructor { var prototype: Array } -external interface ArrayLike { +internal external interface ArrayLike { var length: Number @nativeGetter @@ -83,4 +79,4 @@ external interface ArrayLike { operator fun set(n: Number, value: T) } -typealias Extract = Any \ No newline at end of file +internal typealias Extract = Any diff --git a/kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt b/kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt deleted file mode 100644 index b55785a8e..000000000 --- a/kmath-ast/src/jsMain/kotlin/lib.es2015.iterable.kt +++ /dev/null @@ -1,28 +0,0 @@ -@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", - "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation", "PackageDirectoryMismatch" -) -package tsstdlib - -external interface IteratorYieldResult { - var done: Boolean? - get() = definedExternally - set(value) = definedExternally - var value: TYield -} - -external interface IteratorReturnResult { - var done: Boolean - var value: TReturn -} - -external interface Iterator { - fun next(vararg args: Any /* JsTuple<> | JsTuple */): dynamic /* IteratorYieldResult | IteratorReturnResult */ - val `return`: ((value: TReturn) -> dynamic)? - val `throw`: ((e: Any) -> dynamic)? -} - -typealias Iterator__1 = Iterator - -external interface Iterable - -external interface IterableIterator : Iterator__1 \ No newline at end of file diff --git a/kmath-ast/src/jsMain/kotlin/stream.kt b/kmath-ast/src/jsMain/kotlin/stream.kt deleted file mode 100644 index c6c30446c..000000000 --- a/kmath-ast/src/jsMain/kotlin/stream.kt +++ /dev/null @@ -1,13 +0,0 @@ -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", - "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "SortModifiers", - "KDocMissingDocumentation", "PackageDirectoryMismatch" -) - -package stream - -import emitter.Emitter - -external open class Stream : Emitter { - open fun pipe(dest: Any, options: Any): Any -} \ No newline at end of file From d70b185b3ea80f4686e860f6edf9d8bc0c334652 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 20:41:17 +0700 Subject: [PATCH 162/199] Update documentation for Algebra, add overloads for xOperation that invokes an operation not dispatches it --- .../kscience/kmath/operations/Algebra.kt | 153 +++++++++++++++--- 1 file changed, 132 insertions(+), 21 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index 2661525fb..3dfd14921 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -13,21 +13,79 @@ public annotation class KMathContext */ public interface Algebra { /** - * Wraps raw string or variable. + * Wraps a raw string to [T] object. This method is designed for three purposes: + * + * 1. Mathematical constants (`e`, `pi`). + * 2. Variables for expression-like contexts (`a`, `b`, `c`...). + * 3. Literals (`{1, 2}`, (`(3; 4)`)). + * + * In case if algebra can't parse the string, this method must throw [kotlin.IllegalStateException]. + * + * @param value the raw string. + * @return an object. */ public fun symbol(value: String): T = error("Wrapping of '$value' is not supported in $this") /** - * Dynamically dispatches an unary operation with name [operation]. + * Dynamically dispatches an unary operation with the certain name. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with second `unaryOperation` overload: + * i.e. `unaryOperation(a)(b) == unaryOperation(a, b)`. + * + * @param operation the name of operation. + * @return an operation. */ public fun unaryOperation(operation: String): (arg: T) -> T = error("Unary operation $operation not defined in $this") /** - * Dynamically dispatches a binary operation with name [operation]. + * Dynamically invokes an unary operation with the certain name. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with second [unaryOperation] overload: + * i.e. `unaryOperation(a)(b) == unaryOperation(a, b)`. + * + * @param operation the name of operation. + * @param arg the argument of operation. + * @return a result of operation. + */ + public fun unaryOperation(operation: String, arg: T): T = unaryOperation(operation)(arg) + + /** + * Dynamically dispatches a binary operation with the certain name. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with second [binaryOperation] overload: + * i.e. `binaryOperation(a)(b, c) == binaryOperation(a, b, c)`. + * + * @param operation the name of operation. + * @return an operation. */ public fun binaryOperation(operation: String): (left: T, right: T) -> T = error("Binary operation $operation not defined in $this") + + /** + * Dynamically invokes a binary operation with the certain name. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with second [binaryOperation] overload: + * i.e. `binaryOperation(a)(b, c) == binaryOperation(a, b, c)`. + * + * @param operation the name of operation. + * @param left the first argument of operation. + * @param right the second argument of operation. + * @return a result of operation. + */ + public fun binaryOperation(operation: String, left: T, right: T): T = binaryOperation(operation)(left, right) } /** @@ -37,33 +95,76 @@ public interface Algebra { */ public interface NumericAlgebra : Algebra { /** - * Wraps a number. + * Wraps a number to [T] object. + * + * @param value the number to wrap. + * @return an object. */ public fun number(value: Number): T /** - * Dynamically dispatches a binary operation with name [operation] where the left argument is [Number]. + * Dynamically dispatches a binary operation with the certain name with numeric first argument. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with the other [leftSideNumberOperation] overload: + * i.e. `leftSideNumberOperation(a)(b, c) == leftSideNumberOperation(a, b)`. + * + * @param operation the name of operation. + * @return an operation. */ public fun leftSideNumberOperation(operation: String): (left: Number, right: T) -> T = { l, r -> binaryOperation(operation)(number(l), r) } -// /** -// * Dynamically calls a binary operation with name [operation] where the left argument is [Number]. -// */ -// public fun leftSideNumberOperation(operation: String, left: Number, right: T): T = -// leftSideNumberOperation(operation)(left, right) + /** + * Dynamically invokes a binary operation with the certain name with numeric first argument. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with second [leftSideNumberOperation] overload: + * i.e. `leftSideNumberOperation(a)(b, c) == leftSideNumberOperation(a, b, c)`. + * + * @param operation the name of operation. + * @param left the first argument of operation. + * @param right the second argument of operation. + * @return a result of operation. + */ + public fun leftSideNumberOperation(operation: String, left: Number, right: T): T = + leftSideNumberOperation(operation)(left, right) /** - * Dynamically dispatches a binary operation with name [operation] where the right argument is [Number]. + * Dynamically dispatches a binary operation with the certain name with numeric first argument. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with the other [rightSideNumberOperation] overload: + * i.e. `rightSideNumberOperation(a)(b, c) == leftSideNumberOperation(a, b, c)`. + * + * @param operation the name of operation. + * @return an operation. */ public fun rightSideNumberOperation(operation: String): (left: T, right: Number) -> T = { l, r -> binaryOperation(operation)(l, number(r)) } -// /** -// * Dynamically calls a binary operation with name [operation] where the right argument is [Number]. -// */ -// public fun rightSideNumberOperation(operation: String, left: T, right: Number): T = -// rightSideNumberOperation(operation)(left, right) + /** + * Dynamically invokes a binary operation with the certain name with numeric second argument. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with the other [rightSideNumberOperation] overload: + * i.e. `rightSideNumberOperation(a)(b, c) == rightSideNumberOperation(a, b, c)`. + * + * @param operation the name of operation. + * @param left the first argument of operation. + * @param right the second argument of operation. + * @return a result of operation. + */ + public fun rightSideNumberOperation(operation: String, left: T, right: Number): T = + rightSideNumberOperation(operation)(left, right) } /** @@ -160,13 +261,13 @@ public interface SpaceOperations : Algebra { */ public operator fun Number.times(b: T): T = b * this - override fun unaryOperation(operation: String): (arg: T) -> T = when (operation) { + public override fun unaryOperation(operation: String): (arg: T) -> T = when (operation) { PLUS_OPERATION -> { arg -> arg } MINUS_OPERATION -> { arg -> -arg } else -> super.unaryOperation(operation) } - override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { + public override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { PLUS_OPERATION -> ::add MINUS_OPERATION -> { left, right -> left - right } else -> super.binaryOperation(operation) @@ -196,6 +297,11 @@ public interface Space : SpaceOperations { * The neutral element of addition. */ public val zero: T + + public override fun symbol(value: String): T = when (value) { + "zero" -> zero + else -> super.symbol(value) + } } /** @@ -221,7 +327,7 @@ public interface RingOperations : SpaceOperations { */ public operator fun T.times(b: T): T = multiply(this, b) - override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { + public override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { TIMES_OPERATION -> ::multiply else -> super.binaryOperation(operation) } @@ -246,7 +352,12 @@ public interface Ring : Space, RingOperations, NumericAlgebra { */ public val one: T - override fun number(value: Number): T = one * value.toDouble() + public override fun number(value: Number): T = one * value.toDouble() + + public override fun symbol(value: String): T = when (value) { + "one" -> one + else -> super.symbol(value) + } /** * Addition of element and scalar. @@ -308,7 +419,7 @@ public interface FieldOperations : RingOperations { */ public operator fun T.div(b: T): T = divide(this, b) - override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { + public override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { DIV_OPERATION -> ::divide else -> super.binaryOperation(operation) } From 9fbca45235ba88186170a2f909c456abac5ef71e Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 20:48:38 +0700 Subject: [PATCH 163/199] Fix incorrect properties in verifier classes --- .../kotlin/kscience/kmath/operations/internal/FieldVerifier.kt | 2 ++ .../kotlin/kscience/kmath/operations/internal/RingVerifier.kt | 2 +- .../kotlin/kscience/kmath/operations/internal/SpaceVerifier.kt | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/FieldVerifier.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/FieldVerifier.kt index 1ca09ab0c..89f31c75b 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/FieldVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/FieldVerifier.kt @@ -12,6 +12,8 @@ internal class FieldVerifier(override val algebra: Field, a: T, b: T, c: T super.verify() algebra { + assertEquals(a + b, b + a, "Addition in $algebra is not commutative.") + assertEquals(a * b, b * a, "Multiplication in $algebra is not commutative.") assertNotEquals(a / b, b / a, "Division in $algebra is not anti-commutative.") assertNotEquals((a / b) / c, a / (b / c), "Division in $algebra is associative.") assertEquals((a + b) / c, (a / c) + (b / c), "Division in $algebra is not right-distributive.") diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/RingVerifier.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/RingVerifier.kt index 863169b9b..359ba1701 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/RingVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/RingVerifier.kt @@ -10,7 +10,7 @@ internal open class RingVerifier(override val algebra: Ring, a: T, b: T, c super.verify() algebra { - assertEquals(a * b, a * b, "Multiplication in $algebra is not commutative.") + assertEquals(a + b, b + a, "Addition in $algebra is not commutative.") assertEquals(a * b * c, a * (b * c), "Multiplication in $algebra is not associative.") assertEquals(c * (a + b), (c * a) + (c * b), "Multiplication in $algebra is not distributive.") assertEquals(a * one, one * a, "$one in $algebra is not a neutral multiplication element.") diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/SpaceVerifier.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/SpaceVerifier.kt index 4dc855829..045abb71f 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/SpaceVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/operations/internal/SpaceVerifier.kt @@ -15,7 +15,6 @@ internal open class SpaceVerifier( AlgebraicVerifier> { override fun verify() { algebra { - assertEquals(a + b, b + a, "Addition in $algebra is not commutative.") assertEquals(a + b + c, a + (b + c), "Addition in $algebra is not associative.") assertEquals(x * (a + b), x * a + x * b, "Addition in $algebra is not distributive.") assertEquals((a + b) * x, a * x + b * x, "Addition in $algebra is not distributive.") From c8df741a4e2c7d45f25d4ce8c083250a524f514a Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 20:58:52 +0700 Subject: [PATCH 164/199] Remove incorrent symbol decl. --- .../kotlin/kscience/kmath/operations/Algebra.kt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index 3dfd14921..6cf9eeb78 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -297,11 +297,6 @@ public interface Space : SpaceOperations { * The neutral element of addition. */ public val zero: T - - public override fun symbol(value: String): T = when (value) { - "zero" -> zero - else -> super.symbol(value) - } } /** @@ -354,11 +349,6 @@ public interface Ring : Space, RingOperations, NumericAlgebra { public override fun number(value: Number): T = one * value.toDouble() - public override fun symbol(value: String): T = when (value) { - "one" -> one - else -> super.symbol(value) - } - /** * Addition of element and scalar. * From 69b1952c15150b0a4a39330ed82be52b93671d38 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 21:13:11 +0700 Subject: [PATCH 165/199] Add verification of NDField --- .../kotlin/kscience/kmath/structures/NDFieldTest.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt index 79b56ea4a..b763ec7de 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt @@ -1,10 +1,16 @@ package kscience.kmath.structures +import kscience.kmath.operations.internal.FieldVerifier +import kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals +internal class NDFieldTest { + @Test + fun verify() { + (NDField.real(12, 32)) { FieldVerifier(this, one + 3, one - 23, one * 12, 6.66) } + } -class NDFieldTest { @Test fun testStrides() { val ndArray = NDElement.real(intArrayOf(10, 10)) { (it[0] + it[1]).toDouble() } From 12d64220659051a9723446c4f0b86559b1a1d199 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 21:43:04 +0700 Subject: [PATCH 166/199] Fix wrong package --- .../jsMain/kotlin/kscience/kmath/estree/Codegen.kt | 1 + .../kscience/kmath/estree/internal/JSBuilder.kt | 11 ----------- .../kmath/estree/internal/astring/astring.kt | 2 +- .../estree/internal/estree/estree.extensions.kt | 12 ------------ .../kscience/kmath/estree/internal/estree/estree.kt | 2 +- 5 files changed, 3 insertions(+), 25 deletions(-) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt index d10c9c0cf..50454fa34 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt @@ -4,6 +4,7 @@ import estree.* import kscience.kmath.ast.MST import kscience.kmath.ast.MstExpression import kscience.kmath.estree.internal.JSBuilder +import kscience.kmath.estree.internal.estree.BaseExpression import kscience.kmath.expressions.Expression import kscience.kmath.operations.Algebra import kscience.kmath.operations.NumericAlgebra diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt index b38be085d..a55ac62a4 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt @@ -1,18 +1,7 @@ package kscience.kmath.estree.internal import kscience.kmath.estree.internal.astring.generate -import estree.* import kscience.kmath.estree.internal.estree.* -import kscience.kmath.estree.internal.estree.BlockStatement -import kscience.kmath.estree.internal.estree.FunctionExpression -import kscience.kmath.estree.internal.estree.Identifier -import kscience.kmath.estree.internal.estree.MemberExpression -import kscience.kmath.estree.internal.estree.Program -import kscience.kmath.estree.internal.estree.ReturnStatement -import kscience.kmath.estree.internal.estree.SimpleCallExpression -import kscience.kmath.estree.internal.estree.SimpleLiteral -import kscience.kmath.estree.internal.estree.VariableDeclaration -import kscience.kmath.estree.internal.estree.VariableDeclarator import kscience.kmath.expressions.Expression import kscience.kmath.expressions.Symbol diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.kt index 4ef3acf20..cf0a8de25 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/astring/astring.kt @@ -3,7 +3,7 @@ package kscience.kmath.estree.internal.astring -import estree.BaseNode +import kscience.kmath.estree.internal.estree.BaseNode internal external interface Options { var indent: String? diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.extensions.kt index 951cd9ef8..5bc197d0c 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.extensions.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.extensions.kt @@ -1,17 +1,5 @@ package kscience.kmath.estree.internal.estree -import estree.* -import estree.BlockStatement -import estree.FunctionExpression -import estree.Identifier -import estree.MemberExpression -import estree.Program -import estree.ReturnStatement -import estree.SimpleCallExpression -import estree.SimpleLiteral -import estree.VariableDeclaration -import estree.VariableDeclarator - internal fun Program(sourceType: String, vararg body: dynamic) = object : Program { override var type = "Program" override var sourceType = sourceType diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.kt index 8d894a1b1..a5385d1ee 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/estree/estree.kt @@ -1,4 +1,4 @@ -package estree +package kscience.kmath.estree.internal.estree import kotlin.js.RegExp From 7002bdb5bdd37fce26c0b63195a3b6db462082c7 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 21:45:02 +0700 Subject: [PATCH 167/199] Remove redundant suppression --- .../jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt index a55ac62a4..6845437b3 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt @@ -7,7 +7,7 @@ import kscience.kmath.expressions.Symbol internal class JSBuilder(val bodyCallback: JSBuilder.() -> BaseExpression) { private class GeneratedExpression(val executable: dynamic, val constants: Array) : Expression { - @Suppress("UNUSED_VARIABLE", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") + @Suppress("UNUSED_VARIABLE") override fun invoke(arguments: Map): T { val e = executable val c = constants From 306eaecdb1cd323525ff0be855e55ada4a4a6160 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Dec 2020 21:55:20 +0700 Subject: [PATCH 168/199] Remove invalid import --- kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt index 50454fa34..f5727fb16 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt @@ -1,6 +1,5 @@ package kscience.kmath.estree -import estree.* import kscience.kmath.ast.MST import kscience.kmath.ast.MstExpression import kscience.kmath.estree.internal.JSBuilder From cfc13cda8fbc97137ee9345942531611b3aa5367 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 12:57:50 +0700 Subject: [PATCH 169/199] Rename files and JSBuilder --- .../kotlin/kscience/kmath/estree/{Codegen.kt => estree.kt} | 6 +++--- .../estree/internal/{JSBuilder.kt => ESTreeBuilder.kt} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/{Codegen.kt => estree.kt} (92%) rename kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/{JSBuilder.kt => ESTreeBuilder.kt} (96%) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt similarity index 92% rename from kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt rename to kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt index f5727fb16..5036e96c0 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/Codegen.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt @@ -2,7 +2,7 @@ package kscience.kmath.estree import kscience.kmath.ast.MST import kscience.kmath.ast.MstExpression -import kscience.kmath.estree.internal.JSBuilder +import kscience.kmath.estree.internal.ESTreeBuilder import kscience.kmath.estree.internal.estree.BaseExpression import kscience.kmath.expressions.Expression import kscience.kmath.operations.Algebra @@ -11,7 +11,7 @@ import kscience.kmath.operations.RealField @PublishedApi internal fun MST.compileWith(algebra: Algebra): Expression { - fun JSBuilder.visit(node: MST): BaseExpression = when (node) { + fun ESTreeBuilder.visit(node: MST): BaseExpression = when (node) { is MST.Symbolic -> { val symbol = try { algebra.symbol(node.value) @@ -57,7 +57,7 @@ internal fun MST.compileWith(algebra: Algebra): Expression { } } - return JSBuilder { visit(this@compileWith) }.instance + return ESTreeBuilder { visit(this@compileWith) }.instance } diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt similarity index 96% rename from kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt rename to kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt index 6845437b3..e58ad54b3 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/JSBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -5,7 +5,7 @@ import kscience.kmath.estree.internal.estree.* import kscience.kmath.expressions.Expression import kscience.kmath.expressions.Symbol -internal class JSBuilder(val bodyCallback: JSBuilder.() -> BaseExpression) { +internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExpression) { private class GeneratedExpression(val executable: dynamic, val constants: Array) : Expression { @Suppress("UNUSED_VARIABLE") override fun invoke(arguments: Map): T { From d657f40e3f84542de429ac314a1c62a3eaad2304 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 12:58:35 +0700 Subject: [PATCH 170/199] Fix KDoc comments --- kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt index 5036e96c0..f9996b61a 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt @@ -62,7 +62,7 @@ internal fun MST.compileWith(algebra: Algebra): Expression { /** - * Compiles an [MST] to ASM using given algebra. + * Compiles an [MST] to ESTree generated expression using given algebra. * * @author Alexander Nozik. */ @@ -70,7 +70,7 @@ public fun Algebra.expression(mst: MST): Expression = mst.compileWith(this) /** - * Optimizes performance of an [MstExpression] using ASM codegen. + * Optimizes performance of an [MstExpression] by compiling it into ESTree generated expression. * * @author Alexander Nozik. */ From 46ac73d2c167be6d3cdb154b755f03c7d1f04817 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 13:11:12 +0700 Subject: [PATCH 171/199] Add undefined handling in constant insertion --- .../kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt index e58ad54b3..349686b83 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -40,9 +40,10 @@ internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExp private val keys = mutableListOf() fun constant(value: Any?) = when { - value == null || jsTypeOf(value) == "number" || jsTypeOf(value) == "string" || jsTypeOf(value) == "boolean" -> { + value == null || jsTypeOf(value) == "number" || jsTypeOf(value) == "string" || jsTypeOf(value) == "boolean" -> SimpleLiteral(value) - } + + jsType(value) == "undefined" -> Identifier("undefined") else -> { val idx = if (value in constants) constants.indexOf(value) else constants.also { it += value }.lastIndex From 1ab6702bb4eac6a5ef1381bac29d3d3c34ac96b2 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 13:11:44 +0700 Subject: [PATCH 172/199] Delete unused property --- .../kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt index 349686b83..e03a71123 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -37,7 +37,6 @@ internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExp } private val constants = mutableListOf() - private val keys = mutableListOf() fun constant(value: Any?) = when { value == null || jsTypeOf(value) == "number" || jsTypeOf(value) == "string" || jsTypeOf(value) == "boolean" -> From d521fa0d8d7e0be670d019431209fad8ca8ab4f5 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 13:15:01 +0700 Subject: [PATCH 173/199] Fix wrong function name --- .../kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt index e03a71123..e1823813a 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -42,7 +42,7 @@ internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExp value == null || jsTypeOf(value) == "number" || jsTypeOf(value) == "string" || jsTypeOf(value) == "boolean" -> SimpleLiteral(value) - jsType(value) == "undefined" -> Identifier("undefined") + jsTypeOf(value) == "undefined" -> Identifier("undefined") else -> { val idx = if (value in constants) constants.indexOf(value) else constants.also { it += value }.lastIndex From 2310aca9dbaf151a00119bd66fc440799f8281f2 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 13:42:12 +0700 Subject: [PATCH 174/199] Improve consistency of operations in MstAlgebra --- .../kotlin/kscience/kmath/ast/MstAlgebra.kt | 20 +++++++++++++------ .../kscience/kmath/operations/Algebra.kt | 4 ++-- .../kmath/operations/NumberAlgebra.kt | 5 ++--- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt index 96703ffb8..970ef3570 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt @@ -25,7 +25,9 @@ public object MstSpace : Space, NumericAlgebra { public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value) public override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b) - public override fun MST.unaryMinus(): MST = unaryOperation(SpaceOperations.MINUS_OPERATION)(this) + public override operator fun MST.unaryPlus(): MST = unaryOperation(SpaceOperations.PLUS_OPERATION)(this) + public override operator fun MST.unaryMinus(): MST = unaryOperation(SpaceOperations.MINUS_OPERATION)(this) + public override operator fun MST.minus(b: MST): MST = binaryOperation(SpaceOperations.MINUS_OPERATION)(this, b) public override fun multiply(a: MST, k: Number): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k)) @@ -41,17 +43,19 @@ public object MstSpace : Space, NumericAlgebra { * [Ring] over [MST] nodes. */ public object MstRing : Ring, NumericAlgebra { - override val zero: MST.Numeric + public override val zero: MST.Numeric get() = MstSpace.zero - override val one: MST.Numeric by lazy { number(1.0) } + public override val one: MST.Numeric by lazy { number(1.0) } public override fun number(value: Number): MST.Numeric = MstSpace.number(value) public override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value) public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b) public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION)(a, b) - public override fun MST.unaryMinus(): MST = MstSpace.unaryOperation(SpaceOperations.MINUS_OPERATION)(this) + public override operator fun MST.unaryPlus(): MST = MstSpace { this@unaryPlus } + public override operator fun MST.unaryMinus(): MST = MstSpace { -this@unaryMinus } + public override operator fun MST.minus(b: MST): MST = MstSpace { this@minus - b } public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstSpace.binaryOperation(operation) @@ -76,7 +80,9 @@ public object MstField : Field { public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) public override fun divide(a: MST, b: MST): MST.Binary = binaryOperation(FieldOperations.DIV_OPERATION)(a, b) - public override fun MST.unaryMinus(): MST = MstSpace.unaryOperation(SpaceOperations.MINUS_OPERATION)(this) + public override operator fun MST.unaryPlus(): MST = MstRing { this@unaryPlus } + public override operator fun MST.unaryMinus(): MST = MstRing { -this@unaryMinus } + public override operator fun MST.minus(b: MST): MST = MstRing { this@minus - b } public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstRing.binaryOperation(operation) @@ -111,7 +117,9 @@ public object MstExtendedField : ExtendedField { public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b) - public override fun MST.unaryMinus(): MST = MstSpace.unaryOperation(SpaceOperations.MINUS_OPERATION)(this) + public override operator fun MST.unaryPlus(): MST = MstField { this@unaryPlus } + public override operator fun MST.unaryMinus(): MST = MstField { -this@unaryMinus } + public override operator fun MST.minus(b: MST): MST = MstField { this@minus - b } public override fun power(arg: MST, pow: Number): MST.Binary = binaryOperation(PowerOperations.POW_OPERATION)(arg, number(pow)) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index 6cf9eeb78..f1ceb8858 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -275,12 +275,12 @@ public interface SpaceOperations : Algebra { public companion object { /** - * The identifier of addition. + * The identifier of addition and unary positive. */ public const val PLUS_OPERATION: String = "+" /** - * The identifier of subtraction (and negation). + * The identifier of subtraction and unary negation. */ public const val MINUS_OPERATION: String = "-" } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt index cd2bd0417..84d89b7eb 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt @@ -1,6 +1,5 @@ package kscience.kmath.operations -import kotlin.math.abs import kotlin.math.pow as kpow /** @@ -249,10 +248,10 @@ public object ByteRing : Ring, Norm { @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object LongRing : Ring, Norm { public override val zero: Long - get() = 0 + get() = 0L public override val one: Long - get() = 1 + get() = 1L public override inline fun add(a: Long, b: Long): Long = a + b public override inline fun multiply(a: Long, k: Number): Long = a * k.toLong() From c738fb1f2a5e85ee1b5ec7166d9e4aa860971627 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 13:44:52 +0700 Subject: [PATCH 175/199] Make return types more specific in MstAlgebra.kt --- .../kotlin/kscience/kmath/ast/MstAlgebra.kt | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt index 970ef3570..edbd7f92b 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt @@ -25,9 +25,9 @@ public object MstSpace : Space, NumericAlgebra { public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value) public override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b) - public override operator fun MST.unaryPlus(): MST = unaryOperation(SpaceOperations.PLUS_OPERATION)(this) - public override operator fun MST.unaryMinus(): MST = unaryOperation(SpaceOperations.MINUS_OPERATION)(this) - public override operator fun MST.minus(b: MST): MST = binaryOperation(SpaceOperations.MINUS_OPERATION)(this, b) + public override operator fun MST.unaryPlus(): MST.Unary = unaryOperation(SpaceOperations.PLUS_OPERATION)(this) + public override operator fun MST.unaryMinus(): MST.Unary = unaryOperation(SpaceOperations.MINUS_OPERATION)(this) + public override operator fun MST.minus(b: MST): MST.Binary = binaryOperation(SpaceOperations.MINUS_OPERATION)(this, b) public override fun multiply(a: MST, k: Number): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k)) @@ -53,9 +53,9 @@ public object MstRing : Ring, NumericAlgebra { public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b) public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION)(a, b) - public override operator fun MST.unaryPlus(): MST = MstSpace { this@unaryPlus } - public override operator fun MST.unaryMinus(): MST = MstSpace { -this@unaryMinus } - public override operator fun MST.minus(b: MST): MST = MstSpace { this@minus - b } + public override operator fun MST.unaryPlus(): MST.Unary = MstSpace { +this@unaryPlus } + public override operator fun MST.unaryMinus(): MST.Unary = MstSpace { -this@unaryMinus } + public override operator fun MST.minus(b: MST): MST.Binary = MstSpace { this@minus - b } public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstSpace.binaryOperation(operation) @@ -80,9 +80,9 @@ public object MstField : Field { public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) public override fun divide(a: MST, b: MST): MST.Binary = binaryOperation(FieldOperations.DIV_OPERATION)(a, b) - public override operator fun MST.unaryPlus(): MST = MstRing { this@unaryPlus } - public override operator fun MST.unaryMinus(): MST = MstRing { -this@unaryMinus } - public override operator fun MST.minus(b: MST): MST = MstRing { this@minus - b } + public override operator fun MST.unaryPlus(): MST.Unary = MstRing { +this@unaryPlus } + public override operator fun MST.unaryMinus(): MST.Unary = MstRing { -this@unaryMinus } + public override operator fun MST.minus(b: MST): MST.Binary = MstRing { this@minus - b } public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = MstRing.binaryOperation(operation) @@ -100,7 +100,7 @@ public object MstExtendedField : ExtendedField { public override val one: MST.Numeric get() = MstField.one - public override fun symbol(value: String): MST = MstField.symbol(value) + public override fun symbol(value: String): MST.Symbolic = MstField.symbol(value) public override fun sin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.SIN_OPERATION)(arg) public override fun cos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.COS_OPERATION)(arg) public override fun tan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.TAN_OPERATION)(arg) @@ -117,9 +117,9 @@ public object MstExtendedField : ExtendedField { public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b) - public override operator fun MST.unaryPlus(): MST = MstField { this@unaryPlus } - public override operator fun MST.unaryMinus(): MST = MstField { -this@unaryMinus } - public override operator fun MST.minus(b: MST): MST = MstField { this@minus - b } + public override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus } + public override operator fun MST.unaryMinus(): MST.Unary = MstField { -this@unaryMinus } + public override operator fun MST.minus(b: MST): MST.Binary = MstField { this@minus - b } public override fun power(arg: MST, pow: Number): MST.Binary = binaryOperation(PowerOperations.POW_OPERATION)(arg, number(pow)) From d631c048c746fab1200ce853086b45e9ea6b0ecb Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 16:00:51 +0700 Subject: [PATCH 176/199] Fix minor problems, update README --- kmath-ast/README.md | 41 +++++++++++++++---- .../kotlin/kscience/kmath/ast/MstAlgebra.kt | 4 +- .../kscience/kmath/asm/internal/AsmBuilder.kt | 13 +++++- .../kotlin/kscience/kmath/ast/AsmTest.kt | 2 - .../kmath/ast/ParserPrecedenceTest.kt | 2 - .../kscience/kmath/operations/Algebra.kt | 4 +- 6 files changed, 48 insertions(+), 18 deletions(-) diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 043224800..ea89883ab 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -38,7 +38,9 @@ This subproject implements the following features: > ``` > -## Dynamic Expression Code Generation with ObjectWeb ASM +## Dynamic expression code generation + +### 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. @@ -55,19 +57,20 @@ RealField.mstInField { symbol("x") + 2 }.compile() package kscience.kmath.asm.generated; import java.util.Map; +import kotlin.jvm.functions.Function2; import kscience.kmath.asm.internal.MapIntrinsics; import kscience.kmath.expressions.Expression; -import kscience.kmath.operations.RealField; +import kscience.kmath.expressions.Symbol; -public final class AsmCompiledExpression_1073786867_0 implements Expression { - private final RealField algebra; +public final class AsmCompiledExpression_45045_0 implements Expression { + private final Object[] constants; - public final Double invoke(Map arguments) { - return (Double)this.algebra.add(((Double)MapIntrinsics.getOrFail(arguments, "x")).doubleValue(), 2.0D); + public final Double invoke(Map arguments) { + return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2); } - public AsmCompiledExpression_1073786867_0(RealField algebra) { - this.algebra = algebra; + public AsmCompiledExpression_45045_0(Object[] constants) { + this.constants = constants; } } @@ -82,10 +85,30 @@ RealField.mstInField { symbol("x") + 2 }.compile() RealField.expression("x+2".parseMath()) ``` -### Known issues +#### Known issues - 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. Contributed by [Iaroslav Postovalov](https://github.com/CommanderTvis). + +### On JS + +A similar feature is also available on JS. + +```kotlin +RealField.mstInField { symbol("x") + 2 }.compile() +``` + +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); +}; +``` + +#### Known issues + +- This feature uses `eval` which can be unavailable in several environments. diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt index edbd7f92b..55d5b659d 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt @@ -27,7 +27,9 @@ public object MstSpace : Space, NumericAlgebra { public override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b) public override operator fun MST.unaryPlus(): MST.Unary = unaryOperation(SpaceOperations.PLUS_OPERATION)(this) public override operator fun MST.unaryMinus(): MST.Unary = unaryOperation(SpaceOperations.MINUS_OPERATION)(this) - public override operator fun MST.minus(b: MST): MST.Binary = binaryOperation(SpaceOperations.MINUS_OPERATION)(this, b) + + public override operator fun MST.minus(b: MST): MST.Binary = + binaryOperation(SpaceOperations.MINUS_OPERATION)(this, b) public override fun multiply(a: MST, k: Number): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k)) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index 882b95bf0..af7dc61b9 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -2,13 +2,16 @@ package kscience.kmath.asm.internal import kscience.kmath.asm.internal.AsmBuilder.ClassLoader import kscience.kmath.ast.MST +import kscience.kmath.ast.mstInField import kscience.kmath.expressions.Expression +import kscience.kmath.operations.RealField import org.objectweb.asm.* import org.objectweb.asm.Opcodes.* import org.objectweb.asm.Type.* import org.objectweb.asm.commons.InstructionAdapter import java.lang.invoke.MethodHandles import java.lang.invoke.MethodType +import java.lang.reflect.Modifier import java.util.stream.Collectors.toMap import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -82,7 +85,7 @@ internal class AsmBuilder( ACC_PUBLIC or ACC_FINAL, "invoke", getMethodDescriptor(tType, MAP_TYPE), - "(L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;)${tType.descriptor}", + "(L${MAP_TYPE.internalName}<${SYMBOL_TYPE.descriptor}${if (Modifier.isFinal(classOfT.modifiers)) "" else "+"}${tType.descriptor}>;)${tType.descriptor}", null, ).instructionAdapter { invokeMethodVisitor = this @@ -159,7 +162,7 @@ internal class AsmBuilder( "", getMethodDescriptor(VOID_TYPE, *OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }), null, - null + null, ).instructionAdapter { val l0 = label() load(0, classType) @@ -190,6 +193,7 @@ internal class AsmBuilder( } val cls = classLoader.defineClass(className, classWriter.toByteArray()) + java.io.File("dump.class").writeBytes(classWriter.toByteArray()) val l = MethodHandles.publicLookup() if (hasConstants) @@ -334,5 +338,10 @@ internal class AsmBuilder( * ASM type for MapIntrinsics. */ val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("kscience/kmath/asm/internal/MapIntrinsics") } + + /** + * ASM Type for [kscience.kmath.expressions.Symbol]. + */ + val SYMBOL_TYPE: Type by lazy { getObjectType("kscience/kmath/expressions/Symbol") } } } diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt index 1ca8aa5dd..992f4024e 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt @@ -2,8 +2,6 @@ package kscience.kmath.ast import kscience.kmath.asm.compile import kscience.kmath.asm.expression -import kscience.kmath.ast.mstInField -import kscience.kmath.ast.parseMath import kscience.kmath.expressions.invoke import kscience.kmath.operations.Complex import kscience.kmath.operations.ComplexField diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserPrecedenceTest.kt index 1844a0991..561fe51bd 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -1,7 +1,5 @@ package kscience.kmath.ast -import kscience.kmath.ast.evaluate -import kscience.kmath.ast.parseMath import kscience.kmath.operations.Field import kscience.kmath.operations.RealField import kotlin.test.Test diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index f1ceb8858..d2cf8e0dd 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -275,12 +275,12 @@ public interface SpaceOperations : Algebra { public companion object { /** - * The identifier of addition and unary positive. + * The identifier of addition and unary positive operator. */ public const val PLUS_OPERATION: String = "+" /** - * The identifier of subtraction and unary negation. + * The identifier of subtraction and unary negative operator. */ public const val MINUS_OPERATION: String = "-" } From 1b0f462e54a3ab2f61a09978b63fef7bf479b7d6 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 17:49:32 +0700 Subject: [PATCH 177/199] Reformat build.gradle.kts --- kmath-ast/build.gradle.kts | 8 +++++--- .../kotlin/kscience/kmath/asm/internal/AsmBuilder.kt | 2 -- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 1f4a87b12..574793124 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,3 +1,5 @@ +import ru.mipt.npm.gradle.Maturity + plugins { id("ru.mipt.npm.mpp") } @@ -38,6 +40,6 @@ kotlin.sourceSets { } } -readme{ - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE -} \ No newline at end of file +readme { + maturity = Maturity.PROTOTYPE +} diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index af7dc61b9..1edbed28d 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -2,9 +2,7 @@ package kscience.kmath.asm.internal import kscience.kmath.asm.internal.AsmBuilder.ClassLoader import kscience.kmath.ast.MST -import kscience.kmath.ast.mstInField import kscience.kmath.expressions.Expression -import kscience.kmath.operations.RealField import org.objectweb.asm.* import org.objectweb.asm.Opcodes.* import org.objectweb.asm.Type.* From 50b62f8a3b5a59ddabe1f17551643bac2919f66a Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 18:02:02 +0700 Subject: [PATCH 178/199] Update readme --- README.md | 13 ++++- kmath-ast/README.md | 44 ++++++++++------- kmath-ast/build.gradle.kts | 37 ++++++++++++++ kmath-ast/docs/README-TEMPLATE.md | 80 +++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 kmath-ast/docs/README-TEMPLATE.md diff --git a/README.md b/README.md index 50a916d2c..0899f77cc 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,16 @@ submit a feature request if you want something to be implemented first. * ### [kmath-ast](kmath-ast) > > -> **Maturity**: EXPERIMENTAL +> **Maturity**: PROTOTYPE +> +> **Features:** +> - [expression-language](kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser +> - [mst](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation +> - [mst-building](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure +> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter +> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler +> - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler +
* ### [kmath-commons](kmath-commons) @@ -122,7 +131,7 @@ submit a feature request if you want something to be implemented first. * ### [kmath-dimensions](kmath-dimensions) > > -> **Maturity**: EXPERIMENTAL +> **Maturity**: PROTOTYPE
* ### [kmath-ejml](kmath-ejml) diff --git a/kmath-ast/README.md b/kmath-ast/README.md index ea89883ab..bddc1c563 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -2,56 +2,66 @@ This subproject implements the following features: -- Expression Language and its parser. -- MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation. -- Type-safe builder for MST. -- Evaluating expressions by traversing MST. + - [expression-language](src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser + - [mst](src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation + - [mst-building](src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure + - [mst-interpreter](src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter + - [mst-jvm-codegen](src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler + - [mst-js-codegen](src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler + > #### Artifact: -> This module is distributed in the artifact `kscience.kmath:kmath-ast:0.1.4-dev-8`. -> +> +> This module artifact: `kscience.kmath:kmath-ast:0.2.0-dev-4`. +> +> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ast/_latestVersion) +> +> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-ast/_latestVersion) +> > **Gradle:** > > ```gradle > repositories { +> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } > maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } -> maven { url https://dl.bintray.com/hotkeytlt/maven' } +> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + > } > > dependencies { -> implementation 'kscience.kmath:kmath-ast:0.1.4-dev-8' +> implementation 'kscience.kmath:kmath-ast:0.2.0-dev-4' > } > ``` > **Gradle Kotlin DSL:** > > ```kotlin > repositories { +> maven("https://dl.bintray.com/kotlin/kotlin-eap") > maven("https://dl.bintray.com/mipt-npm/kscience") > maven("https://dl.bintray.com/mipt-npm/dev") > maven("https://dl.bintray.com/hotkeytlt/maven") > } > > dependencies { -> implementation("kscience.kmath:kmath-ast:0.1.4-dev-8") +> implementation("kscience.kmath:kmath-ast:0.2.0-dev-4") > } > ``` -> ## Dynamic expression code generation ### 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: +For example, the following builder: ```kotlin RealField.mstInField { symbol("x") + 2 }.compile() ``` -… 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 kscience.kmath.asm.generated; @@ -78,7 +88,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression { ### Example Usage -This API extends MST and MstExpression, so you may optimize as both of them: +This API extends MST and MstExpression, so you may optimize as both of them: ```kotlin RealField.mstInField { symbol("x") + 2 }.compile() @@ -88,11 +98,9 @@ RealField.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 -class loading overhead. + class loading overhead. - This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders. -Contributed by [Iaroslav Postovalov](https://github.com/CommanderTvis). - ### On JS A similar feature is also available on JS. diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 574793124..b2d027d35 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -42,4 +42,41 @@ kotlin.sourceSets { readme { maturity = Maturity.PROTOTYPE + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + + feature( + id = "expression-language", + description = "Expression language and its parser", + ref = "src/jvmMain/kotlin/kscience/kmath/ast/parser.kt" + ) + + feature( + id = "mst", + description = "MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation", + ref = "src/commonMain/kotlin/kscience/kmath/ast/MST.kt" + ) + + feature( + id = "mst-building", + description = "MST building algebraic structure", + ref = "src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt" + ) + + feature( + id = "mst-interpreter", + description = "MST interpreter", + ref = "src/commonMain/kotlin/kscience/kmath/ast/MST.kt" + ) + + feature( + id = "mst-jvm-codegen", + description = "Dynamic MST to JVM bytecode compiler", + ref = "src/jvmMain/kotlin/kscience/kmath/asm/asm.kt" + ) + + feature( + id = "mst-js-codegen", + description = "Dynamic MST to JS compiler", + ref = "src/jsMain/kotlin/kscience/kmath/estree/estree.kt" + ) } diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md new file mode 100644 index 000000000..3227a2ad3 --- /dev/null +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -0,0 +1,80 @@ +# Abstract Syntax Tree Expression Representation and Operations (`kmath-ast`) + +This subproject implements the following features: + +${features} + +${artifact} + +## Dynamic expression code generation + +### 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. + +For example, the following builder: + +```kotlin +RealField.mstInField { symbol("x") + 2 }.compile() +``` + +… leads to generation of bytecode, which can be decompiled to the following Java class: + +```java +package kscience.kmath.asm.generated; + +import java.util.Map; +import kotlin.jvm.functions.Function2; +import kscience.kmath.asm.internal.MapIntrinsics; +import kscience.kmath.expressions.Expression; +import kscience.kmath.expressions.Symbol; + +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); + } + + public AsmCompiledExpression_45045_0(Object[] constants) { + this.constants = constants; + } +} + +``` + +### Example Usage + +This API extends MST and MstExpression, so you may optimize as both of them: + +```kotlin +RealField.mstInField { symbol("x") + 2 }.compile() +RealField.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 + class loading overhead. +- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders. + +### On JS + +A similar feature is also available on JS. + +```kotlin +RealField.mstInField { symbol("x") + 2 }.compile() +``` + +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); +}; +``` + +#### Known issues + +- This feature uses `eval` which can be unavailable in several environments. From 1a5efd0a1730d52fa1a10540a3cf169284ff6413 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 18:17:24 +0700 Subject: [PATCH 179/199] Improve ASM and ESTree tests quality --- ...> TestESTreeConsistencyWithInterpreter.kt} | 43 ++++++++++++++----- ...ions.kt => TestESTreeOperationsSupport.kt} | 23 ++-------- .../kmath/estree/TestESTreeVariables.kt | 4 +- ...t => TestAsmConsistencyWithInterpreter.kt} | 43 ++++++++++++++----- ...essions.kt => TestAsmOperationsSupport.kt} | 2 +- .../kscience/kmath/asm/TestAsmVariables.kt | 4 +- .../kotlin/kscience/kmath/ast/AsmTest.kt | 23 ---------- 7 files changed, 73 insertions(+), 69 deletions(-) rename kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/{TestESTreeAlgebras.kt => TestESTreeConsistencyWithInterpreter.kt} (68%) rename kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/{TestESTreeExpressions.kt => TestESTreeOperationsSupport.kt} (56%) rename kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/{TestAsmAlgebras.kt => TestAsmConsistencyWithInterpreter.kt} (69%) rename kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/{TestAsmExpressions.kt => TestAsmOperationsSupport.kt} (96%) delete mode 100644 kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt diff --git a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeAlgebras.kt b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt similarity index 68% rename from kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeAlgebras.kt rename to kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index 09a8ab3e5..242a4154d 100644 --- a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeAlgebras.kt +++ b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -1,18 +1,18 @@ package kscience.kmath.estree -import kscience.kmath.ast.mstInField -import kscience.kmath.ast.mstInRing -import kscience.kmath.ast.mstInSpace +import kscience.kmath.ast.* import kscience.kmath.expressions.invoke import kscience.kmath.operations.ByteRing +import kscience.kmath.operations.ComplexField import kscience.kmath.operations.RealField +import kscience.kmath.operations.toComplex import kotlin.test.Test import kotlin.test.assertEquals -internal class TestESTreeAlgebras { +internal class TestESTreeConsistencyWithInterpreter { @Test - fun space() { - val res1 = ByteRing.mstInSpace { + fun mstSpace() { + val res1 = MstSpace.mstInSpace { binaryOperation("+")( unaryOperation("+")( number(3.toByte()) - (number(2.toByte()) + (multiply( @@ -23,9 +23,9 @@ internal class TestESTreeAlgebras { number(1) ) + symbol("x") + zero - }("x" to 2.toByte()) + }("x" to MST.Numeric(2)) - val res2 = ByteRing.mstInSpace { + val res2 = MstSpace.mstInSpace { binaryOperation("+")( unaryOperation("+")( number(3.toByte()) - (number(2.toByte()) + (multiply( @@ -36,13 +36,13 @@ internal class TestESTreeAlgebras { number(1) ) + symbol("x") + zero - }.compile()("x" to 2.toByte()) + }.compile()("x" to MST.Numeric(2)) assertEquals(res1, res2) } @Test - fun ring() { + fun byteRing() { val res1 = ByteRing.mstInRing { binaryOperation("+")( unaryOperation("+")( @@ -72,7 +72,7 @@ internal class TestESTreeAlgebras { } @Test - fun field() { + fun realField() { val res1 = RealField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 @@ -91,4 +91,25 @@ internal class TestESTreeAlgebras { assertEquals(res1, res2) } + + @Test + fun complexField() { + val res1 = ComplexField.mstInField { + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + + number(1), + number(1) / 2 + number(2.0) * one + ) + zero + }("x" to 2.0.toComplex()) + + val res2 = ComplexField.mstInField { + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + + number(1), + number(1) / 2 + number(2.0) * one + ) + zero + }.compile()("x" to 2.0.toComplex()) + + assertEquals(res1, res2) + } } diff --git a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeExpressions.kt b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeOperationsSupport.kt similarity index 56% rename from kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeExpressions.kt rename to kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeOperationsSupport.kt index 3dc259cb3..72a4669d9 100644 --- a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeExpressions.kt +++ b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeOperationsSupport.kt @@ -3,17 +3,13 @@ package kscience.kmath.estree import kscience.kmath.ast.mstInExtendedField import kscience.kmath.ast.mstInField import kscience.kmath.ast.mstInSpace -import kscience.kmath.expressions.Expression -import kscience.kmath.expressions.StringSymbol import kscience.kmath.expressions.invoke import kscience.kmath.operations.RealField -import kotlin.math.pow import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.time.measureTime -internal class TestESTreeExpressions { +internal class TestESTreeOperationsSupport { @Test fun testUnaryOperationInvocation() { val expression = RealField.mstInSpace { -symbol("x") }.compile() @@ -36,21 +32,10 @@ internal class TestESTreeExpressions { @Test fun testMultipleCalls() { - val e1 = - RealField.mstInExtendedField { sin(symbol("x")).pow(4) - 6 * symbol("x") / tanh(symbol("x")) }.compile() - - val e2 = Expression { a -> - val x = a.getValue(StringSymbol("x")) - kotlin.math.sin(x).pow(4) - 6 * x / kotlin.math.tanh(x) - } - - var r = Random(0) + val e = RealField.mstInExtendedField { sin(symbol("x")).pow(4) - 6 * symbol("x") / tanh(symbol("x")) }.compile() + val r = Random(0) var s = 0.0 - measureTime { repeat(1000000) { s += e1("x" to r.nextDouble()) } }.also(::println) - println(s) - s = 0.0 - r = Random(0) - measureTime { repeat(1000000) { s += e2("x" to r.nextDouble()) } }.also(::println) + repeat(1000000) { s += e("x" to r.nextDouble()) } println(s) } } diff --git a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeVariables.kt b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeVariables.kt index b6f59247d..846120ee2 100644 --- a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeVariables.kt +++ b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeVariables.kt @@ -9,13 +9,13 @@ import kotlin.test.assertFailsWith internal class TestESTreeVariables { @Test - fun testVariableWithoutDefault() { + fun testVariable() { val expr = ByteRing.mstInRing { symbol("x") }.compile() assertEquals(1.toByte(), expr("x" to 1.toByte())) } @Test - fun testVariableWithoutDefaultFails() { + fun testUndefinedVariableFails() { val expr = ByteRing.mstInRing { symbol("x") }.compile() assertFailsWith { expr() } } diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt similarity index 69% rename from kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt rename to kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index a1687c1c7..013ae789d 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmAlgebras.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -1,18 +1,18 @@ package kscience.kmath.asm -import kscience.kmath.ast.mstInField -import kscience.kmath.ast.mstInRing -import kscience.kmath.ast.mstInSpace +import kscience.kmath.ast.* import kscience.kmath.expressions.invoke import kscience.kmath.operations.ByteRing +import kscience.kmath.operations.ComplexField import kscience.kmath.operations.RealField +import kscience.kmath.operations.toComplex import kotlin.test.Test import kotlin.test.assertEquals -internal class TestAsmAlgebras { +internal class TestAsmConsistencyWithInterpreter { @Test - fun space() { - val res1 = ByteRing.mstInSpace { + fun mstSpace() { + val res1 = MstSpace.mstInSpace { binaryOperation("+")( unaryOperation("+")( number(3.toByte()) - (number(2.toByte()) + (multiply( @@ -23,9 +23,9 @@ internal class TestAsmAlgebras { number(1) ) + symbol("x") + zero - }("x" to 2.toByte()) + }("x" to MST.Numeric(2)) - val res2 = ByteRing.mstInSpace { + val res2 = MstSpace.mstInSpace { binaryOperation("+")( unaryOperation("+")( number(3.toByte()) - (number(2.toByte()) + (multiply( @@ -36,13 +36,13 @@ internal class TestAsmAlgebras { number(1) ) + symbol("x") + zero - }.compile()("x" to 2.toByte()) + }.compile()("x" to MST.Numeric(2)) assertEquals(res1, res2) } @Test - fun ring() { + fun byteRing() { val res1 = ByteRing.mstInRing { binaryOperation("+")( unaryOperation("+")( @@ -72,7 +72,7 @@ internal class TestAsmAlgebras { } @Test - fun field() { + fun realField() { val res1 = RealField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 @@ -91,4 +91,25 @@ internal class TestAsmAlgebras { assertEquals(res1, res2) } + + @Test + fun complexField() { + val res1 = ComplexField.mstInField { + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + + number(1), + number(1) / 2 + number(2.0) * one + ) + zero + }("x" to 2.0.toComplex()) + + val res2 = ComplexField.mstInField { + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + + number(1), + number(1) / 2 + number(2.0) * one + ) + zero + }.compile()("x" to 2.0.toComplex()) + + assertEquals(res1, res2) + } } diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmExpressions.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmOperationsSupport.kt similarity index 96% rename from kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmExpressions.kt rename to kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmOperationsSupport.kt index acd9e21ea..2ce52aa87 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmExpressions.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmOperationsSupport.kt @@ -9,7 +9,7 @@ import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals -internal class TestAsmExpressions { +internal class TestAsmOperationsSupport { @Test fun testUnaryOperationInvocation() { val expression = RealField.mstInSpace { -symbol("x") }.compile() diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt index 0ebc31be4..c91568dbf 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmVariables.kt @@ -9,13 +9,13 @@ import kotlin.test.assertFailsWith internal class TestAsmVariables { @Test - fun testVariableWithoutDefault() { + fun testVariable() { val expr = ByteRing.mstInRing { symbol("x") }.compile() assertEquals(1.toByte(), expr("x" to 1.toByte())) } @Test - fun testVariableWithoutDefaultFails() { + fun testUndefinedVariableFails() { val expr = ByteRing.mstInRing { symbol("x") }.compile() assertFailsWith { expr() } } diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt deleted file mode 100644 index 992f4024e..000000000 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/AsmTest.kt +++ /dev/null @@ -1,23 +0,0 @@ -package kscience.kmath.ast - -import kscience.kmath.asm.compile -import kscience.kmath.asm.expression -import kscience.kmath.expressions.invoke -import kscience.kmath.operations.Complex -import kscience.kmath.operations.ComplexField -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class AsmTest { - @Test - fun `compile MST`() { - val res = ComplexField.expression("2+2*(2+2)".parseMath())() - assertEquals(Complex(10.0, 0.0), res) - } - - @Test - fun `compile MSTExpression`() { - val res = ComplexField.mstInField { number(2) + number(2) * (number(2) + number(2)) }.compile()() - assertEquals(Complex(10.0, 0.0), res) - } -} From dab6b0e385791d960bb98a1624c22827a3cb5393 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 22:15:24 +0700 Subject: [PATCH 180/199] Add Space repository URL --- build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 561a2212b..90a39c531 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,3 +38,7 @@ readme { apiValidation { validationDisabled = true } + +ksciencePublish { + spaceRepo = "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven" +} From 024800605f852eac9f3934961243c288adfa31aa Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 22 Dec 2020 22:20:30 +0700 Subject: [PATCH 181/199] Update ASM --- kmath-ast/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index b2d027d35..39de4256d 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -34,8 +34,8 @@ kotlin.sourceSets { jvmMain { dependencies { api("com.github.h0tk3y.betterParse:better-parse:0.4.0") - implementation("org.ow2.asm:asm:8.0.1") - implementation("org.ow2.asm:asm-commons:8.0.1") + implementation("org.ow2.asm:asm:9.0") + implementation("org.ow2.asm:asm-commons:9.0") } } } From 2c7cb1b04fc06ac68176aa05d5d2504754f94e53 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 5 Jan 2021 19:56:42 +0700 Subject: [PATCH 182/199] Rename ...Operation functions returning function to ...OperationFunction --- .../kotlin/kscience/kmath/ast/MST.kt | 12 +-- .../kotlin/kscience/kmath/ast/MstAlgebra.kt | 76 +++++++++---------- .../kscience/kmath/ast/MstExpression.kt | 4 +- .../kotlin/kscience/kmath/estree/estree.kt | 10 +-- .../TestESTreeConsistencyWithInterpreter.kt | 24 +++--- .../kmath/estree/TestESTreeSpecialization.kt | 14 ++-- .../jvmMain/kotlin/kscience/kmath/asm/asm.kt | 10 +-- .../asm/TestAsmConsistencyWithInterpreter.kt | 24 +++--- .../kmath/asm/TestAsmSpecialization.kt | 14 ++-- .../kotlin/kscience/kmath/ast/ParserTest.kt | 4 +- .../FunctionalExpressionAlgebra.kt | 62 +++++++-------- .../kscience/kmath/linear/MatrixContext.kt | 4 +- .../kscience/kmath/operations/Algebra.kt | 62 +++++++-------- .../kmath/operations/NumberAlgebra.kt | 16 ++-- 14 files changed, 168 insertions(+), 168 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt index 4ff4d7354..6cf746722 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt @@ -57,22 +57,22 @@ public fun Algebra.evaluate(node: MST): T = when (node) { ?: error("Numeric nodes are not supported by $this") is MST.Symbolic -> symbol(node.value) - is MST.Unary -> unaryOperation(node.operation)(evaluate(node.value)) + is MST.Unary -> unaryOperationFunction(node.operation)(evaluate(node.value)) is MST.Binary -> when { - this !is NumericAlgebra -> binaryOperation(node.operation)(evaluate(node.left), evaluate(node.right)) + this !is NumericAlgebra -> binaryOperationFunction(node.operation)(evaluate(node.left), evaluate(node.right)) node.left is MST.Numeric && node.right is MST.Numeric -> { val number = RealField - .binaryOperation(node.operation) + .binaryOperationFunction(node.operation) .invoke(node.left.value.toDouble(), node.right.value.toDouble()) number(number) } - node.left is MST.Numeric -> leftSideNumberOperation(node.operation)(node.left.value, evaluate(node.right)) - node.right is MST.Numeric -> rightSideNumberOperation(node.operation)(evaluate(node.left), node.right.value) - else -> binaryOperation(node.operation)(evaluate(node.left), evaluate(node.right)) + node.left is MST.Numeric -> leftSideNumberOperationFunction(node.operation)(node.left.value, evaluate(node.right)) + node.right is MST.Numeric -> rightSideNumberOperationFunction(node.operation)(evaluate(node.left), node.right.value) + else -> binaryOperationFunction(node.operation)(evaluate(node.left), evaluate(node.right)) } } diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt index 55d5b659d..80b164a7c 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt @@ -9,10 +9,10 @@ public object MstAlgebra : NumericAlgebra { public override fun number(value: Number): MST.Numeric = MST.Numeric(value) public override fun symbol(value: String): MST.Symbolic = MST.Symbolic(value) - public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = + public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = { arg -> MST.Unary(operation, arg) } - public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = + public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = { left, right -> MST.Binary(operation, left, right) } } @@ -24,21 +24,21 @@ public object MstSpace : Space, NumericAlgebra { public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value) - public override fun add(a: MST, b: MST): MST.Binary = binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b) - public override operator fun MST.unaryPlus(): MST.Unary = unaryOperation(SpaceOperations.PLUS_OPERATION)(this) - public override operator fun MST.unaryMinus(): MST.Unary = unaryOperation(SpaceOperations.MINUS_OPERATION)(this) + public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b) + public override operator fun MST.unaryPlus(): MST.Unary = unaryOperationFunction(SpaceOperations.PLUS_OPERATION)(this) + public override operator fun MST.unaryMinus(): MST.Unary = unaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this) public override operator fun MST.minus(b: MST): MST.Binary = - binaryOperation(SpaceOperations.MINUS_OPERATION)(this, b) + binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b) public override fun multiply(a: MST, k: Number): MST.Binary = - binaryOperation(RingOperations.TIMES_OPERATION)(a, number(k)) + binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(k)) - public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = - MstAlgebra.binaryOperation(operation) + public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = + MstAlgebra.binaryOperationFunction(operation) - public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = - MstAlgebra.unaryOperation(operation) + public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = + MstAlgebra.unaryOperationFunction(operation) } /** @@ -54,16 +54,16 @@ public object MstRing : Ring, NumericAlgebra { public override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value) public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b) public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k) - public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperation(RingOperations.TIMES_OPERATION)(a, b) + public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b) public override operator fun MST.unaryPlus(): MST.Unary = MstSpace { +this@unaryPlus } public override operator fun MST.unaryMinus(): MST.Unary = MstSpace { -this@unaryMinus } public override operator fun MST.minus(b: MST): MST.Binary = MstSpace { this@minus - b } - public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = - MstSpace.binaryOperation(operation) + public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = + MstSpace.binaryOperationFunction(operation) - public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = - MstAlgebra.unaryOperation(operation) + public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = + MstAlgebra.unaryOperationFunction(operation) } /** @@ -81,15 +81,15 @@ public object MstField : Field { public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) - public override fun divide(a: MST, b: MST): MST.Binary = binaryOperation(FieldOperations.DIV_OPERATION)(a, b) + public override fun divide(a: MST, b: MST): MST.Binary = binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b) public override operator fun MST.unaryPlus(): MST.Unary = MstRing { +this@unaryPlus } public override operator fun MST.unaryMinus(): MST.Unary = MstRing { -this@unaryMinus } public override operator fun MST.minus(b: MST): MST.Binary = MstRing { this@minus - b } - public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = - MstRing.binaryOperation(operation) + public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = + MstRing.binaryOperationFunction(operation) - public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = MstRing.unaryOperation(operation) + public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = MstRing.unaryOperationFunction(operation) } /** @@ -103,18 +103,18 @@ public object MstExtendedField : ExtendedField { get() = MstField.one public override fun symbol(value: String): MST.Symbolic = MstField.symbol(value) - public override fun sin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.SIN_OPERATION)(arg) - public override fun cos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.COS_OPERATION)(arg) - public override fun tan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.TAN_OPERATION)(arg) - public override fun asin(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ASIN_OPERATION)(arg) - public override fun acos(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ACOS_OPERATION)(arg) - public override fun atan(arg: MST): MST.Unary = unaryOperation(TrigonometricOperations.ATAN_OPERATION)(arg) - public override fun sinh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.SINH_OPERATION)(arg) - public override fun cosh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.COSH_OPERATION)(arg) - public override fun tanh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.TANH_OPERATION)(arg) - public override fun asinh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ASINH_OPERATION)(arg) - public override fun acosh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ACOSH_OPERATION)(arg) - public override fun atanh(arg: MST): MST.Unary = unaryOperation(HyperbolicOperations.ATANH_OPERATION)(arg) + public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg) + public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg) + public override fun tan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.TAN_OPERATION)(arg) + public override fun asin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ASIN_OPERATION)(arg) + public override fun acos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ACOS_OPERATION)(arg) + public override fun atan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ATAN_OPERATION)(arg) + public override fun sinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.SINH_OPERATION)(arg) + public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.COSH_OPERATION)(arg) + public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.TANH_OPERATION)(arg) + public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ASINH_OPERATION)(arg) + public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ACOSH_OPERATION)(arg) + public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ATANH_OPERATION)(arg) public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) @@ -124,13 +124,13 @@ public object MstExtendedField : ExtendedField { public override operator fun MST.minus(b: MST): MST.Binary = MstField { this@minus - b } public override fun power(arg: MST, pow: Number): MST.Binary = - binaryOperation(PowerOperations.POW_OPERATION)(arg, number(pow)) + binaryOperationFunction(PowerOperations.POW_OPERATION)(arg, number(pow)) - public override fun exp(arg: MST): MST.Unary = unaryOperation(ExponentialOperations.EXP_OPERATION)(arg) - public override fun ln(arg: MST): MST.Unary = unaryOperation(ExponentialOperations.LN_OPERATION)(arg) + public override fun exp(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.EXP_OPERATION)(arg) + public override fun ln(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.LN_OPERATION)(arg) - public override fun binaryOperation(operation: String): (left: MST, right: MST) -> MST.Binary = - MstField.binaryOperation(operation) + public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = + MstField.binaryOperationFunction(operation) - public override fun unaryOperation(operation: String): (arg: MST) -> MST.Unary = MstField.unaryOperation(operation) + public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = MstField.unaryOperationFunction(operation) } diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt index 4d1b65621..03d33aa2b 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstExpression.kt @@ -21,8 +21,8 @@ public class MstExpression>(public val algebra: A, public null } ?: arguments.getValue(StringSymbol(value)) - override fun unaryOperation(operation: String): (arg: T) -> T = algebra.unaryOperation(operation) - override fun binaryOperation(operation: String): (left: T, right: T) -> T = algebra.binaryOperation(operation) + override fun unaryOperationFunction(operation: String): (arg: T) -> T = algebra.unaryOperationFunction(operation) + override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = algebra.binaryOperationFunction(operation) @Suppress("UNCHECKED_CAST") override fun number(value: Number): T = if (algebra is NumericAlgebra<*>) diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt index f9996b61a..159c5d5ec 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt @@ -26,31 +26,31 @@ internal fun MST.compileWith(algebra: Algebra): Expression { } is MST.Numeric -> constant(node.value) - is MST.Unary -> call(algebra.unaryOperation(node.operation), visit(node.value)) + is MST.Unary -> call(algebra.unaryOperationFunction(node.operation), visit(node.value)) is MST.Binary -> when { algebra is NumericAlgebra && node.left is MST.Numeric && node.right is MST.Numeric -> constant( algebra.number( RealField - .binaryOperation(node.operation) + .binaryOperationFunction(node.operation) .invoke(node.left.value.toDouble(), node.right.value.toDouble()) ) ) algebra is NumericAlgebra && node.left is MST.Numeric -> call( - algebra.leftSideNumberOperation(node.operation), + algebra.leftSideNumberOperationFunction(node.operation), visit(node.left), visit(node.right), ) algebra is NumericAlgebra && node.right is MST.Numeric -> call( - algebra.rightSideNumberOperation(node.operation), + algebra.rightSideNumberOperationFunction(node.operation), visit(node.left), visit(node.right), ) else -> call( - algebra.binaryOperation(node.operation), + algebra.binaryOperationFunction(node.operation), visit(node.left), visit(node.right), ) diff --git a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index 242a4154d..b9be02d49 100644 --- a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -13,8 +13,8 @@ internal class TestESTreeConsistencyWithInterpreter { @Test fun mstSpace() { val res1 = MstSpace.mstInSpace { - binaryOperation("+")( - unaryOperation("+")( + binaryOperationFunction("+")( + unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (multiply( add(number(1), number(1)), 2 @@ -26,8 +26,8 @@ internal class TestESTreeConsistencyWithInterpreter { }("x" to MST.Numeric(2)) val res2 = MstSpace.mstInSpace { - binaryOperation("+")( - unaryOperation("+")( + binaryOperationFunction("+")( + unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (multiply( add(number(1), number(1)), 2 @@ -44,8 +44,8 @@ internal class TestESTreeConsistencyWithInterpreter { @Test fun byteRing() { val res1 = ByteRing.mstInRing { - binaryOperation("+")( - unaryOperation("+")( + binaryOperationFunction("+")( + unaryOperationFunction("+")( (symbol("x") - (2.toByte() + (multiply( add(number(1), number(1)), 2 @@ -57,8 +57,8 @@ internal class TestESTreeConsistencyWithInterpreter { }("x" to 3.toByte()) val res2 = ByteRing.mstInRing { - binaryOperation("+")( - unaryOperation("+")( + binaryOperationFunction("+")( + unaryOperationFunction("+")( (symbol("x") - (2.toByte() + (multiply( add(number(1), number(1)), 2 @@ -74,7 +74,7 @@ internal class TestESTreeConsistencyWithInterpreter { @Test fun realField() { val res1 = RealField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one @@ -82,7 +82,7 @@ internal class TestESTreeConsistencyWithInterpreter { }("x" to 2.0) val res2 = RealField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one @@ -95,7 +95,7 @@ internal class TestESTreeConsistencyWithInterpreter { @Test fun complexField() { val res1 = ComplexField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one @@ -103,7 +103,7 @@ internal class TestESTreeConsistencyWithInterpreter { }("x" to 2.0.toComplex()) val res2 = ComplexField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one diff --git a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeSpecialization.kt index 0821686fc..9d0d17e58 100644 --- a/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeSpecialization.kt +++ b/kmath-ast/src/jsTest/kotlin/kscience/kmath/estree/TestESTreeSpecialization.kt @@ -9,44 +9,44 @@ import kotlin.test.assertEquals internal class TestESTreeSpecialization { @Test fun testUnaryPlus() { - val expr = RealField.mstInField { unaryOperation("+")(symbol("x")) }.compile() + val expr = RealField.mstInField { unaryOperationFunction("+")(symbol("x")) }.compile() assertEquals(2.0, expr("x" to 2.0)) } @Test fun testUnaryMinus() { - val expr = RealField.mstInField { unaryOperation("-")(symbol("x")) }.compile() + val expr = RealField.mstInField { unaryOperationFunction("-")(symbol("x")) }.compile() assertEquals(-2.0, expr("x" to 2.0)) } @Test fun testAdd() { - val expr = RealField.mstInField { binaryOperation("+")(symbol("x"), symbol("x")) }.compile() + val expr = RealField.mstInField { binaryOperationFunction("+")(symbol("x"), symbol("x")) }.compile() assertEquals(4.0, expr("x" to 2.0)) } @Test fun testSine() { - val expr = RealField.mstInField { unaryOperation("sin")(symbol("x")) }.compile() + val expr = RealField.mstInField { unaryOperationFunction("sin")(symbol("x")) }.compile() assertEquals(0.0, expr("x" to 0.0)) } @Test fun testMinus() { - val expr = RealField.mstInField { binaryOperation("-")(symbol("x"), symbol("x")) }.compile() + val expr = RealField.mstInField { binaryOperationFunction("-")(symbol("x"), symbol("x")) }.compile() assertEquals(0.0, expr("x" to 2.0)) } @Test fun testDivide() { - val expr = RealField.mstInField { binaryOperation("/")(symbol("x"), symbol("x")) }.compile() + val expr = RealField.mstInField { binaryOperationFunction("/")(symbol("x"), symbol("x")) }.compile() assertEquals(1.0, expr("x" to 2.0)) } @Test fun testPower() { val expr = RealField - .mstInField { binaryOperation("pow")(symbol("x"), number(2)) } + .mstInField { binaryOperationFunction("pow")(symbol("x"), number(2)) } .compile() assertEquals(4.0, expr("x" to 2.0)) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt index 932813182..b98c0bfce 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt @@ -34,28 +34,28 @@ internal fun MST.compileWith(type: Class, algebra: Algebra): Exp } is MST.Numeric -> loadNumberConstant(node.value) - is MST.Unary -> buildCall(algebra.unaryOperation(node.operation)) { visit(node.value) } + is MST.Unary -> buildCall(algebra.unaryOperationFunction(node.operation)) { visit(node.value) } is MST.Binary -> when { algebra is NumericAlgebra && node.left is MST.Numeric && node.right is MST.Numeric -> loadObjectConstant( algebra.number( RealField - .binaryOperation(node.operation) + .binaryOperationFunction(node.operation) .invoke(node.left.value.toDouble(), node.right.value.toDouble()) ) ) - algebra is NumericAlgebra && node.left is MST.Numeric -> buildCall(algebra.leftSideNumberOperation(node.operation)) { + algebra is NumericAlgebra && node.left is MST.Numeric -> buildCall(algebra.leftSideNumberOperationFunction(node.operation)) { visit(node.left) visit(node.right) } - algebra is NumericAlgebra && node.right is MST.Numeric -> buildCall(algebra.rightSideNumberOperation(node.operation)) { + algebra is NumericAlgebra && node.right is MST.Numeric -> buildCall(algebra.rightSideNumberOperationFunction(node.operation)) { visit(node.left) visit(node.right) } - else -> buildCall(algebra.binaryOperation(node.operation)) { + else -> buildCall(algebra.binaryOperationFunction(node.operation)) { visit(node.left) visit(node.right) } diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index 013ae789d..ae180bf3f 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -13,8 +13,8 @@ internal class TestAsmConsistencyWithInterpreter { @Test fun mstSpace() { val res1 = MstSpace.mstInSpace { - binaryOperation("+")( - unaryOperation("+")( + binaryOperationFunction("+")( + unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (multiply( add(number(1), number(1)), 2 @@ -26,8 +26,8 @@ internal class TestAsmConsistencyWithInterpreter { }("x" to MST.Numeric(2)) val res2 = MstSpace.mstInSpace { - binaryOperation("+")( - unaryOperation("+")( + binaryOperationFunction("+")( + unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (multiply( add(number(1), number(1)), 2 @@ -44,8 +44,8 @@ internal class TestAsmConsistencyWithInterpreter { @Test fun byteRing() { val res1 = ByteRing.mstInRing { - binaryOperation("+")( - unaryOperation("+")( + binaryOperationFunction("+")( + unaryOperationFunction("+")( (symbol("x") - (2.toByte() + (multiply( add(number(1), number(1)), 2 @@ -57,8 +57,8 @@ internal class TestAsmConsistencyWithInterpreter { }("x" to 3.toByte()) val res2 = ByteRing.mstInRing { - binaryOperation("+")( - unaryOperation("+")( + binaryOperationFunction("+")( + unaryOperationFunction("+")( (symbol("x") - (2.toByte() + (multiply( add(number(1), number(1)), 2 @@ -74,7 +74,7 @@ internal class TestAsmConsistencyWithInterpreter { @Test fun realField() { val res1 = RealField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one @@ -82,7 +82,7 @@ internal class TestAsmConsistencyWithInterpreter { }("x" to 2.0) val res2 = RealField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one @@ -95,7 +95,7 @@ internal class TestAsmConsistencyWithInterpreter { @Test fun complexField() { val res1 = ComplexField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one @@ -103,7 +103,7 @@ internal class TestAsmConsistencyWithInterpreter { }("x" to 2.0.toComplex()) val res2 = ComplexField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperation("+")( + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt index ce9e602d3..602c54651 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/asm/TestAsmSpecialization.kt @@ -9,44 +9,44 @@ import kotlin.test.assertEquals internal class TestAsmSpecialization { @Test fun testUnaryPlus() { - val expr = RealField.mstInField { unaryOperation("+")(symbol("x")) }.compile() + val expr = RealField.mstInField { unaryOperationFunction("+")(symbol("x")) }.compile() assertEquals(2.0, expr("x" to 2.0)) } @Test fun testUnaryMinus() { - val expr = RealField.mstInField { unaryOperation("-")(symbol("x")) }.compile() + val expr = RealField.mstInField { unaryOperationFunction("-")(symbol("x")) }.compile() assertEquals(-2.0, expr("x" to 2.0)) } @Test fun testAdd() { - val expr = RealField.mstInField { binaryOperation("+")(symbol("x"), symbol("x")) }.compile() + val expr = RealField.mstInField { binaryOperationFunction("+")(symbol("x"), symbol("x")) }.compile() assertEquals(4.0, expr("x" to 2.0)) } @Test fun testSine() { - val expr = RealField.mstInField { unaryOperation("sin")(symbol("x")) }.compile() + val expr = RealField.mstInField { unaryOperationFunction("sin")(symbol("x")) }.compile() assertEquals(0.0, expr("x" to 0.0)) } @Test fun testMinus() { - val expr = RealField.mstInField { binaryOperation("-")(symbol("x"), symbol("x")) }.compile() + val expr = RealField.mstInField { binaryOperationFunction("-")(symbol("x"), symbol("x")) }.compile() assertEquals(0.0, expr("x" to 2.0)) } @Test fun testDivide() { - val expr = RealField.mstInField { binaryOperation("/")(symbol("x"), symbol("x")) }.compile() + val expr = RealField.mstInField { binaryOperationFunction("/")(symbol("x"), symbol("x")) }.compile() assertEquals(1.0, expr("x" to 2.0)) } @Test fun testPower() { val expr = RealField - .mstInField { binaryOperation("pow")(symbol("x"), number(2)) } + .mstInField { binaryOperationFunction("pow")(symbol("x"), number(2)) } .compile() assertEquals(4.0, expr("x" to 2.0)) diff --git a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt index e2029ce19..3aa5392c8 100644 --- a/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/kscience/kmath/ast/ParserTest.kt @@ -42,11 +42,11 @@ internal class ParserTest { val magicalAlgebra = object : Algebra { override fun symbol(value: String): String = value - override fun unaryOperation(operation: String): (arg: String) -> String { + override fun unaryOperationFunction(operation: String): (arg: String) -> String { throw NotImplementedError() } - override fun binaryOperation(operation: String): (left: String, right: String) -> String = + override fun binaryOperationFunction(operation: String): (left: String, right: String) -> String = when (operation) { "magic" -> { left, right -> "$left ★ $right" } else -> throw NotImplementedError() 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 e2413dea8..afbaf16e1 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -24,18 +24,18 @@ public abstract class FunctionalExpressionAlgebra>(public val /** * Builds an Expression of dynamic call of binary operation [operation] on [left] and [right]. */ - public override fun binaryOperation(operation: String): (left: Expression, right: Expression) -> Expression = + public override fun binaryOperationFunction(operation: String): (left: Expression, right: Expression) -> Expression = { left, right -> Expression { arguments -> - algebra.binaryOperation(operation)(left.invoke(arguments), right.invoke(arguments)) + algebra.binaryOperationFunction(operation)(left.invoke(arguments), right.invoke(arguments)) } } /** * Builds an Expression of dynamic call of unary operation with name [operation] on [arg]. */ - public override fun unaryOperation(operation: String): (arg: Expression) -> Expression = { arg -> - Expression { arguments -> algebra.unaryOperation(operation)(arg.invoke(arguments)) } + public override fun unaryOperationFunction(operation: String): (arg: Expression) -> Expression = { arg -> + Expression { arguments -> algebra.unaryOperationFunction(operation)(arg.invoke(arguments)) } } } @@ -50,7 +50,7 @@ public open class FunctionalExpressionSpace>(algebra: A) : * Builds an Expression of addition of two another expressions. */ public override fun add(a: Expression, b: Expression): Expression = - binaryOperation(SpaceOperations.PLUS_OPERATION)(a, b) + binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b) /** * Builds an Expression of multiplication of expression by number. @@ -64,11 +64,11 @@ public open class FunctionalExpressionSpace>(algebra: A) : public operator fun T.plus(arg: Expression): Expression = arg + this public operator fun T.minus(arg: Expression): Expression = arg - this - public override fun unaryOperation(operation: String): (arg: Expression) -> Expression = - super.unaryOperation(operation) + public override fun unaryOperationFunction(operation: String): (arg: Expression) -> Expression = + super.unaryOperationFunction(operation) - public override fun binaryOperation(operation: String): (left: Expression, right: Expression) -> Expression = - super.binaryOperation(operation) + public override fun binaryOperationFunction(operation: String): (left: Expression, right: Expression) -> Expression = + super.binaryOperationFunction(operation) } public open class FunctionalExpressionRing(algebra: A) : FunctionalExpressionSpace(algebra), @@ -80,16 +80,16 @@ public open class FunctionalExpressionRing(algebra: A) : FunctionalExpress * Builds an Expression of multiplication of two expressions. */ public override fun multiply(a: Expression, b: Expression): Expression = - binaryOperation(RingOperations.TIMES_OPERATION)(a, b) + binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b) public operator fun Expression.times(arg: T): Expression = this * const(arg) public operator fun T.times(arg: Expression): Expression = arg * this - public override fun unaryOperation(operation: String): (arg: Expression) -> Expression = - super.unaryOperation(operation) + public override fun unaryOperationFunction(operation: String): (arg: Expression) -> Expression = + super.unaryOperationFunction(operation) - public override fun binaryOperation(operation: String): (left: Expression, right: Expression) -> Expression = - super.binaryOperation(operation) + public override fun binaryOperationFunction(operation: String): (left: Expression, right: Expression) -> Expression = + super.binaryOperationFunction(operation) } public open class FunctionalExpressionField(algebra: A) : @@ -99,49 +99,49 @@ public open class FunctionalExpressionField(algebra: A) : * Builds an Expression of division an expression by another one. */ public override fun divide(a: Expression, b: Expression): Expression = - binaryOperation(FieldOperations.DIV_OPERATION)(a, b) + binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b) public operator fun Expression.div(arg: T): Expression = this / const(arg) public operator fun T.div(arg: Expression): Expression = arg / this - public override fun unaryOperation(operation: String): (arg: Expression) -> Expression = - super.unaryOperation(operation) + public override fun unaryOperationFunction(operation: String): (arg: Expression) -> Expression = + super.unaryOperationFunction(operation) - public override fun binaryOperation(operation: String): (left: Expression, right: Expression) -> Expression = - super.binaryOperation(operation) + public override fun binaryOperationFunction(operation: String): (left: Expression, right: Expression) -> Expression = + super.binaryOperationFunction(operation) } public open class FunctionalExpressionExtendedField(algebra: A) : FunctionalExpressionField(algebra), ExtendedField> where A : ExtendedField, A : NumericAlgebra { public override fun sin(arg: Expression): Expression = - unaryOperation(TrigonometricOperations.SIN_OPERATION)(arg) + unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg) public override fun cos(arg: Expression): Expression = - unaryOperation(TrigonometricOperations.COS_OPERATION)(arg) + unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg) public override fun asin(arg: Expression): Expression = - unaryOperation(TrigonometricOperations.ASIN_OPERATION)(arg) + unaryOperationFunction(TrigonometricOperations.ASIN_OPERATION)(arg) public override fun acos(arg: Expression): Expression = - unaryOperation(TrigonometricOperations.ACOS_OPERATION)(arg) + unaryOperationFunction(TrigonometricOperations.ACOS_OPERATION)(arg) public override fun atan(arg: Expression): Expression = - unaryOperation(TrigonometricOperations.ATAN_OPERATION)(arg) + unaryOperationFunction(TrigonometricOperations.ATAN_OPERATION)(arg) public override fun power(arg: Expression, pow: Number): Expression = - binaryOperation(PowerOperations.POW_OPERATION)(arg, number(pow)) + binaryOperationFunction(PowerOperations.POW_OPERATION)(arg, number(pow)) public override fun exp(arg: Expression): Expression = - unaryOperation(ExponentialOperations.EXP_OPERATION)(arg) + unaryOperationFunction(ExponentialOperations.EXP_OPERATION)(arg) - public override fun ln(arg: Expression): Expression = unaryOperation(ExponentialOperations.LN_OPERATION)(arg) + public override fun ln(arg: Expression): Expression = unaryOperationFunction(ExponentialOperations.LN_OPERATION)(arg) - public override fun unaryOperation(operation: String): (arg: Expression) -> Expression = - super.unaryOperation(operation) + public override fun unaryOperationFunction(operation: String): (arg: Expression) -> Expression = + super.unaryOperationFunction(operation) - public override fun binaryOperation(operation: String): (left: Expression, right: Expression) -> Expression = - super.binaryOperation(operation) + public override fun binaryOperationFunction(operation: String): (left: Expression, right: Expression) -> Expression = + super.binaryOperationFunction(operation) } public inline fun > A.expressionInSpace(block: FunctionalExpressionSpace.() -> Expression): Expression = diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt index 912c3f950..648af605c 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt @@ -19,10 +19,10 @@ public interface MatrixContext> : SpaceOperations T): M @Suppress("UNCHECKED_CAST") - public override fun binaryOperation(operation: String): (left: Matrix, right: Matrix) -> M = + public override fun binaryOperationFunction(operation: String): (left: Matrix, right: Matrix) -> M = when (operation) { "dot" -> { left, right -> left dot right } - else -> super.binaryOperation(operation) as (Matrix, Matrix) -> M + else -> super.binaryOperationFunction(operation) as (Matrix, Matrix) -> M } /** diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index d2cf8e0dd..24b417860 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -33,12 +33,12 @@ public interface Algebra { * * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. * 2. This function is symmetric with second `unaryOperation` overload: - * i.e. `unaryOperation(a)(b) == unaryOperation(a, b)`. + * i.e. `unaryOperationFunction(a)(b) == unaryOperation(a, b)`. * * @param operation the name of operation. * @return an operation. */ - public fun unaryOperation(operation: String): (arg: T) -> T = + public fun unaryOperationFunction(operation: String): (arg: T) -> T = error("Unary operation $operation not defined in $this") /** @@ -47,14 +47,14 @@ public interface Algebra { * This function must follow two properties: * * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. - * 2. This function is symmetric with second [unaryOperation] overload: - * i.e. `unaryOperation(a)(b) == unaryOperation(a, b)`. + * 2. This function is symmetric with second [unaryOperationFunction] overload: + * i.e. `unaryOperationFunction(a)(b) == unaryOperation(a, b)`. * * @param operation the name of operation. * @param arg the argument of operation. * @return a result of operation. */ - public fun unaryOperation(operation: String, arg: T): T = unaryOperation(operation)(arg) + public fun unaryOperation(operation: String, arg: T): T = unaryOperationFunction(operation)(arg) /** * Dynamically dispatches a binary operation with the certain name. @@ -62,13 +62,13 @@ public interface Algebra { * This function must follow two properties: * * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. - * 2. This function is symmetric with second [binaryOperation] overload: - * i.e. `binaryOperation(a)(b, c) == binaryOperation(a, b, c)`. + * 2. This function is symmetric with second [binaryOperationFunction] overload: + * i.e. `binaryOperationFunction(a)(b, c) == binaryOperation(a, b, c)`. * * @param operation the name of operation. * @return an operation. */ - public fun binaryOperation(operation: String): (left: T, right: T) -> T = + public fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = error("Binary operation $operation not defined in $this") /** @@ -77,15 +77,15 @@ public interface Algebra { * This function must follow two properties: * * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. - * 2. This function is symmetric with second [binaryOperation] overload: - * i.e. `binaryOperation(a)(b, c) == binaryOperation(a, b, c)`. + * 2. This function is symmetric with second [binaryOperationFunction] overload: + * i.e. `binaryOperationFunction(a)(b, c) == binaryOperation(a, b, c)`. * * @param operation the name of operation. * @param left the first argument of operation. * @param right the second argument of operation. * @return a result of operation. */ - public fun binaryOperation(operation: String, left: T, right: T): T = binaryOperation(operation)(left, right) + public fun binaryOperation(operation: String, left: T, right: T): T = binaryOperationFunction(operation)(left, right) } /** @@ -109,13 +109,13 @@ public interface NumericAlgebra : Algebra { * * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. * 2. This function is symmetric with the other [leftSideNumberOperation] overload: - * i.e. `leftSideNumberOperation(a)(b, c) == leftSideNumberOperation(a, b)`. + * i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b)`. * * @param operation the name of operation. * @return an operation. */ - public fun leftSideNumberOperation(operation: String): (left: Number, right: T) -> T = - { l, r -> binaryOperation(operation)(number(l), r) } + public fun leftSideNumberOperationFunction(operation: String): (left: Number, right: T) -> T = + { l, r -> binaryOperationFunction(operation)(number(l), r) } /** * Dynamically invokes a binary operation with the certain name with numeric first argument. @@ -124,7 +124,7 @@ public interface NumericAlgebra : Algebra { * * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. * 2. This function is symmetric with second [leftSideNumberOperation] overload: - * i.e. `leftSideNumberOperation(a)(b, c) == leftSideNumberOperation(a, b, c)`. + * i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`. * * @param operation the name of operation. * @param left the first argument of operation. @@ -132,7 +132,7 @@ public interface NumericAlgebra : Algebra { * @return a result of operation. */ public fun leftSideNumberOperation(operation: String, left: Number, right: T): T = - leftSideNumberOperation(operation)(left, right) + leftSideNumberOperationFunction(operation)(left, right) /** * Dynamically dispatches a binary operation with the certain name with numeric first argument. @@ -140,14 +140,14 @@ public interface NumericAlgebra : Algebra { * This function must follow two properties: * * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. - * 2. This function is symmetric with the other [rightSideNumberOperation] overload: - * i.e. `rightSideNumberOperation(a)(b, c) == leftSideNumberOperation(a, b, c)`. + * 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload: + * i.e. `rightSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`. * * @param operation the name of operation. * @return an operation. */ - public fun rightSideNumberOperation(operation: String): (left: T, right: Number) -> T = - { l, r -> binaryOperation(operation)(l, number(r)) } + public fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = + { l, r -> binaryOperationFunction(operation)(l, number(r)) } /** * Dynamically invokes a binary operation with the certain name with numeric second argument. @@ -155,8 +155,8 @@ public interface NumericAlgebra : Algebra { * This function must follow two properties: * * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. - * 2. This function is symmetric with the other [rightSideNumberOperation] overload: - * i.e. `rightSideNumberOperation(a)(b, c) == rightSideNumberOperation(a, b, c)`. + * 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload: + * i.e. `rightSideNumberOperationFunction(a)(b, c) == rightSideNumberOperation(a, b, c)`. * * @param operation the name of operation. * @param left the first argument of operation. @@ -164,7 +164,7 @@ public interface NumericAlgebra : Algebra { * @return a result of operation. */ public fun rightSideNumberOperation(operation: String, left: T, right: Number): T = - rightSideNumberOperation(operation)(left, right) + rightSideNumberOperationFunction(operation)(left, right) } /** @@ -261,16 +261,16 @@ public interface SpaceOperations : Algebra { */ public operator fun Number.times(b: T): T = b * this - public override fun unaryOperation(operation: String): (arg: T) -> T = when (operation) { + public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) { PLUS_OPERATION -> { arg -> arg } MINUS_OPERATION -> { arg -> -arg } - else -> super.unaryOperation(operation) + else -> super.unaryOperationFunction(operation) } - public override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { + public override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) { PLUS_OPERATION -> ::add MINUS_OPERATION -> { left, right -> left - right } - else -> super.binaryOperation(operation) + else -> super.binaryOperationFunction(operation) } public companion object { @@ -322,9 +322,9 @@ public interface RingOperations : SpaceOperations { */ public operator fun T.times(b: T): T = multiply(this, b) - public override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { + public override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) { TIMES_OPERATION -> ::multiply - else -> super.binaryOperation(operation) + else -> super.binaryOperationFunction(operation) } public companion object { @@ -409,9 +409,9 @@ public interface FieldOperations : RingOperations { */ public operator fun T.div(b: T): T = divide(this, b) - public override fun binaryOperation(operation: String): (left: T, right: T) -> T = when (operation) { + public override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) { DIV_OPERATION -> ::divide - else -> super.binaryOperation(operation) + else -> super.binaryOperationFunction(operation) } public companion object { diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt index 84d89b7eb..a7b73d5e0 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt @@ -14,7 +14,7 @@ public interface ExtendedFieldOperations : public override fun tan(arg: T): T = sin(arg) / cos(arg) public override fun tanh(arg: T): T = sinh(arg) / cosh(arg) - public override fun unaryOperation(operation: String): (arg: T) -> T = when (operation) { + public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) { TrigonometricOperations.COS_OPERATION -> ::cos TrigonometricOperations.SIN_OPERATION -> ::sin TrigonometricOperations.TAN_OPERATION -> ::tan @@ -30,7 +30,7 @@ public interface ExtendedFieldOperations : PowerOperations.SQRT_OPERATION -> ::sqrt ExponentialOperations.EXP_OPERATION -> ::exp ExponentialOperations.LN_OPERATION -> ::ln - else -> super.unaryOperation(operation) + else -> super.unaryOperationFunction(operation) } } @@ -45,10 +45,10 @@ public interface ExtendedField : ExtendedFieldOperations, Field { 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 - public override fun rightSideNumberOperation(operation: String): (left: T, right: Number) -> T = + public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = when (operation) { PowerOperations.POW_OPERATION -> ::power - else -> super.rightSideNumberOperation(operation) + else -> super.rightSideNumberOperationFunction(operation) } } @@ -80,10 +80,10 @@ public object RealField : ExtendedField, Norm { public override val one: Double get() = 1.0 - public override fun binaryOperation(operation: String): (left: Double, right: Double) -> Double = + public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double = when (operation) { PowerOperations.POW_OPERATION -> ::power - else -> super.binaryOperation(operation) + else -> super.binaryOperationFunction(operation) } public override inline fun add(a: Double, b: Double): Double = a + b @@ -131,9 +131,9 @@ public object FloatField : ExtendedField, Norm { public override val one: Float get() = 1.0f - public override fun binaryOperation(operation: String): (left: Float, right: Float) -> Float = when (operation) { + public override fun binaryOperationFunction(operation: String): (left: Float, right: Float) -> Float = when (operation) { PowerOperations.POW_OPERATION -> ::power - else -> super.binaryOperation(operation) + else -> super.binaryOperationFunction(operation) } public override inline fun add(a: Float, b: Float): Float = a + b From ea8dc63b1a327a5c773dbd33691cc48f61ee61b3 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 5 Jan 2021 20:14:50 +0700 Subject: [PATCH 183/199] Update doc comments in parser.kt --- .../src/jvmMain/kotlin/kscience/kmath/ast/parser.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt index 79cf77a6a..0b66e2c31 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt @@ -1,3 +1,5 @@ +// TODO move to common when https://github.com/h0tk3y/better-parse/pull/33 is merged + package kscience.kmath.ast import com.github.h0tk3y.betterParse.combinators.* @@ -17,7 +19,8 @@ import kscience.kmath.operations.RingOperations import kscience.kmath.operations.SpaceOperations /** - * TODO move to common after IR version is released + * better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4. + * * @author Alexander Nozik and Iaroslav Postovalov */ public object ArithmeticsEvaluator : Grammar() { @@ -83,7 +86,7 @@ public object ArithmeticsEvaluator : Grammar() { } /** - * Tries to parse the string into [MST]. Returns [ParseResult] representing expression or error. + * Tries to parse the string into [MST] using [ArithmeticsEvaluator]. Returns [ParseResult] representing expression or error. * * @receiver the string to parse. * @return the [MST] node. @@ -91,7 +94,7 @@ public object ArithmeticsEvaluator : Grammar() { public fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryParseToEnd(this) /** - * Parses the string into [MST]. + * Parses the string into [MST] using [ArithmeticsEvaluator]. * * @receiver the string to parse. * @return the [MST] node. From fc152dec4fd514866ca37bef34a899e6bbea5e21 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 5 Jan 2021 20:15:50 +0700 Subject: [PATCH 184/199] Fix readme template --- docs/templates/ARTIFACT-TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md index c77948d4b..d46a431bd 100644 --- a/docs/templates/ARTIFACT-TEMPLATE.md +++ b/docs/templates/ARTIFACT-TEMPLATE.md @@ -14,7 +14,7 @@ > maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - +> > } > > dependencies { From 28ddc7cd959f4d524f3071e068f28591ab723db7 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 5 Jan 2021 20:16:42 +0700 Subject: [PATCH 185/199] Minor: regenerate readme files --- kmath-ast/README.md | 2 +- kmath-core/README.md | 2 +- kmath-for-real/README.md | 2 +- kmath-nd4j/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kmath-ast/README.md b/kmath-ast/README.md index bddc1c563..19e9ee4a9 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -26,7 +26,7 @@ This subproject implements the following features: > maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - +> > } > > dependencies { diff --git a/kmath-core/README.md b/kmath-core/README.md index 3a919e85a..7882e5252 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -26,7 +26,7 @@ The core features of KMath: > maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - +> > } > > dependencies { diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 2ddf78e57..d6b66b7da 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -21,7 +21,7 @@ > maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - +> > } > > dependencies { diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 176dfc09d..ff4ff4542 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -23,7 +23,7 @@ This subproject implements the following features: > maven { url 'https://dl.bintray.com/mipt-npm/kscience' } > maven { url 'https://dl.bintray.com/mipt-npm/dev' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - +> > } > > dependencies { From 06c551d3462724beb22c74a549862bd6f523dc96 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 5 Jan 2021 20:23:07 +0700 Subject: [PATCH 186/199] Update Gradle --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index be52383ef..4d9ca1649 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From b288704528ca54ace552369ca068cd1bf1983992 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 7 Jan 2021 18:07:00 +0300 Subject: [PATCH 187/199] Optimize RealMatrix dot operation --- ...iplicationBenchmark.kt => DotBenchmark.kt} | 24 ++++-- .../kmath/structures/typeSafeDimensions.kt | 5 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 1 + .../kscience/kmath/linear/BufferMatrix.kt | 24 +----- .../kscience/kmath/linear/LUPDecomposition.kt | 11 +-- .../kscience/kmath/linear/MatrixContext.kt | 14 ++-- .../kmath/linear/RealMatrixContext.kt | 84 +++++++++++++++++++ .../kscience/kmath/dimensions/Wrappers.kt | 38 ++++----- .../kscience/dimensions/DMatrixContextTest.kt | 1 + .../kotlin/kscience/kmath/real/RealMatrix.kt | 11 +-- 10 files changed, 135 insertions(+), 78 deletions(-) rename examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/{MultiplicationBenchmark.kt => DotBenchmark.kt} (73%) create mode 100644 kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/MultiplicationBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/DotBenchmark.kt similarity index 73% rename from examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/MultiplicationBenchmark.kt rename to examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/DotBenchmark.kt index 9d2b02245..8823e86db 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/MultiplicationBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/DotBenchmark.kt @@ -2,19 +2,22 @@ package kscience.kmath.benchmarks import kotlinx.benchmark.Benchmark import kscience.kmath.commons.linear.CMMatrixContext -import kscience.kmath.commons.linear.CMMatrixContext.dot 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 +import kscience.kmath.operations.RealField import kscience.kmath.operations.invoke +import kscience.kmath.structures.Buffer import kscience.kmath.structures.Matrix import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State import kotlin.random.Random @State(Scope.Benchmark) -class MultiplicationBenchmark { +class DotBenchmark { companion object { val random = Random(12224) val dim = 1000 @@ -32,14 +35,14 @@ class MultiplicationBenchmark { @Benchmark fun commonsMathMultiplication() { - CMMatrixContext.invoke { + CMMatrixContext { cmMatrix1 dot cmMatrix2 } } @Benchmark fun ejmlMultiplication() { - EjmlMatrixContext.invoke { + EjmlMatrixContext { ejmlMatrix1 dot ejmlMatrix2 } } @@ -48,13 +51,22 @@ class MultiplicationBenchmark { fun ejmlMultiplicationwithConversion() { val ejmlMatrix1 = matrix1.toEjml() val ejmlMatrix2 = matrix2.toEjml() - EjmlMatrixContext.invoke { + EjmlMatrixContext { ejmlMatrix1 dot ejmlMatrix2 } } @Benchmark fun bufferedMultiplication() { - matrix1 dot matrix2 + BufferMatrixContext(RealField, Buffer.Companion::real).invoke{ + matrix1 dot matrix2 + } + } + + @Benchmark + fun realMultiplication(){ + RealMatrixContext { + matrix1 dot matrix2 + } } } \ No newline at end of file diff --git a/examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt index 987eea16f..96684f7dc 100644 --- a/examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/typeSafeDimensions.kt @@ -4,9 +4,8 @@ import kscience.kmath.dimensions.D2 import kscience.kmath.dimensions.D3 import kscience.kmath.dimensions.DMatrixContext import kscience.kmath.dimensions.Dimension -import kscience.kmath.operations.RealField -private fun DMatrixContext.simple() { +private fun DMatrixContext.simple() { val m1 = produce { i, j -> (i + j).toDouble() } val m2 = produce { i, j -> (i + j).toDouble() } @@ -18,7 +17,7 @@ private object D5 : Dimension { override val dim: UInt = 5u } -private fun DMatrixContext.custom() { +private fun DMatrixContext.custom() { val m1 = produce { i, j -> (i + j).toDouble() } val m2 = produce { i, j -> (i - j).toDouble() } val m3 = produce { i, j -> (i - j).toDouble() } diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt index 712927400..49888f8d6 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt @@ -29,6 +29,7 @@ public class CMMatrix(public val origin: RealMatrix, features: Set.toCM(): CMMatrix = if (this is CMMatrix) { this } else { diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt index 8b50bbe33..402161207 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt @@ -1,8 +1,10 @@ package kscience.kmath.linear -import kscience.kmath.operations.RealField import kscience.kmath.operations.Ring -import kscience.kmath.structures.* +import kscience.kmath.structures.Buffer +import kscience.kmath.structures.BufferFactory +import kscience.kmath.structures.NDStructure +import kscience.kmath.structures.asSequence /** * Basic implementation of Matrix space based on [NDStructure] @@ -21,24 +23,6 @@ public class BufferMatrixContext>( public companion object } -@Suppress("OVERRIDE_BY_INLINE") -public object RealMatrixContext : GenericMatrixContext> { - public override val elementContext: RealField - get() = RealField - - public override inline fun produce( - rows: Int, - columns: Int, - initializer: (i: Int, j: Int) -> Double, - ): BufferMatrix { - val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) } - return BufferMatrix(rows, columns, buffer) - } - - public override inline fun point(size: Int, initializer: (Int) -> Double): Point = - RealBuffer(size, initializer) -} - public class BufferMatrix( public override val rowNum: Int, public override val colNum: Int, 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 099fa1909..bf2a9f59e 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt @@ -213,17 +213,8 @@ public inline fun , F : Field> GenericMatrixContext return decomposition.solveWithLUP(bufferFactory, b) } -public fun RealMatrixContext.solveWithLUP(a: Matrix, b: Matrix): FeaturedMatrix = - solveWithLUP(a, b) { it < 1e-11 } - public inline fun , F : Field> GenericMatrixContext>.inverseWithLUP( matrix: Matrix, noinline bufferFactory: MutableBufferFactory = MutableBuffer.Companion::auto, noinline checkSingular: (T) -> Boolean, -): FeaturedMatrix = solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum), bufferFactory, checkSingular) - -/** - * Inverses a square matrix using LUP decomposition. Non square matrix will throw a error. - */ -public fun RealMatrixContext.inverseWithLUP(matrix: Matrix): FeaturedMatrix = - solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum), Buffer.Companion::real) { it < 1e-11 } +): FeaturedMatrix = solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum), bufferFactory, checkSingular) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt index d9dc57b0f..9bc79e12b 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt @@ -18,6 +18,11 @@ public interface MatrixContext> : SpaceOperations T): M + /** + * Produce a point compatible with matrix space (and possibly optimized for it) + */ + public fun point(size: Int, initializer: (Int) -> T): Point = Buffer.boxing(size, initializer) + @Suppress("UNCHECKED_CAST") public override fun binaryOperation(operation: String, left: Matrix, right: Matrix): M = when (operation) { "dot" -> left dot right @@ -61,10 +66,6 @@ public interface MatrixContext> : SpaceOperations): M = m * this public companion object { - /** - * Non-boxing double matrix - */ - public val real: RealMatrixContext = RealMatrixContext /** * A structured matrix with custom buffer @@ -88,11 +89,6 @@ public interface GenericMatrixContext, out M : Matrix> : */ public val elementContext: R - /** - * Produce a point compatible with matrix space - */ - public fun point(size: Int, initializer: (Int) -> T): Point - public override infix fun Matrix.dot(other: Matrix): M { //TODO add typed error require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt new file mode 100644 index 000000000..772b20f3b --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt @@ -0,0 +1,84 @@ +package kscience.kmath.linear + +import kscience.kmath.operations.RealField +import kscience.kmath.structures.Matrix +import kscience.kmath.structures.MutableBuffer +import kscience.kmath.structures.MutableBufferFactory +import kscience.kmath.structures.RealBuffer + +@Suppress("OVERRIDE_BY_INLINE") +public object RealMatrixContext : MatrixContext> { + + public override inline fun produce( + rows: Int, + columns: Int, + initializer: (i: Int, j: Int) -> Double, + ): BufferMatrix { + val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) } + return BufferMatrix(rows, columns, buffer) + } + + private fun Matrix.wrap(): BufferMatrix = if (this is BufferMatrix) this else { + produce(rowNum, colNum) { i, j -> get(i, j) } + } + + public fun one(rows: Int, columns: Int): FeaturedMatrix = VirtualMatrix(rows, columns, DiagonalFeature) { i, j -> + if (i == j) 1.0 else 0.0 + } + + public override infix fun Matrix.dot(other: Matrix): BufferMatrix { + require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } + return produce(rowNum, other.colNum) { i, j -> + var res = 0.0 + for (l in 0 until colNum) { + res += get(i, l) * other.get(l, j) + } + res + } + } + + public override infix fun Matrix.dot(vector: Point): Point { + require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } + return RealBuffer(rowNum) { i -> + var res = 0.0 + for (j in 0 until colNum) { + res += get(i, j) * vector[j] + } + res + } + } + + override fun add(a: Matrix, b: Matrix): BufferMatrix { + require(a.rowNum == b.rowNum) { "Row number mismatch in matrix addition. Left side: ${a.rowNum}, right side: ${b.rowNum}" } + require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" } + return produce(a.rowNum, a.colNum) { i, j -> + a[i, j] + b[i, j] + } + } + + override fun Matrix.times(value: Double): BufferMatrix = + produce(rowNum, colNum) { i, j -> get(i, j) * value } + + + override fun multiply(a: Matrix, k: Number): BufferMatrix = + produce(a.rowNum, a.colNum) { i, j -> a.get(i, j) * k.toDouble() } +} + + +/** + * Partially optimized real-valued matrix + */ +public val MatrixContext.Companion.real: RealMatrixContext get() = RealMatrixContext + +public fun RealMatrixContext.solveWithLUP(a: Matrix, b: Matrix): FeaturedMatrix { + // Use existing decomposition if it is provided by matrix + val bufferFactory: MutableBufferFactory = MutableBuffer.Companion::real + val decomposition = a.getFeature() ?: lup(bufferFactory, RealField, a) { it < 1e-11 } + return decomposition.solveWithLUP(bufferFactory, b) +} + +/** + * Inverses a square matrix using LUP decomposition. Non square matrix will throw a error. + */ +public fun RealMatrixContext.inverseWithLUP(matrix: Matrix): FeaturedMatrix = + solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum)) diff --git a/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt index 68a5dc262..0422d11b2 100644 --- a/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt @@ -1,11 +1,6 @@ package kscience.kmath.dimensions -import kscience.kmath.linear.GenericMatrixContext -import kscience.kmath.linear.MatrixContext -import kscience.kmath.linear.Point -import kscience.kmath.linear.transpose -import kscience.kmath.operations.RealField -import kscience.kmath.operations.Ring +import kscience.kmath.linear.* import kscience.kmath.operations.invoke import kscience.kmath.structures.Matrix import kscience.kmath.structures.Structure2D @@ -42,7 +37,7 @@ public interface DMatrix : Structure2D { * An inline wrapper for a Matrix */ public inline class DMatrixWrapper( - private val structure: Structure2D + private val structure: Structure2D, ) : DMatrix { override val shape: IntArray get() = structure.shape override operator fun get(i: Int, j: Int): T = structure[i, j] @@ -81,7 +76,7 @@ public inline class DPointWrapper(public val point: Point) /** * Basic operations on dimension-safe matrices. Operates on [Matrix] */ -public inline class DMatrixContext>(public val context: GenericMatrixContext>) { +public inline class DMatrixContext(public val context: MatrixContext>) { public inline fun Matrix.coerce(): DMatrix { require(rowNum == Dimension.dim().toInt()) { "Row number mismatch: expected ${Dimension.dim()} but found $rowNum" @@ -115,7 +110,7 @@ public inline class DMatrixContext>(public val context: Ge } public inline infix fun DMatrix.dot( - other: DMatrix + other: DMatrix, ): DMatrix = context { this@dot dot other }.coerce() public inline infix fun DMatrix.dot(vector: DPoint): DPoint = @@ -139,18 +134,19 @@ public inline class DMatrixContext>(public val context: Ge public inline fun DMatrix.transpose(): DMatrix = context { (this@transpose as Matrix).transpose() }.coerce() - /** - * A square unit matrix - */ - public inline fun one(): DMatrix = produce { i, j -> - if (i == j) context.elementContext.one else context.elementContext.zero - } - - public inline fun zero(): DMatrix = produce { _, _ -> - context.elementContext.zero - } - public companion object { - public val real: DMatrixContext = DMatrixContext(MatrixContext.real) + public val real: DMatrixContext = DMatrixContext(MatrixContext.real) } } + + +/** + * A square unit matrix + */ +public inline fun DMatrixContext.one(): DMatrix = produce { i, j -> + if (i == j) 1.0 else 0.0 +} + +public inline fun DMatrixContext.zero(): DMatrix = produce { _, _ -> + 0.0 +} \ No newline at end of file diff --git a/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt b/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt index f44b16753..5b330fcce 100644 --- a/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt +++ b/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt @@ -3,6 +3,7 @@ package kscience.dimensions import kscience.kmath.dimensions.D2 import kscience.kmath.dimensions.D3 import kscience.kmath.dimensions.DMatrixContext +import kscience.kmath.dimensions.one import kotlin.test.Test internal class DMatrixContextTest { diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt index e8ad835e5..772abfbed 100644 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt @@ -1,13 +1,7 @@ package kscience.kmath.real -import kscience.kmath.linear.FeaturedMatrix -import kscience.kmath.linear.MatrixContext -import kscience.kmath.linear.RealMatrixContext.elementContext -import kscience.kmath.linear.VirtualMatrix -import kscience.kmath.linear.inverseWithLUP +import kscience.kmath.linear.* import kscience.kmath.misc.UnstableKMathAPI -import kscience.kmath.operations.invoke -import kscience.kmath.operations.sum import kscience.kmath.structures.Buffer import kscience.kmath.structures.RealBuffer import kscience.kmath.structures.asIterable @@ -122,8 +116,7 @@ public fun RealMatrix.extractColumn(columnIndex: Int): RealMatrix = extractColumns(columnIndex..columnIndex) public fun RealMatrix.sumByColumn(): RealBuffer = RealBuffer(colNum) { j -> - val column = columns[j] - elementContext { sum(column.asIterable()) } + columns[j].asIterable().sum() } public fun RealMatrix.minByColumn(): RealBuffer = RealBuffer(colNum) { j -> From 2012d2c3f1a5a81e1a54fa98baef501c48f8321d Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 7 Jan 2021 22:40:30 +0700 Subject: [PATCH 188/199] Fix #172, add constant folding for unary operations from numeric nodes --- .../kotlin/kscience/kmath/ast/MST.kt | 24 +++++++------- .../kotlin/kscience/kmath/estree/estree.kt | 30 ++++++++++-------- .../jvmMain/kotlin/kscience/kmath/asm/asm.kt | 31 +++++++++++-------- .../kscience/kmath/asm/internal/AsmBuilder.kt | 2 +- 4 files changed, 48 insertions(+), 39 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt index 6cf746722..212fd0d0b 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt @@ -2,10 +2,9 @@ package kscience.kmath.ast import kscience.kmath.operations.Algebra import kscience.kmath.operations.NumericAlgebra -import kscience.kmath.operations.RealField /** - * A Mathematical Syntax Tree node for mathematical expressions. + * A Mathematical Syntax Tree (MST) node for mathematical expressions. * * @author Alexander Nozik */ @@ -57,21 +56,22 @@ public fun Algebra.evaluate(node: MST): T = when (node) { ?: error("Numeric nodes are not supported by $this") is MST.Symbolic -> symbol(node.value) - is MST.Unary -> unaryOperationFunction(node.operation)(evaluate(node.value)) + + is MST.Unary -> when { + this is NumericAlgebra && node.value is MST.Numeric -> unaryOperationFunction(node.operation)(number(node.value.value)) + else -> unaryOperationFunction(node.operation)(evaluate(node.value)) + } is MST.Binary -> when { - this !is NumericAlgebra -> binaryOperationFunction(node.operation)(evaluate(node.left), evaluate(node.right)) + this is NumericAlgebra && node.left is MST.Numeric && node.right is MST.Numeric -> + binaryOperationFunction(node.operation)(number(node.left.value), number(node.right.value)) - node.left is MST.Numeric && node.right is MST.Numeric -> { - val number = RealField - .binaryOperationFunction(node.operation) - .invoke(node.left.value.toDouble(), node.right.value.toDouble()) + this is NumericAlgebra && node.left is MST.Numeric -> + leftSideNumberOperationFunction(node.operation)(node.left.value, evaluate(node.right)) - number(number) - } + this is NumericAlgebra && node.right is MST.Numeric -> + rightSideNumberOperationFunction(node.operation)(evaluate(node.left), node.right.value) - node.left is MST.Numeric -> leftSideNumberOperationFunction(node.operation)(node.left.value, evaluate(node.right)) - node.right is MST.Numeric -> rightSideNumberOperationFunction(node.operation)(evaluate(node.left), node.right.value) else -> binaryOperationFunction(node.operation)(evaluate(node.left), evaluate(node.right)) } } diff --git a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt index 159c5d5ec..5c08ada31 100644 --- a/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt @@ -1,18 +1,18 @@ package kscience.kmath.estree import kscience.kmath.ast.MST +import kscience.kmath.ast.MST.* import kscience.kmath.ast.MstExpression import kscience.kmath.estree.internal.ESTreeBuilder import kscience.kmath.estree.internal.estree.BaseExpression import kscience.kmath.expressions.Expression import kscience.kmath.operations.Algebra import kscience.kmath.operations.NumericAlgebra -import kscience.kmath.operations.RealField @PublishedApi internal fun MST.compileWith(algebra: Algebra): Expression { fun ESTreeBuilder.visit(node: MST): BaseExpression = when (node) { - is MST.Symbolic -> { + is Symbolic -> { val symbol = try { algebra.symbol(node.value) } catch (ignored: IllegalStateException) { @@ -25,25 +25,29 @@ internal fun MST.compileWith(algebra: Algebra): Expression { variable(node.value) } - is MST.Numeric -> constant(node.value) - is MST.Unary -> call(algebra.unaryOperationFunction(node.operation), visit(node.value)) + is Numeric -> constant(node.value) - is MST.Binary -> when { - algebra is NumericAlgebra && node.left is MST.Numeric && node.right is MST.Numeric -> constant( - algebra.number( - RealField - .binaryOperationFunction(node.operation) - .invoke(node.left.value.toDouble(), node.right.value.toDouble()) - ) + is Unary -> when { + algebra is NumericAlgebra && node.value is Numeric -> constant( + algebra.unaryOperationFunction(node.operation)(algebra.number(node.value.value))) + + else -> call(algebra.unaryOperationFunction(node.operation), visit(node.value)) + } + + is Binary -> when { + algebra is NumericAlgebra && node.left is Numeric && node.right is Numeric -> constant( + algebra + .binaryOperationFunction(node.operation) + .invoke(algebra.number(node.left.value), algebra.number(node.right.value)) ) - algebra is NumericAlgebra && node.left is MST.Numeric -> call( + algebra is NumericAlgebra && node.left is Numeric -> call( algebra.leftSideNumberOperationFunction(node.operation), visit(node.left), visit(node.right), ) - algebra is NumericAlgebra && node.right is MST.Numeric -> call( + algebra is NumericAlgebra && node.right is Numeric -> call( algebra.rightSideNumberOperationFunction(node.operation), visit(node.left), visit(node.right), diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt index b98c0bfce..55cdec243 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt @@ -3,11 +3,11 @@ package kscience.kmath.asm import kscience.kmath.asm.internal.AsmBuilder import kscience.kmath.asm.internal.buildName import kscience.kmath.ast.MST +import kscience.kmath.ast.MST.* import kscience.kmath.ast.MstExpression import kscience.kmath.expressions.Expression import kscience.kmath.operations.Algebra import kscience.kmath.operations.NumericAlgebra -import kscience.kmath.operations.RealField /** * Compiles given MST to an Expression using AST compiler. @@ -20,7 +20,7 @@ import kscience.kmath.operations.RealField @PublishedApi internal fun MST.compileWith(type: Class, algebra: Algebra): Expression { fun AsmBuilder.visit(node: MST): Unit = when (node) { - is MST.Symbolic -> { + is Symbolic -> { val symbol = try { algebra.symbol(node.value) } catch (ignored: IllegalStateException) { @@ -33,24 +33,29 @@ internal fun MST.compileWith(type: Class, algebra: Algebra): Exp loadVariable(node.value) } - is MST.Numeric -> loadNumberConstant(node.value) - is MST.Unary -> buildCall(algebra.unaryOperationFunction(node.operation)) { visit(node.value) } + is Numeric -> loadNumberConstant(node.value) - is MST.Binary -> when { - algebra is NumericAlgebra && node.left is MST.Numeric && node.right is MST.Numeric -> loadObjectConstant( - algebra.number( - RealField - .binaryOperationFunction(node.operation) - .invoke(node.left.value.toDouble(), node.right.value.toDouble()) - ) + is Unary -> when { + algebra is NumericAlgebra && node.value is Numeric -> loadObjectConstant( + algebra.unaryOperationFunction(node.operation)(algebra.number(node.value.value))) + + else -> buildCall(algebra.unaryOperationFunction(node.operation)) { visit(node.value) } + } + + is Binary -> when { + algebra is NumericAlgebra && node.left is Numeric && node.right is Numeric -> loadObjectConstant( + algebra.binaryOperationFunction(node.operation) + .invoke(algebra.number(node.left.value), algebra.number(node.right.value)) ) - algebra is NumericAlgebra && node.left is MST.Numeric -> buildCall(algebra.leftSideNumberOperationFunction(node.operation)) { + algebra is NumericAlgebra && node.left is Numeric -> buildCall( + algebra.leftSideNumberOperationFunction(node.operation)) { visit(node.left) visit(node.right) } - algebra is NumericAlgebra && node.right is MST.Numeric -> buildCall(algebra.rightSideNumberOperationFunction(node.operation)) { + algebra is NumericAlgebra && node.right is Numeric -> buildCall( + algebra.rightSideNumberOperationFunction(node.operation)) { visit(node.left) visit(node.right) } diff --git a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt index 1edbed28d..93d8d1143 100644 --- a/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/internal/AsmBuilder.kt @@ -191,7 +191,7 @@ internal class AsmBuilder( } val cls = classLoader.defineClass(className, classWriter.toByteArray()) - java.io.File("dump.class").writeBytes(classWriter.toByteArray()) + // java.io.File("dump.class").writeBytes(classWriter.toByteArray()) val l = MethodHandles.publicLookup() if (hasConstants) From 0ef7e7ca52ab6bedc1f33f6b5e2e1572c61b83f6 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 10 Jan 2021 17:53:15 +0700 Subject: [PATCH 189/199] Update Gradle again --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4d9ca1649..da9702f9e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 7fdd001a77e14aa745d629d528971b979a2f019a Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 16 Jan 2021 15:51:36 +0700 Subject: [PATCH 190/199] Update KDoc comments for Matrix classes, improve MatrixFeature API, implement new features with EJML matrix, delete inversion API from EJML in favor of InverseMatrixFeature, override point by EJML matrix --- .../kscience/kmath/linear/FeaturedMatrix.kt | 10 +- .../kscience/kmath/linear/LUPDecomposition.kt | 14 ++- .../kscience/kmath/linear/MatrixFeatures.kt | 114 ++++++++++++++++-- .../kscience/kmath/structures/Structure2D.kt | 45 +++++-- .../kotlin/kscience/kmath/ejml/EjmlMatrix.kt | 83 ++++++++----- .../kscience/kmath/ejml/EjmlMatrixContext.kt | 15 +-- .../kscience/kmath/ejml/EjmlMatrixTest.kt | 4 +- 7 files changed, 217 insertions(+), 68 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt index 68272203c..119f5d844 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt @@ -7,10 +7,16 @@ import kscience.kmath.structures.asBuffer import kotlin.math.sqrt /** - * A 2d structure plus optional matrix-specific features + * A [Matrix] that holds [MatrixFeature] objects. + * + * @param T the type of items. */ public interface FeaturedMatrix : Matrix { - override val shape: IntArray get() = intArrayOf(rowNum, colNum) + public override val shape: IntArray get() = intArrayOf(rowNum, colNum) + + /** + * The set of features this matrix possesses. + */ public val features: Set /** 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 bf2a9f59e..75acaf8a1 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt @@ -4,16 +4,15 @@ import kscience.kmath.operations.* import kscience.kmath.structures.* /** - * Common implementation of [LUPDecompositionFeature] + * Common implementation of [LupDecompositionFeature]. */ public class LUPDecomposition( public val context: MatrixContext>, public val elementContext: Field, - public val lu: Structure2D, + public val lu: Matrix, public val pivot: IntArray, private val even: Boolean, -) : LUPDecompositionFeature, DeterminantFeature { - +) : LupDecompositionFeature, DeterminantFeature { /** * Returns the matrix L of the decomposition. * @@ -151,7 +150,10 @@ public inline fun , F : Field> GenericMatrixContext public fun MatrixContext>.lup(matrix: Matrix): LUPDecomposition = lup(Buffer.Companion::real, RealField, matrix) { it < 1e-11 } -public fun LUPDecomposition.solveWithLUP(factory: MutableBufferFactory, matrix: Matrix): FeaturedMatrix { +public fun LUPDecomposition.solveWithLUP( + factory: MutableBufferFactory, + matrix: Matrix +): FeaturedMatrix { require(matrix.rowNum == pivot.size) { "Matrix dimension mismatch. Expected ${pivot.size}, but got ${matrix.colNum}" } BufferAccessor2D(matrix.rowNum, matrix.colNum, factory).run { @@ -217,4 +219,4 @@ public inline fun , F : Field> GenericMatrixContext matrix: Matrix, noinline bufferFactory: MutableBufferFactory = MutableBuffer.Companion::auto, noinline checkSingular: (T) -> Boolean, -): FeaturedMatrix = solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum), bufferFactory, checkSingular) \ No newline at end of file +): FeaturedMatrix = solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum), bufferFactory, checkSingular) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt index a82032e50..767b58eba 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt @@ -1,62 +1,154 @@ package kscience.kmath.linear /** - * A marker interface representing some matrix feature like diagonal, sparse, zero, etc. Features used to optimize matrix - * operations performance in some cases. + * A marker interface representing some properties of matrices or additional transformations of them. Features are used + * to optimize matrix operations performance in some cases or retrieve the APIs. */ public interface MatrixFeature /** - * The matrix with this feature is considered to have only diagonal non-null elements + * Matrices with this feature are considered to have only diagonal non-null elements. */ public object DiagonalFeature : MatrixFeature /** - * Matrix with this feature has all zero elements + * Matrices with this feature have all zero elements. */ public object ZeroFeature : MatrixFeature /** - * Matrix with this feature have unit elements on diagonal and zero elements in all other places + * Matrices with this feature have unit elements on diagonal and zero elements in all other places. */ public object UnitFeature : MatrixFeature /** - * Inverted matrix feature + * Matrices with this feature can be inverted: [inverse] = `a`-1 where `a` is the owning matrix. + * + * @param T the type of matrices' items. */ public interface InverseMatrixFeature : MatrixFeature { + /** + * The inverse matrix of the matrix that owns this feature. + */ public val inverse: FeaturedMatrix } /** - * A determinant container + * Matrices with this feature can compute their determinant. */ public interface DeterminantFeature : MatrixFeature { + /** + * The determinant of the matrix that owns this feature. + */ public val determinant: T } +/** + * Produces a [DeterminantFeature] where the [DeterminantFeature.determinant] is [determinant]. + * + * @param determinant the value of determinant. + * @return a new [DeterminantFeature]. + */ @Suppress("FunctionName") public fun DeterminantFeature(determinant: T): DeterminantFeature = object : DeterminantFeature { override val determinant: T = determinant } /** - * Lower triangular matrix + * Matrices with this feature are lower triangular ones. */ public object LFeature : MatrixFeature /** - * Upper triangular feature + * Matrices with this feature are upper triangular ones. */ public object UFeature : MatrixFeature /** - * TODO add documentation + * Matrices with this feature support LU factorization with partial pivoting: *[p] · a = [l] · [u]* where + * *a* is the owning matrix. + * + * @param T the type of matrices' items. */ -public interface LUPDecompositionFeature : MatrixFeature { +public interface LupDecompositionFeature : MatrixFeature { + /** + * The lower triangular matrix in this decomposition. It may have [LFeature]. + */ public val l: FeaturedMatrix + + /** + * The upper triangular matrix in this decomposition. It may have [UFeature]. + */ public val u: FeaturedMatrix + + /** + * The permutation matrix in this decomposition. + */ public val p: FeaturedMatrix } +/** + * Matrices with this feature are orthogonal ones: *a · aT = u* where *a* is the owning matrix, *u* + * is the unit matrix ([UnitFeature]). + */ +public object OrthogonalFeature : MatrixFeature + +/** + * Matrices with this feature support QR factorization: *a = [q] · [r]* where *a* is the owning matrix. + * + * @param T the type of matrices' items. + */ +public interface QRDecompositionFeature : MatrixFeature { + /** + * The orthogonal matrix in this decomposition. It may have [OrthogonalFeature]. + */ + public val q: FeaturedMatrix + + /** + * The upper triangular matrix in this decomposition. It may have [UFeature]. + */ + public val r: FeaturedMatrix +} + +/** + * Matrices with this feature support Cholesky factorization: *a = [l] · [l]H* where *a* is the + * owning matrix. + * + * @param T the type of matrices' items. + */ +public interface CholeskyDecompositionFeature : MatrixFeature { + /** + * The triangular matrix in this decomposition. It may have either [UFeature] or [LFeature]. + */ + public val l: FeaturedMatrix +} + +/** + * Matrices with this feature support SVD: *a = [u] · [s] · [v]H* where *a* is the owning + * matrix. + * + * @param T the type of matrices' items. + */ +public interface SingularValueDecompositionFeature : MatrixFeature { + /** + * The matrix in this decomposition. It is unitary, and it consists from left singular vectors. + */ + public val u: FeaturedMatrix + + /** + * The matrix in this decomposition. Its main diagonal elements are singular values. + */ + public val s: FeaturedMatrix + + /** + * The matrix in this decomposition. It is unitary, and it consists from right singular vectors. + */ + public val v: FeaturedMatrix + + /** + * The buffer of singular values of this SVD. + */ + public val singularValues: Point +} + //TODO add sparse matrix feature diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt index 25fdf3f3d..bac7d3389 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt @@ -1,12 +1,40 @@ package kscience.kmath.structures /** - * A structure that is guaranteed to be two-dimensional + * A structure that is guaranteed to be two-dimensional. + * + * @param T the type of items. */ public interface Structure2D : NDStructure { + /** + * The number of rows in this structure. + */ public val rowNum: Int get() = shape[0] + + /** + * The number of columns in this structure. + */ public val colNum: Int get() = shape[1] + /** + * The buffer of rows of this structure. It gets elements from the structure dynamically. + */ + public val rows: Buffer> + get() = VirtualBuffer(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } } + + /** + * The buffer of columns of this structure. It gets elements from the structure dynamically. + */ + public val columns: Buffer> + get() = VirtualBuffer(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } } + + /** + * Retrieves an element from the structure by two indices. + * + * @param i the first index. + * @param j the second index. + * @return an element. + */ public operator fun get(i: Int, j: Int): T override operator fun get(index: IntArray): T { @@ -14,15 +42,9 @@ public interface Structure2D : NDStructure { return get(index[0], index[1]) } - public val rows: Buffer> - get() = VirtualBuffer(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } } - - public val columns: Buffer> - get() = VirtualBuffer(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } } - 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)) + for (i in 0 until rowNum) + for (j in 0 until colNum) yield(intArrayOf(i, j) to get(i, j)) } public companion object @@ -47,4 +69,9 @@ public fun NDStructure.as2D(): Structure2D = if (shape.size == 2) else error("Can't create 2d-structure from ${shape.size}d-structure") +/** + * Alias for [Structure2D] with more familiar name. + * + * @param T the type of items. + */ public typealias Matrix = Structure2D diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt index ed6b1571e..5b7d0a01b 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt @@ -1,12 +1,10 @@ package kscience.kmath.ejml +import kscience.kmath.linear.* +import kscience.kmath.structures.NDStructure +import kscience.kmath.structures.RealBuffer import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix -import kscience.kmath.linear.DeterminantFeature -import kscience.kmath.linear.FeaturedMatrix -import kscience.kmath.linear.LUPDecompositionFeature -import kscience.kmath.linear.MatrixFeature -import kscience.kmath.structures.NDStructure /** * Represents featured matrix over EJML [SimpleMatrix]. @@ -14,42 +12,71 @@ import kscience.kmath.structures.NDStructure * @property origin the underlying [SimpleMatrix]. * @author Iaroslav Postovalov */ -public class EjmlMatrix(public val origin: SimpleMatrix, features: Set? = null) : FeaturedMatrix { +public class EjmlMatrix(public val origin: SimpleMatrix, features: Set = emptySet()) : + FeaturedMatrix { public override val rowNum: Int get() = origin.numRows() public override val colNum: Int get() = origin.numCols() - public override val shape: IntArray - get() = intArrayOf(origin.numRows(), origin.numCols()) + public override val shape: IntArray by lazy { intArrayOf(rowNum, colNum) } - public override val features: Set = setOf( - object : LUPDecompositionFeature, DeterminantFeature { - override val determinant: Double - get() = origin.determinant() + public override val features: Set = hashSetOf( + object : InverseMatrixFeature { + override val inverse: FeaturedMatrix by lazy { EjmlMatrix(origin.invert()) } + }, - private val lup by lazy { - val ludecompositionF64 = DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()) - .also { it.decompose(origin.ddrm.copy()) } + object : DeterminantFeature { + override val determinant: Double by lazy(origin::determinant) + }, - Triple( - EjmlMatrix(SimpleMatrix(ludecompositionF64.getRowPivot(null))), - EjmlMatrix(SimpleMatrix(ludecompositionF64.getLower(null))), - EjmlMatrix(SimpleMatrix(ludecompositionF64.getUpper(null))), - ) + object : SingularValueDecompositionFeature { + private val svd by lazy { + DecompositionFactory_DDRM.svd(origin.numRows(), origin.numCols(), true, true, false) + .apply { decompose(origin.ddrm.copy()) } } - override val l: FeaturedMatrix - get() = lup.second + override val u: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(svd.getU(null, false))) } + override val s: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(svd.getW(null))) } + override val v: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(svd.getV(null, false))) } + override val singularValues: Point by lazy { RealBuffer(svd.singularValues) } + }, - override val u: FeaturedMatrix - get() = lup.third + object : QRDecompositionFeature { + private val qr by lazy { + DecompositionFactory_DDRM.qr().apply { decompose(origin.ddrm.copy()) } + } - override val p: FeaturedMatrix - get() = lup.first - } - ) union features.orEmpty() + override val q: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) } + override val r: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) } + }, + + object : CholeskyDecompositionFeature { + override val l: FeaturedMatrix by lazy { + val cholesky = + DecompositionFactory_DDRM.chol(rowNum, true).apply { decompose(origin.ddrm.copy()) } + + EjmlMatrix(SimpleMatrix(cholesky.getT(null)), setOf(LFeature)) + } + }, + + object : LupDecompositionFeature { + private val lup by lazy { + DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()).apply { decompose(origin.ddrm.copy()) } + } + + override val l: FeaturedMatrix by lazy { + EjmlMatrix(SimpleMatrix(lup.getLower(null)), setOf(LFeature)) + } + + override val u: FeaturedMatrix by lazy { + EjmlMatrix(SimpleMatrix(lup.getUpper(null)), setOf(UFeature)) + } + + override val p: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) } + }, + ) union features public override fun suggestFeature(vararg features: MatrixFeature): EjmlMatrix = EjmlMatrix(origin, this.features + features) diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt index 31792e39c..f8791b72c 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt @@ -17,7 +17,6 @@ public fun Matrix.toEjml(): EjmlMatrix = * @author Iaroslav Postovalov */ public object EjmlMatrixContext : MatrixContext { - /** * Converts this vector to EJML one. */ @@ -33,6 +32,11 @@ public object EjmlMatrixContext : MatrixContext { } }) + override fun point(size: Int, initializer: (Int) -> Double): Point = + EjmlVector(SimpleMatrix(size, 1).also { + (0 until it.numRows()).forEach { row -> it[row, 0] = initializer(row) } + }) + public override fun Matrix.dot(other: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) @@ -73,12 +77,3 @@ public fun EjmlMatrixContext.solve(a: Matrix, b: Matrix): EjmlMa */ public fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) - -/** - * Returns the inverse of given matrix: b = a^(-1). - * - * @param a the matrix. - * @return the inverse of this matrix. - * @author Iaroslav Postovalov - */ -public fun EjmlMatrixContext.inverse(a: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.invert()) diff --git a/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt index e0f15be83..70b82a3cb 100644 --- a/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -1,7 +1,7 @@ package kscience.kmath.ejml import kscience.kmath.linear.DeterminantFeature -import kscience.kmath.linear.LUPDecompositionFeature +import kscience.kmath.linear.LupDecompositionFeature import kscience.kmath.linear.MatrixFeature import kscience.kmath.linear.getFeature import org.ejml.dense.row.factory.DecompositionFactory_DDRM @@ -44,7 +44,7 @@ internal class EjmlMatrixTest { val w = EjmlMatrix(m) val det = w.getFeature>() ?: fail() assertEquals(m.determinant(), det.determinant) - val lup = w.getFeature>() ?: fail() + val lup = w.getFeature>() ?: fail() val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows(), m.numCols()) .also { it.decompose(m.ddrm.copy()) } From 4635080317826427189bec6802e18922b60972eb Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 18 Jan 2021 21:33:53 +0300 Subject: [PATCH 191/199] Optimize RealMatrix dot operation --- examples/src/main/kotlin/kscience/kmath/structures/NDField.kt | 4 ++-- .../kotlin/kscience/kmath/linear/RealMatrixContext.kt | 2 +- .../kotlin/kscience/kmath/structures/NDStructure.kt | 4 ++++ settings.gradle.kts | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt index e53af0dee..778d811fd 100644 --- a/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt @@ -45,14 +45,14 @@ fun main() { measureAndPrint("Specialized addition") { specializedField { var res: NDBuffer = one - repeat(n) { res += 1.0 } + repeat(n) { res += one } } } measureAndPrint("Nd4j specialized addition") { nd4jField { var res = one - repeat(n) { res += 1.0 as Number } + repeat(n) { res += one } } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt index 772b20f3b..90e251c3a 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt @@ -61,7 +61,7 @@ public object RealMatrixContext : MatrixContext> { override fun multiply(a: Matrix, k: Number): BufferMatrix = - produce(a.rowNum, a.colNum) { i, j -> a.get(i, j) * k.toDouble() } + produce(a.rowNum, a.colNum) { i, j -> a[i, j] * k.toDouble() } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt index 08160adf4..5c5d28882 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt @@ -38,6 +38,7 @@ public interface NDStructure { */ public fun elements(): Sequence> + //force override equality and hash code public override fun equals(other: Any?): Boolean public override fun hashCode(): Int @@ -133,6 +134,9 @@ public interface MutableNDStructure : NDStructure { public operator fun set(index: IntArray, value: T) } +/** + * Transform a structure element-by element in place. + */ public inline fun MutableNDStructure.mapInPlace(action: (IntArray, T) -> T): Unit = elements().forEach { (index, oldValue) -> this[index] = action(index, oldValue) } diff --git a/settings.gradle.kts b/settings.gradle.kts index da33fea59..025e4a3c6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,7 +8,7 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlinx") } - val toolsVersion = "0.7.1" + val toolsVersion = "0.7.2-dev-2" val kotlinVersion = "1.4.21" plugins { From ad822271b3f552ff2e57d44031e9bb1fb4f00dc0 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 19 Jan 2021 20:25:26 +0700 Subject: [PATCH 192/199] Update changelog --- CHANGELOG.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e542d210c..0a2ae4109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,27 +4,28 @@ ### Added - `fun` annotation for SAM interfaces in library - Explicit `public` visibility for all public APIs -- Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140). +- Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140) - Automatic README generation for features (#139) - Native support for `memory`, `core` and `dimensions` -- `kmath-ejml` to supply EJML SimpleMatrix wrapper (https://github.com/mipt-npm/kmath/pull/136). +- `kmath-ejml` to supply EJML SimpleMatrix wrapper (https://github.com/mipt-npm/kmath/pull/136) - A separate `Symbol` entity, which is used for global unbound symbol. - A `Symbol` indexing scope. - Basic optimization API for Commons-math. - Chi squared optimization for array-like data in CM - `Fitting` utility object in prob/stat -- ND4J support module submitting `NDStructure` and `NDAlgebra` over `INDArray`. -- Coroutine-deterministic Monte-Carlo scope with a random number generator. -- Some minor utilities to `kmath-for-real`. +- ND4J support module submitting `NDStructure` and `NDAlgebra` over `INDArray` +- Coroutine-deterministic Monte-Carlo scope with a random number generator +- Some minor utilities to `kmath-for-real` - Generic operation result parameter to `MatrixContext` +- New `MatrixFeature` interfaces for matrix decompositions ### Changed -- Package changed from `scientifik` to `kscience.kmath`. -- Gradle version: 6.6 -> 6.7.1 +- Package changed from `scientifik` to `kscience.kmath` +- Gradle version: 6.6 -> 6.8 - Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`) -- `Polynomial` secondary constructor made function. -- Kotlin version: 1.3.72 -> 1.4.20 -- `kmath-ast` doesn't depend on heavy `kotlin-reflect` library. +- `Polynomial` secondary constructor made function +- Kotlin version: 1.3.72 -> 1.4.21 +- `kmath-ast` doesn't depend on heavy `kotlin-reflect` library - Full autodiff refactoring based on `Symbol` - `kmath-prob` renamed to `kmath-stat` - Grid generators moved to `kmath-for-real` From ab32cd95616adfb409c28cc0fb13754f69031081 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 19 Jan 2021 17:16:43 +0300 Subject: [PATCH 193/199] Numeric operations are decoupled from Ring --- CHANGELOG.md | 1 + build.gradle.kts | 2 +- .../kmath/benchmarks/LargeNDBenchmark.kt | 25 ++++ .../kmath/stat/DistributionBenchmark.kt | 3 +- .../kscience/kmath/structures/ComplexND.kt | 2 +- .../kscience/kmath/structures/NDField.kt | 8 +- .../kotlin/kscience/kmath/ast/MstAlgebra.kt | 31 +++-- .../DerivativeStructureExpression.kt | 7 +- .../FunctionalExpressionAlgebra.kt | 32 +++-- .../kmath/expressions/SimpleAutoDiff.kt | 4 +- .../kscience/kmath/linear/MatrixFeatures.kt | 4 +- .../kscience/kmath/operations/Algebra.kt | 117 +--------------- .../kscience/kmath/operations/BigInt.kt | 4 +- .../kscience/kmath/operations/Complex.kt | 4 +- .../kmath/operations/NumericAlgebra.kt | 125 ++++++++++++++++++ .../{NumberAlgebra.kt => numbers.kt} | 15 ++- .../kmath/structures/ComplexNDField.kt | 23 ++-- .../kmath/structures/RealBufferField.kt | 2 + .../kscience/kmath/structures/RealNDField.kt | 16 ++- .../kscience/kmath/structures/NDFieldTest.kt | 3 +- .../kscience/kmath/operations/BigNumbers.kt | 8 +- .../kotlin/kscience/kmath/ejml/EjmlMatrix.kt | 14 +- .../kscience/kmath/ejml/EjmlMatrixContext.kt | 6 + .../kscience.kmath.nd4j/Nd4jArrayAlgebra.kt | 46 ++++--- settings.gradle.kts | 4 +- 25 files changed, 300 insertions(+), 206 deletions(-) create mode 100644 examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LargeNDBenchmark.kt create mode 100644 kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumericAlgebra.kt rename kmath-core/src/commonMain/kotlin/kscience/kmath/operations/{NumberAlgebra.kt => numbers.kt} (97%) diff --git a/CHANGELOG.md b/CHANGELOG.md index e542d210c..840733d92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - Optimized dot product for buffer matrices moved to `kmath-for-real` - EjmlMatrix context is an object - Matrix LUP `inverse` renamed to `inverseWithLUP` +- `NumericAlgebra` moved outside of regular algebra chain (`Ring` no longer implements it). ### Deprecated diff --git a/build.gradle.kts b/build.gradle.kts index 90a39c531..d171bd608 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-4") +internal val kmathVersion: String by extra("0.2.0-dev-5") internal val bintrayRepo: String by extra("kscience") internal val githubProject: String by extra("kmath") diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LargeNDBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LargeNDBenchmark.kt new file mode 100644 index 000000000..395fde619 --- /dev/null +++ b/examples/src/benchmarks/kotlin/kscience/kmath/benchmarks/LargeNDBenchmark.kt @@ -0,0 +1,25 @@ +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/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt index ef554aeff..99d3cd504 100644 --- a/examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt @@ -3,7 +3,6 @@ package kscience.kmath.commons.prob import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking -import kscience.kmath.chains.BlockingRealChain import kscience.kmath.stat.* import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler import org.apache.commons.rng.simple.RandomSource @@ -13,7 +12,7 @@ import java.time.Instant private fun runChain(): Duration { val generator = RandomGenerator.fromSource(RandomSource.MT, 123L) val normal = Distribution.normal(NormalSamplerMethod.Ziggurat) - val chain = normal.sample(generator) as BlockingRealChain + val chain = normal.sample(generator) val startTime = Instant.now() var sum = 0.0 diff --git a/examples/src/main/kotlin/kscience/kmath/structures/ComplexND.kt b/examples/src/main/kotlin/kscience/kmath/structures/ComplexND.kt index aa4b10ef2..b69590473 100644 --- a/examples/src/main/kotlin/kscience/kmath/structures/ComplexND.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/ComplexND.kt @@ -11,7 +11,7 @@ fun main() { val n = 1000 val realField = NDField.real(dim, dim) - val complexField = NDField.complex(dim, dim) + val complexField: ComplexNDField = NDField.complex(dim, dim) val realTime = measureTimeMillis { realField { diff --git a/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt index 778d811fd..b5130c92b 100644 --- a/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/NDField.kt @@ -33,7 +33,7 @@ fun main() { measureAndPrint("Automatic field addition") { autoField { var res: NDBuffer = one - repeat(n) { res += number(1.0) } + repeat(n) { res += 1.0 } } } @@ -45,14 +45,14 @@ fun main() { measureAndPrint("Specialized addition") { specializedField { var res: NDBuffer = one - repeat(n) { res += one } + repeat(n) { res += 1.0 } } } measureAndPrint("Nd4j specialized addition") { nd4jField { var res = one - repeat(n) { res += one } + repeat(n) { res += 1.0 } } } @@ -73,7 +73,7 @@ fun main() { genericField { var res: NDBuffer = one repeat(n) { - res += one // couldn't avoid using `one` due to resolution ambiguity } + res += 1.0 // couldn't avoid using `one` due to resolution ambiguity } } } } diff --git a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt index 80b164a7c..eadbc85ee 100644 --- a/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt @@ -1,5 +1,6 @@ package kscience.kmath.ast +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.* /** @@ -25,8 +26,11 @@ public object MstSpace : Space, NumericAlgebra { public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value) public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b) - public override operator fun MST.unaryPlus(): MST.Unary = unaryOperationFunction(SpaceOperations.PLUS_OPERATION)(this) - public override operator fun MST.unaryMinus(): MST.Unary = unaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this) + public override operator fun MST.unaryPlus(): MST.Unary = + unaryOperationFunction(SpaceOperations.PLUS_OPERATION)(this) + + public override operator fun MST.unaryMinus(): MST.Unary = + unaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this) public override operator fun MST.minus(b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b) @@ -44,7 +48,8 @@ public object MstSpace : Space, NumericAlgebra { /** * [Ring] over [MST] nodes. */ -public object MstRing : Ring, NumericAlgebra { +@OptIn(UnstableKMathAPI::class) +public object MstRing : Ring, RingWithNumbers { public override val zero: MST.Numeric get() = MstSpace.zero @@ -54,7 +59,9 @@ public object MstRing : Ring, NumericAlgebra { public override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value) public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b) public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k) - public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b) + public override fun multiply(a: MST, b: MST): MST.Binary = + binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b) + public override operator fun MST.unaryPlus(): MST.Unary = MstSpace { +this@unaryPlus } public override operator fun MST.unaryMinus(): MST.Unary = MstSpace { -this@unaryMinus } public override operator fun MST.minus(b: MST): MST.Binary = MstSpace { this@minus - b } @@ -69,7 +76,8 @@ public object MstRing : Ring, NumericAlgebra { /** * [Field] over [MST] nodes. */ -public object MstField : Field { +@OptIn(UnstableKMathAPI::class) +public object MstField : Field, RingWithNumbers { public override val zero: MST.Numeric get() = MstRing.zero @@ -81,7 +89,9 @@ public object MstField : Field { public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k) public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) - public override fun divide(a: MST, b: MST): MST.Binary = binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b) + public override fun divide(a: MST, b: MST): MST.Binary = + binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b) + public override operator fun MST.unaryPlus(): MST.Unary = MstRing { +this@unaryPlus } public override operator fun MST.unaryMinus(): MST.Unary = MstRing { -this@unaryMinus } public override operator fun MST.minus(b: MST): MST.Binary = MstRing { this@minus - b } @@ -89,13 +99,14 @@ public object MstField : Field { public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = MstRing.binaryOperationFunction(operation) - public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = MstRing.unaryOperationFunction(operation) + public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = + MstRing.unaryOperationFunction(operation) } /** * [ExtendedField] over [MST] nodes. */ -public object MstExtendedField : ExtendedField { +public object MstExtendedField : ExtendedField, NumericAlgebra { public override val zero: MST.Numeric get() = MstField.zero @@ -103,6 +114,7 @@ public object MstExtendedField : ExtendedField { get() = MstField.one public override fun symbol(value: String): MST.Symbolic = MstField.symbol(value) + public override fun number(value: Number): MST.Numeric = MstRing.number(value) public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg) public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg) public override fun tan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.TAN_OPERATION)(arg) @@ -132,5 +144,6 @@ public object MstExtendedField : ExtendedField { public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = MstField.binaryOperationFunction(operation) - public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = MstField.unaryOperationFunction(operation) + public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = + MstField.unaryOperationFunction(operation) } diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 345babe8b..2912ddc4c 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -1,7 +1,9 @@ package kscience.kmath.commons.expressions import kscience.kmath.expressions.* +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.ExtendedField +import kscience.kmath.operations.RingWithNumbers import org.apache.commons.math3.analysis.differentiation.DerivativeStructure /** @@ -10,15 +12,18 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure * @property order The derivation order. * @property bindings The map of bindings values. All bindings are considered free parameters */ +@OptIn(UnstableKMathAPI::class) public class DerivativeStructureField( public val order: Int, bindings: Map, -) : ExtendedField, ExpressionAlgebra { +) : ExtendedField, ExpressionAlgebra, RingWithNumbers { public val numberOfVariables: Int = bindings.size public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) } public override val one: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order, 1.0) } + override fun number(value: Number): DerivativeStructure = const(value.toDouble()) + /** * A class that implements both [DerivativeStructure] and a [Symbol] */ 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 afbaf16e1..880a4e34c 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -7,8 +7,9 @@ import kscience.kmath.operations.* * * @param algebra The algebra to provide for Expressions built. */ -public abstract class FunctionalExpressionAlgebra>(public val algebra: A) : - ExpressionAlgebra> { +public abstract class FunctionalExpressionAlgebra>( + public val algebra: A, +) : ExpressionAlgebra> { /** * Builds an Expression of constant expression which does not depend on arguments. */ @@ -42,8 +43,9 @@ public abstract class FunctionalExpressionAlgebra>(public val /** * A context class for [Expression] construction for [Space] algebras. */ -public open class FunctionalExpressionSpace>(algebra: A) : - FunctionalExpressionAlgebra(algebra), Space> { +public open class FunctionalExpressionSpace>( + algebra: A, +) : FunctionalExpressionAlgebra(algebra), Space> { public override val zero: Expression get() = const(algebra.zero) /** @@ -71,8 +73,9 @@ public open class FunctionalExpressionSpace>(algebra: A) : super.binaryOperationFunction(operation) } -public open class FunctionalExpressionRing(algebra: A) : FunctionalExpressionSpace(algebra), - Ring> where A : Ring, A : NumericAlgebra { +public open class FunctionalExpressionRing>( + algebra: A, +) : FunctionalExpressionSpace(algebra), Ring> { public override val one: Expression get() = const(algebra.one) @@ -92,9 +95,8 @@ public open class FunctionalExpressionRing(algebra: A) : FunctionalExpress super.binaryOperationFunction(operation) } -public open class FunctionalExpressionField(algebra: A) : - FunctionalExpressionRing(algebra), Field> - where A : Field, A : NumericAlgebra { +public open class FunctionalExpressionField>(algebra: A) : + FunctionalExpressionRing(algebra), Field> { /** * Builds an Expression of division an expression by another one. */ @@ -111,9 +113,12 @@ public open class FunctionalExpressionField(algebra: A) : super.binaryOperationFunction(operation) } -public open class FunctionalExpressionExtendedField(algebra: A) : - FunctionalExpressionField(algebra), - ExtendedField> where A : ExtendedField, A : NumericAlgebra { +public open class FunctionalExpressionExtendedField>( + algebra: A, +) : FunctionalExpressionField(algebra), ExtendedField> { + + override fun number(value: Number): Expression = const(algebra.number(value)) + public override fun sin(arg: Expression): Expression = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg) @@ -135,7 +140,8 @@ public open class FunctionalExpressionExtendedField(algebra: A) : public override fun exp(arg: Expression): Expression = unaryOperationFunction(ExponentialOperations.EXP_OPERATION)(arg) - public override fun ln(arg: Expression): Expression = unaryOperationFunction(ExponentialOperations.LN_OPERATION)(arg) + public override fun ln(arg: Expression): Expression = + unaryOperationFunction(ExponentialOperations.LN_OPERATION)(arg) public override fun unaryOperationFunction(operation: String): (arg: Expression) -> Expression = super.unaryOperationFunction(operation) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt index e8a894d23..0621e82bd 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -1,6 +1,7 @@ package kscience.kmath.expressions import kscience.kmath.linear.Point +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.* import kscience.kmath.structures.asBuffer import kotlin.contracts.InvocationKind @@ -79,10 +80,11 @@ public fun > F.simpleAutoDiff( /** * Represents field in context of which functions can be derived. */ +@OptIn(UnstableKMathAPI::class) public open class SimpleAutoDiffField>( public val context: F, bindings: Map, -) : Field>, ExpressionAlgebra> { +) : Field>, ExpressionAlgebra>, RingWithNumbers> { public override val zero: AutoDiffValue get() = const(context.zero) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt index 767b58eba..1f93309a6 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt @@ -1,5 +1,7 @@ package kscience.kmath.linear +import kscience.kmath.structures.Matrix + /** * A marker interface representing some properties of matrices or additional transformations of them. Features are used * to optimize matrix operations performance in some cases or retrieve the APIs. @@ -30,7 +32,7 @@ public interface InverseMatrixFeature : MatrixFeature { /** * The inverse matrix of the matrix that owns this feature. */ - public val inverse: FeaturedMatrix + public val inverse: Matrix } /** diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index 24b417860..2bafd377e 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -88,85 +88,6 @@ public interface Algebra { public fun binaryOperation(operation: String, left: T, right: T): T = binaryOperationFunction(operation)(left, right) } -/** - * An algebraic structure where elements can have numeric representation. - * - * @param T the type of element of this structure. - */ -public interface NumericAlgebra : Algebra { - /** - * Wraps a number to [T] object. - * - * @param value the number to wrap. - * @return an object. - */ - public fun number(value: Number): T - - /** - * Dynamically dispatches a binary operation with the certain name with numeric first argument. - * - * This function must follow two properties: - * - * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. - * 2. This function is symmetric with the other [leftSideNumberOperation] overload: - * i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b)`. - * - * @param operation the name of operation. - * @return an operation. - */ - public fun leftSideNumberOperationFunction(operation: String): (left: Number, right: T) -> T = - { l, r -> binaryOperationFunction(operation)(number(l), r) } - - /** - * Dynamically invokes a binary operation with the certain name with numeric first argument. - * - * This function must follow two properties: - * - * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. - * 2. This function is symmetric with second [leftSideNumberOperation] overload: - * i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`. - * - * @param operation the name of operation. - * @param left the first argument of operation. - * @param right the second argument of operation. - * @return a result of operation. - */ - public fun leftSideNumberOperation(operation: String, left: Number, right: T): T = - leftSideNumberOperationFunction(operation)(left, right) - - /** - * Dynamically dispatches a binary operation with the certain name with numeric first argument. - * - * This function must follow two properties: - * - * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. - * 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload: - * i.e. `rightSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`. - * - * @param operation the name of operation. - * @return an operation. - */ - public fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = - { l, r -> binaryOperationFunction(operation)(l, number(r)) } - - /** - * Dynamically invokes a binary operation with the certain name with numeric second argument. - * - * This function must follow two properties: - * - * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. - * 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload: - * i.e. `rightSideNumberOperationFunction(a)(b, c) == rightSideNumberOperation(a, b, c)`. - * - * @param operation the name of operation. - * @param left the first argument of operation. - * @param right the second argument of operation. - * @return a result of operation. - */ - public fun rightSideNumberOperation(operation: String, left: T, right: Number): T = - rightSideNumberOperationFunction(operation)(left, right) -} - /** * Call a block with an [Algebra] as receiver. */ @@ -341,47 +262,11 @@ public interface RingOperations : SpaceOperations { * * @param T the type of element of this ring. */ -public interface Ring : Space, RingOperations, NumericAlgebra { +public interface Ring : Space, RingOperations { /** * neutral operation for multiplication */ public val one: T - - public override fun number(value: Number): T = one * value.toDouble() - - /** - * Addition of element and scalar. - * - * @receiver the addend. - * @param b the augend. - */ - public operator fun T.plus(b: Number): T = this + number(b) - - /** - * Addition of scalar and element. - * - * @receiver the addend. - * @param b the augend. - */ - public operator fun Number.plus(b: T): T = b + this - - /** - * Subtraction of element from number. - * - * @receiver the minuend. - * @param b the subtrahend. - * @receiver the difference. - */ - public operator fun T.minus(b: Number): T = this - number(b) - - /** - * Subtraction of number from element. - * - * @receiver the minuend. - * @param b the subtrahend. - * @receiver the difference. - */ - public operator fun Number.minus(b: T): T = -b + this } /** diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt index 20f289596..0be72e80c 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt @@ -1,5 +1,6 @@ package kscience.kmath.operations +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.BigInt.Companion.BASE import kscience.kmath.operations.BigInt.Companion.BASE_SIZE import kscience.kmath.structures.* @@ -16,7 +17,8 @@ public typealias TBase = ULong * * @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai) */ -public object BigIntField : Field { +@OptIn(UnstableKMathAPI::class) +public object BigIntField : Field, RingWithNumbers { override val zero: BigInt = BigInt.ZERO override val one: BigInt = BigInt.ONE 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 703931c7c..5695e6696 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Complex.kt @@ -41,7 +41,7 @@ private val PI_DIV_2 = Complex(PI / 2, 0) /** * A field of [Complex]. */ -public object ComplexField : ExtendedField, Norm { +public object ComplexField : ExtendedField, Norm, RingWithNumbers { override val zero: Complex = 0.0.toComplex() override val one: Complex = 1.0.toComplex() @@ -156,7 +156,7 @@ public object ComplexField : ExtendedField, Norm { override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg) - override fun symbol(value: String): Complex = if (value == "i") i else super.symbol(value) + override fun symbol(value: String): Complex = if (value == "i") i else super.symbol(value) } /** diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumericAlgebra.kt new file mode 100644 index 000000000..26f93fae8 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumericAlgebra.kt @@ -0,0 +1,125 @@ +package kscience.kmath.operations + +import kscience.kmath.misc.UnstableKMathAPI + +/** + * An algebraic structure where elements can have numeric representation. + * + * @param T the type of element of this structure. + */ +public interface NumericAlgebra : Algebra { + /** + * Wraps a number to [T] object. + * + * @param value the number to wrap. + * @return an object. + */ + public fun number(value: Number): T + + /** + * Dynamically dispatches a binary operation with the certain name with numeric first argument. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with the other [leftSideNumberOperation] overload: + * i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b)`. + * + * @param operation the name of operation. + * @return an operation. + */ + public fun leftSideNumberOperationFunction(operation: String): (left: Number, right: T) -> T = + { l, r -> binaryOperationFunction(operation)(number(l), r) } + + /** + * Dynamically invokes a binary operation with the certain name with numeric first argument. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with second [leftSideNumberOperation] overload: + * i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`. + * + * @param operation the name of operation. + * @param left the first argument of operation. + * @param right the second argument of operation. + * @return a result of operation. + */ + public fun leftSideNumberOperation(operation: String, left: Number, right: T): T = + leftSideNumberOperationFunction(operation)(left, right) + + /** + * Dynamically dispatches a binary operation with the certain name with numeric first argument. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload: + * i.e. `rightSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`. + * + * @param operation the name of operation. + * @return an operation. + */ + public fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = + { l, r -> binaryOperationFunction(operation)(l, number(r)) } + + /** + * Dynamically invokes a binary operation with the certain name with numeric second argument. + * + * This function must follow two properties: + * + * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload: + * i.e. `rightSideNumberOperationFunction(a)(b, c) == rightSideNumberOperation(a, b, c)`. + * + * @param operation the name of operation. + * @param left the first argument of operation. + * @param right the second argument of operation. + * @return a result of operation. + */ + public fun rightSideNumberOperation(operation: String, left: T, right: Number): T = + rightSideNumberOperationFunction(operation)(left, right) +} + +/** + * A combination of [NumericAlgebra] and [Ring] that adds intrinsic simple operations on numbers like `T+1` + * TODO to be removed and replaced by extensions after multiple receivers are there + */ +@UnstableKMathAPI +public interface RingWithNumbers: Ring, NumericAlgebra{ + public override fun number(value: Number): T = one * value + + /** + * Addition of element and scalar. + * + * @receiver the addend. + * @param b the augend. + */ + public operator fun T.plus(b: Number): T = this + number(b) + + /** + * Addition of scalar and element. + * + * @receiver the addend. + * @param b the augend. + */ + public operator fun Number.plus(b: T): T = b + this + + /** + * Subtraction of element from number. + * + * @receiver the minuend. + * @param b the subtrahend. + * @receiver the difference. + */ + public operator fun T.minus(b: Number): T = this - number(b) + + /** + * Subtraction of number from element. + * + * @receiver the minuend. + * @param b the subtrahend. + * @receiver the difference. + */ + public operator fun Number.minus(b: T): T = -b + this +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/numbers.kt similarity index 97% rename from kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/operations/numbers.kt index a7b73d5e0..de3818aa6 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/NumberAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/numbers.kt @@ -37,7 +37,7 @@ public interface ExtendedFieldOperations : /** * Advanced Number-like field that implements basic operations. */ -public interface ExtendedField : ExtendedFieldOperations, Field { +public interface ExtendedField : ExtendedFieldOperations, Field, NumericAlgebra { public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2 public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2 public override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg)) @@ -80,6 +80,8 @@ public object RealField : ExtendedField, Norm { public override val one: Double get() = 1.0 + override fun number(value: Number): Double = value.toDouble() + public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double = when (operation) { PowerOperations.POW_OPERATION -> ::power @@ -131,10 +133,13 @@ public object FloatField : ExtendedField, Norm { public override val one: Float get() = 1.0f - public override fun binaryOperationFunction(operation: String): (left: Float, right: Float) -> Float = when (operation) { - PowerOperations.POW_OPERATION -> ::power - else -> super.binaryOperationFunction(operation) - } + override fun number(value: Number): Float = value.toFloat() + + public override fun binaryOperationFunction(operation: String): (left: Float, right: Float) -> Float = + when (operation) { + PowerOperations.POW_OPERATION -> ::power + else -> super.binaryOperationFunction(operation) + } public override inline fun add(a: Float, b: Float): Float = a + b public override inline fun multiply(a: Float, k: Number): Float = a * k.toFloat() diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ComplexNDField.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ComplexNDField.kt index f1f1074e5..6de69cabe 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ComplexNDField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/ComplexNDField.kt @@ -1,9 +1,7 @@ package kscience.kmath.structures -import kscience.kmath.operations.Complex -import kscience.kmath.operations.ComplexField -import kscience.kmath.operations.FieldElement -import kscience.kmath.operations.complex +import kscience.kmath.misc.UnstableKMathAPI +import kscience.kmath.operations.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -12,15 +10,22 @@ public typealias ComplexNDElement = BufferedNDFieldElement, - ExtendedNDField> { + ExtendedNDField>, + RingWithNumbers>{ override val strides: Strides = DefaultStrides(shape) override val elementContext: ComplexField get() = ComplexField override val zero: ComplexNDElement by lazy { produce { zero } } override val one: ComplexNDElement by lazy { produce { one } } + override fun number(value: Number): NDBuffer { + val c = value.toComplex() + return produce { c } + } + public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Complex): Buffer = Buffer.complex(size) { initializer(it) } @@ -29,7 +34,7 @@ public class ComplexNDField(override val shape: IntArray) : */ override fun map( arg: NDBuffer, - transform: ComplexField.(Complex) -> Complex + transform: ComplexField.(Complex) -> Complex, ): ComplexNDElement { check(arg) val array = buildBuffer(arg.strides.linearSize) { offset -> ComplexField.transform(arg.buffer[offset]) } @@ -43,7 +48,7 @@ public class ComplexNDField(override val shape: IntArray) : override fun mapIndexed( arg: NDBuffer, - transform: ComplexField.(index: IntArray, Complex) -> Complex + transform: ComplexField.(index: IntArray, Complex) -> Complex, ): ComplexNDElement { check(arg) @@ -60,7 +65,7 @@ public class ComplexNDField(override val shape: IntArray) : override fun combine( a: NDBuffer, b: NDBuffer, - transform: ComplexField.(Complex, Complex) -> Complex + transform: ComplexField.(Complex, Complex) -> Complex, ): ComplexNDElement { check(a, b) @@ -141,7 +146,7 @@ public fun NDField.Companion.complex(vararg shape: Int): ComplexNDField = Comple public fun NDElement.Companion.complex( vararg shape: Int, - initializer: ComplexField.(IntArray) -> Complex + initializer: ComplexField.(IntArray) -> Complex, ): ComplexNDElement = NDField.complex(*shape).produce(initializer) /** diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBufferField.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBufferField.kt index f7b2ee31e..3f4d15c4d 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBufferField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealBufferField.kt @@ -150,6 +150,8 @@ public class RealBufferField(public val size: Int) : ExtendedField by lazy { RealBuffer(size) { 0.0 } } public override val one: Buffer by lazy { RealBuffer(size) { 1.0 } } + override fun number(value: Number): Buffer = RealBuffer(size) { value.toDouble() } + public override fun add(a: Buffer, b: Buffer): RealBuffer { require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } return RealBufferFieldOperations.add(a, b) 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 ed28fb9f2..3eb1dc4ca 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealNDField.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/RealNDField.kt @@ -1,13 +1,17 @@ package kscience.kmath.structures +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.FieldElement import kscience.kmath.operations.RealField +import kscience.kmath.operations.RingWithNumbers public typealias RealNDElement = BufferedNDFieldElement +@OptIn(UnstableKMathAPI::class) public class RealNDField(override val shape: IntArray) : BufferedNDField, - ExtendedNDField> { + ExtendedNDField>, + RingWithNumbers>{ override val strides: Strides = DefaultStrides(shape) @@ -15,7 +19,12 @@ public class RealNDField(override val shape: IntArray) : override val zero: RealNDElement by lazy { produce { zero } } override val one: RealNDElement by lazy { produce { one } } - public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer = + override fun number(value: Number): NDBuffer { + val d = value.toDouble() + return produce { d } + } + + private inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer = RealBuffer(DoubleArray(size) { initializer(it) }) /** @@ -59,7 +68,8 @@ public class RealNDField(override val shape: IntArray) : check(a, b) return BufferedNDFieldElement( this, - buildBuffer(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) }) + buildBuffer(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) } + ) } override fun NDBuffer.toElement(): FieldElement, *, out BufferedNDField> = diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt index b763ec7de..1129a8a36 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NDFieldTest.kt @@ -1,14 +1,13 @@ package kscience.kmath.structures import kscience.kmath.operations.internal.FieldVerifier -import kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class NDFieldTest { @Test fun verify() { - (NDField.real(12, 32)) { FieldVerifier(this, one + 3, one - 23, one * 12, 6.66) } + NDField.real(12, 32).run { FieldVerifier(this, one + 3, one - 23, one * 12, 6.66) } } @Test diff --git a/kmath-core/src/jvmMain/kotlin/kscience/kmath/operations/BigNumbers.kt b/kmath-core/src/jvmMain/kotlin/kscience/kmath/operations/BigNumbers.kt index 2f0978237..9bd6a9fc4 100644 --- a/kmath-core/src/jvmMain/kotlin/kscience/kmath/operations/BigNumbers.kt +++ b/kmath-core/src/jvmMain/kotlin/kscience/kmath/operations/BigNumbers.kt @@ -7,7 +7,7 @@ import java.math.MathContext /** * A field over [BigInteger]. */ -public object JBigIntegerField : Field { +public object JBigIntegerField : Field, NumericAlgebra { public override val zero: BigInteger get() = BigInteger.ZERO @@ -28,9 +28,9 @@ public object JBigIntegerField : Field { * * @property mathContext the [MathContext] to use. */ -public abstract class JBigDecimalFieldBase internal constructor(public val mathContext: MathContext = MathContext.DECIMAL64) : - Field, - PowerOperations { +public abstract class JBigDecimalFieldBase internal constructor( + private val mathContext: MathContext = MathContext.DECIMAL64, +) : Field, PowerOperations, NumericAlgebra { public override val zero: BigDecimal get() = BigDecimal.ZERO diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt index 5b7d0a01b..a7d571b58 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt @@ -12,8 +12,10 @@ import org.ejml.simple.SimpleMatrix * @property origin the underlying [SimpleMatrix]. * @author Iaroslav Postovalov */ -public class EjmlMatrix(public val origin: SimpleMatrix, features: Set = emptySet()) : - FeaturedMatrix { +public class EjmlMatrix( + public val origin: SimpleMatrix, + features: Set = emptySet() +) : FeaturedMatrix { public override val rowNum: Int get() = origin.numRows() @@ -88,11 +90,7 @@ public class EjmlMatrix(public val origin: SimpleMatrix, features: Set ?: return false) } - public override fun hashCode(): Int { - var result = origin.hashCode() - result = 31 * result + features.hashCode() - return result - } + public override fun hashCode(): Int = origin.hashCode() - public override fun toString(): String = "EjmlMatrix(origin=$origin, features=$features)" + public override fun toString(): String = "EjmlMatrix($origin)" } diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt index f8791b72c..c8789a4a7 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt @@ -1,7 +1,9 @@ package kscience.kmath.ejml +import kscience.kmath.linear.InverseMatrixFeature import kscience.kmath.linear.MatrixContext import kscience.kmath.linear.Point +import kscience.kmath.linear.getFeature import kscience.kmath.structures.Matrix import org.ejml.simple.SimpleMatrix @@ -77,3 +79,7 @@ public fun EjmlMatrixContext.solve(a: Matrix, b: Matrix): EjmlMa */ public fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) + +public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature>()!!.inverse as EjmlMatrix + +public fun EjmlMatrixContext.inverse(matrix: Matrix): Matrix = matrix.toEjml().inverted() \ No newline at end of file diff --git a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt index a8c874fc3..db2a44861 100644 --- a/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/kscience.kmath.nd4j/Nd4jArrayAlgebra.kt @@ -1,5 +1,6 @@ package kscience.kmath.nd4j +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.* import kscience.kmath.structures.NDAlgebra import kscience.kmath.structures.NDField @@ -35,7 +36,7 @@ public interface Nd4jArrayAlgebra : NDAlgebra> public override fun mapIndexed( arg: Nd4jArrayStructure, - transform: C.(index: IntArray, T) -> T + transform: C.(index: IntArray, T) -> T, ): Nd4jArrayStructure { check(arg) val new = Nd4j.create(*shape).wrap() @@ -46,7 +47,7 @@ public interface Nd4jArrayAlgebra : NDAlgebra> public override fun combine( a: Nd4jArrayStructure, b: Nd4jArrayStructure, - transform: C.(T, T) -> T + transform: C.(T, T) -> T, ): Nd4jArrayStructure { check(a, b) val new = Nd4j.create(*shape).wrap() @@ -61,8 +62,8 @@ public interface Nd4jArrayAlgebra : NDAlgebra> * @param T the type of the element contained in ND structure. * @param S the type of space of structure elements. */ -public interface Nd4jArraySpace : NDSpace>, - Nd4jArrayAlgebra where S : Space { +public interface Nd4jArraySpace> : NDSpace>, Nd4jArrayAlgebra { + public override val zero: Nd4jArrayStructure get() = Nd4j.zeros(*shape).wrap() @@ -103,7 +104,9 @@ public interface Nd4jArraySpace : NDSpace>, * @param T the type of the element contained in ND structure. * @param R the type of ring of structure elements. */ -public interface Nd4jArrayRing : NDRing>, Nd4jArraySpace where R : Ring { +@OptIn(UnstableKMathAPI::class) +public interface Nd4jArrayRing> : NDRing>, Nd4jArraySpace { + public override val one: Nd4jArrayStructure get() = Nd4j.ones(*shape).wrap() @@ -111,21 +114,21 @@ public interface Nd4jArrayRing : NDRing>, Nd4j check(a, b) return a.ndArray.mul(b.ndArray).wrap() } - - public override operator fun Nd4jArrayStructure.minus(b: Number): Nd4jArrayStructure { - check(this) - return ndArray.sub(b).wrap() - } - - public override operator fun Nd4jArrayStructure.plus(b: Number): Nd4jArrayStructure { - check(this) - return ndArray.add(b).wrap() - } - - public override operator fun Number.minus(b: Nd4jArrayStructure): Nd4jArrayStructure { - check(b) - return b.ndArray.rsub(this).wrap() - } +// +// public override operator fun Nd4jArrayStructure.minus(b: Number): Nd4jArrayStructure { +// check(this) +// return ndArray.sub(b).wrap() +// } +// +// public override operator fun Nd4jArrayStructure.plus(b: Number): Nd4jArrayStructure { +// check(this) +// return ndArray.add(b).wrap() +// } +// +// public override operator fun Number.minus(b: Nd4jArrayStructure): Nd4jArrayStructure { +// check(b) +// return b.ndArray.rsub(this).wrap() +// } public companion object { private val intNd4jArrayRingCache: ThreadLocal> = @@ -165,7 +168,8 @@ public interface Nd4jArrayRing : NDRing>, Nd4j * @param N the type of ND structure. * @param F the type field of structure elements. */ -public interface Nd4jArrayField : NDField>, Nd4jArrayRing where F : Field { +public interface Nd4jArrayField> : NDField>, Nd4jArrayRing { + public override fun divide(a: Nd4jArrayStructure, b: Nd4jArrayStructure): Nd4jArrayStructure { check(a, b) return a.ndArray.div(b.ndArray).wrap() diff --git a/settings.gradle.kts b/settings.gradle.kts index 025e4a3c6..a1ea40148 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,8 +8,8 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlinx") } - val toolsVersion = "0.7.2-dev-2" - val kotlinVersion = "1.4.21" + val toolsVersion = "0.7.3-1.4.30-RC" + val kotlinVersion = "1.4.30-RC" plugins { id("kotlinx.benchmark") version "0.2.0-dev-20" From 4c256a9f14f4db251cb2797f8ddcfb1b88ab8dac Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 19 Jan 2021 19:32:13 +0300 Subject: [PATCH 194/199] Features refactoring. --- CHANGELOG.md | 1 + .../kscience/kmath/commons/linear/CMMatrix.kt | 50 +++++----- .../kscience/kmath/linear/BufferMatrix.kt | 26 +++--- ...UPDecomposition.kt => LupDecomposition.kt} | 58 +++++++----- .../kscience/kmath/linear/MatrixBuilder.kt | 15 ++- .../kscience/kmath/linear/MatrixContext.kt | 2 - .../kscience/kmath/linear/MatrixFeatures.kt | 26 +++--- .../{FeaturedMatrix.kt => MatrixWrapper.kt} | 78 +++++++++------- .../kmath/linear/RealMatrixContext.kt | 20 +--- .../kscience/kmath/linear/VirtualMatrix.kt | 31 +------ .../kscience/kmath/operations/numbers.kt | 16 +++- .../kscience/kmath/structures/NDStructure.kt | 11 +++ .../kscience/kmath/structures/Structure2D.kt | 9 +- .../kscience/kmath/dimensions/Wrappers.kt | 9 +- .../kotlin/kscience/kmath/ejml/EjmlMatrix.kt | 91 ++++++++----------- .../kscience/kmath/ejml/EjmlMatrixContext.kt | 21 +++-- .../kscience/kmath/ejml/EjmlMatrixTest.kt | 5 +- .../kotlin/kscience/kmath/real/RealMatrix.kt | 8 +- .../kaceince/kmath/real/RealMatrixTest.kt | 3 +- 19 files changed, 236 insertions(+), 244 deletions(-) rename kmath-core/src/commonMain/kotlin/kscience/kmath/linear/{LUPDecomposition.kt => LupDecomposition.kt} (78%) rename kmath-core/src/commonMain/kotlin/kscience/kmath/linear/{FeaturedMatrix.kt => MatrixWrapper.kt} (50%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 840733d92..27d4dd1aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ - EjmlMatrix context is an object - Matrix LUP `inverse` renamed to `inverseWithLUP` - `NumericAlgebra` moved outside of regular algebra chain (`Ring` no longer implements it). +- Features moved to NDStructure and became transparent. ### Deprecated diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt index 49888f8d6..48b6e0ef1 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt @@ -1,42 +1,28 @@ package kscience.kmath.commons.linear -import kscience.kmath.linear.* +import kscience.kmath.linear.DiagonalFeature +import kscience.kmath.linear.MatrixContext +import kscience.kmath.linear.MatrixWrapper +import kscience.kmath.linear.Point +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.structures.Matrix -import kscience.kmath.structures.NDStructure import org.apache.commons.math3.linear.* +import kotlin.reflect.KClass +import kotlin.reflect.cast -public class CMMatrix(public val origin: RealMatrix, features: Set? = null) : FeaturedMatrix { +public inline class CMMatrix(public val origin: RealMatrix) : Matrix { public override val rowNum: Int get() = origin.rowDimension public override val colNum: Int get() = origin.columnDimension - public override val features: Set = features ?: sequence { - if (origin is DiagonalMatrix) yield(DiagonalFeature) - }.toHashSet() - - public override fun suggestFeature(vararg features: MatrixFeature): CMMatrix = - CMMatrix(origin, this.features + features) + @UnstableKMathAPI + override fun getFeature(type: KClass): T? = when (type) { + DiagonalFeature::class -> if (origin is DiagonalMatrix) DiagonalFeature else null + else -> null + }?.let { type.cast(it) } public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j) - - public override fun equals(other: Any?): Boolean { - return NDStructure.equals(this, other as? NDStructure<*> ?: return false) - } - - public override fun hashCode(): Int { - var result = origin.hashCode() - result = 31 * result + features.hashCode() - return result - } } -//TODO move inside context -public fun Matrix.toCM(): CMMatrix = if (this is CMMatrix) { - this -} else { - //TODO add feature analysis - val array = Array(rowNum) { i -> DoubleArray(colNum) { j -> get(i, j) } } - CMMatrix(Array2DRowRealMatrix(array)) -} public fun RealMatrix.asMatrix(): CMMatrix = CMMatrix(this) @@ -61,6 +47,16 @@ public object CMMatrixContext : MatrixContext { return CMMatrix(Array2DRowRealMatrix(array)) } + public fun Matrix.toCM(): CMMatrix = when { + this is CMMatrix -> this + this is MatrixWrapper && matrix is CMMatrix -> matrix as CMMatrix + else -> { + //TODO add feature analysis + val array = Array(rowNum) { i -> DoubleArray(colNum) { j -> get(i, j) } } + CMMatrix(Array2DRowRealMatrix(array)) + } + } + public override fun Matrix.dot(other: Matrix): CMMatrix = CMMatrix(toCM().origin.multiply(other.toCM().origin)) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt index 402161207..80460baca 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt @@ -1,10 +1,7 @@ package kscience.kmath.linear import kscience.kmath.operations.Ring -import kscience.kmath.structures.Buffer -import kscience.kmath.structures.BufferFactory -import kscience.kmath.structures.NDStructure -import kscience.kmath.structures.asSequence +import kscience.kmath.structures.* /** * Basic implementation of Matrix space based on [NDStructure] @@ -27,8 +24,7 @@ public class BufferMatrix( public override val rowNum: Int, public override val colNum: Int, public val buffer: Buffer, - public override val features: Set = emptySet(), -) : FeaturedMatrix { +) : Matrix { init { require(buffer.size == rowNum * colNum) { "Dimension mismatch for matrix structure" } @@ -36,9 +32,6 @@ public class BufferMatrix( override val shape: IntArray get() = intArrayOf(rowNum, colNum) - public override fun suggestFeature(vararg features: MatrixFeature): BufferMatrix = - BufferMatrix(rowNum, colNum, buffer, this.features + features) - public override operator fun get(index: IntArray): T = get(index[0], index[1]) public override operator fun get(i: Int, j: Int): T = buffer[i * colNum + j] @@ -50,23 +43,26 @@ public class BufferMatrix( if (this === other) return true return when (other) { - is NDStructure<*> -> return NDStructure.equals(this, other) + is NDStructure<*> -> NDStructure.equals(this, other) else -> false } } - public override fun hashCode(): Int { - var result = buffer.hashCode() - result = 31 * result + features.hashCode() + override fun hashCode(): Int { + var result = rowNum + result = 31 * result + colNum + result = 31 * result + buffer.hashCode() return result } public override fun toString(): String { return if (rowNum <= 5 && colNum <= 5) - "Matrix(rowsNum = $rowNum, colNum = $colNum, features=$features)\n" + + "Matrix(rowsNum = $rowNum, colNum = $colNum)\n" + rows.asSequence().joinToString(prefix = "(", postfix = ")", separator = "\n ") { buffer -> buffer.asSequence().joinToString(separator = "\t") { it.toString() } } - else "Matrix(rowsNum = $rowNum, colNum = $colNum, features=$features)" + else "Matrix(rowsNum = $rowNum, colNum = $colNum)" } + + } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LupDecomposition.kt similarity index 78% rename from kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LupDecomposition.kt index 75acaf8a1..f4f998da2 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LUPDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/LupDecomposition.kt @@ -1,13 +1,14 @@ package kscience.kmath.linear +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.* import kscience.kmath.structures.* /** * Common implementation of [LupDecompositionFeature]. */ -public class LUPDecomposition( - public val context: MatrixContext>, +public class LupDecomposition( + public val context: MatrixContext>, public val elementContext: Field, public val lu: Matrix, public val pivot: IntArray, @@ -18,13 +19,13 @@ public class LUPDecomposition( * * L is a lower-triangular matrix with [Ring.one] in diagonal */ - override val l: FeaturedMatrix = VirtualMatrix(lu.shape[0], lu.shape[1], setOf(LFeature)) { i, j -> + override val l: Matrix = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j -> when { j < i -> lu[i, j] j == i -> elementContext.one else -> elementContext.zero } - } + } + LFeature /** @@ -32,9 +33,9 @@ public class LUPDecomposition( * * U is an upper-triangular matrix including the diagonal */ - override val u: FeaturedMatrix = VirtualMatrix(lu.shape[0], lu.shape[1], setOf(UFeature)) { i, j -> + override val u: Matrix = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j -> if (j >= i) lu[i, j] else elementContext.zero - } + } + UFeature /** * Returns the P rows permutation matrix. @@ -42,7 +43,7 @@ public class LUPDecomposition( * P is a sparse matrix with exactly one element set to [Ring.one] in * each row and each column, all other elements being set to [Ring.zero]. */ - override val p: FeaturedMatrix = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j -> + override val p: Matrix = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j -> if (j == pivot[i]) elementContext.one else elementContext.zero } @@ -63,12 +64,12 @@ internal fun , F : Field> GenericMatrixContext.abs /** * Create a lup decomposition of generic matrix. */ -public fun > MatrixContext>.lup( +public fun > MatrixContext>.lup( factory: MutableBufferFactory, elementContext: Field, matrix: Matrix, checkSingular: (T) -> Boolean, -): LUPDecomposition { +): LupDecomposition { require(matrix.rowNum == matrix.colNum) { "LU decomposition supports only square matrices" } val m = matrix.colNum val pivot = IntArray(matrix.rowNum) @@ -137,23 +138,23 @@ public fun > MatrixContext>.lup( for (row in col + 1 until m) lu[row, col] /= luDiag } - return LUPDecomposition(this@lup, elementContext, lu.collect(), pivot, even) + return LupDecomposition(this@lup, elementContext, lu.collect(), pivot, even) } } } -public inline fun , F : Field> GenericMatrixContext>.lup( +public inline fun , F : Field> GenericMatrixContext>.lup( matrix: Matrix, noinline checkSingular: (T) -> Boolean, -): LUPDecomposition = lup(MutableBuffer.Companion::auto, elementContext, matrix, checkSingular) +): LupDecomposition = lup(MutableBuffer.Companion::auto, elementContext, matrix, checkSingular) -public fun MatrixContext>.lup(matrix: Matrix): LUPDecomposition = +public fun MatrixContext>.lup(matrix: Matrix): LupDecomposition = lup(Buffer.Companion::real, RealField, matrix) { it < 1e-11 } -public fun LUPDecomposition.solveWithLUP( +public fun LupDecomposition.solveWithLUP( factory: MutableBufferFactory, - matrix: Matrix -): FeaturedMatrix { + matrix: Matrix, +): Matrix { require(matrix.rowNum == pivot.size) { "Matrix dimension mismatch. Expected ${pivot.size}, but got ${matrix.colNum}" } BufferAccessor2D(matrix.rowNum, matrix.colNum, factory).run { @@ -198,25 +199,40 @@ public fun LUPDecomposition.solveWithLUP( } } -public inline fun LUPDecomposition.solveWithLUP(matrix: Matrix): Matrix = +public inline fun LupDecomposition.solveWithLUP(matrix: Matrix): Matrix = solveWithLUP(MutableBuffer.Companion::auto, matrix) /** * Solve a linear equation **a*x = b** using LUP decomposition */ -public inline fun , F : Field> GenericMatrixContext>.solveWithLUP( +@OptIn(UnstableKMathAPI::class) +public inline fun , F : Field> GenericMatrixContext>.solveWithLUP( a: Matrix, b: Matrix, noinline bufferFactory: MutableBufferFactory = MutableBuffer.Companion::auto, noinline checkSingular: (T) -> Boolean, -): FeaturedMatrix { +): Matrix { // Use existing decomposition if it is provided by matrix val decomposition = a.getFeature() ?: lup(bufferFactory, elementContext, a, checkSingular) return decomposition.solveWithLUP(bufferFactory, b) } -public inline fun , F : Field> GenericMatrixContext>.inverseWithLUP( +public inline fun , F : Field> GenericMatrixContext>.inverseWithLUP( matrix: Matrix, noinline bufferFactory: MutableBufferFactory = MutableBuffer.Companion::auto, noinline checkSingular: (T) -> Boolean, -): FeaturedMatrix = solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum), bufferFactory, checkSingular) +): Matrix = solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum), bufferFactory, checkSingular) + + +public fun RealMatrixContext.solveWithLUP(a: Matrix, b: Matrix): Matrix { + // Use existing decomposition if it is provided by matrix + val bufferFactory: MutableBufferFactory = MutableBuffer.Companion::real + val decomposition: LupDecomposition = a.getFeature() ?: lup(bufferFactory, RealField, a) { it < 1e-11 } + return decomposition.solveWithLUP(bufferFactory, b) +} + +/** + * Inverses a square matrix using LUP decomposition. Non square matrix will throw a error. + */ +public fun RealMatrixContext.inverseWithLUP(matrix: Matrix): Matrix = + solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum)) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixBuilder.kt index 91c1ec824..c0c209248 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixBuilder.kt @@ -1,12 +1,9 @@ package kscience.kmath.linear -import kscience.kmath.structures.Buffer -import kscience.kmath.structures.BufferFactory -import kscience.kmath.structures.Structure2D -import kscience.kmath.structures.asBuffer +import kscience.kmath.structures.* public class MatrixBuilder(public val rows: Int, public val columns: Int) { - public operator fun invoke(vararg elements: T): FeaturedMatrix { + public operator fun invoke(vararg elements: T): Matrix { require(rows * columns == elements.size) { "The number of elements ${elements.size} is not equal $rows * $columns" } val buffer = elements.asBuffer() return BufferMatrix(rows, columns, buffer) @@ -17,7 +14,7 @@ public class MatrixBuilder(public val rows: Int, public val columns: Int) { public fun Structure2D.Companion.build(rows: Int, columns: Int): MatrixBuilder = MatrixBuilder(rows, columns) -public fun Structure2D.Companion.row(vararg values: T): FeaturedMatrix { +public fun Structure2D.Companion.row(vararg values: T): Matrix { val buffer = values.asBuffer() return BufferMatrix(1, values.size, buffer) } @@ -26,12 +23,12 @@ public inline fun Structure2D.Companion.row( size: Int, factory: BufferFactory = Buffer.Companion::auto, noinline builder: (Int) -> T -): FeaturedMatrix { +): Matrix { val buffer = factory(size, builder) return BufferMatrix(1, size, buffer) } -public fun Structure2D.Companion.column(vararg values: T): FeaturedMatrix { +public fun Structure2D.Companion.column(vararg values: T): Matrix { val buffer = values.asBuffer() return BufferMatrix(values.size, 1, buffer) } @@ -40,7 +37,7 @@ public inline fun Structure2D.Companion.column( size: Int, factory: BufferFactory = Buffer.Companion::auto, noinline builder: (Int) -> T -): FeaturedMatrix { +): Matrix { val buffer = factory(size, builder) return BufferMatrix(size, 1, buffer) } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt index 8c28a240f..59a41f840 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixContext.kt @@ -133,8 +133,6 @@ public interface GenericMatrixContext, out M : Matrix> : public override fun multiply(a: Matrix, k: Number): M = produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } } - public operator fun Number.times(matrix: FeaturedMatrix): M = multiply(matrix, this) - public override operator fun Matrix.times(value: T): M = produce(rowNum, colNum) { i, j -> elementContext { get(i, j) * value } } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt index 1f93309a6..e61feec6c 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixFeatures.kt @@ -11,17 +11,19 @@ public interface MatrixFeature /** * Matrices with this feature are considered to have only diagonal non-null elements. */ -public object DiagonalFeature : MatrixFeature +public interface DiagonalFeature : MatrixFeature{ + public companion object: DiagonalFeature +} /** * Matrices with this feature have all zero elements. */ -public object ZeroFeature : MatrixFeature +public object ZeroFeature : DiagonalFeature /** * Matrices with this feature have unit elements on diagonal and zero elements in all other places. */ -public object UnitFeature : MatrixFeature +public object UnitFeature : DiagonalFeature /** * Matrices with this feature can be inverted: [inverse] = `a`-1 where `a` is the owning matrix. @@ -76,17 +78,17 @@ public interface LupDecompositionFeature : MatrixFeature { /** * The lower triangular matrix in this decomposition. It may have [LFeature]. */ - public val l: FeaturedMatrix + public val l: Matrix /** * The upper triangular matrix in this decomposition. It may have [UFeature]. */ - public val u: FeaturedMatrix + public val u: Matrix /** * The permutation matrix in this decomposition. */ - public val p: FeaturedMatrix + public val p: Matrix } /** @@ -104,12 +106,12 @@ public interface QRDecompositionFeature : MatrixFeature { /** * The orthogonal matrix in this decomposition. It may have [OrthogonalFeature]. */ - public val q: FeaturedMatrix + public val q: Matrix /** * The upper triangular matrix in this decomposition. It may have [UFeature]. */ - public val r: FeaturedMatrix + public val r: Matrix } /** @@ -122,7 +124,7 @@ public interface CholeskyDecompositionFeature : MatrixFeature { /** * The triangular matrix in this decomposition. It may have either [UFeature] or [LFeature]. */ - public val l: FeaturedMatrix + public val l: Matrix } /** @@ -135,17 +137,17 @@ public interface SingularValueDecompositionFeature : MatrixFeature { /** * The matrix in this decomposition. It is unitary, and it consists from left singular vectors. */ - public val u: FeaturedMatrix + public val u: Matrix /** * The matrix in this decomposition. Its main diagonal elements are singular values. */ - public val s: FeaturedMatrix + public val s: Matrix /** * The matrix in this decomposition. It is unitary, and it consists from right singular vectors. */ - public val v: FeaturedMatrix + public val v: Matrix /** * The buffer of singular values of this SVD. diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt similarity index 50% rename from kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt rename to kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt index 119f5d844..bbe9c1195 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt @@ -1,35 +1,57 @@ package kscience.kmath.linear +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.operations.Ring import kscience.kmath.structures.Matrix import kscience.kmath.structures.Structure2D import kscience.kmath.structures.asBuffer +import kscience.kmath.structures.getFeature import kotlin.math.sqrt +import kotlin.reflect.KClass +import kotlin.reflect.safeCast /** * A [Matrix] that holds [MatrixFeature] objects. * * @param T the type of items. */ -public interface FeaturedMatrix : Matrix { - public override val shape: IntArray get() = intArrayOf(rowNum, colNum) +public class MatrixWrapper( + public val matrix: Matrix, + public val features: Set, +) : Matrix by matrix { /** - * The set of features this matrix possesses. + * Get the first feature matching given class. Does not guarantee that matrix has only one feature matching the criteria */ - public val features: Set + @UnstableKMathAPI + override fun getFeature(type: KClass): T? = type.safeCast(features.find { type.isInstance(it) }) - /** - * Suggest new feature for this matrix. The result is the new matrix that may or may not reuse existing data structure. - * - * The implementation does not guarantee to check that matrix actually have the feature, so one should be careful to - * add only those features that are valid. - */ - public fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix - - public companion object + override fun equals(other: Any?): Boolean = matrix == other + override fun hashCode(): Int = matrix.hashCode() + override fun toString(): String { + return "MatrixWrapper(matrix=$matrix, features=$features)" + } } +/** + * Add a single feature to a [Matrix] + */ +public operator fun Matrix.plus(newFeature: MatrixFeature): MatrixWrapper = if (this is MatrixWrapper) { + MatrixWrapper(matrix, features + newFeature) +} else { + MatrixWrapper(this, setOf(newFeature)) +} + +/** + * Add a collection of features to a [Matrix] + */ +public operator fun Matrix.plus(newFeatures: Collection): MatrixWrapper = + if (this is MatrixWrapper) { + MatrixWrapper(matrix, features + newFeatures) + } else { + MatrixWrapper(this, newFeatures.toSet()) + } + public inline fun Structure2D.Companion.real( rows: Int, columns: Int, @@ -39,51 +61,37 @@ public inline fun Structure2D.Companion.real( /** * Build a square matrix from given elements. */ -public fun Structure2D.Companion.square(vararg elements: T): FeaturedMatrix { +public fun Structure2D.Companion.square(vararg elements: T): Matrix { val size: Int = sqrt(elements.size.toDouble()).toInt() require(size * size == elements.size) { "The number of elements ${elements.size} is not a full square" } val buffer = elements.asBuffer() return BufferMatrix(size, size, buffer) } -public val Matrix<*>.features: Set get() = (this as? FeaturedMatrix)?.features ?: emptySet() - -/** - * Check if matrix has the given feature class - */ -public inline fun Matrix<*>.hasFeature(): Boolean = - features.find { it is T } != null - -/** - * Get the first feature matching given class. Does not guarantee that matrix has only one feature matching the criteria - */ -public inline fun Matrix<*>.getFeature(): T? = - features.filterIsInstance().firstOrNull() - /** * Diagonal matrix of ones. The matrix is virtual no actual matrix is created */ -public fun > GenericMatrixContext.one(rows: Int, columns: Int): FeaturedMatrix = - VirtualMatrix(rows, columns, DiagonalFeature) { i, j -> +public fun > GenericMatrixContext.one(rows: Int, columns: Int): Matrix = + VirtualMatrix(rows, columns) { i, j -> if (i == j) elementContext.one else elementContext.zero - } + } + UnitFeature /** * A virtual matrix of zeroes */ -public fun > GenericMatrixContext.zero(rows: Int, columns: Int): FeaturedMatrix = - VirtualMatrix(rows, columns) { _, _ -> elementContext.zero } +public fun > GenericMatrixContext.zero(rows: Int, columns: Int): Matrix = + VirtualMatrix(rows, columns) { _, _ -> elementContext.zero } + ZeroFeature public class TransposedFeature(public val original: Matrix) : MatrixFeature /** * Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A` */ +@OptIn(UnstableKMathAPI::class) public fun Matrix.transpose(): Matrix { return getFeature>()?.original ?: VirtualMatrix( colNum, rowNum, - setOf(TransposedFeature(this)) - ) { i, j -> get(j, i) } + ) { i, j -> get(j, i) } + TransposedFeature(this) } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt index 90e251c3a..8e197672f 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/RealMatrixContext.kt @@ -1,9 +1,6 @@ package kscience.kmath.linear -import kscience.kmath.operations.RealField import kscience.kmath.structures.Matrix -import kscience.kmath.structures.MutableBuffer -import kscience.kmath.structures.MutableBufferFactory import kscience.kmath.structures.RealBuffer @Suppress("OVERRIDE_BY_INLINE") @@ -22,9 +19,9 @@ public object RealMatrixContext : MatrixContext> { produce(rowNum, colNum) { i, j -> get(i, j) } } - public fun one(rows: Int, columns: Int): FeaturedMatrix = VirtualMatrix(rows, columns, DiagonalFeature) { i, j -> + public fun one(rows: Int, columns: Int): Matrix = VirtualMatrix(rows, columns) { i, j -> if (i == j) 1.0 else 0.0 - } + } + DiagonalFeature public override infix fun Matrix.dot(other: Matrix): BufferMatrix { require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } @@ -69,16 +66,3 @@ public object RealMatrixContext : MatrixContext> { * Partially optimized real-valued matrix */ public val MatrixContext.Companion.real: RealMatrixContext get() = RealMatrixContext - -public fun RealMatrixContext.solveWithLUP(a: Matrix, b: Matrix): FeaturedMatrix { - // Use existing decomposition if it is provided by matrix - val bufferFactory: MutableBufferFactory = MutableBuffer.Companion::real - val decomposition = a.getFeature() ?: lup(bufferFactory, RealField, a) { it < 1e-11 } - return decomposition.solveWithLUP(bufferFactory, b) -} - -/** - * Inverses a square matrix using LUP decomposition. Non square matrix will throw a error. - */ -public fun RealMatrixContext.inverseWithLUP(matrix: Matrix): FeaturedMatrix = - solveWithLUP(matrix, one(matrix.rowNum, matrix.colNum)) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VirtualMatrix.kt index e0a1d0026..0269a64d1 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/VirtualMatrix.kt @@ -5,31 +5,16 @@ import kscience.kmath.structures.Matrix public class VirtualMatrix( override val rowNum: Int, override val colNum: Int, - override val features: Set = emptySet(), public val generator: (i: Int, j: Int) -> T -) : FeaturedMatrix { - public constructor( - rowNum: Int, - colNum: Int, - vararg features: MatrixFeature, - generator: (i: Int, j: Int) -> T - ) : this( - rowNum, - colNum, - setOf(*features), - generator - ) +) : Matrix { override val shape: IntArray get() = intArrayOf(rowNum, colNum) override operator fun get(i: Int, j: Int): T = generator(i, j) - override fun suggestFeature(vararg features: MatrixFeature): VirtualMatrix = - VirtualMatrix(rowNum, colNum, this.features + features, generator) - override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is FeaturedMatrix<*>) return false + if (other !is Matrix<*>) return false if (rowNum != other.rowNum) return false if (colNum != other.colNum) return false @@ -40,21 +25,9 @@ public class VirtualMatrix( override fun hashCode(): Int { var result = rowNum result = 31 * result + colNum - result = 31 * result + features.hashCode() result = 31 * result + generator.hashCode() return result } - public companion object { - /** - * Wrap a matrix adding additional features to it - */ - public fun wrap(matrix: Matrix, vararg features: MatrixFeature): FeaturedMatrix { - return if (matrix is VirtualMatrix) - VirtualMatrix(matrix.rowNum, matrix.colNum, matrix.features + features, matrix.generator) - else - VirtualMatrix(matrix.rowNum, matrix.colNum, matrix.features + features) { i, j -> matrix[i, j] } - } - } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/numbers.kt index de3818aa6..0440d74e8 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/numbers.kt @@ -179,13 +179,15 @@ public object FloatField : ExtendedField, Norm { * A field for [Int] without boxing. Does not produce corresponding ring element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public object IntRing : Ring, Norm { +public object IntRing : Ring, Norm, NumericAlgebra { public override val zero: Int get() = 0 public override val one: Int get() = 1 + override fun number(value: Number): Int = value.toInt() + public override inline fun add(a: Int, b: Int): Int = a + b public override inline fun multiply(a: Int, k: Number): Int = k.toInt() * a @@ -203,13 +205,15 @@ public object IntRing : Ring, Norm { * A field for [Short] without boxing. Does not produce appropriate ring element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public object ShortRing : Ring, Norm { +public object ShortRing : Ring, Norm, NumericAlgebra { public override val zero: Short get() = 0 public override val one: Short get() = 1 + override fun number(value: Number): Short = value.toShort() + public override inline fun add(a: Short, b: Short): Short = (a + b).toShort() public override inline fun multiply(a: Short, k: Number): Short = (a * k.toShort()).toShort() @@ -227,13 +231,15 @@ public object ShortRing : Ring, Norm { * A field for [Byte] without boxing. Does not produce appropriate ring element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public object ByteRing : Ring, Norm { +public object ByteRing : Ring, Norm, NumericAlgebra { public override val zero: Byte get() = 0 public override val one: Byte get() = 1 + override fun number(value: Number): Byte = value.toByte() + public override inline fun add(a: Byte, b: Byte): Byte = (a + b).toByte() public override inline fun multiply(a: Byte, k: Number): Byte = (a * k.toByte()).toByte() @@ -251,13 +257,15 @@ public object ByteRing : Ring, Norm { * A field for [Double] without boxing. Does not produce appropriate ring element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public object LongRing : Ring, Norm { +public object LongRing : Ring, Norm, NumericAlgebra { public override val zero: Long get() = 0L public override val one: Long get() = 1L + override fun number(value: Number): Long = value.toLong() + public override inline fun add(a: Long, b: Long): Long = a + b public override inline fun multiply(a: Long, k: Number): Long = a * k.toLong() diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt index 5c5d28882..64e723581 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt @@ -1,5 +1,6 @@ package kscience.kmath.structures +import kscience.kmath.misc.UnstableKMathAPI import kotlin.jvm.JvmName import kotlin.native.concurrent.ThreadLocal import kotlin.reflect.KClass @@ -42,6 +43,13 @@ public interface NDStructure { public override fun equals(other: Any?): Boolean public override fun hashCode(): Int + /** + * Feature is additional property or hint that does not directly affect the structure, but could in some cases help + * optimize operations and performance. If the feature is not present, null is defined. + */ + @UnstableKMathAPI + public fun getFeature(type: KClass): T? = null + public companion object { /** * Indicates whether some [NDStructure] is equal to another one. @@ -121,6 +129,9 @@ public interface NDStructure { */ public operator fun NDStructure.get(vararg index: Int): T = get(index) +@UnstableKMathAPI +public inline fun NDStructure<*>.getFeature(): T? = getFeature(T::class) + /** * Represents mutable [NDStructure]. */ diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt index bac7d3389..d20e9e53b 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt @@ -9,12 +9,14 @@ public interface Structure2D : NDStructure { /** * The number of rows in this structure. */ - public val rowNum: Int get() = shape[0] + public val rowNum: Int /** * The number of columns in this structure. */ - public val colNum: Int get() = shape[1] + public val colNum: Int + + public override val shape: IntArray get() = intArrayOf(rowNum, colNum) /** * The buffer of rows of this structure. It gets elements from the structure dynamically. @@ -56,6 +58,9 @@ public interface Structure2D : NDStructure { private inline class Structure2DWrapper(val structure: NDStructure) : Structure2D { 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 elements(): Sequence> = structure.elements() diff --git a/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt index 0422d11b2..0244eae7f 100644 --- a/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/kscience/kmath/dimensions/Wrappers.kt @@ -40,6 +40,8 @@ public inline class DMatrixWrapper( private val structure: Structure2D, ) : DMatrix { 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] } @@ -147,6 +149,7 @@ public inline fun DMatrixContext.one(): DMatrix< if (i == j) 1.0 else 0.0 } -public inline fun DMatrixContext.zero(): DMatrix = produce { _, _ -> - 0.0 -} \ No newline at end of file +public inline fun DMatrixContext.zero(): DMatrix = + produce { _, _ -> + 0.0 + } \ No newline at end of file diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt index a7d571b58..1c2ded447 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt @@ -1,10 +1,13 @@ package kscience.kmath.ejml import kscience.kmath.linear.* -import kscience.kmath.structures.NDStructure +import kscience.kmath.misc.UnstableKMathAPI +import kscience.kmath.structures.Matrix import kscience.kmath.structures.RealBuffer import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix +import kotlin.reflect.KClass +import kotlin.reflect.cast /** * Represents featured matrix over EJML [SimpleMatrix]. @@ -12,85 +15,65 @@ import org.ejml.simple.SimpleMatrix * @property origin the underlying [SimpleMatrix]. * @author Iaroslav Postovalov */ -public class EjmlMatrix( +public inline class EjmlMatrix( public val origin: SimpleMatrix, - features: Set = emptySet() -) : FeaturedMatrix { - public override val rowNum: Int - get() = origin.numRows() +) : Matrix { + public override val rowNum: Int get() = origin.numRows() - public override val colNum: Int - get() = origin.numCols() + public override val colNum: Int get() = origin.numCols() - public override val shape: IntArray by lazy { intArrayOf(rowNum, colNum) } - - public override val features: Set = hashSetOf( - object : InverseMatrixFeature { - override val inverse: FeaturedMatrix by lazy { EjmlMatrix(origin.invert()) } - }, - - object : DeterminantFeature { + @UnstableKMathAPI + override fun getFeature(type: KClass): T? = when (type) { + InverseMatrixFeature::class -> object : InverseMatrixFeature { + override val inverse: Matrix by lazy { EjmlMatrix(origin.invert()) } + } + DeterminantFeature::class -> object : DeterminantFeature { override val determinant: Double by lazy(origin::determinant) - }, - - object : SingularValueDecompositionFeature { + } + SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { private val svd by lazy { DecompositionFactory_DDRM.svd(origin.numRows(), origin.numCols(), true, true, false) .apply { decompose(origin.ddrm.copy()) } } - override val u: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(svd.getU(null, false))) } - override val s: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(svd.getW(null))) } - override val v: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(svd.getV(null, false))) } + 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 singularValues: Point by lazy { RealBuffer(svd.singularValues) } - }, - - object : QRDecompositionFeature { + } + QRDecompositionFeature::class -> object : QRDecompositionFeature { private val qr by lazy { DecompositionFactory_DDRM.qr().apply { decompose(origin.ddrm.copy()) } } - override val q: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) } - override val r: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) } - }, - - object : CholeskyDecompositionFeature { - override val l: FeaturedMatrix by lazy { + override val q: Matrix by lazy { EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) } + override val r: Matrix by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) } + } + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { val cholesky = DecompositionFactory_DDRM.chol(rowNum, true).apply { decompose(origin.ddrm.copy()) } - EjmlMatrix(SimpleMatrix(cholesky.getT(null)), setOf(LFeature)) + EjmlMatrix(SimpleMatrix(cholesky.getT(null))) + LFeature } - }, - - object : LupDecompositionFeature { + } + LupDecompositionFeature::class -> object : LupDecompositionFeature { private val lup by lazy { DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()).apply { decompose(origin.ddrm.copy()) } } - override val l: FeaturedMatrix by lazy { - EjmlMatrix(SimpleMatrix(lup.getLower(null)), setOf(LFeature)) + override val l: Matrix by lazy { + EjmlMatrix(SimpleMatrix(lup.getLower(null))) + LFeature } - override val u: FeaturedMatrix by lazy { - EjmlMatrix(SimpleMatrix(lup.getUpper(null)), setOf(UFeature)) + override val u: Matrix by lazy { + EjmlMatrix(SimpleMatrix(lup.getUpper(null))) + UFeature } - override val p: FeaturedMatrix by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) } - }, - ) union features - - public override fun suggestFeature(vararg features: MatrixFeature): EjmlMatrix = - EjmlMatrix(origin, this.features + features) + override val p: Matrix by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) } + } + else -> null + }?.let{type.cast(it)} public override operator fun get(i: Int, j: Int): Double = origin[i, j] - - public override fun equals(other: Any?): Boolean { - if (other is EjmlMatrix) return origin.isIdentical(other.origin, 0.0) - return NDStructure.equals(this, other as? NDStructure<*> ?: return false) - } - - public override fun hashCode(): Int = origin.hashCode() - - public override fun toString(): String = "EjmlMatrix($origin)" } diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt index c8789a4a7..7198bbd0d 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt @@ -2,23 +2,29 @@ package kscience.kmath.ejml import kscience.kmath.linear.InverseMatrixFeature import kscience.kmath.linear.MatrixContext +import kscience.kmath.linear.MatrixWrapper import kscience.kmath.linear.Point -import kscience.kmath.linear.getFeature +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.structures.Matrix +import kscience.kmath.structures.getFeature import org.ejml.simple.SimpleMatrix -/** - * Converts this matrix to EJML one. - */ -public fun Matrix.toEjml(): EjmlMatrix = - if (this is EjmlMatrix) this else EjmlMatrixContext.produce(rowNum, colNum) { i, j -> get(i, j) } - /** * Represents context of basic operations operating with [EjmlMatrix]. * * @author Iaroslav Postovalov */ public object EjmlMatrixContext : MatrixContext { + + /** + * Converts this matrix to EJML one. + */ + public fun Matrix.toEjml(): EjmlMatrix = when { + this is EjmlMatrix -> this + this is MatrixWrapper && matrix is EjmlMatrix -> matrix as EjmlMatrix + else -> produce(rowNum, colNum) { i, j -> get(i, j) } + } + /** * Converts this vector to EJML one. */ @@ -80,6 +86,7 @@ public fun EjmlMatrixContext.solve(a: Matrix, b: Matrix): EjmlMa public fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) +@OptIn(UnstableKMathAPI::class) public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature>()!!.inverse as EjmlMatrix public fun EjmlMatrixContext.inverse(matrix: Matrix): Matrix = matrix.toEjml().inverted() \ No newline at end of file diff --git a/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt index 70b82a3cb..30d146779 100644 --- a/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -3,7 +3,8 @@ package kscience.kmath.ejml import kscience.kmath.linear.DeterminantFeature import kscience.kmath.linear.LupDecompositionFeature import kscience.kmath.linear.MatrixFeature -import kscience.kmath.linear.getFeature +import kscience.kmath.linear.plus +import kscience.kmath.structures.getFeature import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix import kotlin.random.Random @@ -58,7 +59,7 @@ internal class EjmlMatrixTest { @Test fun suggestFeature() { - assertNotNull(EjmlMatrix(randomMatrix).suggestFeature(SomeFeature).getFeature()) + assertNotNull((EjmlMatrix(randomMatrix) + SomeFeature).getFeature()) } @Test diff --git a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt index 772abfbed..274030aff 100644 --- a/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt @@ -1,8 +1,12 @@ package kscience.kmath.real -import kscience.kmath.linear.* +import kscience.kmath.linear.MatrixContext +import kscience.kmath.linear.VirtualMatrix +import kscience.kmath.linear.inverseWithLUP +import kscience.kmath.linear.real import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.structures.Buffer +import kscience.kmath.structures.Matrix import kscience.kmath.structures.RealBuffer import kscience.kmath.structures.asIterable import kotlin.math.pow @@ -19,7 +23,7 @@ import kotlin.math.pow * Functions that help create a real (Double) matrix */ -public typealias RealMatrix = FeaturedMatrix +public typealias RealMatrix = Matrix public fun realMatrix(rowNum: Int, colNum: Int, initializer: (i: Int, j: Int) -> Double): RealMatrix = MatrixContext.real.produce(rowNum, colNum, initializer) diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt index 5c33b76a9..a89f99b3c 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt @@ -1,6 +1,5 @@ package kaceince.kmath.real -import kscience.kmath.linear.VirtualMatrix import kscience.kmath.linear.build import kscience.kmath.real.* import kscience.kmath.structures.Matrix @@ -42,7 +41,7 @@ internal class RealMatrixTest { 1.0, 0.0, 0.0, 0.0, 1.0, 2.0 ) - assertEquals(VirtualMatrix.wrap(matrix2), matrix1.repeatStackVertical(3)) + assertEquals(matrix2, matrix1.repeatStackVertical(3)) } @Test From d0c9d97706fa21584af1e99984a2763810bcd4f9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 19 Jan 2021 22:24:42 +0300 Subject: [PATCH 195/199] 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 1c7bd05c584528cf569aa5f7f537c056e89e4a6e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 19 Jan 2021 22:48:43 +0300 Subject: [PATCH 196/199] Add proper equality check for EJML matrices --- .../kscience/kmath/linear/BufferMatrix.kt | 2 +- .../kscience/kmath/structures/NDStructure.kt | 4 ++-- .../kmath/structures/LazyNDStructure.kt | 2 +- .../kotlin/kscience/kmath/ejml/EjmlMatrix.kt | 19 +++++++++++++++---- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt index 80460baca..a74d948fc 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/BufferMatrix.kt @@ -43,7 +43,7 @@ public class BufferMatrix( if (this === other) return true return when (other) { - is NDStructure<*> -> NDStructure.equals(this, other) + is NDStructure<*> -> NDStructure.contentEquals(this, other) else -> false } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt index 64e723581..e7d89ca7e 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt @@ -54,7 +54,7 @@ public interface NDStructure { /** * Indicates whether some [NDStructure] is equal to another one. */ - public fun equals(st1: NDStructure<*>, st2: NDStructure<*>): Boolean { + public fun contentEquals(st1: NDStructure<*>, st2: NDStructure<*>): Boolean { if (st1 === st2) return true // fast comparison of buffers if possible @@ -275,7 +275,7 @@ public abstract class NDBuffer : NDStructure { override fun elements(): Sequence> = strides.indices().map { it to this[it] } override fun equals(other: Any?): Boolean { - return NDStructure.equals(this, other as? NDStructure<*> ?: return false) + return NDStructure.contentEquals(this, other as? NDStructure<*> ?: return false) } override fun hashCode(): Int { diff --git a/kmath-coroutines/src/jvmMain/kotlin/kscience/kmath/structures/LazyNDStructure.kt b/kmath-coroutines/src/jvmMain/kotlin/kscience/kmath/structures/LazyNDStructure.kt index bb0d19c23..7aa746797 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/kscience/kmath/structures/LazyNDStructure.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/kscience/kmath/structures/LazyNDStructure.kt @@ -24,7 +24,7 @@ public class LazyNDStructure( } public override fun equals(other: Any?): Boolean { - return NDStructure.equals(this, other as? NDStructure<*> ?: return false) + return NDStructure.contentEquals(this, other as? NDStructure<*> ?: return false) } public override fun hashCode(): Int { diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt index 1c2ded447..82a5399fd 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrix.kt @@ -3,6 +3,7 @@ package kscience.kmath.ejml import kscience.kmath.linear.* import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.structures.Matrix +import kscience.kmath.structures.NDStructure import kscience.kmath.structures.RealBuffer import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix @@ -15,7 +16,7 @@ import kotlin.reflect.cast * @property origin the underlying [SimpleMatrix]. * @author Iaroslav Postovalov */ -public inline class EjmlMatrix( +public class EjmlMatrix( public val origin: SimpleMatrix, ) : Matrix { public override val rowNum: Int get() = origin.numRows() @@ -49,7 +50,7 @@ public inline class EjmlMatrix( override val q: Matrix by lazy { EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) } override val r: Matrix by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) } } - CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { override val l: Matrix by lazy { val cholesky = DecompositionFactory_DDRM.chol(rowNum, true).apply { decompose(origin.ddrm.copy()) } @@ -57,7 +58,7 @@ public inline class EjmlMatrix( EjmlMatrix(SimpleMatrix(cholesky.getT(null))) + LFeature } } - LupDecompositionFeature::class -> object : LupDecompositionFeature { + LupDecompositionFeature::class -> object : LupDecompositionFeature { private val lup by lazy { DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()).apply { decompose(origin.ddrm.copy()) } } @@ -73,7 +74,17 @@ public inline class EjmlMatrix( override val p: Matrix by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) } } else -> null - }?.let{type.cast(it)} + }?.let { type.cast(it) } public override operator fun get(i: Int, j: Int): Double = origin[i, j] + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Matrix<*>) return false + return NDStructure.contentEquals(this, other) + } + + override fun hashCode(): Int = origin.hashCode() + + } From d00e7434a4e14a5fbc6039f823b02fffd7b86d47 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 20 Jan 2021 15:07:39 +0300 Subject: [PATCH 197/199] Fix for #193 --- .../src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt index bbe9c1195..1db905bf2 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt @@ -25,6 +25,7 @@ public class MatrixWrapper( */ @UnstableKMathAPI override fun getFeature(type: KClass): T? = type.safeCast(features.find { type.isInstance(it) }) + ?: matrix.getFeature(type) override fun equals(other: Any?): Boolean = matrix == other override fun hashCode(): Int = matrix.hashCode() From 881b85a1d9dabc30c5d5baa8821d170800e64700 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 20 Jan 2021 15:32:55 +0300 Subject: [PATCH 198/199] Add `origin` (optin) extension property to expose MatrixWrapper content --- .../kscience/kmath/commons/linear/CMMatrix.kt | 8 +++--- .../kscience/kmath/linear/MatrixWrapper.kt | 25 ++++++++++++------- .../kscience/kmath/ejml/EjmlMatrixContext.kt | 8 +++--- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt index 48b6e0ef1..850446afa 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/linear/CMMatrix.kt @@ -2,8 +2,8 @@ package kscience.kmath.commons.linear import kscience.kmath.linear.DiagonalFeature import kscience.kmath.linear.MatrixContext -import kscience.kmath.linear.MatrixWrapper import kscience.kmath.linear.Point +import kscience.kmath.linear.origin import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.structures.Matrix import org.apache.commons.math3.linear.* @@ -47,9 +47,9 @@ public object CMMatrixContext : MatrixContext { return CMMatrix(Array2DRowRealMatrix(array)) } - public fun Matrix.toCM(): CMMatrix = when { - this is CMMatrix -> this - this is MatrixWrapper && matrix is CMMatrix -> matrix as CMMatrix + @OptIn(UnstableKMathAPI::class) + public fun Matrix.toCM(): CMMatrix = when (val matrix = origin) { + is CMMatrix -> matrix else -> { //TODO add feature analysis val array = Array(rowNum) { i -> DoubleArray(colNum) { j -> get(i, j) } } diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt index 1db905bf2..362db1fe7 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/linear/MatrixWrapper.kt @@ -15,30 +15,37 @@ import kotlin.reflect.safeCast * * @param T the type of items. */ -public class MatrixWrapper( - public val matrix: Matrix, +public class MatrixWrapper internal constructor( + public val origin: Matrix, public val features: Set, -) : Matrix by matrix { +) : Matrix by origin { /** * Get the first feature matching given class. Does not guarantee that matrix has only one feature matching the criteria */ @UnstableKMathAPI override fun getFeature(type: KClass): T? = type.safeCast(features.find { type.isInstance(it) }) - ?: matrix.getFeature(type) + ?: origin.getFeature(type) - override fun equals(other: Any?): Boolean = matrix == other - override fun hashCode(): Int = matrix.hashCode() + override fun equals(other: Any?): Boolean = origin == other + override fun hashCode(): Int = origin.hashCode() override fun toString(): String { - return "MatrixWrapper(matrix=$matrix, features=$features)" + return "MatrixWrapper(matrix=$origin, features=$features)" } } +/** + * Return the original matrix. If this is a wrapper, return its origin. If not, this matrix. + * Origin does not necessary store all features. + */ +@UnstableKMathAPI +public val Matrix.origin: Matrix get() = (this as? MatrixWrapper)?.origin ?: this + /** * Add a single feature to a [Matrix] */ public operator fun Matrix.plus(newFeature: MatrixFeature): MatrixWrapper = if (this is MatrixWrapper) { - MatrixWrapper(matrix, features + newFeature) + MatrixWrapper(origin, features + newFeature) } else { MatrixWrapper(this, setOf(newFeature)) } @@ -48,7 +55,7 @@ public operator fun Matrix.plus(newFeature: MatrixFeature): MatrixW */ public operator fun Matrix.plus(newFeatures: Collection): MatrixWrapper = if (this is MatrixWrapper) { - MatrixWrapper(matrix, features + newFeatures) + MatrixWrapper(origin, features + newFeatures) } else { MatrixWrapper(this, newFeatures.toSet()) } diff --git a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt index 7198bbd0d..8184d0110 100644 --- a/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/kscience/kmath/ejml/EjmlMatrixContext.kt @@ -2,8 +2,8 @@ package kscience.kmath.ejml import kscience.kmath.linear.InverseMatrixFeature import kscience.kmath.linear.MatrixContext -import kscience.kmath.linear.MatrixWrapper import kscience.kmath.linear.Point +import kscience.kmath.linear.origin import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.structures.Matrix import kscience.kmath.structures.getFeature @@ -19,9 +19,9 @@ public object EjmlMatrixContext : MatrixContext { /** * Converts this matrix to EJML one. */ - public fun Matrix.toEjml(): EjmlMatrix = when { - this is EjmlMatrix -> this - this is MatrixWrapper && matrix is EjmlMatrix -> matrix as EjmlMatrix + @OptIn(UnstableKMathAPI::class) + public fun Matrix.toEjml(): EjmlMatrix = when (val matrix = origin) { + is EjmlMatrix -> matrix else -> produce(rowNum, colNum) { i, j -> get(i, j) } } From d10ae66e580f7d87410d44cc082b5adb79554769 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 20 Jan 2021 17:08:29 +0300 Subject: [PATCH 199/199] Deploy fixes for 0.2.0-dev-5 --- .../src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt | 2 +- .../src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt | 3 +++ .../src/jvmTest/kotlin/kscience/kmath/stat/MCScopeTest.kt | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt index 2bafd377e..e7eb2770d 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt @@ -92,7 +92,7 @@ public interface Algebra { * Call a block with an [Algebra] as receiver. */ // TODO add contract when KT-32313 is fixed -public inline operator fun
, R> A.invoke(block: A.() -> R): R = block() +public inline operator fun , R> A.invoke(block: A.() -> R): R = run(block) /** * Represents "semispace", i.e. algebraic structure with associative binary operation called "addition" as well as diff --git a/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt index 30d146779..455b52d9d 100644 --- a/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -4,6 +4,7 @@ import kscience.kmath.linear.DeterminantFeature import kscience.kmath.linear.LupDecompositionFeature import kscience.kmath.linear.MatrixFeature import kscience.kmath.linear.plus +import kscience.kmath.misc.UnstableKMathAPI import kscience.kmath.structures.getFeature import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix @@ -39,6 +40,7 @@ internal class EjmlMatrixTest { assertEquals(listOf(m.numRows(), m.numCols()), w.shape.toList()) } + @OptIn(UnstableKMathAPI::class) @Test fun features() { val m = randomMatrix @@ -57,6 +59,7 @@ internal class EjmlMatrixTest { private object SomeFeature : MatrixFeature {} + @OptIn(UnstableKMathAPI::class) @Test fun suggestFeature() { assertNotNull((EjmlMatrix(randomMatrix) + SomeFeature).getFeature()) diff --git a/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/MCScopeTest.kt b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/MCScopeTest.kt index c2304070f..4e29e6105 100644 --- a/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/MCScopeTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/MCScopeTest.kt @@ -62,6 +62,7 @@ class MCScopeTest { } + @OptIn(ObsoleteCoroutinesApi::class) fun compareResult(test: ATest) { val res1 = runBlocking(Dispatchers.Default) { test() } val res2 = runBlocking(newSingleThreadContext("test")) { test() }