diff --git a/.gitignore b/.gitignore
index d6c4af4e3..79f3238e1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,8 +4,6 @@ out/
.idea/
-!.idea/copyright/
-!.idea/scopes/
.vscode/
@@ -18,3 +16,6 @@ out/
# Generated by javac -h and runtime
*.class
*.log
+
+!/.idea/copyright/
+!/.idea/scopes/
diff --git a/.idea/copyright/kmath.xml b/.idea/copyright/kmath.xml
new file mode 100644
index 000000000..17e44e4d0
--- /dev/null
+++ b/.idea/copyright/kmath.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 000000000..b538bdf41
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/scopes/Apply_copyright.xml b/.idea/scopes/Apply_copyright.xml
new file mode 100644
index 000000000..a2575f774
--- /dev/null
+++ b/.idea/scopes/Apply_copyright.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bb267744e..a19b1f467 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,8 @@
- `BigInt` operation performance improvement and fixes by @zhelenskiy (#328)
- Integration between `MST` and Symja `IExpr`
- Complex power
+- Separate methods for UInt, Int and Number powers. NaN safety.
+- Tensorflow prototype
### Changed
- Exponential operations merged with hyperbolic functions
@@ -45,6 +47,7 @@
- Buffer algebra does not require size anymore
- Operations -> Ops
- Default Buffer and ND algebras are now Ops and lack neutral elements (0, 1) as well as algebra-level shapes.
+- Tensor algebra takes read-only structures as input and inherits AlgebraND
### Deprecated
- Specialized `DoubleBufferAlgebra`
diff --git a/README.md b/README.md
index db069d4e0..99dd6d00f 100644
--- a/README.md
+++ b/README.md
@@ -50,35 +50,6 @@ module definitions below. The module stability could have the following levels:
with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
## Modules
@@ -240,6 +211,12 @@ One can still use generic algebras though.
> **Maturity**: DEVELOPMENT
+* ### [kmath-multik](kmath-multik)
+>
+>
+> **Maturity**: PROTOTYPE
+
+
* ### [kmath-nd4j](kmath-nd4j)
>
>
@@ -252,6 +229,12 @@ One can still use generic algebras though.
+* ### [kmath-optimization](kmath-optimization)
+>
+>
+> **Maturity**: EXPERIMENTAL
+
+
* ### [kmath-stat](kmath-stat)
>
>
@@ -264,6 +247,12 @@ One can still use generic algebras though.
> **Maturity**: PROTOTYPE
+* ### [kmath-tensorflow](kmath-tensorflow)
+>
+>
+> **Maturity**: PROTOTYPE
+
+
* ### [kmath-tensors](kmath-tensors)
>
>
@@ -319,8 +308,8 @@ repositories {
}
dependencies {
- api("space.kscience:kmath-core:0.3.0-dev-14")
- // api("space.kscience:kmath-core-jvm:0.3.0-dev-14") for jvm-specific version
+ api("space.kscience:kmath-core:0.3.0-dev-17")
+ // api("space.kscience:kmath-core-jvm:0.3.0-dev-17") for jvm-specific version
}
```
diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts
index cca3d312d..90ec5dfbe 100644
--- a/benchmarks/build.gradle.kts
+++ b/benchmarks/build.gradle.kts
@@ -13,19 +13,22 @@ sourceSets.register("benchmarks")
repositories {
mavenCentral()
- maven("https://repo.kotlin.link")
- maven("https://clojars.org/repo")
- maven("https://jitpack.io")
-
- maven("http://logicrunch.research.it.uu.se/maven") {
- isAllowInsecureProtocol = true
- }
}
kotlin {
jvm()
+ js(IR) {
+ nodejs()
+ }
+
sourceSets {
+ all {
+ languageSettings {
+ progressiveMode = true
+ }
+ }
+
val commonMain by getting {
dependencies {
implementation(project(":kmath-ast"))
@@ -35,9 +38,8 @@ kotlin {
implementation(project(":kmath-stat"))
implementation(project(":kmath-dimensions"))
implementation(project(":kmath-for-real"))
- implementation(project(":kmath-jafama"))
implementation(project(":kmath-tensors"))
- implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.1")
+ implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.2")
}
}
@@ -48,7 +50,8 @@ kotlin {
implementation(project(":kmath-nd4j"))
implementation(project(":kmath-kotlingrad"))
implementation(project(":kmath-viktor"))
- implementation(projects.kmathMultik)
+ implementation(project(":kmath-jafama"))
+ implementation(project(":kmath-multik"))
implementation("org.nd4j:nd4j-native:1.0.0-M1")
// uncomment if your system supports AVX2
// val os = System.getProperty("os.name")
@@ -69,12 +72,13 @@ benchmark {
// Setup configurations
targets {
register("jvm")
+ register("js")
}
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
- warmups = 1
+ warmups = 2
iterations = 5
- iterationTime = 1000
+ iterationTime = 2000
iterationTimeUnit = "ms"
}
@@ -94,7 +98,12 @@ benchmark {
}
configurations.register("expressions") {
- commonConfiguration()
+ // Some extra precision
+ warmups = 2
+ iterations = 10
+ iterationTime = 10
+ iterationTimeUnit = "s"
+ outputTimeUnit = "s"
include("ExpressionsInterpretersBenchmark")
}
@@ -131,23 +140,21 @@ afterEvaluate {
}
}
-
kotlin.sourceSets.all {
with(languageSettings) {
- useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
- useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
- useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI")
+ optIn("kotlin.contracts.ExperimentalContracts")
+ optIn("kotlin.ExperimentalUnsignedTypes")
+ optIn("space.kscience.kmath.misc.UnstableKMathAPI")
}
}
tasks.withType {
kotlinOptions {
jvmTarget = "11"
- freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
+ freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xlambdas=indy"
}
}
-
readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
}
diff --git a/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
new file mode 100644
index 000000000..126a2e648
--- /dev/null
+++ b/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.benchmarks
+
+import kotlinx.benchmark.Benchmark
+import kotlinx.benchmark.Blackhole
+import kotlinx.benchmark.Scope
+import kotlinx.benchmark.State
+import space.kscience.kmath.expressions.*
+import space.kscience.kmath.operations.Algebra
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.operations.bindSymbol
+import space.kscience.kmath.operations.invoke
+import kotlin.math.sin
+import kotlin.random.Random
+import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
+import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
+
+@State(Scope.Benchmark)
+class ExpressionsInterpretersBenchmark {
+ /**
+ * Benchmark case for [Expression] created with [expressionInExtendedField].
+ */
+ @Benchmark
+ fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
+
+ /**
+ * Benchmark case for [Expression] created with [toExpression].
+ */
+ @Benchmark
+ fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
+
+ /**
+ * Benchmark case for [Expression] created with [compileToExpression].
+ */
+ @Benchmark
+ fun wasmExpression(blackhole: Blackhole) = invokeAndSum(wasm, blackhole)
+
+ /**
+ * Benchmark case for [Expression] created with [compileToExpression].
+ */
+ @Benchmark
+ fun estreeExpression(blackhole: Blackhole) = invokeAndSum(estree, blackhole)
+
+ /**
+ * Benchmark case for [Expression] implemented manually with `kotlin.math` functions.
+ */
+ @Benchmark
+ fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole)
+
+ /**
+ * Benchmark case for direct computation w/o [Expression].
+ */
+ @Benchmark
+ fun justCalculate(blackhole: Blackhole) {
+ val random = Random(0)
+ var sum = 0.0
+
+ repeat(times) {
+ val x = random.nextDouble()
+ sum += x * 2.0 + 2.0 / x - 16.0 / sin(x)
+ }
+
+ blackhole.consume(sum)
+ }
+
+ private fun invokeAndSum(expr: Expression, blackhole: Blackhole) {
+ val random = Random(0)
+ var sum = 0.0
+ val m = HashMap()
+
+ repeat(times) {
+ m[x] = random.nextDouble()
+ sum += expr(m)
+ }
+
+ blackhole.consume(sum)
+ }
+
+ private companion object {
+ private val x by symbol
+ private const val times = 1_000_000
+
+ private val functional = DoubleField.expression {
+ val x = bindSymbol(Symbol.x)
+ x * number(2.0) + 2.0 / x - 16.0 / sin(x)
+ }
+
+ private val node = MstExtendedField {
+ x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
+ }
+
+ private val mst = node.toExpression(DoubleField)
+ private val wasm = node.wasmCompileToExpression(DoubleField)
+ private val estree = node.estreeCompileToExpression(DoubleField)
+
+ private val raw = Expression { args ->
+ val x = args[x]!!
+ x * 2.0 + 2.0 / x - 16.0 / sin(x)
+ }
+ }
+}
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt
index 17983e88c..ff933997f 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt
index f2b2d4d7a..188a48ca7 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt
index 5cf194b67..39819d407 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt
index 64f9b5dff..63165baaa 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
@@ -13,6 +13,7 @@ import space.kscience.kmath.commons.linear.CMLinearSpace
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
import space.kscience.kmath.linear.invoke
import space.kscience.kmath.linear.linearSpace
+import space.kscience.kmath.multik.multikAlgebra
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.structures.Buffer
import kotlin.random.Random
@@ -58,6 +59,16 @@ internal class DotBenchmark {
blackhole.consume(matrix1 dot matrix2)
}
+// @Benchmark
+// fun tensorDot(blackhole: Blackhole) = with(Double.tensorAlgebra) {
+// blackhole.consume(matrix1 dot matrix2)
+// }
+
+ @Benchmark
+ fun multikDot(blackhole: Blackhole) = with(Double.multikAlgebra) {
+ blackhole.consume(matrix1 dot matrix2)
+ }
+
@Benchmark
fun bufferedDot(blackhole: Blackhole) = with(DoubleField.linearSpace(Buffer.Companion::auto)) {
blackhole.consume(matrix1 dot matrix2)
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
index 63e1511bd..db3524e67 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
@@ -11,6 +11,7 @@ import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.asm.compileToExpression
import space.kscience.kmath.expressions.*
+import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
@@ -35,7 +36,30 @@ internal class ExpressionsInterpretersBenchmark {
* Benchmark case for [Expression] created with [compileToExpression].
*/
@Benchmark
- fun asmExpression(blackhole: Blackhole) = invokeAndSum(asm, blackhole)
+ fun asmGenericExpression(blackhole: Blackhole) = invokeAndSum(asmGeneric, blackhole)
+
+ /**
+ * Benchmark case for [Expression] created with [compileToExpression].
+ */
+ @Benchmark
+ fun asmPrimitiveExpressionArray(blackhole: Blackhole) {
+ val random = Random(0)
+ var sum = 0.0
+ val m = DoubleArray(1)
+
+ repeat(times) {
+ m[xIdx] = random.nextDouble()
+ sum += asmPrimitive(m)
+ }
+
+ blackhole.consume(sum)
+ }
+
+ /**
+ * Benchmark case for [Expression] created with [compileToExpression].
+ */
+ @Benchmark
+ fun asmPrimitiveExpression(blackhole: Blackhole) = invokeAndSum(asmPrimitive, blackhole)
/**
* Benchmark case for [Expression] implemented manually with `kotlin.math` functions.
@@ -62,9 +86,11 @@ internal class ExpressionsInterpretersBenchmark {
private fun invokeAndSum(expr: Expression, blackhole: Blackhole) {
val random = Random(0)
var sum = 0.0
+ val m = HashMap()
repeat(times) {
- sum += expr(x to random.nextDouble())
+ m[x] = random.nextDouble()
+ sum += expr(m)
}
blackhole.consume(sum)
@@ -72,7 +98,6 @@ internal class ExpressionsInterpretersBenchmark {
private companion object {
private val x by symbol
- private val algebra = DoubleField
private const val times = 1_000_000
private val functional = DoubleField.expression {
@@ -85,7 +110,11 @@ internal class ExpressionsInterpretersBenchmark {
}
private val mst = node.toExpression(DoubleField)
- private val asm = node.compileToExpression(DoubleField)
+
+ private val asmPrimitive = node.compileToExpression(DoubleField)
+ private val xIdx = asmPrimitive.indexer.indexOf(x)
+
+ private val asmGeneric = node.compileToExpression(DoubleField as Algebra)
private val raw = Expression { args ->
val x = args[x]!!
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt
index 9c6551302..5d4eee7c0 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt
index 5d331af9a..4ff687aac 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt
index 8f9a3e2b8..e3b3dde05 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
@@ -13,8 +13,7 @@ import org.jetbrains.kotlinx.multik.api.Multik
import org.jetbrains.kotlinx.multik.api.ones
import org.jetbrains.kotlinx.multik.ndarray.data.DN
import org.jetbrains.kotlinx.multik.ndarray.data.DataType
-import space.kscience.kmath.multik.multikND
-import space.kscience.kmath.multik.multikTensorAlgebra
+import space.kscience.kmath.multik.multikAlgebra
import space.kscience.kmath.nd.BufferedFieldOpsND
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.nd.ndAlgebra
@@ -79,7 +78,7 @@ internal class NDFieldBenchmark {
}
@Benchmark
- fun multikInPlaceAdd(blackhole: Blackhole) = with(DoubleField.multikTensorAlgebra) {
+ fun multikInPlaceAdd(blackhole: Blackhole) = with(DoubleField.multikAlgebra) {
val res = Multik.ones(shape, DataType.DoubleDataType).wrap()
repeat(n) { res += 1.0 }
blackhole.consume(res)
@@ -100,7 +99,7 @@ internal class NDFieldBenchmark {
private val specializedField = DoubleField.ndAlgebra
private val genericField = BufferedFieldOpsND(DoubleField, Buffer.Companion::boxing)
private val nd4jField = DoubleField.nd4j
- private val multikField = DoubleField.multikND
+ private val multikField = DoubleField.multikAlgebra
private val viktorField = DoubleField.viktorAlgebra
}
}
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt
index 6b4d5759b..de301678c 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt
index a9d1e68fc..dfdd89d74 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
diff --git a/build.gradle.kts b/build.gradle.kts
index c2347f7be..a07bcd2c5 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,31 +1,22 @@
-import java.net.URL
-
plugins {
id("ru.mipt.npm.gradle.project")
- kotlin("jupyter.api") apply false
+ id("org.jetbrains.kotlinx.kover") version "0.5.0-RC"
}
allprojects {
repositories {
- maven("https://clojars.org/repo")
- maven("https://jitpack.io")
-
- maven("http://logicrunch.research.it.uu.se/maven") {
- isAllowInsecureProtocol = true
- }
-
maven("https://oss.sonatype.org/content/repositories/snapshots")
mavenCentral()
}
group = "space.kscience"
- version = "0.3.0-dev-17"
+ version = "0.3.0-dev-18"
}
subprojects {
if (name.startsWith("kmath")) apply()
- afterEvaluate {
+ plugins.withId("org.jetbrains.dokka"){
tasks.withType {
dependsOn(tasks["assemble"])
@@ -39,7 +30,7 @@ subprojects {
localDirectory.set(kotlinDir)
remoteUrl.set(
- URL("https://github.com/mipt-npm/${rootProject.name}/tree/master/${this@subprojects.name}/$kotlinDirPath")
+ java.net.URL("https://github.com/mipt-npm/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath")
)
}
@@ -64,9 +55,9 @@ subprojects {
readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md")
ksciencePublish {
- vcs("https://github.com/mipt-npm/kmath")
- space(publish = true)
- sonatype(publish = true)
+ github("kmath")
+ space()
+ sonatype()
}
apiValidation.nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI")
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 36a1ffd9e..ceb220bd5 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -1,20 +1,30 @@
plugins {
`kotlin-dsl`
- kotlin("plugin.serialization") version "1.4.31"
+ `version-catalog`
+ alias(npmlibs.plugins.kotlin.plugin.serialization)
}
+java.targetCompatibility = JavaVersion.VERSION_11
+
repositories {
maven("https://repo.kotlin.link")
mavenCentral()
gradlePluginPortal()
}
+val toolsVersion: String by extra
+val kotlinVersion = npmlibs.versions.kotlin.asProvider().get()
+val benchmarksVersion = "0.4.2"
+
dependencies {
- api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
- api("ru.mipt.npm:gradle-tools:0.10.2")
- api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.3.1")
+ api("ru.mipt.npm:gradle-tools:$toolsVersion")
+ //plugins form benchmarks
+ api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:$benchmarksVersion")
+ api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
+ //to be used inside build-script only
+ implementation(npmlibs.kotlinx.serialization.json)
}
kotlin.sourceSets.all {
- languageSettings.useExperimentalAnnotation("kotlin.ExperimentalStdlibApi")
+ languageSettings.optIn("kotlin.OptIn")
}
diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties
new file mode 100644
index 000000000..6678f24a8
--- /dev/null
+++ b/buildSrc/gradle.properties
@@ -0,0 +1,14 @@
+#
+# Copyright 2018-2021 KMath contributors.
+# Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+#
+
+kotlin.code.style=official
+kotlin.mpp.stability.nowarn=true
+
+kotlin.jupyter.add.scanner=false
+
+org.gradle.configureondemand=true
+org.gradle.parallel=true
+
+toolsVersion=0.10.9-kotlin-1.6.10
diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts
new file mode 100644
index 000000000..87ff205f6
--- /dev/null
+++ b/buildSrc/settings.gradle.kts
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+
+enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
+enableFeaturePreview("VERSION_CATALOGS")
+
+dependencyResolutionManagement {
+
+ val toolsVersion: String by extra
+
+ repositories {
+ maven("https://repo.kotlin.link")
+ mavenCentral()
+ }
+
+ versionCatalogs {
+ create("npmlibs") {
+ from("ru.mipt.npm:version-catalog:$toolsVersion")
+ }
+ }
+}
diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt
index 6859de845..eaa0f59d8 100644
--- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt
+++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt
index 72c9ff0ad..dc9327348 100644
--- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt
+++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt
@@ -1,17 +1,20 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.benchmarks
import kotlinx.benchmark.gradle.BenchmarksExtension
-import kotlinx.serialization.*
-import kotlinx.serialization.json.*
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.json.Json
import org.gradle.api.Project
import ru.mipt.npm.gradle.KScienceReadmeExtension
-import java.time.*
-import java.time.format.*
+import java.time.LocalDateTime
+import java.time.ZoneId
+import java.time.format.DateTimeFormatter
+import java.time.format.DateTimeFormatterBuilder
+import java.time.format.SignStyle
import java.time.temporal.ChronoField.*
private val ISO_DATE_TIME: DateTimeFormatter = DateTimeFormatterBuilder().run {
@@ -47,14 +50,14 @@ fun Project.addBenchmarkProperties() {
rootProject.subprojects.forEach { p ->
p.extensions.findByType(KScienceReadmeExtension::class.java)?.run {
benchmarksProject.extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg ->
- property("benchmark${cfg.name.replaceFirstChar(Char::uppercase)}") {
+ property("benchmark${cfg.name.capitalize()}") {
val launches = benchmarksProject.buildDir.resolve("reports/benchmarks/${cfg.name}")
val resDirectory = launches.listFiles()?.maxByOrNull {
LocalDateTime.parse(it.name, ISO_DATE_TIME).atZone(ZoneId.systemDefault()).toInstant()
}
- if (resDirectory == null) {
+ if (resDirectory == null || !(resDirectory.resolve("jvm.json")).exists()) {
"> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**."
} else {
val reports =
diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt
index cfebf61e7..7f8cb35b3 100644
--- a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt
+++ b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("KDocUnresolvedReference")
diff --git a/docs/images/KM.svg b/docs/images/KM.svg
index f5ec452c7..6f80e4d08 100644
--- a/docs/images/KM.svg
+++ b/docs/images/KM.svg
@@ -1,7 +1,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
## Modules
$modules
diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts
index 7b1bce26a..36715cd78 100644
--- a/examples/build.gradle.kts
+++ b/examples/build.gradle.kts
@@ -5,12 +5,7 @@ plugins {
repositories {
mavenCentral()
maven("https://repo.kotlin.link")
- maven("https://clojars.org/repo")
- maven("https://jitpack.io")
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers")
- maven("http://logicrunch.research.it.uu.se/maven") {
- isAllowInsecureProtocol = true
- }
}
dependencies {
@@ -32,7 +27,7 @@ dependencies {
//jafama
implementation(project(":kmath-jafama"))
//multik
- implementation(projects.kmathMultik)
+ implementation(project(":kmath-multik"))
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
@@ -57,16 +52,16 @@ dependencies {
kotlin.sourceSets.all {
with(languageSettings) {
- useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
- useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
- useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI")
+ optIn("kotlin.contracts.ExperimentalContracts")
+ optIn("kotlin.ExperimentalUnsignedTypes")
+ optIn("space.kscience.kmath.misc.UnstableKMathAPI")
}
}
tasks.withType {
- kotlinOptions{
+ kotlinOptions {
jvmTarget = "11"
- freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn"
+ freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy"
}
}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt
index 0c16d82d1..c4f263f97 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
index 887d76c42..907f1bbe4 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
@@ -1,22 +1,26 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
-import space.kscience.kmath.expressions.MstField
+import space.kscience.kmath.asm.compileToExpression
+import space.kscience.kmath.expressions.MstExtendedField
import space.kscience.kmath.expressions.Symbol.Companion.x
-import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
fun main() {
- val expr = MstField {
- x * 2.0 + number(2.0) / x - 16.0
- }
+ val expr = MstExtendedField {
+ x * 2.0 + number(2.0) / x - number(16.0) + asinh(x) / sin(x)
+ }.compileToExpression(DoubleField)
+
+ val m = DoubleArray(expr.indexer.symbols.size)
+ val xIdx = expr.indexer.indexOf(x)
repeat(10000000) {
- expr.interpret(DoubleField, x to 1.0)
+ m[xIdx] = 1.0
+ expr(m)
}
-}
\ No newline at end of file
+}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt
index 4e3528b3e..dec3bfb81 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt
index 209523c89..7e09faeff 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
diff --git a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt
index dbe0b8454..63e57bd8c 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.fit
diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt
index c77d1d70c..f60b1ab45 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.functions
diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt
index a98467ced..8dbc7b7a4 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.functions
diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt
index 3f958b3b0..091242829 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.functions
diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt
index 4b6ac475c..4f99aeb47 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.functions
diff --git a/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt
index 10ed30728..9c3d0fdbe 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.jafama
diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt
index 6e8767a5b..a2d7d7c27 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.linear
diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt
index afc42ea26..a01ea7fe2 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.linear
diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt
index 2039953b5..51f439612 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.operations
diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt
index 3b9c32f4b..2e1801cc2 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.operations
diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt
index f517046ee..62c9c8076 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt
@@ -1,3 +1,8 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
package space.kscience.kmath.operations
import space.kscience.kmath.commons.linear.CMLinearSpace
diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt
index 732c9a8e3..8e3cdf86f 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.stat
diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt
index 685214c39..15654971f 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt
@@ -1,13 +1,13 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.stat
import kotlinx.coroutines.runBlocking
import space.kscience.kmath.chains.Chain
-import space.kscience.kmath.chains.collectWithState
+import space.kscience.kmath.chains.combineWithState
import space.kscience.kmath.distributions.NormalDistribution
private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)
@@ -15,11 +15,11 @@ private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0
/**
* Averaging.
*/
-private fun Chain.mean(): Chain = collectWithState(AveragingChainState(), { it.copy() }) { chain ->
+private fun Chain.mean(): Chain = combineWithState(AveragingChainState(), { it.copy() }) { chain ->
val next = chain.next()
num++
value += next
- return@collectWithState value / num
+ return@combineWithState value / num
}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt
index 61df3d065..d55f3df09 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("unused")
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt
index cf0721ce7..b680e267d 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.structures
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt
index 2b3e72136..548fb16c1 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.structures
@@ -36,7 +36,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND this.buffer as DoubleBuffer
+ this is BufferND && this.indices == this@StreamDoubleFieldND.strides -> this.buffer as DoubleBuffer
else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt
index 84dd6538c..de36c664d 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.structures
@@ -19,24 +19,24 @@ fun main() {
measureTimeMillis {
var res = 0.0
- strides.indices().forEach { res = structure[it] }
+ strides.asSequence().forEach { res = structure[it] }
} // warmup
val time1 = measureTimeMillis {
var res = 0.0
- strides.indices().forEach { res = structure[it] }
+ strides.asSequence().forEach { res = structure[it] }
}
println("Structure reading finished in $time1 millis")
val time2 = measureTimeMillis {
var res = 0.0
- strides.indices().forEach { res = buffer[strides.offset(it)] }
+ strides.asSequence().forEach { res = buffer[strides.offset(it)] }
}
println("Buffer reading finished in $time2 millis")
val time3 = measureTimeMillis {
var res = 0.0
- strides.indices().forEach { res = array[strides.offset(it)] }
+ strides.asSequence().forEach { res = array[strides.offset(it)] }
}
println("Array reading finished in $time3 millis")
}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt
index 84644ddd9..dea7095a8 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.structures
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt
index 853ebad32..c28b566b9 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.structures
diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt
index a266d4849..b42602988 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.tensors
diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt
index d83d47805..aced0cf7d 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.tensors
diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt
index 9d5b8c2a5..a436ae1c3 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.tensors
diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt
index 846e338da..f465fc424 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.tensors
diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt
index f0b776f75..f2d1f0b41 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt
@@ -1,18 +1,18 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.tensors
import org.jetbrains.kotlinx.multik.api.Multik
import org.jetbrains.kotlinx.multik.api.ndarray
-import space.kscience.kmath.multik.multikND
+import space.kscience.kmath.multik.multikAlgebra
import space.kscience.kmath.nd.one
import space.kscience.kmath.operations.DoubleField
-fun main(): Unit = with(DoubleField.multikND) {
+fun main(): Unit = with(DoubleField.multikAlgebra) {
val a = Multik.ndarray(intArrayOf(1, 2, 3)).asType().wrap()
val b = Multik.ndarray(doubleArrayOf(1.0, 2.0, 3.0)).wrap()
- one(a.shape) - a + b * 3
+ one(a.shape) - a + b * 3.0
}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt
index 3025ff8a3..5c41ab0f1 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.tensors
@@ -9,7 +9,7 @@ import space.kscience.kmath.operations.invoke
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
import space.kscience.kmath.tensors.core.DoubleTensor
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
-import space.kscience.kmath.tensors.core.toDoubleArray
+import space.kscience.kmath.tensors.core.copyArray
import kotlin.math.sqrt
const val seed = 100500L
@@ -111,7 +111,7 @@ class NeuralNetwork(private val layers: List) {
private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra {
val onesForAnswers = yPred.zeroesLike()
- yTrue.toDoubleArray().forEachIndexed { index, labelDouble ->
+ yTrue.copyArray().forEachIndexed { index, labelDouble ->
val label = labelDouble.toInt()
onesForAnswers[intArrayOf(index, label)] = 1.0
}
@@ -163,7 +163,7 @@ class NeuralNetwork(private val layers: List) {
for ((xBatch, yBatch) in iterBatch(xTrain, yTrain)) {
train(xBatch, yBatch)
}
- println("Accuracy:${accuracy(yTrain, predict(xTrain).argMax(1, true))}")
+ println("Accuracy:${accuracy(yTrain, predict(xTrain).argMax(1, true).asDouble())}")
}
}
@@ -230,7 +230,7 @@ fun main() = BroadcastDoubleTensorAlgebra {
val prediction = model.predict(xTest)
// process raw prediction via argMax
- val predictionLabels = prediction.argMax(1, true)
+ val predictionLabels = prediction.argMax(1, true).asDouble()
// find out accuracy
val acc = accuracy(yTest, predictionLabels)
diff --git a/gradle.properties b/gradle.properties
index 959511c68..7dd9e6d61 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -6,11 +6,10 @@
kotlin.code.style=official
kotlin.mpp.stability.nowarn=true
-#kotlin.mpp.enableGranularSourceSetsMetadata=true
-#kotlin.native.enableDependencyPropagation=false
-
kotlin.jupyter.add.scanner=false
org.gradle.configureondemand=true
-org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G
org.gradle.parallel=true
+org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G
+
+toolsVersion=0.11.1-kotlin-1.6.10
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index ffed3a254..2e6e5897b 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-7.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 744e882ed..1b6c78733 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
-#!/usr/bin/env sh
+#!/bin/sh
#
-# Copyright 2015 the original author or authors.
+# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,67 +17,101 @@
#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
# Attempt to set APP_HOME
+
# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
+APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MSYS* | MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD="java"
+ JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@@ -106,80 +140,95 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-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
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=`expr $i + 1`
- done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
exec "$JAVACMD" "$@"
diff --git a/kmath-ast/README.md b/kmath-ast/README.md
index 686506f6f..bedf17486 100644
--- a/kmath-ast/README.md
+++ b/kmath-ast/README.md
@@ -1,6 +1,6 @@
# Module kmath-ast
-Performance and visualization extensions to MST API.
+Extensions to MST API: transformations, dynamic compilation and visualization.
- [expression-language](src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
- [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
@@ -10,7 +10,7 @@ Performance and visualization extensions to MST API.
## Artifact:
-The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-14`.
+The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-17`.
**Gradle:**
```gradle
@@ -20,7 +20,7 @@ repositories {
}
dependencies {
- implementation 'space.kscience:kmath-ast:0.3.0-dev-14'
+ implementation 'space.kscience:kmath-ast:0.3.0-dev-17'
}
```
**Gradle Kotlin DSL:**
@@ -31,10 +31,30 @@ repositories {
}
dependencies {
- implementation("space.kscience:kmath-ast:0.3.0-dev-14")
+ implementation("space.kscience:kmath-ast:0.3.0-dev-17")
}
```
+## Parsing expressions
+
+In this module there is a parser from human-readable strings like `"x^3-x+3"` (in the more specific [grammar](reference/ArithmeticsEvaluator.g4)) to MST instances.
+
+Supported literals:
+1. Constants and variables (consist of latin letters, digits and underscores, can't start with digit): `x`, `_Abc2`.
+2. Numbers: `123`, `1.02`, `1e10`, `1e-10`, `1.0e+3`—all parsed either as `kotlin.Long` or `kotlin.Double`.
+
+Supported binary operators (from the highest precedence to the lowest one):
+1. `^`
+2. `*`, `/`
+3. `+`, `-`
+
+Supported unary operator:
+1. `-`, e. g. `-x`
+
+Arbitrary unary and binary functions are also supported: names consist of latin letters, digits and underscores, can't start with digit. Examples:
+1. `sin(x)`
+2. `add(x, y)`
+
## Dynamic expression code generation
### On JVM
@@ -42,48 +62,41 @@ dependencies {
`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 code:
```kotlin
-import space.kscience.kmath.expressions.Symbol.Companion.x
-import space.kscience.kmath.expressions.*
-import space.kscience.kmath.operations.*
-import space.kscience.kmath.asm.*
+import space.kscience.kmath.asm.compileToExpression
+import space.kscience.kmath.complex.ComplexField
-MstField { x + 2 }.compileToExpression(DoubleField)
-```
+"x+2".parseMath().compileToExpression(ComplexField)
+```
-... leads to generation of bytecode, which can be decompiled to the following Java class:
+… leads to generation of bytecode, which can be decompiled to the following Java class:
```java
-package space.kscience.kmath.asm.generated;
-
import java.util.Map;
-
import kotlin.jvm.functions.Function2;
import space.kscience.kmath.asm.internal.MapIntrinsics;
+import space.kscience.kmath.complex.Complex;
import space.kscience.kmath.expressions.Expression;
import space.kscience.kmath.expressions.Symbol;
-public final class AsmCompiledExpression_45045_0 implements Expression {
+public final class CompiledExpression_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;
+ public Complex invoke(Map arguments) {
+ Complex var2 = (Complex)MapIntrinsics.getOrFail(arguments, "x");
+ return (Complex)((Function2)this.constants[0]).invoke(var2, (Complex)this.constants[1]);
}
}
-
```
-#### Known issues
+Setting JVM system property `space.kscience.kmath.ast.dump.generated.classes` to `1` makes the translator dump class files to program's working directory, so they can be reviewed manually.
-- 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.
+#### Limitations
+
+- 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 or GraalVM Native Image because they may not support class loaders.
### On JS
@@ -129,7 +142,7 @@ An example of emitted Wasm IR in the form of WAT:
)
```
-#### Known issues
+#### Limitations
- ESTree expression compilation uses `eval` which can be unavailable in several environments.
- WebAssembly isn't supported by old versions of browsers (see https://webassembly.org/roadmap/).
diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts
index 9de7e9980..15b1d0900 100644
--- a/kmath-ast/build.gradle.kts
+++ b/kmath-ast/build.gradle.kts
@@ -20,7 +20,7 @@ kotlin.js {
kotlin.sourceSets {
filter { it.name.contains("test", true) }
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
- .forEach { it.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") }
+ .forEach { it.optIn("space.kscience.kmath.misc.UnstableKMathAPI") }
commonMain {
dependencies {
@@ -55,6 +55,11 @@ tasks.dokkaHtml {
dependsOn(tasks.build)
}
+if (System.getProperty("space.kscience.kmath.ast.dump.generated.classes") == "1")
+ tasks.jvmTest {
+ jvmArgs = (jvmArgs ?: emptyList()) + listOf("-Dspace.kscience.kmath.ast.dump.generated.classes=1")
+ }
+
readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md
index 9494af63a..e9e22f4d4 100644
--- a/kmath-ast/docs/README-TEMPLATE.md
+++ b/kmath-ast/docs/README-TEMPLATE.md
@@ -1,11 +1,31 @@
# Module kmath-ast
-Performance and visualization extensions to MST API.
+Extensions to MST API: transformations, dynamic compilation and visualization.
${features}
${artifact}
+## Parsing expressions
+
+In this module there is a parser from human-readable strings like `"x^3-x+3"` (in the more specific [grammar](reference/ArithmeticsEvaluator.g4)) to MST instances.
+
+Supported literals:
+1. Constants and variables (consist of latin letters, digits and underscores, can't start with digit): `x`, `_Abc2`.
+2. Numbers: `123`, `1.02`, `1e10`, `1e-10`, `1.0e+3`—all parsed either as `kotlin.Long` or `kotlin.Double`.
+
+Supported binary operators (from the highest precedence to the lowest one):
+1. `^`
+2. `*`, `/`
+3. `+`, `-`
+
+Supported unary operator:
+1. `-`, e. g. `-x`
+
+Arbitrary unary and binary functions are also supported: names consist of latin letters, digits and underscores, can't start with digit. Examples:
+1. `sin(x)`
+2. `add(x, y)`
+
## Dynamic expression code generation
### On JVM
@@ -13,48 +33,66 @@ ${artifact}
`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 code:
```kotlin
-import space.kscience.kmath.expressions.Symbol.Companion.x
-import space.kscience.kmath.expressions.*
-import space.kscience.kmath.operations.*
-import space.kscience.kmath.asm.*
-
-MstField { x + 2 }.compileToExpression(DoubleField)
-```
-
-... leads to generation of bytecode, which can be decompiled to the following Java class:
-
-```java
-package space.kscience.kmath.asm.generated;
-
-import java.util.Map;
-
-import kotlin.jvm.functions.Function2;
-import space.kscience.kmath.asm.internal.MapIntrinsics;
-import space.kscience.kmath.expressions.Expression;
-import space.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;
- }
-}
+import space.kscience.kmath.asm.compileToExpression
+import space.kscience.kmath.operations.DoubleField
+"x^3-x+3".parseMath().compileToExpression(DoubleField)
```
-#### Known issues
+… leads to generation of bytecode, which can be decompiled to the following Java class:
-- 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.
+```java
+import java.util.*;
+import kotlin.jvm.functions.*;
+import space.kscience.kmath.asm.internal.*;
+import space.kscience.kmath.complex.*;
+import space.kscience.kmath.expressions.*;
+
+public final class CompiledExpression_45045_0 implements Expression {
+ private final Object[] constants;
+
+ public Complex invoke(Map arguments) {
+ Complex var2 = (Complex)MapIntrinsics.getOrFail(arguments, "x");
+ return (Complex)((Function2)this.constants[0]).invoke(var2, (Complex)this.constants[1]);
+ }
+}
+```
+
+For `LongRing`, `IntRing`, and `DoubleField` specialization is supported for better performance:
+
+```java
+import java.util.*;
+import space.kscience.kmath.asm.internal.*;
+import space.kscience.kmath.expressions.*;
+
+public final class CompiledExpression_-386104628_0 implements DoubleExpression {
+ private final SymbolIndexer indexer;
+
+ public SymbolIndexer getIndexer() {
+ return this.indexer;
+ }
+
+ public double invoke(double[] arguments) {
+ double var2 = arguments[0];
+ return Math.pow(var2, 3.0D) - var2 + 3.0D;
+ }
+
+ public final Double invoke(Map arguments) {
+ double var2 = ((Double)MapIntrinsics.getOrFail(arguments, "x")).doubleValue();
+ return Math.pow(var2, 3.0D) - var2 + 3.0D;
+ }
+}
+```
+
+Setting JVM system property `space.kscience.kmath.ast.dump.generated.classes` to `1` makes the translator dump class files to program's working directory, so they can be reviewed manually.
+
+#### Limitations
+
+- 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 or GraalVM Native Image because they may not support class loaders.
### On JS
@@ -100,7 +138,7 @@ An example of emitted Wasm IR in the form of WAT:
)
```
-#### Known issues
+#### Limitations
- ESTree expression compilation uses `eval` which can be unavailable in several environments.
- WebAssembly isn't supported by old versions of browsers (see https://webassembly.org/roadmap/).
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt
new file mode 100644
index 000000000..8a8b8797d
--- /dev/null
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.ast
+
+import space.kscience.kmath.expressions.Expression
+import space.kscience.kmath.expressions.Symbol
+import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.operations.Algebra
+import space.kscience.kmath.operations.NumericAlgebra
+
+/**
+ * MST form where all values belong to the type [T]. It is optimal for constant folding, dynamic compilation, etc.
+ *
+ * @param T the type.
+ */
+@UnstableKMathAPI
+public sealed interface TypedMst {
+ /**
+ * A node containing a unary operation.
+ *
+ * @param T the type.
+ * @property operation The identifier of operation.
+ * @property function The function implementing this operation.
+ * @property value The argument of this operation.
+ */
+ public class Unary(public val operation: String, public val function: (T) -> T, public val value: TypedMst) :
+ TypedMst {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other == null || this::class != other::class) return false
+ other as Unary<*>
+ if (operation != other.operation) return false
+ if (value != other.value) return false
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = operation.hashCode()
+ result = 31 * result + value.hashCode()
+ return result
+ }
+
+ override fun toString(): String = "Unary(operation=$operation, value=$value)"
+ }
+
+ /**
+ * A node containing binary operation.
+ *
+ * @param T the type.
+ * @property operation The identifier of operation.
+ * @property function The binary function implementing this operation.
+ * @property left The left operand.
+ * @property right The right operand.
+ */
+ public class Binary(
+ public val operation: String,
+ public val function: Function,
+ public val left: TypedMst,
+ public val right: TypedMst,
+ ) : TypedMst {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other == null || this::class != other::class) return false
+
+ other as Binary<*>
+
+ if (operation != other.operation) return false
+ if (left != other.left) return false
+ if (right != other.right) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = operation.hashCode()
+ result = 31 * result + left.hashCode()
+ result = 31 * result + right.hashCode()
+ return result
+ }
+
+ override fun toString(): String = "Binary(operation=$operation, left=$left, right=$right)"
+ }
+
+ /**
+ * The non-numeric constant value.
+ *
+ * @param T the type.
+ * @property value The held value.
+ * @property number The number this value corresponds.
+ */
+ public class Constant(public val value: T, public val number: Number?) : TypedMst {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other == null || this::class != other::class) return false
+ other as Constant<*>
+ if (value != other.value) return false
+ if (number != other.number) return false
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = value?.hashCode() ?: 0
+ result = 31 * result + (number?.hashCode() ?: 0)
+ return result
+ }
+
+ override fun toString(): String = "Constant(value=$value, number=$number)"
+ }
+
+ /**
+ * The node containing a variable
+ *
+ * @param T the type.
+ * @property symbol The symbol of the variable.
+ */
+ public class Variable(public val symbol: Symbol) : TypedMst {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other == null || this::class != other::class) return false
+ other as Variable<*>
+ if (symbol != other.symbol) return false
+ return true
+ }
+
+ override fun hashCode(): Int = symbol.hashCode()
+ override fun toString(): String = "Variable(symbol=$symbol)"
+ }
+}
+
+/**
+ * Interprets the [TypedMst] node with this [Algebra] and [arguments].
+ */
+@UnstableKMathAPI
+public fun TypedMst.interpret(algebra: Algebra, arguments: Map): T = when (this) {
+ is TypedMst.Unary -> algebra.unaryOperation(operation, interpret(algebra, arguments))
+
+ is TypedMst.Binary -> when {
+ algebra is NumericAlgebra && left is TypedMst.Constant && left.number != null ->
+ algebra.leftSideNumberOperation(operation, left.number, right.interpret(algebra, arguments))
+
+ algebra is NumericAlgebra && right is TypedMst.Constant && right.number != null ->
+ algebra.rightSideNumberOperation(operation, left.interpret(algebra, arguments), right.number)
+
+ else -> algebra.binaryOperation(
+ operation,
+ left.interpret(algebra, arguments),
+ right.interpret(algebra, arguments),
+ )
+ }
+
+ is TypedMst.Constant -> value
+ is TypedMst.Variable -> arguments.getValue(symbol)
+}
+
+/**
+ * Interprets the [TypedMst] node with this [Algebra] and optional [arguments].
+ */
+@UnstableKMathAPI
+public fun TypedMst.interpret(algebra: Algebra, vararg arguments: Pair): T = interpret(
+ algebra,
+ when (arguments.size) {
+ 0 -> emptyMap()
+ 1 -> mapOf(arguments[0])
+ else -> hashMapOf(*arguments)
+ },
+)
+
+/**
+ * Interpret this [TypedMst] node as expression.
+ */
+@UnstableKMathAPI
+public fun TypedMst.toExpression(algebra: Algebra): Expression = Expression { arguments ->
+ interpret(algebra, arguments)
+}
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt
new file mode 100644
index 000000000..71fb154c9
--- /dev/null
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.ast
+
+import space.kscience.kmath.expressions.MST
+import space.kscience.kmath.expressions.Symbol
+import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.operations.Algebra
+import space.kscience.kmath.operations.NumericAlgebra
+import space.kscience.kmath.operations.bindSymbolOrNull
+
+/**
+ * Evaluates constants in given [MST] for given [algebra] at the same time with converting to [TypedMst].
+ */
+@UnstableKMathAPI
+public fun MST.evaluateConstants(algebra: Algebra): TypedMst = when (this) {
+ is MST.Numeric -> TypedMst.Constant(
+ (algebra as? NumericAlgebra)?.number(value) ?: error("Numeric nodes are not supported by $algebra"),
+ value,
+ )
+
+ is MST.Unary -> when (val arg = value.evaluateConstants(algebra)) {
+ is TypedMst.Constant -> {
+ val value = algebra.unaryOperation(
+ operation,
+ arg.value,
+ )
+
+ TypedMst.Constant(value, if (value is Number) value else null)
+ }
+
+ else -> TypedMst.Unary(operation, algebra.unaryOperationFunction(operation), arg)
+ }
+
+ is MST.Binary -> {
+ val left = left.evaluateConstants(algebra)
+ val right = right.evaluateConstants(algebra)
+
+ when {
+ left is TypedMst.Constant && right is TypedMst.Constant -> {
+ val value = when {
+ algebra is NumericAlgebra && left.number != null -> algebra.leftSideNumberOperation(
+ operation,
+ left.number,
+ right.value,
+ )
+
+ algebra is NumericAlgebra && right.number != null -> algebra.rightSideNumberOperation(
+ operation,
+ left.value,
+ right.number,
+ )
+
+ else -> algebra.binaryOperation(
+ operation,
+ left.value,
+ right.value,
+ )
+ }
+
+ TypedMst.Constant(value, if (value is Number) value else null)
+ }
+
+ algebra is NumericAlgebra && left is TypedMst.Constant && left.number != null -> TypedMst.Binary(
+ operation,
+ algebra.leftSideNumberOperationFunction(operation),
+ left,
+ right,
+ )
+
+ algebra is NumericAlgebra && right is TypedMst.Constant && right.number != null -> TypedMst.Binary(
+ operation,
+ algebra.rightSideNumberOperationFunction(operation),
+ left,
+ right,
+ )
+
+ else -> TypedMst.Binary(operation, algebra.binaryOperationFunction(operation), left, right)
+ }
+ }
+
+ is Symbol -> {
+ val boundSymbol = algebra.bindSymbolOrNull(this)
+
+ if (boundSymbol != null)
+ TypedMst.Constant(boundSymbol, if (boundSymbol is Number) boundSymbol else null)
+ else
+ TypedMst.Variable(this)
+ }
+}
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt
index 7f2780548..012a6e65f 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
@@ -22,6 +22,7 @@ import space.kscience.kmath.operations.FieldOps
import space.kscience.kmath.operations.GroupOps
import space.kscience.kmath.operations.PowerOperations
import space.kscience.kmath.operations.RingOps
+import kotlin.math.floor
/**
* better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4.
@@ -40,9 +41,22 @@ public object ArithmeticsEvaluator : Grammar() {
private val div: Token by literalToken("/")
private val minus: Token by literalToken("-")
private val plus: Token by literalToken("+")
+
+ @Suppress("unused")
private val ws: Token by regexToken("\\s+".toRegex(), ignore = true)
- private val number: Parser by num use { MST.Numeric(text.toDouble()) }
+ // TODO Rewrite as custom parser to handle numbers with better precision. Currently, numbers like 1e10 are handled while they could be stored as longs without precision loss.
+ private val number: Parser by num use {
+ val d = text.toDoubleOrNull()
+
+ MST.Numeric(
+ if (d == null || d == floor(d) && !d.isInfinite()) {
+ text.toLongOrNull() ?: text.toDouble()
+ } else
+ d
+ )
+ }
+
private val singular: Parser by id use { Symbol(text) }
private val unaryFunction: Parser by (id and -lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
@@ -91,7 +105,8 @@ public object ArithmeticsEvaluator : Grammar() {
}
/**
- * Tries to parse the string into [MST] using [ArithmeticsEvaluator]. 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.
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt
index bf5916fa5..2df3d3cc7 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt
index 5439c42fa..8b5819b84 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt
index 24bac425a..fdef35ebd 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt
index 81b7d2afb..ee23ab408 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt
index 2f285c600..362c07d72 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt
index 8b76b6f19..90f78a152 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt
index 3e33d6415..291399cee 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt
index ecea2d104..c0271fbb5 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt
index 802d4c10e..1edb5923e 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt
index f5b1e2842..be8a92f3e 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
@@ -44,6 +44,30 @@ internal class TestCompilerOperations {
assertEquals(1.0, expr(x to 0.0))
}
+ @Test
+ fun testTangent() = runCompilerTest {
+ val expr = MstExtendedField { tan(x) }.compileToExpression(DoubleField)
+ assertEquals(0.0, expr(x to 0.0))
+ }
+
+ @Test
+ fun testArcSine() = runCompilerTest {
+ val expr = MstExtendedField { asin(x) }.compileToExpression(DoubleField)
+ assertEquals(0.0, expr(x to 0.0))
+ }
+
+ @Test
+ fun testArcCosine() = runCompilerTest {
+ val expr = MstExtendedField { acos(x) }.compileToExpression(DoubleField)
+ assertEquals(0.0, expr(x to 1.0))
+ }
+
+ @Test
+ fun testAreaHyperbolicSine() = runCompilerTest {
+ val expr = MstExtendedField { asinh(x) }.compileToExpression(DoubleField)
+ assertEquals(0.0, expr(x to 0.0))
+ }
+
@Test
fun testSubtract() = runCompilerTest {
val expr = MstExtendedField { x - x }.compileToExpression(DoubleField)
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt
index 8d9a2301f..93ef97b0f 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt
@@ -1,13 +1,15 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
import space.kscience.kmath.expressions.MstRing
import space.kscience.kmath.expressions.Symbol.Companion.x
+import space.kscience.kmath.expressions.Symbol.Companion.y
import space.kscience.kmath.expressions.invoke
+import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.operations.invoke
import kotlin.test.Test
@@ -16,11 +18,23 @@ import kotlin.test.assertFailsWith
internal class TestCompilerVariables {
@Test
- fun testVariable() = runCompilerTest {
+ fun testNoVariables() = runCompilerTest {
+ val expr = "0".parseMath().compileToExpression(DoubleField)
+ assertEquals(0.0, expr(), 0.0001)
+ }
+
+ @Test
+ fun testOneVariable() = runCompilerTest {
val expr = MstRing { x }.compileToExpression(IntRing)
assertEquals(1, expr(x to 1))
}
+ @Test
+ fun testTwoVariables() = runCompilerTest {
+ val expr = "y+x/y+x".parseMath().compileToExpression(DoubleField)
+ assertEquals(8.0, expr(x to 4.0, y to 2.0))
+ }
+
@Test
fun testUndefinedVariableFails() = runCompilerTest {
val expr = MstRing { x }.compileToExpression(IntRing)
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt
new file mode 100644
index 000000000..954a0f330
--- /dev/null
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.ast
+
+import space.kscience.kmath.operations.ByteRing
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.operations.IntRing
+import space.kscience.kmath.operations.pi
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.fail
+
+internal class TestFolding {
+ @Test
+ fun foldUnary() = assertEquals(
+ -1,
+ ("-(1)".parseMath().evaluateConstants(IntRing) as? TypedMst.Constant ?: fail()).value,
+ )
+
+ @Test
+ fun foldDeepUnary() = assertEquals(
+ 1,
+ ("-(-(1))".parseMath().evaluateConstants(IntRing) as? TypedMst.Constant ?: fail()).value,
+ )
+
+ @Test
+ fun foldBinary() = assertEquals(
+ 2,
+ ("1*2".parseMath().evaluateConstants(IntRing) as? TypedMst.Constant ?: fail()).value,
+ )
+
+ @Test
+ fun foldDeepBinary() = assertEquals(
+ 10,
+ ("1*2*5".parseMath().evaluateConstants(IntRing) as? TypedMst.Constant ?: fail()).value,
+ )
+
+ @Test
+ fun foldSymbol() = assertEquals(
+ DoubleField.pi,
+ ("pi".parseMath().evaluateConstants(DoubleField) as? TypedMst.Constant ?: fail()).value,
+ )
+
+ @Test
+ fun foldNumeric() = assertEquals(
+ 42.toByte(),
+ ("42".parseMath().evaluateConstants(ByteRing) as? TypedMst.Constant ?: fail()).value,
+ )
+}
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt
index 4c834a9ca..d0c3a789e 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt
@@ -1,13 +1,13 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
import space.kscience.kmath.complex.Complex
import space.kscience.kmath.complex.ComplexField
-import space.kscience.kmath.expressions.evaluate
+import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test
@@ -17,14 +17,14 @@ internal class TestParser {
@Test
fun evaluateParsedMst() {
val mst = "2+2*(2+2)".parseMath()
- val res = ComplexField.evaluate(mst)
+ val res = mst.interpret(ComplexField)
assertEquals(Complex(10.0, 0.0), res)
}
@Test
fun evaluateMstSymbol() {
val mst = "i".parseMath()
- val res = ComplexField.evaluate(mst)
+ val res = mst.interpret(ComplexField)
assertEquals(ComplexField.i, res)
}
@@ -32,7 +32,7 @@ internal class TestParser {
@Test
fun evaluateMstUnary() {
val mst = "sin(0)".parseMath()
- val res = DoubleField.evaluate(mst)
+ val res = mst.interpret(DoubleField)
assertEquals(0.0, res)
}
@@ -53,7 +53,7 @@ internal class TestParser {
}
val mst = "magic(a, b)".parseMath()
- val res = magicalAlgebra.evaluate(mst)
+ val res = mst.interpret(magicalAlgebra)
assertEquals("a ★ b", res)
}
}
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt
index 9776da45c..42cf5ce58 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt
@@ -1,39 +1,39 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
-import space.kscience.kmath.expressions.evaluate
+import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestParserPrecedence {
@Test
- fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath()))
+ fun test1(): Unit = assertEquals(6.0, "2*2+2".parseMath().interpret(f))
@Test
- fun test2(): Unit = assertEquals(6.0, f.evaluate("2+2*2".parseMath()))
+ fun test2(): Unit = assertEquals(6.0, "2+2*2".parseMath().interpret(f))
@Test
- fun test3(): Unit = assertEquals(10.0, f.evaluate("2^3+2".parseMath()))
+ fun test3(): Unit = assertEquals(10.0, "2^3+2".parseMath().interpret(f))
@Test
- fun test4(): Unit = assertEquals(10.0, f.evaluate("2+2^3".parseMath()))
+ fun test4(): Unit = assertEquals(10.0, "2+2^3".parseMath().interpret(f))
@Test
- fun test5(): Unit = assertEquals(16.0, f.evaluate("2^3*2".parseMath()))
+ fun test5(): Unit = assertEquals(16.0, "2^3*2".parseMath().interpret(f))
@Test
- fun test6(): Unit = assertEquals(16.0, f.evaluate("2*2^3".parseMath()))
+ fun test6(): Unit = assertEquals(16.0, "2*2^3".parseMath().interpret(f))
@Test
- fun test7(): Unit = assertEquals(18.0, f.evaluate("2+2^3*2".parseMath()))
+ fun test7(): Unit = assertEquals(18.0, "2+2^3*2".parseMath().interpret(f))
@Test
- fun test8(): Unit = assertEquals(18.0, f.evaluate("2*2^3+2".parseMath()))
+ fun test8(): Unit = assertEquals(18.0, "2*2^3+2".parseMath().interpret(f))
private companion object {
private val f = DoubleField
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt
index ae429d97e..a40c785b9 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt
index aba713c43..43f31baba 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt
index 658ecd47a..145055494 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt
index 4485605a6..09ec127c7 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt
index 6b418821b..bf87b6fd0 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt
index ef9f3145a..ec7436188 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt
index 2e69a536f..521907d2c 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt
index 316fdeeff..a8b1aa2e1 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt
@@ -1,88 +1,52 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.estree
+import space.kscience.kmath.ast.TypedMst
+import space.kscience.kmath.ast.evaluateConstants
import space.kscience.kmath.estree.internal.ESTreeBuilder
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.MST
-import space.kscience.kmath.expressions.MST.*
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.internal.estree.BaseExpression
+import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Algebra
-import space.kscience.kmath.operations.NumericAlgebra
-import space.kscience.kmath.operations.bindSymbolOrNull
-
-@PublishedApi
-internal fun MST.compileWith(algebra: Algebra): Expression {
- fun ESTreeBuilder.visit(node: MST): BaseExpression = when (node) {
- is Symbol -> {
- val symbol = algebra.bindSymbolOrNull(node)
-
- if (symbol != null)
- constant(symbol)
- else
- variable(node.identity)
- }
-
- is Numeric -> constant(node.value)
-
- is Unary -> when {
- algebra is NumericAlgebra && node.value is Numeric -> constant(
- algebra.unaryOperationFunction(node.operation)(algebra.number((node.value as Numeric).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 as Numeric).value),
- algebra.number((node.right as Numeric).value)
- )
- )
-
- algebra is NumericAlgebra && node.left is Numeric -> call(
- algebra.leftSideNumberOperationFunction(node.operation),
- visit(node.left),
- visit(node.right),
- )
-
- algebra is NumericAlgebra && node.right is Numeric -> call(
- algebra.rightSideNumberOperationFunction(node.operation),
- visit(node.left),
- visit(node.right),
- )
-
- else -> call(
- algebra.binaryOperationFunction(node.operation),
- visit(node.left),
- visit(node.right),
- )
- }
- }
-
- return ESTreeBuilder { visit(this@compileWith) }.instance
-}
/**
* Create a compiled expression with given [MST] and given [algebra].
*/
-public fun MST.compileToExpression(algebra: Algebra): Expression = compileWith(algebra)
+@OptIn(UnstableKMathAPI::class)
+public fun MST.compileToExpression(algebra: Algebra): Expression {
+ val typed = evaluateConstants(algebra)
+ if (typed is TypedMst.Constant) return Expression { typed.value }
+ fun ESTreeBuilder.visit(node: TypedMst): BaseExpression = when (node) {
+ is TypedMst.Constant -> constant(node.value)
+ is TypedMst.Variable -> variable(node.symbol)
+ is TypedMst.Unary -> call(node.function, visit(node.value))
+
+ is TypedMst.Binary -> call(
+ node.function,
+ visit(node.left),
+ visit(node.right),
+ )
+ }
+
+ return ESTreeBuilder { visit(typed) }.instance
+}
/**
* Compile given MST to expression and evaluate it against [arguments]
*/
-public inline fun MST.compile(algebra: Algebra, arguments: Map): T =
- compileToExpression(algebra).invoke(arguments)
-
+public fun MST.compile(algebra: Algebra, arguments: Map): T =
+ compileToExpression(algebra)(arguments)
/**
* Compile given MST to expression and evaluate it against [arguments]
*/
-public inline fun MST.compile(algebra: Algebra, vararg arguments: Pair): T =
- compileToExpression(algebra).invoke(*arguments)
+public fun MST.compile(algebra: Algebra, vararg arguments: Pair): T =
+ compileToExpression(algebra)(*arguments)
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt
index 850f20be7..10a6c4a16 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.estree.internal
@@ -61,7 +61,7 @@ internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExp
}
}
- fun variable(name: String): BaseExpression = call(getOrFail, Identifier("arguments"), SimpleLiteral(name))
+ fun variable(name: Symbol): BaseExpression = call(getOrFail, Identifier("arguments"), SimpleLiteral(name.identity))
fun call(function: Function, vararg args: BaseExpression): BaseExpression = SimpleCallExpression(
optional = false,
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt
index c7faf73e0..eb5c1e3dd 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.estree.internal.astring
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt
index c36860654..cca2d83af 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JsModule("astring")
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt
index 0a5b059ba..93b4f6ce6 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.internal.astring
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt
index 26186c453..86e0cede7 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress(
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt
index 13e3a49e2..42b6ac7d8 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress(
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt
index 8e449627c..523b13b40 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation")
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt
index d85857de8..1f7b09af8 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.internal.emitter
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt
index 122a3a397..3aa31f921 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.internal.estree
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt
index ad079dbd0..b62b8c06c 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("ClassName")
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt
index caab91731..52be5530f 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.internal.stream
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt
index 5c091e3a1..9c012e3a3 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.internal.tsstdlib
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt
index bb7fd44ca..0cd395f2c 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION")
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt
index 52dd64a5e..90690abed 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JsQualifier("WebAssembly")
@@ -201,8 +201,8 @@ internal open external class Module {
}
@JsName("Instance")
-internal open external class Instance(module: Module, importObject: Any = definedExternally) {
- open var exports: Any
+internal open external class Instance(module: Module, importObject: dynamic = definedExternally) {
+ open var exports: dynamic
}
@JsName("Memory")
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt
index d59a52701..c5023c384 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress(
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt
index b04c4d48f..aacb62f36 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt
@@ -1,76 +1,34 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.wasm.internal
-import space.kscience.kmath.expressions.Expression
-import space.kscience.kmath.expressions.MST
-import space.kscience.kmath.expressions.MST.*
-import space.kscience.kmath.expressions.Symbol
+import space.kscience.kmath.ast.TypedMst
+import space.kscience.kmath.expressions.*
import space.kscience.kmath.internal.binaryen.*
import space.kscience.kmath.internal.webassembly.Instance
+import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.*
import space.kscience.kmath.internal.binaryen.Module as BinaryenModule
import space.kscience.kmath.internal.webassembly.Module as WasmModule
private val spreader = eval("(obj, args) => obj(...args)")
+@OptIn(UnstableKMathAPI::class)
@Suppress("UnsafeCastFromDynamic")
-internal sealed class WasmBuilder(
- val binaryenType: Type,
- val algebra: Algebra,
- val target: MST,
-) where T : Number {
- val keys: MutableList = mutableListOf()
- lateinit var ctx: BinaryenModule
+internal sealed class WasmBuilder>(
+ protected val binaryenType: Type,
+ protected val algebra: Algebra,
+ protected val target: TypedMst,
+) {
+ protected val keys: MutableList = mutableListOf()
+ protected lateinit var ctx: BinaryenModule
- open fun visitSymbolic(mst: Symbol): ExpressionRef {
- algebra.bindSymbolOrNull(mst)?.let { return visitNumeric(Numeric(it)) }
+ abstract val instance: E
- var idx = keys.indexOf(mst)
-
- if (idx == -1) {
- keys += mst
- idx = keys.lastIndex
- }
-
- return ctx.local.get(idx, binaryenType)
- }
-
- abstract fun visitNumeric(mst: Numeric): ExpressionRef
-
- open fun visitUnary(mst: Unary): ExpressionRef =
- error("Unary operation ${mst.operation} not defined in $this")
-
- open fun visitBinary(mst: Binary): ExpressionRef =
- error("Binary operation ${mst.operation} not defined in $this")
-
- open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()")
-
- fun visit(mst: MST): ExpressionRef = when (mst) {
- is Symbol -> visitSymbolic(mst)
- is Numeric -> visitNumeric(mst)
-
- is Unary -> when {
- algebra is NumericAlgebra && mst.value is Numeric -> visitNumeric(
- Numeric(algebra.unaryOperationFunction(mst.operation)(algebra.number((mst.value as Numeric).value))))
-
- else -> visitUnary(mst)
- }
-
- is Binary -> when {
- algebra is NumericAlgebra && mst.left is Numeric && mst.right is Numeric -> visitNumeric(Numeric(
- algebra.binaryOperationFunction(mst.operation)
- .invoke(algebra.number((mst.left as Numeric).value), algebra.number((mst.right as Numeric).value))
- ))
-
- else -> visitBinary(mst)
- }
- }
-
- val instance by lazy {
+ protected val executable = run {
val c = WasmModule(with(createModule()) {
ctx = this
val expr = visit(target)
@@ -91,44 +49,78 @@ internal sealed class WasmBuilder(
res
})
- val i = Instance(c, js("{}") as Any)
- val symbols = keys
- keys.clear()
+ Instance(c, js("{}")).exports.executable
+ }
- Expression { args ->
- val params = symbols.map(args::getValue).toTypedArray()
- spreader(i.exports.asDynamic().executable, params) as T
+ protected abstract fun visitNumber(number: Number): ExpressionRef
+
+ protected open fun visitVariable(node: TypedMst.Variable): ExpressionRef {
+ var idx = keys.indexOf(node.symbol)
+
+ if (idx == -1) {
+ keys += node.symbol
+ idx = keys.lastIndex
}
+
+ return ctx.local.get(idx, binaryenType)
+ }
+
+ protected open fun visitUnary(node: TypedMst.Unary): ExpressionRef =
+ error("Unary operation ${node.operation} not defined in $this")
+
+ protected open fun visitBinary(mst: TypedMst.Binary): ExpressionRef =
+ error("Binary operation ${mst.operation} not defined in $this")
+
+ protected open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()")
+
+ protected fun visit(node: TypedMst): ExpressionRef = when (node) {
+ is TypedMst.Constant -> visitNumber(
+ node.number ?: error("Object constants are not supported by pritimive ASM builder"),
+ )
+
+ is TypedMst.Variable -> visitVariable(node)
+ is TypedMst.Unary -> visitUnary(node)
+ is TypedMst.Binary -> visitBinary(node)
}
}
-internal class DoubleWasmBuilder(target: MST) : WasmBuilder(f64, DoubleField, target) {
- override fun createModule(): BinaryenModule = readBinary(f64StandardFunctions)
+@UnstableKMathAPI
+internal class DoubleWasmBuilder(target: TypedMst) :
+ WasmBuilder(f64, DoubleField, target) {
+ override val instance by lazy {
+ object : DoubleExpression {
+ override val indexer = SimpleSymbolIndexer(keys)
- override fun visitNumeric(mst: Numeric): ExpressionRef = ctx.f64.const(mst.value)
-
- override fun visitUnary(mst: Unary): ExpressionRef = when (mst.operation) {
- GroupOps.MINUS_OPERATION -> ctx.f64.neg(visit(mst.value))
- GroupOps.PLUS_OPERATION -> visit(mst.value)
- PowerOperations.SQRT_OPERATION -> ctx.f64.sqrt(visit(mst.value))
- TrigonometricOperations.SIN_OPERATION -> ctx.call("sin", arrayOf(visit(mst.value)), f64)
- TrigonometricOperations.COS_OPERATION -> ctx.call("cos", arrayOf(visit(mst.value)), f64)
- TrigonometricOperations.TAN_OPERATION -> ctx.call("tan", arrayOf(visit(mst.value)), f64)
- TrigonometricOperations.ASIN_OPERATION -> ctx.call("asin", arrayOf(visit(mst.value)), f64)
- TrigonometricOperations.ACOS_OPERATION -> ctx.call("acos", arrayOf(visit(mst.value)), f64)
- TrigonometricOperations.ATAN_OPERATION -> ctx.call("atan", arrayOf(visit(mst.value)), f64)
- ExponentialOperations.SINH_OPERATION -> ctx.call("sinh", arrayOf(visit(mst.value)), f64)
- ExponentialOperations.COSH_OPERATION -> ctx.call("cosh", arrayOf(visit(mst.value)), f64)
- ExponentialOperations.TANH_OPERATION -> ctx.call("tanh", arrayOf(visit(mst.value)), f64)
- ExponentialOperations.ASINH_OPERATION -> ctx.call("asinh", arrayOf(visit(mst.value)), f64)
- ExponentialOperations.ACOSH_OPERATION -> ctx.call("acosh", arrayOf(visit(mst.value)), f64)
- ExponentialOperations.ATANH_OPERATION -> ctx.call("atanh", arrayOf(visit(mst.value)), f64)
- ExponentialOperations.EXP_OPERATION -> ctx.call("exp", arrayOf(visit(mst.value)), f64)
- ExponentialOperations.LN_OPERATION -> ctx.call("log", arrayOf(visit(mst.value)), f64)
- else -> super.visitUnary(mst)
+ override fun invoke(arguments: DoubleArray) = spreader(executable, arguments).unsafeCast()
+ }
}
- override fun visitBinary(mst: Binary): ExpressionRef = when (mst.operation) {
+ override fun createModule() = readBinary(f64StandardFunctions)
+
+ override fun visitNumber(number: Number) = ctx.f64.const(number.toDouble())
+
+ override fun visitUnary(node: TypedMst.Unary): ExpressionRef = when (node.operation) {
+ GroupOps.MINUS_OPERATION -> ctx.f64.neg(visit(node.value))
+ GroupOps.PLUS_OPERATION -> visit(node.value)
+ PowerOperations.SQRT_OPERATION -> ctx.f64.sqrt(visit(node.value))
+ TrigonometricOperations.SIN_OPERATION -> ctx.call("sin", arrayOf(visit(node.value)), f64)
+ TrigonometricOperations.COS_OPERATION -> ctx.call("cos", arrayOf(visit(node.value)), f64)
+ TrigonometricOperations.TAN_OPERATION -> ctx.call("tan", arrayOf(visit(node.value)), f64)
+ TrigonometricOperations.ASIN_OPERATION -> ctx.call("asin", arrayOf(visit(node.value)), f64)
+ TrigonometricOperations.ACOS_OPERATION -> ctx.call("acos", arrayOf(visit(node.value)), f64)
+ TrigonometricOperations.ATAN_OPERATION -> ctx.call("atan", arrayOf(visit(node.value)), f64)
+ ExponentialOperations.SINH_OPERATION -> ctx.call("sinh", arrayOf(visit(node.value)), f64)
+ ExponentialOperations.COSH_OPERATION -> ctx.call("cosh", arrayOf(visit(node.value)), f64)
+ ExponentialOperations.TANH_OPERATION -> ctx.call("tanh", arrayOf(visit(node.value)), f64)
+ ExponentialOperations.ASINH_OPERATION -> ctx.call("asinh", arrayOf(visit(node.value)), f64)
+ ExponentialOperations.ACOSH_OPERATION -> ctx.call("acosh", arrayOf(visit(node.value)), f64)
+ ExponentialOperations.ATANH_OPERATION -> ctx.call("atanh", arrayOf(visit(node.value)), f64)
+ ExponentialOperations.EXP_OPERATION -> ctx.call("exp", arrayOf(visit(node.value)), f64)
+ ExponentialOperations.LN_OPERATION -> ctx.call("log", arrayOf(visit(node.value)), f64)
+ else -> super.visitUnary(node)
+ }
+
+ override fun visitBinary(mst: TypedMst.Binary): ExpressionRef = when (mst.operation) {
GroupOps.PLUS_OPERATION -> ctx.f64.add(visit(mst.left), visit(mst.right))
GroupOps.MINUS_OPERATION -> ctx.f64.sub(visit(mst.left), visit(mst.right))
RingOps.TIMES_OPERATION -> ctx.f64.mul(visit(mst.left), visit(mst.right))
@@ -138,16 +130,25 @@ internal class DoubleWasmBuilder(target: MST) : WasmBuilder(f64, DoubleF
}
}
-internal class IntWasmBuilder(target: MST) : WasmBuilder(i32, IntRing, target) {
- override fun visitNumeric(mst: Numeric): ExpressionRef = ctx.i32.const(mst.value)
+@UnstableKMathAPI
+internal class IntWasmBuilder(target: TypedMst) : WasmBuilder(i32, IntRing, target) {
+ override val instance by lazy {
+ object : IntExpression {
+ override val indexer = SimpleSymbolIndexer(keys)
- override fun visitUnary(mst: Unary): ExpressionRef = when (mst.operation) {
- GroupOps.MINUS_OPERATION -> ctx.i32.sub(ctx.i32.const(0), visit(mst.value))
- GroupOps.PLUS_OPERATION -> visit(mst.value)
- else -> super.visitUnary(mst)
+ override fun invoke(arguments: IntArray) = spreader(executable, arguments).unsafeCast()
+ }
}
- override fun visitBinary(mst: Binary): ExpressionRef = when (mst.operation) {
+ override fun visitNumber(number: Number) = ctx.i32.const(number.toInt())
+
+ override fun visitUnary(node: TypedMst.Unary): ExpressionRef = when (node.operation) {
+ GroupOps.MINUS_OPERATION -> ctx.i32.sub(ctx.i32.const(0), visit(node.value))
+ GroupOps.PLUS_OPERATION -> visit(node.value)
+ else -> super.visitUnary(node)
+ }
+
+ override fun visitBinary(mst: TypedMst.Binary): ExpressionRef = when (mst.operation) {
GroupOps.PLUS_OPERATION -> ctx.i32.add(visit(mst.left), visit(mst.right))
GroupOps.MINUS_OPERATION -> ctx.i32.sub(visit(mst.left), visit(mst.right))
RingOps.TIMES_OPERATION -> ctx.i32.mul(visit(mst.left), visit(mst.right))
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt
index fe9c22c18..21a88b5d0 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.wasm.internal
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt
index 5b28b8782..f9540f9db 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt
@@ -1,47 +1,37 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
+@file:Suppress("UNUSED_PARAMETER")
+
package space.kscience.kmath.wasm
-import space.kscience.kmath.estree.compileWith
-import space.kscience.kmath.expressions.Expression
-import space.kscience.kmath.expressions.MST
-import space.kscience.kmath.expressions.Symbol
-import space.kscience.kmath.expressions.invoke
+import space.kscience.kmath.ast.TypedMst
+import space.kscience.kmath.ast.evaluateConstants
+import space.kscience.kmath.expressions.*
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.wasm.internal.DoubleWasmBuilder
import space.kscience.kmath.wasm.internal.IntWasmBuilder
-/**
- * Compiles an [MST] to WASM in the context of reals.
- *
- * @author Iaroslav Postovalov
- */
-@UnstableKMathAPI
-public fun DoubleField.expression(mst: MST): Expression =
- DoubleWasmBuilder(mst).instance
-
-/**
- * Compiles an [MST] to WASM in the context of integers.
- *
- * @author Iaroslav Postovalov
- */
-@UnstableKMathAPI
-public fun IntRing.expression(mst: MST): Expression =
- IntWasmBuilder(mst).instance
-
/**
* Create a compiled expression with given [MST] and given [algebra].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
-public fun MST.compileToExpression(algebra: IntRing): Expression = compileWith(algebra)
+public fun MST.compileToExpression(algebra: IntRing): IntExpression {
+ val typed = evaluateConstants(algebra)
+ return if (typed is TypedMst.Constant) object : IntExpression {
+ override val indexer = SimpleSymbolIndexer(emptyList())
+
+ override fun invoke(arguments: IntArray): Int = typed.value
+ } else
+ IntWasmBuilder(typed).instance
+}
/**
* Compile given MST to expression and evaluate it against [arguments].
@@ -50,7 +40,7 @@ public fun MST.compileToExpression(algebra: IntRing): Expression = compileW
*/
@UnstableKMathAPI
public fun MST.compile(algebra: IntRing, arguments: Map): Int =
- compileToExpression(algebra).invoke(arguments)
+ compileToExpression(algebra)(arguments)
/**
@@ -68,7 +58,16 @@ public fun MST.compile(algebra: IntRing, vararg arguments: Pair): I
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
-public fun MST.compileToExpression(algebra: DoubleField): Expression = compileWith(algebra)
+public fun MST.compileToExpression(algebra: DoubleField): Expression {
+ val typed = evaluateConstants(algebra)
+
+ return if (typed is TypedMst.Constant) object : DoubleExpression {
+ override val indexer = SimpleSymbolIndexer(emptyList())
+
+ override fun invoke(arguments: DoubleArray): Double = typed.value
+ } else
+ DoubleWasmBuilder(typed).instance
+}
/**
@@ -78,7 +77,7 @@ public fun MST.compileToExpression(algebra: DoubleField): Expression = c
*/
@UnstableKMathAPI
public fun MST.compile(algebra: DoubleField, arguments: Map): Double =
- compileToExpression(algebra).invoke(arguments)
+ compileToExpression(algebra)(arguments)
/**
@@ -88,4 +87,4 @@ public fun MST.compile(algebra: DoubleField, arguments: Map): Do
*/
@UnstableKMathAPI
public fun MST.compile(algebra: DoubleField, vararg arguments: Pair): Double =
- compileToExpression(algebra).invoke(*arguments)
+ compileToExpression(algebra)(*arguments)
diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt
deleted file mode 100644
index f8c429d5a..000000000
--- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
- */
-
-package space.kscience.kmath.ast
-
-import space.kscience.kmath.expressions.*
-import space.kscience.kmath.operations.DoubleField
-import space.kscience.kmath.operations.bindSymbol
-import space.kscience.kmath.operations.invoke
-import kotlin.math.sin
-import kotlin.random.Random
-import kotlin.test.Ignore
-import kotlin.test.Test
-import kotlin.time.measureTime
-import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
-import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
-
-// TODO move to benchmarks when https://github.com/Kotlin/kotlinx-benchmark/pull/38 or similar feature is merged
-@Ignore
-internal class TestExecutionTime {
- private companion object {
- private const val times = 1_000_000
- private val x by symbol
- private val algebra = DoubleField
-
- private val functional = algebra.expressionInExtendedField {
- bindSymbol(x) * const(2.0) + const(2.0) / bindSymbol(x) - const(16.0) / sin(bindSymbol(x))
- }
-
- private val node = MstExtendedField {
- x * number(2.0) + number(2.0) / x - number(16.0) / sin(x)
- }
-
- private val mst = node.toExpression(algebra)
- private val wasm = node.wasmCompileToExpression(algebra)
- private val estree = node.estreeCompileToExpression(algebra)
-
- // In JavaScript, the expression below is implemented like
- // _no_name_provided__125.prototype.invoke_178 = function (args) {
- // var tmp = getValue(args, raw$_get_x__3(this._$x$delegate_2)) * 2.0 + 2.0 / getValue(args, raw$_get_x__3(this._$x$delegate_2));
- // var tmp0_sin_0_5 = getValue(args, raw$_get_x__3(this._$x$delegate_2));
- // return tmp - 16.0 / Math.sin(tmp0_sin_0_5);
- // };
-
- private val raw = Expression { args ->
- val x = args[x]!!
- algebra { x * 2.0 + 2.0 / x - 16.0 / sin(x) }
- }
-
- private val justCalculate = { args: dynamic ->
- val x = args[x].unsafeCast()
- x * 2.0 + 2.0 / x - 16.0 / sin(x)
- }
- }
-
- private fun invokeAndSum(name: String, expr: Expression) {
- println(name)
- val rng = Random(0)
- var sum = 0.0
- measureTime {
- repeat(times) { sum += expr(x to rng.nextDouble()) }
- }.also(::println)
- }
-
- /**
- * [Expression] created with [expressionInExtendedField].
- */
- @Test
- fun functionalExpression() = invokeAndSum("functional", functional)
-
- /**
- * [Expression] created with [mstExpression].
- */
- @Test
- fun mstExpression() = invokeAndSum("mst", mst)
-
- /**
- * [Expression] created with [wasmCompileToExpression].
- */
- @Test
- fun wasmExpression() = invokeAndSum("wasm", wasm)
-
- /**
- * [Expression] created with [estreeCompileToExpression].
- */
- @Test
- fun estreeExpression() = invokeAndSum("estree", wasm)
-
- /**
- * [Expression] implemented manually with `kotlin.math`.
- */
- @Test
- fun rawExpression() = invokeAndSum("raw", raw)
-
- /**
- * Direct computation w/o [Expression].
- */
- @Test
- fun justCalculateExpression() {
- println("justCalculate")
- val rng = Random(0)
- var sum = 0.0
- measureTime {
- repeat(times) {
- val arg = rng.nextDouble()
- val o = js("{}")
- o["x"] = arg
- sum += justCalculate(o)
- }
- }.also(::println)
- }
-}
diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt
index 3c2a9bd13..0d896c6f6 100644
--- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt
+++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt
index 6c91df866..8ae5fcb36 100644
--- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt
+++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.wasm
diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt
index 2426d6ee4..73b9c97a7 100644
--- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt
+++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt
@@ -1,20 +1,21 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
+@file:Suppress("UNUSED_PARAMETER")
+
package space.kscience.kmath.asm
-import space.kscience.kmath.asm.internal.AsmBuilder
-import space.kscience.kmath.asm.internal.buildName
-import space.kscience.kmath.expressions.Expression
-import space.kscience.kmath.expressions.MST
-import space.kscience.kmath.expressions.MST.*
-import space.kscience.kmath.expressions.Symbol
-import space.kscience.kmath.expressions.invoke
+import space.kscience.kmath.asm.internal.*
+import space.kscience.kmath.ast.TypedMst
+import space.kscience.kmath.ast.evaluateConstants
+import space.kscience.kmath.expressions.*
+import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Algebra
-import space.kscience.kmath.operations.NumericAlgebra
-import space.kscience.kmath.operations.bindSymbolOrNull
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.operations.IntRing
+import space.kscience.kmath.operations.LongRing
/**
* Compiles given MST to an Expression using AST compiler.
@@ -24,73 +25,171 @@ import space.kscience.kmath.operations.bindSymbolOrNull
* @return the compiled expression.
* @author Alexander Nozik
*/
+@OptIn(UnstableKMathAPI::class)
@PublishedApi
internal fun MST.compileWith(type: Class, algebra: Algebra): Expression {
- fun AsmBuilder.visit(node: MST): Unit = when (node) {
- is Symbol -> {
- val symbol = algebra.bindSymbolOrNull(node)
+ val typed = evaluateConstants(algebra)
+ if (typed is TypedMst.Constant) return Expression { typed.value }
- if (symbol != null)
- loadObjectConstant(symbol as Any)
- else
- loadVariable(node.identity)
+ fun GenericAsmBuilder.variablesVisitor(node: TypedMst): Unit = when (node) {
+ is TypedMst.Unary -> variablesVisitor(node.value)
+
+ is TypedMst.Binary -> {
+ variablesVisitor(node.left)
+ variablesVisitor(node.right)
}
- is Numeric -> loadNumberConstant(node.value)
+ is TypedMst.Variable -> prepareVariable(node.symbol)
+ is TypedMst.Constant -> Unit
+ }
- is Unary -> when {
- algebra is NumericAlgebra && node.value is Numeric -> loadObjectConstant(
- algebra.unaryOperationFunction(node.operation)(algebra.number((node.value as Numeric).value)))
+ fun GenericAsmBuilder.expressionVisitor(node: TypedMst): Unit = when (node) {
+ is TypedMst.Constant -> if (node.number != null)
+ loadNumberConstant(node.number)
+ else
+ loadObjectConstant(node.value)
- else -> buildCall(algebra.unaryOperationFunction(node.operation)) { visit(node.value) }
- }
+ is TypedMst.Variable -> loadVariable(node.symbol)
+ is TypedMst.Unary -> buildCall(node.function) { expressionVisitor(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 as Numeric).value),
- algebra.number((node.right as Numeric).value)
- )
- )
-
- algebra is NumericAlgebra && node.left is Numeric -> buildCall(
- algebra.leftSideNumberOperationFunction(node.operation)) {
- visit(node.left)
- visit(node.right)
- }
-
- algebra is NumericAlgebra && node.right is Numeric -> buildCall(
- algebra.rightSideNumberOperationFunction(node.operation)) {
- visit(node.left)
- visit(node.right)
- }
-
- else -> buildCall(algebra.binaryOperationFunction(node.operation)) {
- visit(node.left)
- visit(node.right)
- }
+ is TypedMst.Binary -> buildCall(node.function) {
+ expressionVisitor(node.left)
+ expressionVisitor(node.right)
}
}
- return AsmBuilder(type, buildName(this)) { visit(this@compileWith) }.instance
+ return GenericAsmBuilder(
+ type,
+ buildName("${typed.hashCode()}_${type.simpleName}"),
+ { variablesVisitor(typed) },
+ { expressionVisitor(typed) },
+ ).instance
}
-
/**
* Create a compiled expression with given [MST] and given [algebra].
*/
public inline fun MST.compileToExpression(algebra: Algebra): Expression =
compileWith(T::class.java, algebra)
-
/**
* Compile given MST to expression and evaluate it against [arguments]
*/
public inline fun MST.compile(algebra: Algebra, arguments: Map): T =
- compileToExpression(algebra).invoke(arguments)
+ compileToExpression(algebra)(arguments)
/**
* Compile given MST to expression and evaluate it against [arguments]
*/
public inline fun MST.compile(algebra: Algebra, vararg arguments: Pair): T =
- compileToExpression(algebra).invoke(*arguments)
+ compileToExpression(algebra)(*arguments)
+
+
+/**
+ * Create a compiled expression with given [MST] and given [algebra].
+ *
+ * @author Iaroslav Postovalov
+ */
+@UnstableKMathAPI
+public fun MST.compileToExpression(algebra: IntRing): IntExpression {
+ val typed = evaluateConstants(algebra)
+
+ return if (typed is TypedMst.Constant) object : IntExpression {
+ override val indexer = SimpleSymbolIndexer(emptyList())
+
+ override fun invoke(arguments: IntArray): Int = typed.value
+ } else
+ IntAsmBuilder(typed).instance
+}
+
+/**
+ * Compile given MST to expression and evaluate it against [arguments].
+ *
+ * @author Iaroslav Postovalov
+ */
+@UnstableKMathAPI
+public fun MST.compile(algebra: IntRing, arguments: Map): Int =
+ compileToExpression(algebra)(arguments)
+
+/**
+ * Compile given MST to expression and evaluate it against [arguments].
+ *
+ * @author Iaroslav Postovalov
+ */
+@UnstableKMathAPI
+public fun MST.compile(algebra: IntRing, vararg arguments: Pair): Int =
+ compileToExpression(algebra)(*arguments)
+
+
+/**
+ * Create a compiled expression with given [MST] and given [algebra].
+ *
+ * @author Iaroslav Postovalov
+ */
+@UnstableKMathAPI
+public fun MST.compileToExpression(algebra: LongRing): LongExpression {
+ val typed = evaluateConstants(algebra)
+
+ return if (typed is TypedMst.Constant) object : LongExpression {
+ override val indexer = SimpleSymbolIndexer(emptyList())
+
+ override fun invoke(arguments: LongArray): Long = typed.value
+ } else
+ LongAsmBuilder(typed).instance
+}
+
+/**
+ * Compile given MST to expression and evaluate it against [arguments].
+ *
+ * @author Iaroslav Postovalov
+ */
+@UnstableKMathAPI
+public fun MST.compile(algebra: LongRing, arguments: Map): Long =
+ compileToExpression(algebra)(arguments)
+
+
+/**
+ * Compile given MST to expression and evaluate it against [arguments].
+ *
+ * @author Iaroslav Postovalov
+ */
+@UnstableKMathAPI
+public fun MST.compile(algebra: LongRing, vararg arguments: Pair): Long =
+ compileToExpression(algebra)(*arguments)
+
+
+/**
+ * Create a compiled expression with given [MST] and given [algebra].
+ *
+ * @author Iaroslav Postovalov
+ */
+@UnstableKMathAPI
+public fun MST.compileToExpression(algebra: DoubleField): DoubleExpression {
+ val typed = evaluateConstants(algebra)
+
+ return if (typed is TypedMst.Constant) object : DoubleExpression {
+ override val indexer = SimpleSymbolIndexer(emptyList())
+
+ override fun invoke(arguments: DoubleArray): Double = typed.value
+ } else
+ DoubleAsmBuilder(typed).instance
+}
+
+
+/**
+ * Compile given MST to expression and evaluate it against [arguments].
+ *
+ * @author Iaroslav Postovalov
+ */
+@UnstableKMathAPI
+public fun MST.compile(algebra: DoubleField, arguments: Map): Double =
+ compileToExpression(algebra)(arguments)
+
+/**
+ * Compile given MST to expression and evaluate it against [arguments].
+ *
+ * @author Iaroslav Postovalov
+ */
+@UnstableKMathAPI
+public fun MST.compile(algebra: DoubleField, vararg arguments: Pair): Double =
+ compileToExpression(algebra)(*arguments)
diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt
index 418d6141b..a85079fc8 100644
--- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt
+++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt
@@ -1,354 +1,53 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.asm.internal
-import org.objectweb.asm.*
-import org.objectweb.asm.Opcodes.*
-import org.objectweb.asm.Type.*
-import org.objectweb.asm.commons.InstructionAdapter
-import space.kscience.kmath.asm.internal.AsmBuilder.ClassLoader
+import org.objectweb.asm.Type
+import org.objectweb.asm.Type.getObjectType
import space.kscience.kmath.expressions.Expression
-import space.kscience.kmath.expressions.MST
-import java.lang.invoke.MethodHandles
-import java.lang.invoke.MethodType
-import java.nio.file.Paths
-import java.util.stream.Collectors.toMap
-import kotlin.contracts.InvocationKind
-import kotlin.contracts.contract
-import kotlin.io.path.writeBytes
-/**
- * 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 className the unique class name of new loaded class.
- * @property callbackAtInvokeL0 the function to apply to this object when generating invoke method, label 0.
- * @author Iaroslav Postovalov
- */
-internal class AsmBuilder(
- classOfT: Class<*>,
- private val className: String,
- private val callbackAtInvokeL0: AsmBuilder.() -> Unit,
-) {
+internal abstract class AsmBuilder {
/**
- * Internal classloader of [AsmBuilder] with alias to define class from byte array.
+ * Internal classloader with alias to define class from byte array.
*/
- private class ClassLoader(parent: java.lang.ClassLoader) : java.lang.ClassLoader(parent) {
+ class ByteArrayClassLoader(parent: ClassLoader) : ClassLoader(parent) {
fun defineClass(name: String?, b: ByteArray): Class<*> = defineClass(name, b, 0, b.size)
}
- /**
- * The instance of [ClassLoader] used by this builder.
- */
- private val classLoader: ClassLoader = ClassLoader(javaClass.classLoader)
-
- /**
- * ASM type for [T].
- */
- private val tType: Type = classOfT.asm
-
- /**
- * ASM type for new class.
- */
- private val classType: Type = getObjectType(className.replace(oldChar = '.', newChar = '/'))
-
- /**
- * List of constants to provide to the subclass.
- */
- private val constants: MutableList = mutableListOf()
-
- /**
- * Method visitor of `invoke` method of the subclass.
- */
- private lateinit var invokeMethodVisitor: InstructionAdapter
-
- /**
- * Subclasses, loads and instantiates [Expression] for given parameters.
- *
- * The built instance is cached.
- */
- @Suppress("UNCHECKED_CAST")
- val instance: Expression by lazy {
- val hasConstants: Boolean
-
- val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) {
- visit(
- V1_8,
- ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
- classType.internalName,
- "${OBJECT_TYPE.descriptor}L${EXPRESSION_TYPE.internalName}<${tType.descriptor}>;",
- OBJECT_TYPE.internalName,
- arrayOf(EXPRESSION_TYPE.internalName),
- )
-
- visitMethod(
- ACC_PUBLIC or ACC_FINAL,
- "invoke",
- getMethodDescriptor(tType, MAP_TYPE),
- "(L${MAP_TYPE.internalName}<${SYMBOL_TYPE.descriptor}+${tType.descriptor}>;)${tType.descriptor}",
- null,
- ).instructionAdapter {
- invokeMethodVisitor = this
- visitCode()
- val l0 = label()
- callbackAtInvokeL0()
- areturn(tType)
- val l1 = label()
-
- visitLocalVariable(
- "this",
- classType.descriptor,
- null,
- l0,
- l1,
- 0,
- )
-
- visitLocalVariable(
- "arguments",
- MAP_TYPE.descriptor,
- "L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;",
- l0,
- l1,
- 1,
- )
-
- visitMaxs(0, 2)
- visitEnd()
- }
-
- visitMethod(
- ACC_PUBLIC or ACC_FINAL or ACC_BRIDGE or ACC_SYNTHETIC,
- "invoke",
- getMethodDescriptor(OBJECT_TYPE, MAP_TYPE),
- null,
- null,
- ).instructionAdapter {
- visitCode()
- val l0 = label()
- load(0, OBJECT_TYPE)
- load(1, MAP_TYPE)
- invokevirtual(classType.internalName, "invoke", getMethodDescriptor(tType, MAP_TYPE), false)
- areturn(tType)
- val l1 = label()
-
- visitLocalVariable(
- "this",
- classType.descriptor,
- null,
- l0,
- l1,
- 0,
- )
-
- visitMaxs(0, 2)
- visitEnd()
- }
-
- hasConstants = constants.isNotEmpty()
-
- if (hasConstants)
- visitField(
- access = ACC_PRIVATE or ACC_FINAL,
- name = "constants",
- descriptor = OBJECT_ARRAY_TYPE.descriptor,
- signature = null,
- value = null,
- block = FieldVisitor::visitEnd,
- )
-
- visitMethod(
- ACC_PUBLIC,
- "",
- getMethodDescriptor(VOID_TYPE, *OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }),
- null,
- null,
- ).instructionAdapter {
- val l0 = label()
- load(0, classType)
- invokespecial(OBJECT_TYPE.internalName, "", getMethodDescriptor(VOID_TYPE), false)
- label()
- load(0, classType)
-
- if (hasConstants) {
- label()
- 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, 0)
-
- if (hasConstants)
- visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l4, 1)
-
- visitMaxs(0, 3)
- visitEnd()
- }
-
- visitEnd()
- }
-
- val binary = classWriter.toByteArray()
- val cls = classLoader.defineClass(className, binary)
-
- if (System.getProperty("space.kscience.communicator.prettyapi.dump.generated.classes") == "1")
- Paths.get("$className.class").writeBytes(binary)
-
- val l = MethodHandles.publicLookup()
-
- (if (hasConstants)
- l.findConstructor(cls, MethodType.methodType(Void.TYPE, Array::class.java))(constants.toTypedArray())
- else
- l.findConstructor(cls, MethodType.methodType(Void.TYPE))()) as Expression
- }
-
- /**
- * Loads [java.lang.Object] constant from constants.
- */
- 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
- invokeMethodVisitor.load(0, classType)
- getfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
- iconst(idx)
- visitInsn(AALOAD)
- if (type != OBJECT_TYPE) checkcast(type)
- }
-
- /**
- * 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) {
- 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())
- }
-
- val r = PRIMITIVES_TO_BOXED.getValue(primitive)
-
- invokeMethodVisitor.invokestatic(
- r.internalName,
- "valueOf",
- getMethodDescriptor(r, primitive),
- false,
- )
-
- return
- }
-
- loadObjectConstant(value, boxed)
- }
-
- /**
- * Loads a variable [name] from arguments [Map] parameter of [Expression.invoke].
- */
- fun loadVariable(name: String): Unit = invokeMethodVisitor.run {
- load(1, MAP_TYPE)
- aconst(name)
-
- invokestatic(
- MAP_INTRINSICS_TYPE.internalName,
- "getOrFail",
- getMethodDescriptor(OBJECT_TYPE, MAP_TYPE, STRING_TYPE),
- false,
- )
-
- checkcast(tType)
- }
-
- inline fun buildCall(function: Function, parameters: AsmBuilder.() -> Unit) {
- contract { callsInPlace(parameters, InvocationKind.EXACTLY_ONCE) }
- 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")
-
- val type = getType(`interface`)
- loadObjectConstant(function, type)
- parameters(this)
-
- invokeMethodVisitor.invokeinterface(
- type.internalName,
- "invoke",
- getMethodDescriptor(OBJECT_TYPE, *Array(arity) { OBJECT_TYPE }),
- )
-
- invokeMethodVisitor.checkcast(tType)
- }
-
- companion object {
- /**
- * Maps JVM primitive numbers boxed ASM types to their primitive ASM types.
- */
- 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),
- )
- }
+ protected val classLoader = ByteArrayClassLoader(javaClass.classLoader)
+ protected companion object {
/**
* ASM type for [Expression].
*/
- val EXPRESSION_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Expression") }
+ val EXPRESSION_TYPE: Type = getObjectType("space/kscience/kmath/expressions/Expression")
/**
* ASM type for [java.util.Map].
*/
- val MAP_TYPE: Type by lazy { getObjectType("java/util/Map") }
+ val MAP_TYPE: Type = getObjectType("java/util/Map")
/**
* ASM type for [java.lang.Object].
*/
- val OBJECT_TYPE: Type by lazy { getObjectType("java/lang/Object") }
-
- /**
- * ASM type for array of [java.lang.Object].
- */
- val OBJECT_ARRAY_TYPE: Type by lazy { getType("[Ljava/lang/Object;") }
+ val OBJECT_TYPE: Type = getObjectType("java/lang/Object")
/**
* ASM type for [java.lang.String].
*/
- val STRING_TYPE: Type by lazy { getObjectType("java/lang/String") }
+ val STRING_TYPE: Type = getObjectType("java/lang/String")
/**
* ASM type for MapIntrinsics.
*/
- val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") }
+ val MAP_INTRINSICS_TYPE: Type = getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics")
/**
* ASM Type for [space.kscience.kmath.expressions.Symbol].
*/
- val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") }
+ val SYMBOL_TYPE: Type = getObjectType("space/kscience/kmath/expressions/Symbol")
}
}
diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt
new file mode 100644
index 000000000..6cf3d8721
--- /dev/null
+++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.asm.internal
+
+import org.objectweb.asm.*
+import org.objectweb.asm.Opcodes.*
+import org.objectweb.asm.Type.*
+import org.objectweb.asm.commons.InstructionAdapter
+import space.kscience.kmath.expressions.*
+import java.lang.invoke.MethodHandles
+import java.lang.invoke.MethodType
+import java.nio.file.Paths
+import java.util.stream.Collectors.toMap
+import kotlin.contracts.InvocationKind
+import kotlin.contracts.contract
+import kotlin.io.path.writeBytes
+
+/**
+ * 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 className the unique class name of new loaded class.
+ * @property expressionResultCallback the function to apply to this object when generating expression value.
+ * @author Iaroslav Postovalov
+ */
+internal class GenericAsmBuilder(
+ classOfT: Class<*>,
+ private val className: String,
+ private val variablesPrepareCallback: GenericAsmBuilder.() -> Unit,
+ private val expressionResultCallback: GenericAsmBuilder.() -> Unit,
+) : AsmBuilder() {
+ /**
+ * ASM type for [T].
+ */
+ private val tType: Type = classOfT.asm
+
+ /**
+ * ASM type for new class.
+ */
+ private val classType: Type = getObjectType(className.replace(oldChar = '.', newChar = '/'))
+
+ /**
+ * List of constants to provide to the subclass.
+ */
+ private val constants = mutableListOf()
+
+ /**
+ * Method visitor of `invoke` method of the subclass.
+ */
+ private lateinit var invokeMethodVisitor: InstructionAdapter
+
+ /**
+ * Local variables indices are indices of symbols in this list.
+ */
+ private val argumentsLocals = mutableListOf()
+
+ /**
+ * Subclasses, loads and instantiates [Expression] for given parameters.
+ *
+ * The built instance is cached.
+ */
+ @Suppress("UNCHECKED_CAST", "UNUSED_VARIABLE")
+ val instance: Expression by lazy {
+ val hasConstants: Boolean
+
+ val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) {
+ visit(
+ V1_8,
+ ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
+ classType.internalName,
+ "${OBJECT_TYPE.descriptor}L${EXPRESSION_TYPE.internalName}<${tType.descriptor}>;",
+ OBJECT_TYPE.internalName,
+ arrayOf(EXPRESSION_TYPE.internalName),
+ )
+
+ visitMethod(
+ ACC_PUBLIC,
+ "invoke",
+ getMethodDescriptor(tType, MAP_TYPE),
+ "(L${MAP_TYPE.internalName}<${SYMBOL_TYPE.descriptor}+${tType.descriptor}>;)${tType.descriptor}",
+ null,
+ ).instructionAdapter {
+ invokeMethodVisitor = this
+ visitCode()
+ val preparingVariables = label()
+ variablesPrepareCallback()
+ val expressionResult = label()
+ expressionResultCallback()
+ areturn(tType)
+ val end = label()
+
+ visitLocalVariable(
+ "this",
+ classType.descriptor,
+ null,
+ preparingVariables,
+ end,
+ 0,
+ )
+
+ visitLocalVariable(
+ "arguments",
+ MAP_TYPE.descriptor,
+ "L${MAP_TYPE.internalName}<${SYMBOL_TYPE.descriptor}+${tType.descriptor}>;",
+ preparingVariables,
+ end,
+ 1,
+ )
+
+ visitMaxs(0, 0)
+ visitEnd()
+ }
+
+ visitMethod(
+ ACC_PUBLIC or ACC_BRIDGE or ACC_SYNTHETIC,
+ "invoke",
+ getMethodDescriptor(OBJECT_TYPE, MAP_TYPE),
+ null,
+ null,
+ ).instructionAdapter {
+ visitCode()
+ val start = label()
+ load(0, OBJECT_TYPE)
+ load(1, MAP_TYPE)
+ invokevirtual(classType.internalName, "invoke", getMethodDescriptor(tType, MAP_TYPE), false)
+ areturn(tType)
+ val end = label()
+
+ visitLocalVariable(
+ "this",
+ classType.descriptor,
+ null,
+ start,
+ end,
+ 0,
+ )
+
+ visitMaxs(0, 0)
+ visitEnd()
+ }
+
+ hasConstants = constants.isNotEmpty()
+
+ if (hasConstants)
+ visitField(
+ access = ACC_PRIVATE or ACC_FINAL,
+ name = "constants",
+ descriptor = OBJECT_ARRAY_TYPE.descriptor,
+ signature = null,
+ value = null,
+ block = FieldVisitor::visitEnd,
+ )
+
+ visitMethod(
+ ACC_PUBLIC or ACC_SYNTHETIC,
+ "",
+ getMethodDescriptor(VOID_TYPE, *OBJECT_ARRAY_TYPE.wrapToArrayIf { hasConstants }),
+ null,
+ null,
+ ).instructionAdapter {
+ val l0 = label()
+ load(0, classType)
+ invokespecial(OBJECT_TYPE.internalName, "", getMethodDescriptor(VOID_TYPE), false)
+ label()
+ load(0, classType)
+
+ if (hasConstants) {
+ label()
+ load(0, classType)
+ load(1, OBJECT_ARRAY_TYPE)
+ putfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
+ }
+
+ label()
+ areturn(VOID_TYPE)
+ val l4 = label()
+ visitLocalVariable("this", classType.descriptor, null, l0, l4, 0)
+
+ if (hasConstants)
+ visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l4, 1)
+
+ visitMaxs(0, 0)
+ visitEnd()
+ }
+
+ visitEnd()
+ }
+
+ val binary = classWriter.toByteArray()
+ val cls = classLoader.defineClass(className, binary)
+
+ if (System.getProperty("space.kscience.kmath.ast.dump.generated.classes") == "1")
+ Paths.get("${className.split('.').last()}.class").writeBytes(binary)
+
+ val l = MethodHandles.publicLookup()
+
+ (if (hasConstants)
+ l.findConstructor(cls, MethodType.methodType(Void.TYPE, Array::class.java))(constants.toTypedArray())
+ else
+ l.findConstructor(cls, MethodType.methodType(Void.TYPE))()) as Expression
+ }
+
+ /**
+ * Loads [java.lang.Object] constant from constants.
+ */
+ 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
+ load(0, classType)
+ getfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
+ iconst(idx)
+ aload(OBJECT_TYPE)
+ if (type != OBJECT_TYPE) checkcast(type)
+ }
+
+ /**
+ * 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) {
+ 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())
+ }
+
+ val r = boxed
+
+ invokeMethodVisitor.invokestatic(
+ r.internalName,
+ "valueOf",
+ getMethodDescriptor(r, primitive),
+ false,
+ )
+
+ return
+ }
+
+ loadObjectConstant(value, boxed)
+ }
+
+ /**
+ * Stores value variable [name] into a local. Should be called within [variablesPrepareCallback] before using
+ * [loadVariable].
+ */
+ fun prepareVariable(name: Symbol): Unit = invokeMethodVisitor.run {
+ if (name in argumentsLocals) return@run
+ load(1, MAP_TYPE)
+ aconst(name.identity)
+
+ invokestatic(
+ MAP_INTRINSICS_TYPE.internalName,
+ "getOrFail",
+ getMethodDescriptor(OBJECT_TYPE, MAP_TYPE, STRING_TYPE),
+ false,
+ )
+
+ checkcast(tType)
+ var idx = argumentsLocals.indexOf(name)
+
+ if (idx == -1) {
+ argumentsLocals += name
+ idx = argumentsLocals.lastIndex
+ }
+
+ store(2 + idx, tType)
+ }
+
+ /**
+ * Loads a variable [name] from arguments [Map] parameter of [Expression.invoke]. The variable should be stored
+ * with [prepareVariable] first.
+ */
+ fun loadVariable(name: Symbol): Unit = invokeMethodVisitor.load(2 + argumentsLocals.indexOf(name), tType)
+
+ inline fun buildCall(function: Function, parameters: GenericAsmBuilder.() -> Unit) {
+ contract { callsInPlace(parameters, InvocationKind.EXACTLY_ONCE) }
+ 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")
+
+ val type = getType(`interface`)
+ loadObjectConstant(function, type)
+ parameters(this)
+
+ invokeMethodVisitor.invokeinterface(
+ type.internalName,
+ "invoke",
+ getMethodDescriptor(OBJECT_TYPE, *Array(arity) { OBJECT_TYPE }),
+ )
+
+ invokeMethodVisitor.checkcast(tType)
+ }
+
+ private companion object {
+ /**
+ * Maps JVM primitive numbers boxed ASM types to their primitive ASM types.
+ */
+ 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,
+ )
+ }
+
+ /**
+ * ASM type for array of [java.lang.Object].
+ */
+ val OBJECT_ARRAY_TYPE: Type = getType("[Ljava/lang/Object;")
+ }
+}
diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt
new file mode 100644
index 000000000..01bad83e5
--- /dev/null
+++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.asm.internal
+
+import org.objectweb.asm.ClassWriter
+import org.objectweb.asm.FieldVisitor
+import org.objectweb.asm.Opcodes.*
+import org.objectweb.asm.Type
+import org.objectweb.asm.Type.*
+import org.objectweb.asm.commons.InstructionAdapter
+import space.kscience.kmath.ast.TypedMst
+import space.kscience.kmath.expressions.*
+import space.kscience.kmath.misc.UnstableKMathAPI
+import space.kscience.kmath.operations.*
+import java.lang.invoke.MethodHandles
+import java.lang.invoke.MethodType
+import java.nio.file.Paths
+import kotlin.io.path.writeBytes
+
+@UnstableKMathAPI
+internal sealed class PrimitiveAsmBuilder>(
+ protected val algebra: NumericAlgebra,
+ classOfT: Class<*>,
+ protected val classOfTPrimitive: Class<*>,
+ expressionParent: Class,
+ protected val target: TypedMst,
+) : AsmBuilder() {
+ private val className: String = buildName("${target.hashCode()}_${classOfT.simpleName}")
+
+ /**
+ * ASM type for [tType].
+ */
+ private val tType: Type = classOfT.asm
+
+ /**
+ * ASM type for [classOfTPrimitive].
+ */
+ protected val tTypePrimitive: Type = classOfTPrimitive.asm
+
+ /**
+ * ASM type for array of [classOfTPrimitive].
+ */
+ protected val tTypePrimitiveArray: Type = getType("[" + classOfTPrimitive.asm.descriptor)
+
+ /**
+ * ASM type for expression parent.
+ */
+ private val expressionParentType = expressionParent.asm
+
+ /**
+ * ASM type for new class.
+ */
+ private val classType: Type = getObjectType(className.replace(oldChar = '.', newChar = '/'))
+
+ /**
+ * Method visitor of `invoke` method of the subclass.
+ */
+ protected lateinit var invokeMethodVisitor: InstructionAdapter
+
+ /**
+ * Indexer for arguments in [target].
+ */
+ private val argumentsIndexer = mutableListOf()
+
+ /**
+ * Subclasses, loads and instantiates [Expression] for given parameters.
+ *
+ * The built instance is cached.
+ */
+ @Suppress("UNCHECKED_CAST")
+ val instance: E by lazy {
+ val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) {
+ visit(
+ V1_8,
+ ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
+ classType.internalName,
+ "${OBJECT_TYPE.descriptor}${expressionParentType.descriptor}",
+ OBJECT_TYPE.internalName,
+ arrayOf(expressionParentType.internalName),
+ )
+
+ visitField(
+ access = ACC_PRIVATE or ACC_FINAL,
+ name = "indexer",
+ descriptor = SYMBOL_INDEXER_TYPE.descriptor,
+ signature = null,
+ value = null,
+ block = FieldVisitor::visitEnd,
+ )
+ visitMethod(
+ ACC_PUBLIC,
+ "getIndexer",
+ getMethodDescriptor(SYMBOL_INDEXER_TYPE),
+ null,
+ null,
+ ).instructionAdapter {
+ visitCode()
+ val start = label()
+ load(0, classType)
+ getfield(classType.internalName, "indexer", SYMBOL_INDEXER_TYPE.descriptor)
+ areturn(SYMBOL_INDEXER_TYPE)
+ val end = label()
+
+ visitLocalVariable(
+ "this",
+ classType.descriptor,
+ null,
+ start,
+ end,
+ 0,
+ )
+
+ visitMaxs(0, 0)
+ visitEnd()
+ }
+
+ visitMethod(
+ ACC_PUBLIC,
+ "invoke",
+ getMethodDescriptor(tTypePrimitive, tTypePrimitiveArray),
+ null,
+ null,
+ ).instructionAdapter {
+ invokeMethodVisitor = this
+ visitCode()
+ val start = label()
+ visitVariables(target, arrayMode = true)
+ visitExpression(target)
+ areturn(tTypePrimitive)
+ val end = label()
+
+ visitLocalVariable(
+ "this",
+ classType.descriptor,
+ null,
+ start,
+ end,
+ 0,
+ )
+
+ visitLocalVariable(
+ "arguments",
+ tTypePrimitiveArray.descriptor,
+ null,
+ start,
+ end,
+ 1,
+ )
+
+ visitMaxs(0, 0)
+ visitEnd()
+ }
+
+ visitMethod(
+ ACC_PUBLIC or ACC_FINAL,
+ "invoke",
+ getMethodDescriptor(tType, MAP_TYPE),
+ "(L${MAP_TYPE.internalName}<${SYMBOL_TYPE.descriptor}+${tType.descriptor}>;)${tType.descriptor}",
+ null,
+ ).instructionAdapter {
+ invokeMethodVisitor = this
+ visitCode()
+ val start = label()
+ visitVariables(target, arrayMode = false)
+ visitExpression(target)
+ box()
+ areturn(tType)
+ val end = label()
+
+ visitLocalVariable(
+ "this",
+ classType.descriptor,
+ null,
+ start,
+ end,
+ 0,
+ )
+
+ visitLocalVariable(
+ "arguments",
+ MAP_TYPE.descriptor,
+ "L${MAP_TYPE.internalName}<${SYMBOL_TYPE.descriptor}+${tType.descriptor}>;",
+ start,
+ end,
+ 1,
+ )
+
+ visitMaxs(0, 0)
+ visitEnd()
+ }
+
+ visitMethod(
+ ACC_PUBLIC or ACC_FINAL or ACC_BRIDGE or ACC_SYNTHETIC,
+ "invoke",
+ getMethodDescriptor(OBJECT_TYPE, MAP_TYPE),
+ null,
+ null,
+ ).instructionAdapter {
+ visitCode()
+ val start = label()
+ load(0, OBJECT_TYPE)
+ load(1, MAP_TYPE)
+ invokevirtual(classType.internalName, "invoke", getMethodDescriptor(tType, MAP_TYPE), false)
+ areturn(tType)
+ val end = label()
+
+ visitLocalVariable(
+ "this",
+ classType.descriptor,
+ null,
+ start,
+ end,
+ 0,
+ )
+
+ visitMaxs(0, 0)
+ visitEnd()
+ }
+
+ visitMethod(
+ ACC_PUBLIC or ACC_SYNTHETIC,
+ "",
+ getMethodDescriptor(VOID_TYPE, SYMBOL_INDEXER_TYPE),
+ null,
+ null,
+ ).instructionAdapter {
+ val start = label()
+ load(0, classType)
+ invokespecial(OBJECT_TYPE.internalName, "", getMethodDescriptor(VOID_TYPE), false)
+ load(0, classType)
+ load(1, SYMBOL_INDEXER_TYPE)
+ putfield(classType.internalName, "indexer", SYMBOL_INDEXER_TYPE.descriptor)
+ areturn(VOID_TYPE)
+ val end = label()
+ visitLocalVariable("this", classType.descriptor, null, start, end, 0)
+ visitLocalVariable("indexer", SYMBOL_INDEXER_TYPE.descriptor, null, start, end, 1)
+ visitMaxs(0, 0)
+ visitEnd()
+ }
+
+ visitEnd()
+ }
+
+ val binary = classWriter.toByteArray()
+ val cls = classLoader.defineClass(className, binary)
+
+ if (System.getProperty("space.kscience.kmath.ast.dump.generated.classes") == "1")
+ Paths.get("${className.split('.').last()}.class").writeBytes(binary)
+
+ MethodHandles
+ .publicLookup()
+ .findConstructor(cls, MethodType.methodType(Void.TYPE, SymbolIndexer::class.java))
+ .invoke(SimpleSymbolIndexer(argumentsIndexer)) as E
+ }
+
+ /**
+ * Loads a numeric constant [value] from the class's constants.
+ */
+ protected fun loadNumberConstant(value: Number) {
+ when (tTypePrimitive) {
+ 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())
+ }
+ }
+
+ /**
+ * Stores value variable [name] into a local. Should be called before using [loadVariable]. Should be called only
+ * once for a variable.
+ */
+ protected fun prepareVariable(name: Symbol, arrayMode: Boolean): Unit = invokeMethodVisitor.run {
+ var argumentIndex = argumentsIndexer.indexOf(name)
+
+ if (argumentIndex == -1) {
+ argumentsIndexer += name
+ argumentIndex = argumentsIndexer.lastIndex
+ }
+
+ val localIndex = 2 + argumentIndex * tTypePrimitive.size
+
+ if (arrayMode) {
+ load(1, tTypePrimitiveArray)
+ iconst(argumentIndex)
+ aload(tTypePrimitive)
+ store(localIndex, tTypePrimitive)
+ } else {
+ load(1, MAP_TYPE)
+ aconst(name.identity)
+
+ invokestatic(
+ MAP_INTRINSICS_TYPE.internalName,
+ "getOrFail",
+ getMethodDescriptor(OBJECT_TYPE, MAP_TYPE, STRING_TYPE),
+ false,
+ )
+
+ checkcast(tType)
+ unbox()
+ store(localIndex, tTypePrimitive)
+ }
+ }
+
+ /**
+ * Loads a variable [name] from arguments [Map] parameter of [Expression.invoke]. The variable should be stored
+ * with [prepareVariable] first.
+ */
+ protected fun loadVariable(name: Symbol) {
+ val argumentIndex = argumentsIndexer.indexOf(name)
+ val localIndex = 2 + argumentIndex * tTypePrimitive.size
+ invokeMethodVisitor.load(localIndex, tTypePrimitive)
+ }
+
+ private fun unbox() = invokeMethodVisitor.run {
+ invokevirtual(
+ NUMBER_TYPE.internalName,
+ "${classOfTPrimitive.simpleName}Value",
+ getMethodDescriptor(tTypePrimitive),
+ false
+ )
+ }
+
+ private fun box() = invokeMethodVisitor.run {
+ invokestatic(tType.internalName, "valueOf", getMethodDescriptor(tType, tTypePrimitive), false)
+ }
+
+ private fun visitVariables(
+ node: TypedMst,
+ arrayMode: Boolean,
+ alreadyLoaded: MutableList = mutableListOf()
+ ): Unit = when (node) {
+ is TypedMst.Variable -> if (node.symbol !in alreadyLoaded) {
+ alreadyLoaded += node.symbol
+ prepareVariable(node.symbol, arrayMode)
+ } else Unit
+
+ is TypedMst.Unary -> visitVariables(node.value, arrayMode, alreadyLoaded)
+
+ is TypedMst.Binary -> {
+ visitVariables(node.left, arrayMode, alreadyLoaded)
+ visitVariables(node.right, arrayMode, alreadyLoaded)
+ }
+
+ is TypedMst.Constant -> Unit
+ }
+
+ private fun visitExpression(node: TypedMst): Unit = when (node) {
+ is TypedMst.Variable -> loadVariable(node.symbol)
+
+ is TypedMst.Constant -> loadNumberConstant(
+ node.number ?: error("Object constants are not supported by pritimive ASM builder"),
+ )
+
+ is TypedMst.Unary -> visitUnary(node)
+ is TypedMst.Binary -> visitBinary(node)
+ }
+
+ protected open fun visitUnary(node: TypedMst.Unary) = visitExpression(node.value)
+
+ protected open fun visitBinary(node: TypedMst.Binary) {
+ visitExpression(node.left)
+ visitExpression(node.right)
+ }
+
+ protected companion object {
+ /**
+ * ASM type for [java.lang.Number].
+ */
+ val NUMBER_TYPE: Type = getObjectType("java/lang/Number")
+
+ /**
+ * ASM type for [SymbolIndexer].
+ */
+ val SYMBOL_INDEXER_TYPE: Type = getObjectType("space/kscience/kmath/expressions/SymbolIndexer")
+ }
+}
+
+@UnstableKMathAPI
+internal class DoubleAsmBuilder(target: TypedMst) : PrimitiveAsmBuilder(
+ DoubleField,
+ java.lang.Double::class.java,
+ java.lang.Double.TYPE,
+ DoubleExpression::class.java,
+ target,
+) {
+ private fun buildUnaryJavaMathCall(name: String) = invokeMethodVisitor.invokestatic(
+ MATH_TYPE.internalName,
+ name,
+ getMethodDescriptor(tTypePrimitive, tTypePrimitive),
+ false,
+ )
+
+ @Suppress("SameParameterValue")
+ private fun buildBinaryJavaMathCall(name: String) = invokeMethodVisitor.invokestatic(
+ MATH_TYPE.internalName,
+ name,
+ getMethodDescriptor(tTypePrimitive, tTypePrimitive, tTypePrimitive),
+ false,
+ )
+
+ private fun buildUnaryKotlinMathCall(name: String) = invokeMethodVisitor.invokestatic(
+ MATH_KT_TYPE.internalName,
+ name,
+ getMethodDescriptor(tTypePrimitive, tTypePrimitive),
+ false,
+ )
+
+ override fun visitUnary(node: TypedMst.Unary) {
+ super.visitUnary(node)
+
+ when (node.operation) {
+ GroupOps.MINUS_OPERATION -> invokeMethodVisitor.visitInsn(DNEG)
+ GroupOps.PLUS_OPERATION -> Unit
+ PowerOperations.SQRT_OPERATION -> buildUnaryJavaMathCall("sqrt")
+ TrigonometricOperations.SIN_OPERATION -> buildUnaryJavaMathCall("sin")
+ TrigonometricOperations.COS_OPERATION -> buildUnaryJavaMathCall("cos")
+ TrigonometricOperations.TAN_OPERATION -> buildUnaryJavaMathCall("tan")
+ TrigonometricOperations.ASIN_OPERATION -> buildUnaryJavaMathCall("asin")
+ TrigonometricOperations.ACOS_OPERATION -> buildUnaryJavaMathCall("acos")
+ TrigonometricOperations.ATAN_OPERATION -> buildUnaryJavaMathCall("atan")
+ ExponentialOperations.SINH_OPERATION -> buildUnaryJavaMathCall("sqrt")
+ ExponentialOperations.COSH_OPERATION -> buildUnaryJavaMathCall("cosh")
+ ExponentialOperations.TANH_OPERATION -> buildUnaryJavaMathCall("tanh")
+ ExponentialOperations.ASINH_OPERATION -> buildUnaryKotlinMathCall("asinh")
+ ExponentialOperations.ACOSH_OPERATION -> buildUnaryKotlinMathCall("acosh")
+ ExponentialOperations.ATANH_OPERATION -> buildUnaryKotlinMathCall("atanh")
+ ExponentialOperations.EXP_OPERATION -> buildUnaryJavaMathCall("exp")
+ ExponentialOperations.LN_OPERATION -> buildUnaryJavaMathCall("log")
+ else -> super.visitUnary(node)
+ }
+ }
+
+ override fun visitBinary(node: TypedMst.Binary) {
+ super.visitBinary(node)
+
+ when (node.operation) {
+ GroupOps.PLUS_OPERATION -> invokeMethodVisitor.visitInsn(DADD)
+ GroupOps.MINUS_OPERATION -> invokeMethodVisitor.visitInsn(DSUB)
+ RingOps.TIMES_OPERATION -> invokeMethodVisitor.visitInsn(DMUL)
+ FieldOps.DIV_OPERATION -> invokeMethodVisitor.visitInsn(DDIV)
+ PowerOperations.POW_OPERATION -> buildBinaryJavaMathCall("pow")
+ else -> super.visitBinary(node)
+ }
+ }
+
+ private companion object {
+ val MATH_TYPE: Type = getObjectType("java/lang/Math")
+ val MATH_KT_TYPE: Type = getObjectType("kotlin/math/MathKt")
+ }
+}
+
+@UnstableKMathAPI
+internal class IntAsmBuilder(target: TypedMst) :
+ PrimitiveAsmBuilder(
+ IntRing,
+ Integer::class.java,
+ Integer.TYPE,
+ IntExpression::class.java,
+ target
+ ) {
+ override fun visitUnary(node: TypedMst.Unary) {
+ super.visitUnary(node)
+
+ when (node.operation) {
+ GroupOps.MINUS_OPERATION -> invokeMethodVisitor.visitInsn(INEG)
+ GroupOps.PLUS_OPERATION -> Unit
+ else -> super.visitUnary(node)
+ }
+ }
+
+ override fun visitBinary(node: TypedMst.Binary) {
+ super.visitBinary(node)
+
+ when (node.operation) {
+ GroupOps.PLUS_OPERATION -> invokeMethodVisitor.visitInsn(IADD)
+ GroupOps.MINUS_OPERATION -> invokeMethodVisitor.visitInsn(ISUB)
+ RingOps.TIMES_OPERATION -> invokeMethodVisitor.visitInsn(IMUL)
+ else -> super.visitBinary(node)
+ }
+ }
+}
+
+@UnstableKMathAPI
+internal class LongAsmBuilder(target: TypedMst) : PrimitiveAsmBuilder(
+ LongRing,
+ java.lang.Long::class.java,
+ java.lang.Long.TYPE,
+ LongExpression::class.java,
+ target,
+) {
+ override fun visitUnary(node: TypedMst.Unary) {
+ super.visitUnary(node)
+
+ when (node.operation) {
+ GroupOps.MINUS_OPERATION -> invokeMethodVisitor.visitInsn(LNEG)
+ GroupOps.PLUS_OPERATION -> Unit
+ else -> super.visitUnary(node)
+ }
+ }
+
+ override fun visitBinary(node: TypedMst.Binary) {
+ super.visitBinary(node)
+
+ when (node.operation) {
+ GroupOps.PLUS_OPERATION -> invokeMethodVisitor.visitInsn(LADD)
+ GroupOps.MINUS_OPERATION -> invokeMethodVisitor.visitInsn(LSUB)
+ RingOps.TIMES_OPERATION -> invokeMethodVisitor.visitInsn(LMUL)
+ else -> super.visitBinary(node)
+ }
+ }
+}
diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt
index 5e2e7d8c6..9e880f4fc 100644
--- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt
+++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.asm.internal
@@ -55,15 +55,15 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.(
internal fun MethodVisitor.label(): Label = Label().also(::visitLabel)
/**
- * Creates a class name for [Expression] subclassed to implement [mst] provided.
+ * Creates a class name for [Expression] based with appending [marker] to reduce collisions.
*
* These methods help 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 = "space.kscience.kmath.asm.generated.CompiledExpression_${mst.hashCode()}_$collision"
+internal tailrec fun buildName(marker: String, collision: Int = 0): String {
+ val name = "space.kscience.kmath.asm.generated.CompiledExpression_${marker}_$collision"
try {
Class.forName(name)
@@ -71,7 +71,7 @@ internal tailrec fun buildName(mst: MST, collision: Int = 0): String {
return name
}
- return buildName(mst, collision + 1)
+ return buildName(marker, collision + 1)
}
@Suppress("FunctionName")
diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt
index 40d9d8fe6..3a5ef74f7 100644
--- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt
+++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("MapIntrinsics")
@@ -14,4 +14,5 @@ import space.kscience.kmath.expressions.Symbol
*
* @author Iaroslav Postovalov
*/
+@Suppress("unused")
internal fun Map.getOrFail(key: String): V = getValue(Symbol(key))
diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt
index 3e5253084..556adbe7d 100644
--- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt
+++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast.rendering
diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt
index a0bdd68a0..47f1cc476 100644
--- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt
+++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
@@ -8,6 +8,7 @@ package space.kscience.kmath.ast
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.Symbol
+import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
import kotlin.contracts.InvocationKind
@@ -15,7 +16,21 @@ import kotlin.contracts.contract
import space.kscience.kmath.asm.compile as asmCompile
import space.kscience.kmath.asm.compileToExpression as asmCompileToExpression
-private object AsmCompilerTestContext : CompilerTestContext {
+private object GenericAsmCompilerTestContext : CompilerTestContext {
+ override fun MST.compileToExpression(algebra: IntRing): Expression =
+ asmCompileToExpression(algebra as Algebra)
+
+ override fun MST.compile(algebra: IntRing, arguments: Map): Int =
+ asmCompile(algebra as Algebra, arguments)
+
+ override fun MST.compileToExpression(algebra: DoubleField): Expression =
+ asmCompileToExpression(algebra as Algebra)
+
+ override fun MST.compile(algebra: DoubleField, arguments: Map): Double =
+ asmCompile(algebra as Algebra, arguments)
+}
+
+private object PrimitiveAsmCompilerTestContext : CompilerTestContext {
override fun MST.compileToExpression(algebra: IntRing): Expression = asmCompileToExpression(algebra)
override fun MST.compile(algebra: IntRing, arguments: Map): Int = asmCompile(algebra, arguments)
override fun MST.compileToExpression(algebra: DoubleField): Expression = asmCompileToExpression(algebra)
@@ -24,7 +39,9 @@ private object AsmCompilerTestContext : CompilerTestContext {
asmCompile(algebra, arguments)
}
+
internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) {
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
- action(AsmCompilerTestContext)
+ action(GenericAsmCompilerTestContext)
+ action(PrimitiveAsmCompilerTestContext)
}
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt
index 4d2bd6237..82694d95a 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.commons.expressions
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt
index 5152b04f9..e0a2f4931 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.commons.integration
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt
index 76a2f297c..257429fa7 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.commons.integration
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt
index 14e7fc365..aa7e0a638 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.commons.linear
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt
index d1fb441b0..9bb5deffd 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.commons.linear
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt
index 28294cf14..194be6002 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.commons.random
@@ -38,10 +38,7 @@ public class CMRandomGeneratorWrapper(
override fun nextInt(): Int = generator.nextInt()
override fun nextInt(n: Int): Int = generator.nextInt(n)
-
- @PerformancePitfall
override fun nextGaussian(): Double = runBlocking { GaussianSampler(0.0, 1.0).next(generator) }
-
override fun nextDouble(): Double = generator.nextDouble()
override fun nextLong(): Long = generator.nextLong()
}
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt
index 73ab91542..40168971e 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.commons.transform
diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt
index eaebc84dc..56252ab34 100644
--- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt
+++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.commons.expressions
diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt
index bab3aecb6..c5573fef1 100644
--- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt
+++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.commons.integration
diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt
index c670ceead..0977dc247 100644
--- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt
+++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.commons.optimization
diff --git a/kmath-complex/README.md b/kmath-complex/README.md
index 110529b72..92f2435ba 100644
--- a/kmath-complex/README.md
+++ b/kmath-complex/README.md
@@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath.
## Artifact:
-The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-14`.
+The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-17`.
**Gradle:**
```gradle
@@ -18,7 +18,7 @@ repositories {
}
dependencies {
- implementation 'space.kscience:kmath-complex:0.3.0-dev-14'
+ implementation 'space.kscience:kmath-complex:0.3.0-dev-17'
}
```
**Gradle Kotlin DSL:**
@@ -29,6 +29,6 @@ repositories {
}
dependencies {
- implementation("space.kscience:kmath-complex:0.3.0-dev-14")
+ implementation("space.kscience:kmath-complex:0.3.0-dev-17")
}
```
diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt
index 879cfe94e..77fe782a9 100644
--- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt
+++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.complex
@@ -41,7 +41,7 @@ public val Complex.r: Double
* An angle between vector represented by complex number and X axis.
*/
public val Complex.theta: Double
- get() = atan(im / re)
+ get() = atan2(im, re)
private val PI_DIV_2 = Complex(PI / 2, 0)
diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt
index 9d5b1cddd..46d4b7c5c 100644
--- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt
+++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt
@@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.complex
@@ -18,7 +18,7 @@ import kotlin.contracts.contract
*/
@OptIn(UnstableKMathAPI::class)
public sealed class ComplexFieldOpsND : BufferedFieldOpsND(ComplexField.bufferAlgebra),
- ScaleOperations>, ExtendedFieldOps> {
+ ScaleOperations>, ExtendedFieldOps>, PowerOperations> {
override fun StructureND.toBufferND(): BufferND = when (this) {
is BufferND -> this
@@ -33,9 +33,6 @@ public sealed class ComplexFieldOpsND : BufferedFieldOpsND, value: Double): BufferND =
mapInline(a.toBufferND()) { it * value }
- override fun power(arg: StructureND, pow: Number): BufferND