forked from kscience/kmath
Merge pull request #284 from mipt-npm/commandertvis/binaryen
MST compilation to WebAssembly with Binaryen, reorganize internal JS bindings, tests refactor
This commit is contained in:
commit
a722672b35
16
README.md
16
README.md
@ -76,6 +76,12 @@ KMath is a modular library. Different modules provide different features with di
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [benchmarks](benchmarks)
|
||||
>
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
<hr/>
|
||||
|
||||
* ### [examples](examples)
|
||||
>
|
||||
>
|
||||
@ -88,12 +94,10 @@ KMath is a modular library. Different modules provide different features with di
|
||||
> **Maturity**: PROTOTYPE
|
||||
>
|
||||
> **Features:**
|
||||
> - [expression-language](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||
> - [mst](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
|
||||
> - [mst-building](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
|
||||
> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter
|
||||
> - [expression-language](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||
> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
|
||||
> - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
|
||||
> - [rendering](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt) : Extendable MST rendering
|
||||
|
||||
<hr/>
|
||||
|
||||
@ -266,8 +270,8 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("space.kscience:kmath-core:0.3.0-dev-6")
|
||||
// api("space.kscience:kmath-core-jvm:0.3.0-dev-6") for jvm-specific version
|
||||
api("space.kscience:kmath-core:0.3.0-dev-7")
|
||||
// api("space.kscience:kmath-core-jvm:0.3.0-dev-7") for jvm-specific version
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -3,8 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
kotlin("plugin.allopen")
|
||||
@ -14,8 +12,6 @@ plugins {
|
||||
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
||||
sourceSets.register("benchmarks")
|
||||
|
||||
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
@ -77,43 +73,35 @@ benchmark {
|
||||
register("jvm")
|
||||
}
|
||||
|
||||
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
|
||||
warmups = 1
|
||||
iterations = 5
|
||||
iterationTime = 1000
|
||||
iterationTimeUnit = "ms"
|
||||
}
|
||||
|
||||
configurations.register("buffer") {
|
||||
warmups = 1 // number of warmup iterations
|
||||
iterations = 3 // number of iterations
|
||||
iterationTime = 500 // time in seconds per iteration
|
||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
||||
commonConfiguration()
|
||||
include("BufferBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("dot") {
|
||||
warmups = 1 // number of warmup iterations
|
||||
iterations = 3 // number of iterations
|
||||
iterationTime = 500 // time in seconds per iteration
|
||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
||||
commonConfiguration()
|
||||
include("DotBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("expressions") {
|
||||
warmups = 1 // number of warmup iterations
|
||||
iterations = 3 // number of iterations
|
||||
iterationTime = 500 // time in seconds per iteration
|
||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
||||
commonConfiguration()
|
||||
include("ExpressionsInterpretersBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("matrixInverse") {
|
||||
warmups = 1 // number of warmup iterations
|
||||
iterations = 3 // number of iterations
|
||||
iterationTime = 500 // time in seconds per iteration
|
||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
||||
commonConfiguration()
|
||||
include("MatrixInverseBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("bigInt") {
|
||||
warmups = 1 // number of warmup iterations
|
||||
iterations = 3 // number of iterations
|
||||
iterationTime = 500 // time in seconds per iteration
|
||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
||||
commonConfiguration()
|
||||
include("BigIntBenchmark")
|
||||
}
|
||||
}
|
||||
@ -121,7 +109,7 @@ benchmark {
|
||||
// Fix kotlinx-benchmarks bug
|
||||
afterEvaluate {
|
||||
val jvmBenchmarkJar by tasks.getting(org.gradle.jvm.tasks.Jar::class) {
|
||||
duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.EXCLUDE
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,5 +131,5 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
|
||||
|
||||
readme {
|
||||
maturity = Maturity.EXPERIMENTAL
|
||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import space.kscience.kmath.asm.compileToExpression
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
@ -20,50 +21,22 @@ import kotlin.random.Random
|
||||
@State(Scope.Benchmark)
|
||||
internal class ExpressionsInterpretersBenchmark {
|
||||
@Benchmark
|
||||
fun functionalExpression(blackhole: Blackhole) {
|
||||
val expr = algebra.expressionInField {
|
||||
val x = bindSymbol(x)
|
||||
x * const(2.0) + const(2.0) / x - const(16.0)
|
||||
}
|
||||
|
||||
invokeAndSum(expr, blackhole)
|
||||
}
|
||||
fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
|
||||
|
||||
@Benchmark
|
||||
fun mstExpression(blackhole: Blackhole) {
|
||||
val expr = MstField {
|
||||
val x = bindSymbol(x)
|
||||
x * 2.0 + number(2.0) / x - 16.0
|
||||
}.toExpression(algebra)
|
||||
|
||||
invokeAndSum(expr, blackhole)
|
||||
}
|
||||
fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
|
||||
|
||||
@Benchmark
|
||||
fun asmExpression(blackhole: Blackhole) {
|
||||
val expr = MstField {
|
||||
val x = bindSymbol(x)
|
||||
x * 2.0 + number(2.0) / x - 16.0
|
||||
}.compileToExpression(algebra)
|
||||
|
||||
invokeAndSum(expr, blackhole)
|
||||
}
|
||||
fun asmExpression(blackhole: Blackhole) = invokeAndSum(asm, blackhole)
|
||||
|
||||
@Benchmark
|
||||
fun rawExpression(blackhole: Blackhole) {
|
||||
val expr = Expression<Double> { args ->
|
||||
val x = args.getValue(x)
|
||||
x * 2.0 + 2.0 / x - 16.0
|
||||
}
|
||||
|
||||
invokeAndSum(expr, blackhole)
|
||||
}
|
||||
fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole)
|
||||
|
||||
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
|
||||
val random = Random(0)
|
||||
var sum = 0.0
|
||||
|
||||
repeat(1000000) {
|
||||
repeat(times) {
|
||||
sum += expr(x to random.nextDouble())
|
||||
}
|
||||
|
||||
@ -71,7 +44,23 @@ internal class ExpressionsInterpretersBenchmark {
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val algebra = DoubleField
|
||||
private val x by symbol
|
||||
private val x: Symbol by symbol
|
||||
private val algebra: DoubleField = DoubleField
|
||||
private const val times = 1_000_000
|
||||
|
||||
private val functional: Expression<Double> = DoubleField.expressionInExtendedField {
|
||||
bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x))
|
||||
}
|
||||
|
||||
private val node = MstExtendedField {
|
||||
bindSymbol(x) * 2.0 + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x))
|
||||
}
|
||||
|
||||
private val mst: Expression<Double> = node.toExpression(DoubleField)
|
||||
private val asm: Expression<Double> = node.compileToExpression(DoubleField)
|
||||
|
||||
private val raw: Expression<Double> = Expression { args ->
|
||||
args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / kotlin.math.sin(args.getValue(x))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import org.jetbrains.dokka.gradle.DokkaTask
|
||||
import java.net.URL
|
||||
|
||||
plugins {
|
||||
id("ru.mipt.npm.gradle.project")
|
||||
}
|
||||
@ -17,8 +14,7 @@ allprojects {
|
||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||
maven("https://jitpack.io")
|
||||
maven{
|
||||
setUrl("http://logicrunch.research.it.uu.se/maven/")
|
||||
maven("http://logicrunch.research.it.uu.se/maven/") {
|
||||
isAllowInsecureProtocol = true
|
||||
}
|
||||
mavenCentral()
|
||||
@ -32,7 +28,7 @@ subprojects {
|
||||
if (name.startsWith("kmath")) apply<MavenPublishPlugin>()
|
||||
|
||||
afterEvaluate {
|
||||
tasks.withType<DokkaTask> {
|
||||
tasks.withType<org.jetbrains.dokka.gradle.DokkaTask> {
|
||||
dokkaSourceSets.all {
|
||||
val readmeFile = File(this@subprojects.projectDir, "./README.md")
|
||||
if (readmeFile.exists())
|
||||
@ -42,7 +38,7 @@ subprojects {
|
||||
"http://ejml.org/javadoc/",
|
||||
"https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/",
|
||||
"https://deeplearning4j.org/api/latest/"
|
||||
).map { URL("${it}package-list") to URL(it) }.forEach { (a, b) ->
|
||||
).map { java.net.URL("${it}package-list") to java.net.URL(it) }.forEach { (a, b) ->
|
||||
externalDocumentationLink {
|
||||
packageListUrl.set(a)
|
||||
url.set(b)
|
||||
|
@ -3,9 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
@ -64,7 +61,7 @@ kotlin.sourceSets.all {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions{
|
||||
jvmTarget = "11"
|
||||
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
|
||||
@ -72,5 +69,5 @@ tasks.withType<KotlinCompile> {
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = Maturity.EXPERIMENTAL
|
||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||
}
|
||||
|
@ -25,5 +25,5 @@ fun main() {
|
||||
|
||||
|
||||
val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField)
|
||||
assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0))
|
||||
assert(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
|
||||
}
|
||||
|
@ -2,17 +2,15 @@
|
||||
|
||||
Abstract syntax tree expression representation and related optimizations.
|
||||
|
||||
- [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||
- [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
|
||||
- [mst-building](src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
|
||||
- [mst-interpreter](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter
|
||||
- [expression-language](src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||
- [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
|
||||
- [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
|
||||
- [rendering](src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt) : Extendable MST rendering
|
||||
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-6`.
|
||||
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-7`.
|
||||
|
||||
**Gradle:**
|
||||
```gradle
|
||||
@ -23,7 +21,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'space.kscience:kmath-ast:0.3.0-dev-6'
|
||||
implementation 'space.kscience:kmath-ast:0.3.0-dev-7'
|
||||
}
|
||||
```
|
||||
**Gradle Kotlin DSL:**
|
||||
@ -35,7 +33,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:kmath-ast:0.3.0-dev-6")
|
||||
implementation("space.kscience:kmath-ast:0.3.0-dev-7")
|
||||
}
|
||||
```
|
||||
|
||||
@ -49,10 +47,10 @@ a special implementation of `Expression<T>` with implemented `invoke` function.
|
||||
For example, the following builder:
|
||||
|
||||
```kotlin
|
||||
DoubleField.mstInField { symbol("x") + 2 }.compile()
|
||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||
```
|
||||
|
||||
… leads to generation of bytecode, which can be decompiled to the following Java class:
|
||||
… leads to generation of bytecode, which can be decompiled to the following Java class:
|
||||
|
||||
```java
|
||||
package space.kscience.kmath.asm.generated;
|
||||
@ -77,15 +75,6 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
||||
|
||||
```
|
||||
|
||||
### Example Usage
|
||||
|
||||
This API extends MST and MstExpression, so you may optimize as both of them:
|
||||
|
||||
```kotlin
|
||||
DoubleField.mstInField { symbol("x") + 2 }.compile()
|
||||
DoubleField.expression("x+2".parseMath())
|
||||
```
|
||||
|
||||
#### Known issues
|
||||
|
||||
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid
|
||||
@ -97,7 +86,7 @@ DoubleField.expression("x+2".parseMath())
|
||||
A similar feature is also available on JS.
|
||||
|
||||
```kotlin
|
||||
DoubleField.mstInField { symbol("x") + 2 }.compile()
|
||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||
```
|
||||
|
||||
The code above returns expression implemented with such a JS function:
|
||||
@ -108,13 +97,32 @@ var executable = function (constants, arguments) {
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
```kotlin
|
||||
import space.kscience.kmath.wasm.*
|
||||
|
||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||
```
|
||||
|
||||
An example of emitted WASM IR in the form of WAT:
|
||||
|
||||
```lisp
|
||||
(func $executable (param $0 f64) (result f64)
|
||||
(f64.add
|
||||
(local.get $0)
|
||||
(f64.const 2)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
#### Known issues
|
||||
|
||||
- This feature uses `eval` which can be unavailable in several environments.
|
||||
- ESTree expression compilation uses `eval` which can be unavailable in several environments.
|
||||
- WebAssembly isn't supported by old versions of browsers (see https://webassembly.org/roadmap/).
|
||||
|
||||
## Rendering expressions
|
||||
|
||||
kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax.
|
||||
kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax.
|
||||
|
||||
Example usage:
|
||||
|
||||
@ -135,7 +143,7 @@ public fun main() {
|
||||
}
|
||||
```
|
||||
|
||||
Result LaTeX:
|
||||
Result LaTeX:
|
||||
|
||||
![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D)
|
||||
|
||||
@ -145,5 +153,5 @@ Result MathML (embedding MathML is not allowed by GitHub Markdown):
|
||||
<mrow><msup><mrow><mi>e</mi></mrow><mrow><msqrt><mi>x</mi></msqrt></mrow></msup><mo>-</mo><mfrac><mrow><mfrac><mrow><msup><mrow><mo>sin</mo></mrow><mrow><mo>-</mo><mn>1</mn></mrow></msup><mspace width="0.167em"></mspace><mfenced open="(" close=")" separators=""><mn>2</mn><mspace width="0.167em"></mspace><mi>x</mi></mfenced></mrow><mrow><mn>2</mn><mo>×</mo><msup><mrow><mn>10</mn></mrow><mrow><mn>10</mn></mrow></msup><mo>+</mo><msup><mrow><mi>x</mi></mrow><mrow><mn>3</mn></mrow></msup></mrow></mfrac></mrow><mrow><mo>-</mo><mn>12</mn></mrow></mfrac></mrow>
|
||||
```
|
||||
|
||||
It is also possible to create custom algorithms of render, and even add support of other markup languages
|
||||
It is also possible to create custom algorithms of render, and even add support of other markup languages
|
||||
(see API reference).
|
||||
|
@ -3,8 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("ru.mipt.npm.gradle.common")
|
||||
@ -41,6 +39,9 @@ kotlin.sourceSets {
|
||||
jsMain {
|
||||
dependencies {
|
||||
implementation(npm("astring", "1.7.4"))
|
||||
implementation(npm("binaryen", "100.0"))
|
||||
implementation(npm("js-base64", "3.6.0"))
|
||||
implementation(npm("webassembly", "0.11.0"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +59,7 @@ tasks.dokkaHtml {
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = Maturity.PROTOTYPE
|
||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
||||
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||
|
||||
feature(
|
||||
|
@ -16,7 +16,7 @@ a special implementation of `Expression<T>` with implemented `invoke` function.
|
||||
For example, the following builder:
|
||||
|
||||
```kotlin
|
||||
DoubleField.mstInField { symbol("x") + 2 }.compile()
|
||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||
```
|
||||
|
||||
… leads to generation of bytecode, which can be decompiled to the following Java class:
|
||||
@ -44,15 +44,6 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
||||
|
||||
```
|
||||
|
||||
### Example Usage
|
||||
|
||||
This API extends MST and MstExpression, so you may optimize as both of them:
|
||||
|
||||
```kotlin
|
||||
DoubleField.mstInField { symbol("x") + 2 }.compile()
|
||||
DoubleField.expression("x+2".parseMath())
|
||||
```
|
||||
|
||||
#### Known issues
|
||||
|
||||
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid
|
||||
@ -64,7 +55,7 @@ DoubleField.expression("x+2".parseMath())
|
||||
A similar feature is also available on JS.
|
||||
|
||||
```kotlin
|
||||
DoubleField.mstInField { symbol("x") + 2 }.compile()
|
||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||
```
|
||||
|
||||
The code above returns expression implemented with such a JS function:
|
||||
@ -75,13 +66,32 @@ var executable = function (constants, arguments) {
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
```kotlin
|
||||
import space.kscience.kmath.wasm.*
|
||||
|
||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||
```
|
||||
|
||||
An example of emitted WASM IR in the form of WAT:
|
||||
|
||||
```lisp
|
||||
(func \$executable (param \$0 f64) (result f64)
|
||||
(f64.add
|
||||
(local.get \$0)
|
||||
(f64.const 2)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
#### Known issues
|
||||
|
||||
- This feature uses `eval` which can be unavailable in several environments.
|
||||
- ESTree expression compilation uses `eval` which can be unavailable in several environments.
|
||||
- WebAssembly isn't supported by old versions of browsers (see https://webassembly.org/roadmap/).
|
||||
|
||||
## Rendering expressions
|
||||
|
||||
kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax.
|
||||
kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax.
|
||||
|
||||
Example usage:
|
||||
|
||||
@ -102,7 +112,7 @@ public fun main() {
|
||||
}
|
||||
```
|
||||
|
||||
Result LaTeX:
|
||||
Result LaTeX:
|
||||
|
||||
![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D)
|
||||
|
||||
@ -112,5 +122,5 @@ Result MathML (embedding MathML is not allowed by GitHub Markdown):
|
||||
<mrow><msup><mrow><mi>e</mi></mrow><mrow><msqrt><mi>x</mi></msqrt></mrow></msup><mo>-</mo><mfrac><mrow><mfrac><mrow><msup><mrow><mo>sin</mo></mrow><mrow><mo>-</mo><mn>1</mn></mrow></msup><mspace width="0.167em"></mspace><mfenced open="(" close=")" separators=""><mn>2</mn><mspace width="0.167em"></mspace><mi>x</mi></mfenced></mrow><mrow><mn>2</mn><mo>×</mo><msup><mrow><mn>10</mn></mrow><mrow><mn>10</mn></mrow></msup><mo>+</mo><msup><mrow><mi>x</mi></mrow><mrow><mn>3</mn></mrow></msup></mrow></mfrac></mrow><mrow><mo>-</mo><mn>12</mn></mrow></mfrac></mrow>
|
||||
```
|
||||
|
||||
It is also possible to create custom algorithms of render, and even add support of other markup languages
|
||||
It is also possible to create custom algorithms of render, and even add support of other markup languages
|
||||
(see API reference).
|
||||
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscisnce.kmath.ast
|
||||
|
||||
import space.kscience.kmath.expressions.MstField
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.expressions.toExpression
|
||||
import space.kscience.kmath.misc.Symbol.Companion.x
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
|
||||
class InterpretTest {
|
||||
|
||||
@Test
|
||||
fun interpretation(){
|
||||
val expr = MstField {
|
||||
val x = bindSymbol(x)
|
||||
x * 2.0 + number(2.0) / x - 16.0
|
||||
}.toExpression(DoubleField)
|
||||
expr(x to 2.2)
|
||||
}
|
||||
}
|
@ -1,19 +1,12 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast
|
||||
package space.kscisnce.kmath.ast
|
||||
|
||||
import space.kscience.kmath.ast.parseMath
|
||||
import space.kscience.kmath.expressions.evaluate
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.Field
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class ParserPrecedenceTest {
|
||||
private val f: Field<Double> = DoubleField
|
||||
|
||||
@Test
|
||||
fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath()))
|
||||
|
||||
@ -37,4 +30,8 @@ internal class ParserPrecedenceTest {
|
||||
|
||||
@Test
|
||||
fun test8(): Unit = assertEquals(18.0, f.evaluate("2*2^3+2".parseMath()))
|
||||
|
||||
private companion object {
|
||||
private val f = DoubleField
|
||||
}
|
||||
}
|
@ -1,37 +1,24 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast
|
||||
package space.kscisnce.kmath.ast
|
||||
|
||||
import space.kscience.kmath.ast.parseMath
|
||||
import space.kscience.kmath.complex.Complex
|
||||
import space.kscience.kmath.complex.ComplexField
|
||||
import space.kscience.kmath.expressions.MstField
|
||||
import space.kscience.kmath.expressions.evaluate
|
||||
import space.kscience.kmath.expressions.interpret
|
||||
import space.kscience.kmath.operations.Algebra
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class ParserTest {
|
||||
@Test
|
||||
fun `evaluate MST`() {
|
||||
fun evaluateParsedMst() {
|
||||
val mst = "2+2*(2+2)".parseMath()
|
||||
val res = ComplexField.evaluate(mst)
|
||||
assertEquals(Complex(10.0, 0.0), res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `evaluate MSTExpression`() {
|
||||
val res = MstField.invoke { number(2) + number(2) * (number(2) + number(2)) }.interpret(ComplexField)
|
||||
assertEquals(Complex(10.0, 0.0), res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `evaluate MST with singular`() {
|
||||
fun evaluateMstSymbol() {
|
||||
val mst = "i".parseMath()
|
||||
val res = ComplexField.evaluate(mst)
|
||||
assertEquals(ComplexField.i, res)
|
||||
@ -39,14 +26,14 @@ internal class ParserTest {
|
||||
|
||||
|
||||
@Test
|
||||
fun `evaluate MST with unary function`() {
|
||||
fun evaluateMstUnary() {
|
||||
val mst = "sin(0)".parseMath()
|
||||
val res = DoubleField.evaluate(mst)
|
||||
assertEquals(0.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `evaluate MST with binary function`() {
|
||||
fun evaluateMstBinary() {
|
||||
val magicalAlgebra = object : Algebra<String> {
|
||||
override fun bindSymbolOrNull(value: String): String = value
|
||||
|
@ -6,11 +6,11 @@
|
||||
package space.kscience.kmath.estree
|
||||
|
||||
import space.kscience.kmath.estree.internal.ESTreeBuilder
|
||||
import space.kscience.kmath.estree.internal.estree.BaseExpression
|
||||
import space.kscience.kmath.expressions.Expression
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.expressions.MST.*
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.internal.estree.BaseExpression
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.operations.Algebra
|
||||
import space.kscience.kmath.operations.NumericAlgebra
|
||||
|
@ -5,9 +5,14 @@
|
||||
|
||||
package space.kscience.kmath.estree.internal
|
||||
|
||||
import space.kscience.kmath.estree.internal.astring.generate
|
||||
import space.kscience.kmath.estree.internal.estree.*
|
||||
import space.kscience.kmath.expressions.Expression
|
||||
import space.kscience.kmath.internal.astring.generate
|
||||
import space.kscience.kmath.internal.estree.*
|
||||
import space.kscience.kmath.internal.estree.BaseExpression
|
||||
import space.kscience.kmath.internal.estree.BlockStatement
|
||||
import space.kscience.kmath.internal.estree.Program
|
||||
import space.kscience.kmath.internal.estree.VariableDeclaration
|
||||
import space.kscience.kmath.internal.estree.VariableDeclarator
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
|
||||
internal class ESTreeBuilder<T>(val bodyCallback: ESTreeBuilder<T>.() -> BaseExpression) {
|
||||
|
@ -1,12 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.estree.internal.stream
|
||||
|
||||
import space.kscience.kmath.estree.internal.emitter.Emitter
|
||||
|
||||
internal open external class Stream : Emitter {
|
||||
open fun pipe(dest: Any, options: Any): Any
|
||||
}
|
@ -6,9 +6,9 @@
|
||||
@file:JsModule("astring")
|
||||
@file:JsNonModule
|
||||
|
||||
package space.kscience.kmath.estree.internal.astring
|
||||
package space.kscience.kmath.internal.astring
|
||||
|
||||
import space.kscience.kmath.estree.internal.estree.BaseNode
|
||||
import space.kscience.kmath.internal.estree.BaseNode
|
||||
|
||||
internal external interface Options {
|
||||
var indent: String?
|
@ -0,0 +1,3 @@
|
||||
package space.kscience.kmath.internal.astring
|
||||
|
||||
internal typealias Generator = Any
|
@ -0,0 +1,49 @@
|
||||
@file:Suppress(
|
||||
"INTERFACE_WITH_SUPERCLASS",
|
||||
"OVERRIDING_FINAL_MEMBER",
|
||||
"RETURN_TYPE_MISMATCH_ON_OVERRIDE",
|
||||
"CONFLICTING_OVERLOADS",
|
||||
"NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING",
|
||||
"ObjectPropertyName",
|
||||
"ClassName",
|
||||
)
|
||||
@file:JsNonModule
|
||||
@file:JsModule("js-base64")
|
||||
|
||||
package space.kscience.kmath.internal.base64
|
||||
|
||||
import org.khronos.webgl.Uint8Array
|
||||
|
||||
internal external var version: Any
|
||||
|
||||
internal external var VERSION: Any
|
||||
|
||||
internal external var btoaPolyfill: (bin: String) -> String
|
||||
|
||||
internal external var _btoa: (bin: String) -> String
|
||||
|
||||
internal external var fromUint8Array: (u8a: Uint8Array, urlsafe: Boolean) -> String
|
||||
|
||||
internal external var utob: (u: String) -> String
|
||||
|
||||
internal external var encode: (src: String, urlsafe: Boolean) -> String
|
||||
|
||||
internal external var encodeURI: (src: String) -> String
|
||||
|
||||
internal external var btou: (b: String) -> String
|
||||
|
||||
internal external var atobPolyfill: (asc: String) -> String
|
||||
|
||||
internal external var _atob: (asc: String) -> String
|
||||
|
||||
internal external var toUint8Array: (a: String) -> Uint8Array
|
||||
|
||||
internal external var decode: (src: String) -> String
|
||||
|
||||
internal external var isValid: (src: Any) -> Boolean
|
||||
|
||||
internal external var extendString: () -> Unit
|
||||
|
||||
internal external var extendUint8Array: () -> Unit
|
||||
|
||||
internal external var extendBuiltins: () -> Unit
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
||||
@file:Suppress("PackageDirectoryMismatch", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation")
|
||||
|
||||
package space.kscience.kmath.internal.binaryen
|
||||
|
||||
internal typealias Type = Number
|
||||
internal typealias ExpressionRef = Number
|
||||
internal typealias FunctionRef = Number
|
||||
internal typealias GlobalRef = Number
|
||||
internal typealias ExportRef = Number
|
||||
internal typealias EventRef = Number
|
||||
internal typealias RelooperBlockRef = Number
|
@ -3,7 +3,7 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.estree.internal.emitter
|
||||
package space.kscience.kmath.internal.emitter
|
||||
|
||||
internal open external class Emitter {
|
||||
constructor(obj: Any)
|
@ -3,7 +3,7 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.estree.internal.estree
|
||||
package space.kscience.kmath.internal.estree
|
||||
|
||||
internal fun Program(sourceType: String, vararg body: dynamic) = object : Program {
|
||||
override var type = "Program"
|
@ -3,7 +3,7 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.estree.internal.estree
|
||||
package space.kscience.kmath.internal.estree
|
||||
|
||||
import kotlin.js.RegExp
|
||||
|
@ -0,0 +1,7 @@
|
||||
package space.kscience.kmath.internal.stream
|
||||
|
||||
import space.kscience.kmath.internal.emitter.Emitter
|
||||
|
||||
internal open external class Stream : Emitter {
|
||||
open fun pipe(dest: Any, options: Any): Any
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.estree.internal.tsstdlib
|
||||
package space.kscience.kmath.internal.tsstdlib
|
||||
|
||||
internal external interface IteratorYieldResult<TYield> {
|
||||
var done: Boolean?
|
@ -5,7 +5,7 @@
|
||||
|
||||
@file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION")
|
||||
|
||||
package space.kscience.kmath.estree.internal.tsstdlib
|
||||
package space.kscience.kmath.internal.tsstdlib
|
||||
|
||||
import kotlin.js.RegExp
|
||||
|
||||
@ -38,6 +38,8 @@ internal external interface RegExpConstructor {
|
||||
var lastMatch: String
|
||||
}
|
||||
|
||||
internal typealias Record<K, T> = Any
|
||||
|
||||
internal external interface ConcatArray<T> {
|
||||
var length: Number
|
||||
|
||||
@ -85,3 +87,10 @@ internal external interface ArrayLike<T> {
|
||||
}
|
||||
|
||||
internal typealias Extract<T, U> = Any
|
||||
|
||||
internal external interface PromiseLike<T> {
|
||||
fun then(
|
||||
onfulfilled: ((value: T) -> Any?)? = definedExternally,
|
||||
onrejected: ((reason: Any) -> Any?)? = definedExternally
|
||||
): PromiseLike<dynamic /* TResult1 | TResult2 */>
|
||||
}
|
@ -0,0 +1,231 @@
|
||||
@file:JsQualifier("WebAssembly")
|
||||
|
||||
@file:Suppress(
|
||||
"INTERFACE_WITH_SUPERCLASS",
|
||||
"OVERRIDING_FINAL_MEMBER",
|
||||
"RETURN_TYPE_MISMATCH_ON_OVERRIDE",
|
||||
"NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING",
|
||||
"ClassName",
|
||||
)
|
||||
|
||||
package space.kscience.kmath.internal.webassembly
|
||||
|
||||
import space.kscience.kmath.internal.tsstdlib.PromiseLike
|
||||
import org.khronos.webgl.ArrayBuffer
|
||||
import org.khronos.webgl.ArrayBufferView
|
||||
import org.khronos.webgl.Uint8Array
|
||||
import org.w3c.fetch.Response
|
||||
import kotlin.js.Promise
|
||||
|
||||
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
|
||||
internal external interface CompileError {
|
||||
companion object {
|
||||
var prototype: CompileError
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
|
||||
internal external interface Global {
|
||||
var value: Any
|
||||
fun valueOf(): Any
|
||||
|
||||
companion object {
|
||||
var prototype: Global
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
|
||||
@JsName("Instance")
|
||||
internal external interface Instance1 {
|
||||
var exports: Exports
|
||||
|
||||
companion object {
|
||||
var prototype: Instance
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
|
||||
internal external interface LinkError {
|
||||
companion object {
|
||||
var prototype: LinkError
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
|
||||
internal external interface Memory {
|
||||
var buffer: ArrayBuffer
|
||||
fun grow(delta: Number): Number
|
||||
|
||||
companion object {
|
||||
var prototype: Memory
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
|
||||
@JsName("Module")
|
||||
internal external interface Module1 {
|
||||
companion object {
|
||||
var prototype: Module
|
||||
fun customSections(moduleObject: Module, sectionName: String): Array<ArrayBuffer>
|
||||
fun exports(moduleObject: Module): Array<ModuleExportDescriptor>
|
||||
fun imports(moduleObject: Module): Array<ModuleImportDescriptor>
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
|
||||
internal external interface RuntimeError {
|
||||
companion object {
|
||||
var prototype: RuntimeError
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
|
||||
internal external interface Table {
|
||||
var length: Number
|
||||
fun get(index: Number): Function<*>?
|
||||
fun grow(delta: Number): Number
|
||||
fun set(index: Number, value: Function<*>?)
|
||||
|
||||
companion object {
|
||||
var prototype: Table
|
||||
}
|
||||
}
|
||||
|
||||
internal external interface GlobalDescriptor {
|
||||
var mutable: Boolean?
|
||||
get() = definedExternally
|
||||
set(value) = definedExternally
|
||||
var value: String /* "f32" | "f64" | "i32" | "i64" */
|
||||
}
|
||||
|
||||
internal external interface MemoryDescriptor {
|
||||
var initial: Number
|
||||
var maximum: Number?
|
||||
get() = definedExternally
|
||||
set(value) = definedExternally
|
||||
}
|
||||
|
||||
internal external interface ModuleExportDescriptor {
|
||||
var kind: String /* "function" | "global" | "memory" | "table" */
|
||||
var name: String
|
||||
}
|
||||
|
||||
internal external interface ModuleImportDescriptor {
|
||||
var kind: String /* "function" | "global" | "memory" | "table" */
|
||||
var module: String
|
||||
var name: String
|
||||
}
|
||||
|
||||
internal external interface TableDescriptor {
|
||||
var element: String /* "anyfunc" */
|
||||
var initial: Number
|
||||
var maximum: Number?
|
||||
get() = definedExternally
|
||||
set(value) = definedExternally
|
||||
}
|
||||
|
||||
internal external interface WebAssemblyInstantiatedSource {
|
||||
var instance: Instance
|
||||
var module: Module
|
||||
}
|
||||
|
||||
internal external fun compile(bytes: ArrayBufferView): Promise<Module>
|
||||
|
||||
internal external fun compile(bytes: ArrayBuffer): Promise<Module>
|
||||
|
||||
internal external fun compileStreaming(source: Response): Promise<Module>
|
||||
|
||||
internal external fun compileStreaming(source: Promise<Response>): Promise<Module>
|
||||
|
||||
internal external fun instantiate(
|
||||
bytes: ArrayBufferView,
|
||||
importObject: Imports = definedExternally,
|
||||
): Promise<WebAssemblyInstantiatedSource>
|
||||
|
||||
internal external fun instantiate(bytes: ArrayBufferView): Promise<WebAssemblyInstantiatedSource>
|
||||
|
||||
internal external fun instantiate(
|
||||
bytes: ArrayBuffer,
|
||||
importObject: Imports = definedExternally,
|
||||
): dynamic /* Promise | Promise */
|
||||
|
||||
internal external fun instantiate(bytes: ArrayBuffer): dynamic /* Promise | Promise */
|
||||
|
||||
internal external fun instantiate(moduleObject: Module, importObject: Imports = definedExternally): Promise<Instance>
|
||||
|
||||
internal external fun instantiate(moduleObject: Module): Promise<Instance>
|
||||
|
||||
internal external fun instantiateStreaming(
|
||||
response: Response,
|
||||
importObject: Imports = definedExternally,
|
||||
): Promise<WebAssemblyInstantiatedSource>
|
||||
|
||||
internal external fun instantiateStreaming(response: Response): Promise<WebAssemblyInstantiatedSource>
|
||||
|
||||
internal external fun instantiateStreaming(
|
||||
response: PromiseLike<Response>,
|
||||
importObject: Imports = definedExternally,
|
||||
): Promise<WebAssemblyInstantiatedSource>
|
||||
|
||||
internal external fun instantiateStreaming(response: PromiseLike<Response>): Promise<WebAssemblyInstantiatedSource>
|
||||
|
||||
internal external fun validate(bytes: ArrayBufferView): Boolean
|
||||
|
||||
internal external fun validate(bytes: ArrayBuffer): Boolean
|
||||
|
||||
internal external interface `T$0` {
|
||||
var name: String
|
||||
var kind: String
|
||||
}
|
||||
|
||||
internal external interface `T$1` {
|
||||
var module: String
|
||||
var name: String
|
||||
var kind: String
|
||||
}
|
||||
|
||||
internal open external class Module {
|
||||
constructor(bufferSource: ArrayBuffer)
|
||||
constructor(bufferSource: Uint8Array)
|
||||
|
||||
companion object {
|
||||
fun customSections(module: Module, sectionName: String): Array<ArrayBuffer>
|
||||
fun exports(module: Module): Array<`T$0`>
|
||||
fun imports(module: Module): Array<`T$1`>
|
||||
}
|
||||
}
|
||||
|
||||
@JsName("Instance")
|
||||
internal open external class Instance(module: Module, importObject: Any = definedExternally) {
|
||||
open var exports: Any
|
||||
}
|
||||
|
||||
@JsName("Memory")
|
||||
internal open external class Memory1(memoryDescriptor: MemoryDescriptor) {
|
||||
open var buffer: ArrayBuffer
|
||||
open fun grow(numPages: Number): Number
|
||||
}
|
||||
|
||||
@JsName("Table")
|
||||
internal open external class Table1(tableDescriptor: TableDescriptor) {
|
||||
open var length: Number
|
||||
open fun get(index: Number): Function<*>
|
||||
open fun grow(numElements: Number): Number
|
||||
open fun set(index: Number, value: Function<*>)
|
||||
}
|
||||
|
||||
internal external fun compile(bufferSource: Uint8Array): Promise<Module>
|
||||
|
||||
internal external interface ResultObject {
|
||||
var module: Module
|
||||
var instance: Instance
|
||||
}
|
||||
|
||||
internal external fun instantiate(
|
||||
bufferSource: Uint8Array,
|
||||
importObject: Any = definedExternally,
|
||||
): Promise<ResultObject>
|
||||
|
||||
internal external fun instantiate(bufferSource: Uint8Array): Promise<ResultObject>
|
||||
|
||||
internal external fun validate(bufferSource: Uint8Array): Boolean
|
@ -0,0 +1,22 @@
|
||||
@file:Suppress("INTERFACE_WITH_SUPERCLASS",
|
||||
"OVERRIDING_FINAL_MEMBER",
|
||||
"RETURN_TYPE_MISMATCH_ON_OVERRIDE",
|
||||
"CONFLICTING_OVERLOADS",
|
||||
"NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING",
|
||||
)
|
||||
|
||||
package space.kscience.kmath.internal.webassembly
|
||||
|
||||
import space.kscience.kmath.internal.tsstdlib.Record
|
||||
|
||||
internal typealias Exports = Record<String, dynamic /* Function<*> | Global | Memory | Table */>
|
||||
|
||||
internal typealias ModuleImports = Record<String, dynamic /* Function<*> | Global | Memory | Table | Number */>
|
||||
|
||||
internal typealias Imports = Record<String, ModuleImports>
|
||||
|
||||
internal typealias CompileError1 = Error
|
||||
|
||||
internal typealias LinkError1 = Error
|
||||
|
||||
internal typealias RuntimeError1 = Error
|
@ -0,0 +1,155 @@
|
||||
package space.kscience.kmath.wasm.internal
|
||||
|
||||
import space.kscience.kmath.expressions.Expression
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.expressions.MST.*
|
||||
import space.kscience.kmath.internal.binaryen.*
|
||||
import space.kscience.kmath.internal.webassembly.Instance
|
||||
import space.kscience.kmath.misc.StringSymbol
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.internal.binaryen.Module as BinaryenModule
|
||||
import space.kscience.kmath.internal.webassembly.Module as WasmModule
|
||||
|
||||
private val spreader = eval("(obj, args) => obj(...args)")
|
||||
|
||||
@Suppress("UnsafeCastFromDynamic")
|
||||
internal sealed class WasmBuilder<T>(
|
||||
val binaryenType: Type,
|
||||
val algebra: Algebra<T>,
|
||||
val target: MST,
|
||||
) where T : Number {
|
||||
val keys: MutableList<String> = mutableListOf()
|
||||
lateinit var ctx: BinaryenModule
|
||||
|
||||
open fun visitSymbolic(mst: MST.Symbolic): ExpressionRef {
|
||||
try {
|
||||
algebra.bindSymbol(mst.value)
|
||||
} catch (ignored: Throwable) {
|
||||
null
|
||||
}?.let { return visitNumeric(Numeric(it)) }
|
||||
|
||||
var idx = keys.indexOf(mst.value)
|
||||
|
||||
if (idx == -1) {
|
||||
keys += mst.value
|
||||
idx = keys.lastIndex
|
||||
}
|
||||
|
||||
return ctx.local.get(idx, binaryenType)
|
||||
}
|
||||
|
||||
abstract fun visitNumeric(mst: Numeric): ExpressionRef
|
||||
|
||||
open fun visitUnary(mst: Unary): ExpressionRef =
|
||||
error("Unary operation ${mst.operation} not defined in $this")
|
||||
|
||||
open fun visitBinary(mst: Binary): ExpressionRef =
|
||||
error("Binary operation ${mst.operation} not defined in $this")
|
||||
|
||||
open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()")
|
||||
|
||||
fun visit(mst: MST): ExpressionRef = when (mst) {
|
||||
is Symbolic -> visitSymbolic(mst)
|
||||
is Numeric -> visitNumeric(mst)
|
||||
|
||||
is Unary -> when {
|
||||
algebra is NumericAlgebra && mst.value is Numeric -> visitNumeric(
|
||||
Numeric(algebra.unaryOperationFunction(mst.operation)(algebra.number((mst.value as Numeric).value))))
|
||||
|
||||
else -> visitUnary(mst)
|
||||
}
|
||||
|
||||
is Binary -> when {
|
||||
algebra is NumericAlgebra && mst.left is Numeric && mst.right is Numeric -> visitNumeric(Numeric(
|
||||
algebra.binaryOperationFunction(mst.operation)
|
||||
.invoke(algebra.number((mst.left as Numeric).value), algebra.number((mst.right as Numeric).value))
|
||||
))
|
||||
|
||||
else -> visitBinary(mst)
|
||||
}
|
||||
}
|
||||
|
||||
val instance by lazy {
|
||||
val c = WasmModule(with(createModule()) {
|
||||
ctx = this
|
||||
val expr = visit(target)
|
||||
|
||||
addFunction(
|
||||
"executable",
|
||||
createType(Array(keys.size) { binaryenType }),
|
||||
binaryenType,
|
||||
arrayOf(),
|
||||
expr
|
||||
)
|
||||
|
||||
setOptimizeLevel(3)
|
||||
optimizeFunction("executable")
|
||||
addFunctionExport("executable", "executable")
|
||||
val res = emitBinary()
|
||||
dispose()
|
||||
res
|
||||
})
|
||||
|
||||
val i = Instance(c, js("{}") as Any)
|
||||
val symbols = keys.map(::StringSymbol)
|
||||
keys.clear()
|
||||
|
||||
Expression<T> { args ->
|
||||
val params = symbols.map(args::getValue).toTypedArray()
|
||||
spreader(i.exports.asDynamic().executable, params) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class DoubleWasmBuilder(target: MST) : WasmBuilder<Double>(f64, DoubleField, target) {
|
||||
override fun createModule(): BinaryenModule = readBinary(f64StandardFunctions)
|
||||
|
||||
override fun visitNumeric(mst: Numeric): ExpressionRef = ctx.f64.const(mst.value)
|
||||
|
||||
override fun visitUnary(mst: Unary): ExpressionRef = when (mst.operation) {
|
||||
GroupOperations.MINUS_OPERATION -> ctx.f64.neg(visit(mst.value))
|
||||
GroupOperations.PLUS_OPERATION -> visit(mst.value)
|
||||
PowerOperations.SQRT_OPERATION -> ctx.f64.sqrt(visit(mst.value))
|
||||
TrigonometricOperations.SIN_OPERATION -> ctx.call("sin", arrayOf(visit(mst.value)), f64)
|
||||
TrigonometricOperations.COS_OPERATION -> ctx.call("cos", arrayOf(visit(mst.value)), f64)
|
||||
TrigonometricOperations.TAN_OPERATION -> ctx.call("tan", arrayOf(visit(mst.value)), f64)
|
||||
TrigonometricOperations.ASIN_OPERATION -> ctx.call("asin", arrayOf(visit(mst.value)), f64)
|
||||
TrigonometricOperations.ACOS_OPERATION -> ctx.call("acos", arrayOf(visit(mst.value)), f64)
|
||||
TrigonometricOperations.ATAN_OPERATION -> ctx.call("atan", arrayOf(visit(mst.value)), f64)
|
||||
ExponentialOperations.SINH_OPERATION -> ctx.call("sinh", arrayOf(visit(mst.value)), f64)
|
||||
ExponentialOperations.COSH_OPERATION -> ctx.call("cosh", arrayOf(visit(mst.value)), f64)
|
||||
ExponentialOperations.TANH_OPERATION -> ctx.call("tanh", arrayOf(visit(mst.value)), f64)
|
||||
ExponentialOperations.ASINH_OPERATION -> ctx.call("asinh", arrayOf(visit(mst.value)), f64)
|
||||
ExponentialOperations.ACOSH_OPERATION -> ctx.call("acosh", arrayOf(visit(mst.value)), f64)
|
||||
ExponentialOperations.ATANH_OPERATION -> ctx.call("atanh", arrayOf(visit(mst.value)), f64)
|
||||
ExponentialOperations.EXP_OPERATION -> ctx.call("exp", arrayOf(visit(mst.value)), f64)
|
||||
ExponentialOperations.LN_OPERATION -> ctx.call("log", arrayOf(visit(mst.value)), f64)
|
||||
else -> super.visitUnary(mst)
|
||||
}
|
||||
|
||||
override fun visitBinary(mst: Binary): ExpressionRef = when (mst.operation) {
|
||||
GroupOperations.PLUS_OPERATION -> ctx.f64.add(visit(mst.left), visit(mst.right))
|
||||
GroupOperations.MINUS_OPERATION -> ctx.f64.sub(visit(mst.left), visit(mst.right))
|
||||
RingOperations.TIMES_OPERATION -> ctx.f64.mul(visit(mst.left), visit(mst.right))
|
||||
FieldOperations.DIV_OPERATION -> ctx.f64.div(visit(mst.left), visit(mst.right))
|
||||
PowerOperations.POW_OPERATION -> ctx.call("pow", arrayOf(visit(mst.left), visit(mst.right)), f64)
|
||||
else -> super.visitBinary(mst)
|
||||
}
|
||||
}
|
||||
|
||||
internal class IntWasmBuilder(target: MST) : WasmBuilder<Int>(i32, IntRing, target) {
|
||||
override fun visitNumeric(mst: Numeric): ExpressionRef = ctx.i32.const(mst.value)
|
||||
|
||||
override fun visitUnary(mst: Unary): ExpressionRef = when (mst.operation) {
|
||||
GroupOperations.MINUS_OPERATION -> ctx.i32.sub(ctx.i32.const(0), visit(mst.value))
|
||||
GroupOperations.PLUS_OPERATION -> visit(mst.value)
|
||||
else -> super.visitUnary(mst)
|
||||
}
|
||||
|
||||
override fun visitBinary(mst: Binary): ExpressionRef = when (mst.operation) {
|
||||
GroupOperations.PLUS_OPERATION -> ctx.i32.add(visit(mst.left), visit(mst.right))
|
||||
GroupOperations.MINUS_OPERATION -> ctx.i32.sub(visit(mst.left), visit(mst.right))
|
||||
RingOperations.TIMES_OPERATION -> ctx.i32.mul(visit(mst.left), visit(mst.right))
|
||||
else -> super.visitBinary(mst)
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,77 @@
|
||||
package space.kscience.kmath.wasm
|
||||
|
||||
import space.kscience.kmath.estree.compileWith
|
||||
import space.kscience.kmath.expressions.Expression
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.IntRing
|
||||
import space.kscience.kmath.wasm.internal.DoubleWasmBuilder
|
||||
import space.kscience.kmath.wasm.internal.IntWasmBuilder
|
||||
|
||||
/**
|
||||
* Compiles an [MST] to WASM in the context of reals.
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun DoubleField.expression(mst: MST): Expression<Double> =
|
||||
DoubleWasmBuilder(mst).instance
|
||||
|
||||
/**
|
||||
* Compiles an [MST] to WASM in the context of integers.
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun IntRing.expression(mst: MST): Expression<Int> =
|
||||
IntWasmBuilder(mst).instance
|
||||
|
||||
/**
|
||||
* Create a compiled expression with given [MST] and given [algebra].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun MST.compileToExpression(algebra: IntRing): Expression<Int> = compileWith(algebra)
|
||||
|
||||
|
||||
/**
|
||||
* Compile given MST to expression and evaluate it against [arguments].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int =
|
||||
compileToExpression(algebra).invoke(arguments)
|
||||
|
||||
|
||||
/**
|
||||
* Compile given MST to expression and evaluate it against [arguments].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun MST.compile(algebra: IntRing, vararg arguments: Pair<Symbol, Int>): Int =
|
||||
compileToExpression(algebra)(*arguments)
|
||||
|
||||
/**
|
||||
* Create a compiled expression with given [MST] and given [algebra].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = compileWith(algebra)
|
||||
|
||||
|
||||
/**
|
||||
* Compile given MST to expression and evaluate it against [arguments].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double =
|
||||
compileToExpression(algebra).invoke(arguments)
|
||||
|
||||
|
||||
/**
|
||||
* Compile given MST to expression and evaluate it against [arguments].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun MST.compile(algebra: DoubleField, vararg arguments: Pair<Symbol, Double>): Double =
|
||||
compileToExpression(algebra).invoke(*arguments)
|
@ -0,0 +1,67 @@
|
||||
package space.kscience.kmath.ast
|
||||
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.math.sin
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.Test
|
||||
import kotlin.time.measureTime
|
||||
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
|
||||
import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
|
||||
|
||||
internal class TestExecutionTime {
|
||||
private companion object {
|
||||
private const val times = 1_000_000
|
||||
private val x by symbol
|
||||
private val algebra: ExtendedField<Double> = DoubleField
|
||||
|
||||
private val functional = DoubleField.expressionInExtendedField {
|
||||
bindSymbol(x) * const(2.0) + const(2.0) / bindSymbol(x) - const(16.0) / sin(bindSymbol(x))
|
||||
}
|
||||
|
||||
private val node = MstExtendedField {
|
||||
bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x))
|
||||
}
|
||||
|
||||
private val mst = node.toExpression(DoubleField)
|
||||
private val wasm = node.wasmCompileToExpression(DoubleField)
|
||||
private val estree = node.estreeCompileToExpression(DoubleField)
|
||||
|
||||
// In JavaScript, the expression below is implemented like
|
||||
// _no_name_provided__125.prototype.invoke_178 = function (args) {
|
||||
// var tmp = getValue(args, raw$_get_x__3(this._$x$delegate_2)) * 2.0 + 2.0 / getValue(args, raw$_get_x__3(this._$x$delegate_2));
|
||||
// var tmp0_sin_0_5 = getValue(args, raw$_get_x__3(this._$x$delegate_2));
|
||||
// return tmp - 16.0 / Math.sin(tmp0_sin_0_5);
|
||||
// };
|
||||
|
||||
private val raw = Expression<Double> { args ->
|
||||
args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / sin(args.getValue(x))
|
||||
}
|
||||
}
|
||||
|
||||
private fun invokeAndSum(name: String, expr: Expression<Double>) {
|
||||
println(name)
|
||||
val rng = Random(0)
|
||||
var sum = 0.0
|
||||
measureTime { repeat(times) { sum += expr(x to rng.nextDouble()) } }.also(::println)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun functionalExpression() = invokeAndSum("functional", functional)
|
||||
|
||||
@Test
|
||||
fun mstExpression() = invokeAndSum("mst", mst)
|
||||
|
||||
@Test
|
||||
fun wasmExpression() = invokeAndSum("wasm", wasm)
|
||||
|
||||
@Test
|
||||
fun estreeExpression() = invokeAndSum("estree", wasm)
|
||||
|
||||
@Test
|
||||
fun rawExpression() = invokeAndSum("raw", raw)
|
||||
}
|
@ -8,18 +8,17 @@ package space.kscience.kmath.estree
|
||||
import space.kscience.kmath.complex.ComplexField
|
||||
import space.kscience.kmath.complex.toComplex
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.ByteRing
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestESTreeConsistencyWithInterpreter {
|
||||
|
||||
@Test
|
||||
fun mstSpace() {
|
||||
|
||||
val mst = MstGroup {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
@ -30,12 +29,12 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
),
|
||||
|
||||
number(1)
|
||||
) + bindSymbol("x") + zero
|
||||
) + bindSymbol(x) + zero
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
mst.interpret(MstGroup, Symbol.x to MST.Numeric(2)),
|
||||
mst.compile(MstGroup, Symbol.x to MST.Numeric(2))
|
||||
mst.interpret(MstGroup, x to MST.Numeric(2)),
|
||||
mst.compile(MstGroup, x to MST.Numeric(2))
|
||||
)
|
||||
}
|
||||
|
||||
@ -44,7 +43,7 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
val mst = MstRing {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
(bindSymbol("x") - (2.toByte() + (scale(
|
||||
(bindSymbol(x) - (2.toByte() + (scale(
|
||||
add(number(1), number(1)),
|
||||
2.0
|
||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||
@ -55,24 +54,24 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
mst.interpret(ByteRing, Symbol.x to 3.toByte()),
|
||||
mst.compile(ByteRing, Symbol.x to 3.toByte())
|
||||
mst.interpret(ByteRing, x to 3.toByte()),
|
||||
mst.compile(ByteRing, x to 3.toByte())
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun realField() {
|
||||
fun doubleField() {
|
||||
val mst = MstField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
mst.interpret(DoubleField, Symbol.x to 2.0),
|
||||
mst.compile(DoubleField, Symbol.x to 2.0)
|
||||
mst.interpret(DoubleField, x to 2.0),
|
||||
mst.compile(DoubleField, x to 2.0)
|
||||
)
|
||||
}
|
||||
|
||||
@ -80,15 +79,19 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
fun complexField() {
|
||||
val mst = MstField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
mst.interpret(ComplexField, Symbol.x to 2.0.toComplex()),
|
||||
mst.compile(ComplexField, Symbol.x to 2.0.toComplex())
|
||||
mst.interpret(ComplexField, x to 2.0.toComplex()),
|
||||
mst.compile(ComplexField, x to 2.0.toComplex()),
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
||||
|
@ -5,43 +5,38 @@
|
||||
|
||||
package space.kscience.kmath.estree
|
||||
|
||||
import space.kscience.kmath.expressions.MstExtendedField
|
||||
import space.kscience.kmath.expressions.MstField
|
||||
import space.kscience.kmath.expressions.MstGroup
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestESTreeOperationsSupport {
|
||||
@Test
|
||||
fun testUnaryOperationInvocation() {
|
||||
val expression = MstExtendedField { -bindSymbol("x") }.compileToExpression(DoubleField)
|
||||
val res = expression("x" to 2.0)
|
||||
val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField)
|
||||
val res = expression(x to 2.0)
|
||||
assertEquals(-2.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBinaryOperationInvocation() {
|
||||
val expression = MstExtendedField { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField)
|
||||
val res = expression("x" to 2.0)
|
||||
val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField)
|
||||
val res = expression(x to 2.0)
|
||||
assertEquals(-1.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testConstProductInvocation() {
|
||||
val res = MstExtendedField { bindSymbol("x") * 2 }.compileToExpression(DoubleField)("x" to 2.0)
|
||||
val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0)
|
||||
assertEquals(4.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMultipleCalls() {
|
||||
val e =
|
||||
MstExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }
|
||||
.compileToExpression(DoubleField)
|
||||
val r = Random(0)
|
||||
var s = 0.0
|
||||
repeat(1000000) { s += e("x" to r.nextDouble()) }
|
||||
println(s)
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,9 @@ package space.kscience.kmath.estree
|
||||
|
||||
import space.kscience.kmath.expressions.MstExtendedField
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -15,55 +17,60 @@ import kotlin.test.assertEquals
|
||||
internal class TestESTreeSpecialization {
|
||||
@Test
|
||||
fun testUnaryPlus() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
||||
assertEquals(2.0, expr("x" to 2.0))
|
||||
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(2.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUnaryMinus() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
||||
assertEquals(-2.0, expr("x" to 2.0))
|
||||
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(-2.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAdd() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("+")(bindSymbol("x"),
|
||||
bindSymbol("x"))
|
||||
binaryOperationFunction("+")(
|
||||
bindSymbol(x),
|
||||
bindSymbol(x),
|
||||
)
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(4.0, expr("x" to 2.0))
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSine() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr("x" to 0.0))
|
||||
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr(x to 0.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinus() {
|
||||
fun testSubtract() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("-")(bindSymbol("x"),
|
||||
bindSymbol("x"))
|
||||
binaryOperationFunction("-")(bindSymbol(x),
|
||||
bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr("x" to 2.0))
|
||||
assertEquals(0.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDivide() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("/")(bindSymbol("x"),
|
||||
bindSymbol("x"))
|
||||
binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(1.0, expr("x" to 2.0))
|
||||
assertEquals(1.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPower() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("pow")(bindSymbol("x"), number(2))
|
||||
binaryOperationFunction("pow")(bindSymbol(x), number(2))
|
||||
}.compileToExpression(DoubleField)
|
||||
|
||||
assertEquals(4.0, expr("x" to 2.0))
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,9 @@ package space.kscience.kmath.estree
|
||||
|
||||
import space.kscience.kmath.expressions.MstRing
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.ByteRing
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -16,13 +18,17 @@ import kotlin.test.assertFailsWith
|
||||
internal class TestESTreeVariables {
|
||||
@Test
|
||||
fun testVariable() {
|
||||
val expr = MstRing{ bindSymbol("x") }.compileToExpression(ByteRing)
|
||||
assertEquals(1.toByte(), expr("x" to 1.toByte()))
|
||||
val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing)
|
||||
assertEquals(1.toByte(), expr(x to 1.toByte()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUndefinedVariableFails() {
|
||||
val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing)
|
||||
val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing)
|
||||
assertFailsWith<NoSuchElementException> { expr() }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.wasm
|
||||
|
||||
import space.kscience.kmath.expressions.MstField
|
||||
import space.kscience.kmath.expressions.MstRing
|
||||
import space.kscience.kmath.expressions.interpret
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.IntRing
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestWasmConsistencyWithInterpreter {
|
||||
@Test
|
||||
fun intRing() {
|
||||
val mst = MstRing {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
(bindSymbol(x) - (2.toByte() + (scale(
|
||||
add(number(1), number(1)),
|
||||
2.0
|
||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||
),
|
||||
|
||||
number(1)
|
||||
) * number(2)
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
mst.interpret(IntRing, x to 3),
|
||||
mst.compile(IntRing, x to 3)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleField() {
|
||||
val mst = MstField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
mst.interpret(DoubleField, x to 2.0),
|
||||
mst.compile(DoubleField, x to 2.0)
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.wasm
|
||||
|
||||
import space.kscience.kmath.expressions.MstField
|
||||
import space.kscience.kmath.expressions.MstGroup
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestWasmOperationsSupport {
|
||||
@Test
|
||||
fun testUnaryOperationInvocation() {
|
||||
val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField)
|
||||
val res = expression(x to 2.0)
|
||||
assertEquals(-2.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBinaryOperationInvocation() {
|
||||
val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField)
|
||||
val res = expression(x to 2.0)
|
||||
assertEquals(-1.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testConstProductInvocation() {
|
||||
val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0)
|
||||
assertEquals(4.0, res)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.wasm
|
||||
|
||||
import space.kscience.kmath.expressions.MstExtendedField
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestWasmSpecialization {
|
||||
@Test
|
||||
fun testUnaryPlus() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(2.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUnaryMinus() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(-2.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAdd() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("+")(
|
||||
bindSymbol(x),
|
||||
bindSymbol(x),
|
||||
)
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSine() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr(x to 0.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSubtract() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("-")(bindSymbol(x),
|
||||
bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDivide() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(1.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPower() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("pow")(bindSymbol(x), number(2))
|
||||
}.compileToExpression(DoubleField)
|
||||
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package space.kscience.kmath.wasm
|
||||
|
||||
import space.kscience.kmath.expressions.MstExtendedField
|
||||
import space.kscience.kmath.expressions.MstRing
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.IntRing
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestWasmSpecific {
|
||||
@Test
|
||||
fun int() {
|
||||
val res = MstRing { number(100000000) + number(10000000) }.compile(IntRing)
|
||||
assertEquals(110000000, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun real() {
|
||||
val res = MstExtendedField { number(100000000) + number(2).pow(10) }.compile(DoubleField)
|
||||
assertEquals(100001024.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun argsPassing() {
|
||||
val res = MstExtendedField { bindSymbol(y) + bindSymbol(x).pow(10) }.compile(
|
||||
DoubleField,
|
||||
x to 2.0,
|
||||
y to 100000000.0,
|
||||
)
|
||||
|
||||
assertEquals(100001024.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun powFunction() {
|
||||
val expr = MstExtendedField { bindSymbol(x).pow(1.0 / 6.0) }.compileToExpression(DoubleField)
|
||||
assertEquals(0.9730585187140817, expr(x to 0.8488554755054833))
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
private val y by symbol
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.wasm
|
||||
|
||||
import space.kscience.kmath.expressions.MstRing
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.IntRing
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
internal class TestWasmVariables {
|
||||
@Test
|
||||
fun testVariable() {
|
||||
val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
|
||||
assertEquals(1, expr(x to 1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUndefinedVariableFails() {
|
||||
val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
|
||||
assertFailsWith<NoSuchElementException> { expr() }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -8,18 +8,17 @@ package space.kscience.kmath.asm
|
||||
import space.kscience.kmath.complex.ComplexField
|
||||
import space.kscience.kmath.complex.toComplex
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.misc.Symbol.Companion.x
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.ByteRing
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestAsmConsistencyWithInterpreter {
|
||||
|
||||
@Test
|
||||
fun mstSpace() {
|
||||
|
||||
val mst = MstGroup {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
@ -30,7 +29,7 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
),
|
||||
|
||||
number(1)
|
||||
) + bindSymbol("x") + zero
|
||||
) + bindSymbol(x) + zero
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
@ -44,7 +43,7 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
val mst = MstRing {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
(bindSymbol("x") - (2.toByte() + (scale(
|
||||
(bindSymbol(x) - (2.toByte() + (scale(
|
||||
add(number(1), number(1)),
|
||||
2.0
|
||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||
@ -61,10 +60,10 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun realField() {
|
||||
fun doubleField() {
|
||||
val mst = MstField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
@ -80,7 +79,7 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
fun complexField() {
|
||||
val mst = MstField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
@ -91,4 +90,8 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
mst.compile(ComplexField, x to 2.0.toComplex())
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
||||
|
@ -5,45 +5,38 @@
|
||||
|
||||
package space.kscience.kmath.asm
|
||||
|
||||
import space.kscience.kmath.expressions.MstExtendedField
|
||||
import space.kscience.kmath.expressions.MstField
|
||||
import space.kscience.kmath.expressions.MstGroup
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestAsmOperationsSupport {
|
||||
@Test
|
||||
fun testUnaryOperationInvocation() {
|
||||
val expression = MstGroup { -bindSymbol("x") }.compileToExpression(DoubleField)
|
||||
val res = expression("x" to 2.0)
|
||||
val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField)
|
||||
val res = expression(x to 2.0)
|
||||
assertEquals(-2.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBinaryOperationInvocation() {
|
||||
val expression = MstGroup { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField)
|
||||
val res = expression("x" to 2.0)
|
||||
val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField)
|
||||
val res = expression(x to 2.0)
|
||||
assertEquals(-1.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testConstProductInvocation() {
|
||||
val res = MstField { bindSymbol("x") * 2 }.compileToExpression(DoubleField)("x" to 2.0)
|
||||
val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0)
|
||||
assertEquals(4.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMultipleCalls() {
|
||||
val e =
|
||||
MstExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }
|
||||
.compileToExpression(DoubleField)
|
||||
val r = Random(0)
|
||||
var s = 0.0
|
||||
repeat(1000000) { s += e("x" to r.nextDouble()) }
|
||||
println(s)
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,9 @@ package space.kscience.kmath.asm
|
||||
|
||||
import space.kscience.kmath.expressions.MstExtendedField
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -15,55 +17,60 @@ import kotlin.test.assertEquals
|
||||
internal class TestAsmSpecialization {
|
||||
@Test
|
||||
fun testUnaryPlus() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
||||
assertEquals(2.0, expr("x" to 2.0))
|
||||
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(2.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUnaryMinus() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
||||
assertEquals(-2.0, expr("x" to 2.0))
|
||||
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(-2.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAdd() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("+")(bindSymbol("x"),
|
||||
bindSymbol("x"))
|
||||
binaryOperationFunction("+")(
|
||||
bindSymbol(x),
|
||||
bindSymbol(x),
|
||||
)
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(4.0, expr("x" to 2.0))
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSine() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr("x" to 0.0))
|
||||
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr(x to 0.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinus() {
|
||||
fun testSubtract() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("-")(bindSymbol("x"),
|
||||
bindSymbol("x"))
|
||||
binaryOperationFunction("-")(bindSymbol(x),
|
||||
bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr("x" to 2.0))
|
||||
assertEquals(0.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDivide() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("/")(bindSymbol("x"),
|
||||
bindSymbol("x"))
|
||||
binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(1.0, expr("x" to 2.0))
|
||||
assertEquals(1.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPower() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("pow")(bindSymbol("x"), number(2))
|
||||
binaryOperationFunction("pow")(bindSymbol(x), number(2))
|
||||
}.compileToExpression(DoubleField)
|
||||
|
||||
assertEquals(4.0, expr("x" to 2.0))
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,9 @@ package space.kscience.kmath.asm
|
||||
|
||||
import space.kscience.kmath.expressions.MstRing
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.ByteRing
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -16,13 +18,17 @@ import kotlin.test.assertFailsWith
|
||||
internal class TestAsmVariables {
|
||||
@Test
|
||||
fun testVariable() {
|
||||
val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing)
|
||||
assertEquals(1.toByte(), expr("x" to 1.toByte()))
|
||||
val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing)
|
||||
assertEquals(1.toByte(), expr(x to 1.toByte()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUndefinedVariableFails() {
|
||||
val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing)
|
||||
val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing)
|
||||
assertFailsWith<NoSuchElementException> { expr() }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
||||
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.ast.rendering.TestUtils.testLatex
|
||||
import space.kscience.kmath.expressions.MST.Numeric
|
||||
import kotlin.test.Test
|
||||
|
||||
internal class TestFeatures {
|
||||
@Test
|
||||
fun printSymbolic() = testLatex("x", "x")
|
||||
|
||||
@Test
|
||||
fun printNumeric() {
|
||||
val num = object : Number() {
|
||||
override fun toByte(): Byte = throw UnsupportedOperationException()
|
||||
override fun toChar(): Char = throw UnsupportedOperationException()
|
||||
override fun toDouble(): Double = throw UnsupportedOperationException()
|
||||
override fun toFloat(): Float = throw UnsupportedOperationException()
|
||||
override fun toInt(): Int = throw UnsupportedOperationException()
|
||||
override fun toLong(): Long = throw UnsupportedOperationException()
|
||||
override fun toShort(): Short = throw UnsupportedOperationException()
|
||||
override fun toString(): String = "foo"
|
||||
}
|
||||
|
||||
testLatex(Numeric(num), "foo")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun prettyPrintFloats() {
|
||||
testLatex(Numeric(Double.NaN), "NaN")
|
||||
testLatex(Numeric(Double.POSITIVE_INFINITY), "\\infty")
|
||||
testLatex(Numeric(Double.NEGATIVE_INFINITY), "-\\infty")
|
||||
testLatex(Numeric(1.0), "1")
|
||||
testLatex(Numeric(-1.0), "-1")
|
||||
testLatex(Numeric(1.42), "1.42")
|
||||
testLatex(Numeric(-1.42), "-1.42")
|
||||
testLatex(Numeric(1.1e10), "1.1\\times10^{10}")
|
||||
testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}")
|
||||
testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}")
|
||||
testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun prettyPrintIntegers() {
|
||||
testLatex(Numeric(42), "42")
|
||||
testLatex(Numeric(-42), "-42")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun prettyPrintPi() {
|
||||
testLatex("pi", "\\pi")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun binaryPlus() = testLatex("2+2", "2+2")
|
||||
|
||||
@Test
|
||||
fun binaryMinus() = testLatex("2-2", "2-2")
|
||||
|
||||
@Test
|
||||
fun fraction() = testLatex("2/2", "\\frac{2}{2}")
|
||||
|
||||
@Test
|
||||
fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)")
|
||||
|
||||
@Test
|
||||
fun unaryOperator() = testLatex("f(x)", "\\operatorname{f}\\,\\left(x\\right)")
|
||||
|
||||
@Test
|
||||
fun power() = testLatex("x^y", "x^{y}")
|
||||
|
||||
@Test
|
||||
fun squareRoot() = testLatex("sqrt(x)", "\\sqrt{x}")
|
||||
|
||||
@Test
|
||||
fun exponential() = testLatex("exp(x)", "e^{x}")
|
||||
|
||||
@Test
|
||||
fun multiplication() = testLatex("x*1", "x\\times1")
|
||||
|
||||
@Test
|
||||
fun inverseTrigonometry() {
|
||||
testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)")
|
||||
testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)")
|
||||
testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)")
|
||||
testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)")
|
||||
testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)")
|
||||
testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)")
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun unaryPlus() {
|
||||
// testLatex("+1", "+1")
|
||||
// testLatex("+1", "++1")
|
||||
// }
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.ast.rendering.TestUtils.testLatex
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.operations.GroupOperations
|
||||
import kotlin.test.Test
|
||||
|
||||
internal class TestLatex {
|
||||
@Test
|
||||
fun number() = testLatex("42", "42")
|
||||
|
||||
@Test
|
||||
fun symbol() = testLatex("x", "x")
|
||||
|
||||
@Test
|
||||
fun operatorName() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)")
|
||||
|
||||
@Test
|
||||
fun specialSymbol() {
|
||||
testLatex(MST.Numeric(Double.POSITIVE_INFINITY), "\\infty")
|
||||
testLatex("pi", "\\pi")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun operand() {
|
||||
testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)")
|
||||
testLatex("1+1", "1+1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun unaryOperator() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)")
|
||||
|
||||
@Test
|
||||
fun unaryPlus() = testLatex(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1")
|
||||
|
||||
@Test
|
||||
fun unaryMinus() = testLatex("-x", "-x")
|
||||
|
||||
@Test
|
||||
fun radical() = testLatex("sqrt(x)", "\\sqrt{x}")
|
||||
|
||||
@Test
|
||||
fun superscript() = testLatex("x^y", "x^{y}")
|
||||
|
||||
@Test
|
||||
fun subscript() = testLatex(SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), "x_{123}")
|
||||
|
||||
@Test
|
||||
fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)")
|
||||
|
||||
@Test
|
||||
fun binaryPlus() = testLatex("x+x", "x+x")
|
||||
|
||||
@Test
|
||||
fun binaryMinus() = testLatex("x-x", "x-x")
|
||||
|
||||
@Test
|
||||
fun fraction() = testLatex("x/x", "\\frac{x}{x}")
|
||||
|
||||
@Test
|
||||
fun radicalWithIndex() = testLatex(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), "\\sqrt[x]{y}")
|
||||
|
||||
@Test
|
||||
fun multiplication() {
|
||||
testLatex("x*1", "x\\times1")
|
||||
testLatex("1*x", "1\\,x")
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.ast.rendering.TestUtils.testMathML
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.operations.GroupOperations
|
||||
import kotlin.test.Test
|
||||
|
||||
internal class TestMathML {
|
||||
@Test
|
||||
fun number() = testMathML("42", "<mn>42</mn>")
|
||||
|
||||
@Test
|
||||
fun symbol() = testMathML("x", "<mi>x</mi>")
|
||||
|
||||
@Test
|
||||
fun operatorName() = testMathML(
|
||||
"sin(1)",
|
||||
"<mo>sin</mo><mspace width=\"0.167em\"></mspace><mfenced open=\"(\" close=\")\" separators=\"\"><mn>1</mn></mfenced>",
|
||||
)
|
||||
|
||||
@Test
|
||||
fun specialSymbol() {
|
||||
testMathML(MST.Numeric(Double.POSITIVE_INFINITY), "<mo>∞</mo>")
|
||||
testMathML("pi", "<mo>π</mo>")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun operand() {
|
||||
testMathML(
|
||||
"sin(1)",
|
||||
"<mo>sin</mo><mspace width=\"0.167em\"></mspace><mfenced open=\"(\" close=\")\" separators=\"\"><mn>1</mn></mfenced>",
|
||||
)
|
||||
|
||||
testMathML("1+1", "<mn>1</mn><mo>+</mo><mn>1</mn>")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun unaryOperator() = testMathML(
|
||||
"sin(1)",
|
||||
"<mo>sin</mo><mspace width=\"0.167em\"></mspace><mfenced open=\"(\" close=\")\" separators=\"\"><mn>1</mn></mfenced>",
|
||||
)
|
||||
|
||||
@Test
|
||||
fun unaryPlus() =
|
||||
testMathML(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "<mo>+</mo><mn>1</mn>")
|
||||
|
||||
@Test
|
||||
fun unaryMinus() = testMathML("-x", "<mo>-</mo><mi>x</mi>")
|
||||
|
||||
@Test
|
||||
fun radical() = testMathML("sqrt(x)", "<msqrt><mi>x</mi></msqrt>")
|
||||
|
||||
@Test
|
||||
fun superscript() = testMathML("x^y", "<msup><mrow><mi>x</mi></mrow><mrow><mi>y</mi></mrow></msup>")
|
||||
|
||||
@Test
|
||||
fun subscript() = testMathML(
|
||||
SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")),
|
||||
"<msub><mrow><mi>x</mi></mrow><mrow><mn>123</mn></mrow></msub>",
|
||||
)
|
||||
|
||||
@Test
|
||||
fun binaryOperator() = testMathML(
|
||||
"f(x, y)",
|
||||
"<mo>f</mo><mfenced open=\"(\" close=\")\" separators=\"\"><mi>x</mi><mo>,</mo><mi>y</mi></mfenced>",
|
||||
)
|
||||
|
||||
@Test
|
||||
fun binaryPlus() = testMathML("x+x", "<mi>x</mi><mo>+</mo><mi>x</mi>")
|
||||
|
||||
@Test
|
||||
fun binaryMinus() = testMathML("x-x", "<mi>x</mi><mo>-</mo><mi>x</mi>")
|
||||
|
||||
@Test
|
||||
fun fraction() = testMathML("x/x", "<mfrac><mrow><mi>x</mi></mrow><mrow><mi>x</mi></mrow></mfrac>")
|
||||
|
||||
@Test
|
||||
fun radicalWithIndex() =
|
||||
testMathML(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")),
|
||||
"<mroot><mrow><mi>y</mi></mrow><mrow><mi>x</mi></mrow></mroot>")
|
||||
|
||||
@Test
|
||||
fun multiplication() {
|
||||
testMathML("x*1", "<mi>x</mi><mo>×</mo><mn>1</mn>")
|
||||
testMathML("1*x", "<mn>1</mn><mspace width=\"0.167em\"></mspace><mi>x</mi>")
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.ast.rendering.TestUtils.testLatex
|
||||
import kotlin.test.Test
|
||||
|
||||
internal class TestStages {
|
||||
@Test
|
||||
fun betterMultiplication() {
|
||||
testLatex("a*1", "a\\times1")
|
||||
testLatex("1*(2/3)", "1\\times\\left(\\frac{2}{3}\\right)")
|
||||
testLatex("1*1", "1\\times1")
|
||||
testLatex("2e10", "2\\times10^{10}")
|
||||
testLatex("2*x", "2\\,x")
|
||||
testLatex("2*(x+1)", "2\\,\\left(x+1\\right)")
|
||||
testLatex("x*y", "x\\,y")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parentheses() {
|
||||
testLatex("(x+1)", "x+1")
|
||||
testLatex("x*x*x", "x\\,x\\,x")
|
||||
testLatex("(x+x)*x", "\\left(x+x\\right)\\,x")
|
||||
testLatex("x+x*x", "x+x\\,x")
|
||||
testLatex("x+x^x*x+x", "x+x^{x}\\,x+x")
|
||||
testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x")
|
||||
testLatex("x^(x+x)", "x^{x+x}")
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.ast.parseMath
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal object TestUtils {
|
||||
private fun mathSyntax(mst: MST) = FeaturedMathRendererWithPostProcess.Default.render(mst)
|
||||
private fun latex(mst: MST) = LatexSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst))
|
||||
private fun mathML(mst: MST) = MathMLSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst))
|
||||
|
||||
internal fun testLatex(mst: MST, expectedLatex: String) = assertEquals(
|
||||
expected = expectedLatex,
|
||||
actual = latex(mst),
|
||||
)
|
||||
|
||||
internal fun testLatex(expression: String, expectedLatex: String) = assertEquals(
|
||||
expected = expectedLatex,
|
||||
actual = latex(expression.parseMath()),
|
||||
)
|
||||
|
||||
internal fun testLatex(expression: MathSyntax, expectedLatex: String) = assertEquals(
|
||||
expected = expectedLatex,
|
||||
actual = LatexSyntaxRenderer.renderWithStringBuilder(expression),
|
||||
)
|
||||
|
||||
internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals(
|
||||
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
|
||||
actual = mathML(mst),
|
||||
)
|
||||
|
||||
internal fun testMathML(expression: String, expectedMathML: String) = assertEquals(
|
||||
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
|
||||
actual = mathML(expression.parseMath()),
|
||||
)
|
||||
|
||||
internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals(
|
||||
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
|
||||
actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression),
|
||||
)
|
||||
}
|
@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath.
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-6`.
|
||||
The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-7`.
|
||||
|
||||
**Gradle:**
|
||||
```gradle
|
||||
@ -19,7 +19,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'space.kscience:kmath-complex:0.3.0-dev-6'
|
||||
implementation 'space.kscience:kmath-complex:0.3.0-dev-7'
|
||||
}
|
||||
```
|
||||
**Gradle Kotlin DSL:**
|
||||
@ -31,6 +31,6 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:kmath-complex:0.3.0-dev-6")
|
||||
implementation("space.kscience:kmath-complex:0.3.0-dev-7")
|
||||
}
|
||||
```
|
||||
|
@ -1,5 +1,3 @@
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
@ -21,7 +19,7 @@ kotlin.sourceSets {
|
||||
|
||||
readme {
|
||||
description = "Complex numbers and quaternions."
|
||||
maturity = Maturity.PROTOTYPE
|
||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
||||
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||
|
||||
feature(
|
||||
|
@ -15,7 +15,7 @@ performance calculations to code generation.
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-6`.
|
||||
The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-7`.
|
||||
|
||||
**Gradle:**
|
||||
```gradle
|
||||
@ -26,7 +26,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'space.kscience:kmath-core:0.3.0-dev-6'
|
||||
implementation 'space.kscience:kmath-core:0.3.0-dev-7'
|
||||
}
|
||||
```
|
||||
**Gradle Kotlin DSL:**
|
||||
@ -38,6 +38,6 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:kmath-core:0.3.0-dev-6")
|
||||
implementation("space.kscience:kmath-core:0.3.0-dev-7")
|
||||
}
|
||||
```
|
||||
|
@ -3,8 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("ru.mipt.npm.gradle.common")
|
||||
@ -21,7 +19,7 @@ kotlin.sourceSets {
|
||||
|
||||
readme {
|
||||
description = "Core classes, algebra definitions, basic linear algebra"
|
||||
maturity = Maturity.DEVELOPMENT
|
||||
maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT
|
||||
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||
|
||||
feature(
|
||||
|
@ -0,0 +1,18 @@
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
|
||||
internal class InterpretTest {
|
||||
@Test
|
||||
fun interpretation() {
|
||||
val expr = MstField {
|
||||
val x = bindSymbol(Symbol.x)
|
||||
x * 2.0 + number(2.0) / x - 16.0
|
||||
}.toExpression(DoubleField)
|
||||
expr(Symbol.x to 2.2)
|
||||
}
|
||||
}
|
@ -3,8 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("ru.mipt.npm.gradle.common")
|
||||
@ -29,5 +27,5 @@ kotlin.sourceSets {
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = Maturity.EXPERIMENTAL
|
||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||
}
|
@ -9,7 +9,7 @@ EJML based linear algebra implementation.
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-6`.
|
||||
The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-7`.
|
||||
|
||||
**Gradle:**
|
||||
```gradle
|
||||
@ -20,7 +20,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'space.kscience:kmath-ejml:0.3.0-dev-6'
|
||||
implementation 'space.kscience:kmath-ejml:0.3.0-dev-7'
|
||||
}
|
||||
```
|
||||
**Gradle Kotlin DSL:**
|
||||
@ -32,6 +32,6 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:kmath-ejml:0.3.0-dev-6")
|
||||
implementation("space.kscience:kmath-ejml:0.3.0-dev-7")
|
||||
}
|
||||
```
|
||||
|
@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers.
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-6`.
|
||||
The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-7`.
|
||||
|
||||
**Gradle:**
|
||||
```gradle
|
||||
@ -20,7 +20,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'space.kscience:kmath-for-real:0.3.0-dev-6'
|
||||
implementation 'space.kscience:kmath-for-real:0.3.0-dev-7'
|
||||
}
|
||||
```
|
||||
**Gradle Kotlin DSL:**
|
||||
@ -32,6 +32,6 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:kmath-for-real:0.3.0-dev-6")
|
||||
implementation("space.kscience:kmath-for-real:0.3.0-dev-7")
|
||||
}
|
||||
```
|
||||
|
@ -11,7 +11,7 @@ Functions and interpolations.
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-6`.
|
||||
The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-7`.
|
||||
|
||||
**Gradle:**
|
||||
```gradle
|
||||
@ -22,7 +22,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'space.kscience:kmath-functions:0.3.0-dev-6'
|
||||
implementation 'space.kscience:kmath-functions:0.3.0-dev-7'
|
||||
}
|
||||
```
|
||||
**Gradle Kotlin DSL:**
|
||||
@ -34,6 +34,6 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:kmath-functions:0.3.0-dev-6")
|
||||
implementation("space.kscience:kmath-functions:0.3.0-dev-7")
|
||||
}
|
||||
```
|
||||
|
@ -3,8 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("ru.mipt.npm.gradle.common")
|
||||
@ -17,5 +15,5 @@ kotlin.sourceSets.commonMain {
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = Maturity.PROTOTYPE
|
||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("ru.mipt.npm.gradle.common")
|
||||
@ -28,5 +26,5 @@ kotlin.sourceSets {
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = Maturity.PROTOTYPE
|
||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import space.kscience.kmath.asm.compileToExpression
|
||||
import space.kscience.kmath.ast.parseMath
|
||||
import space.kscience.kmath.expressions.MstAlgebra
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -19,8 +20,8 @@ import kotlin.test.fail
|
||||
internal class AdaptingTests {
|
||||
@Test
|
||||
fun symbol() {
|
||||
val c1 = MstAlgebra.bindSymbol("x")
|
||||
assertTrue(c1.toSVar<KMathNumber<Double, DoubleField>>().name == "x")
|
||||
val c1 = MstAlgebra.bindSymbol(x.identity)
|
||||
assertEquals(x.identity, c1.toSVar<KMathNumber<Double, DoubleField>>().name)
|
||||
val c2 = "kitten".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
|
||||
if (c2 is SVar) assertTrue(c2.name == "kitten") else fail()
|
||||
}
|
||||
@ -45,23 +46,27 @@ internal class AdaptingTests {
|
||||
|
||||
@Test
|
||||
fun simpleFunctionDerivative() {
|
||||
val x = MstAlgebra.bindSymbol("x").toSVar<KMathNumber<Double, DoubleField>>()
|
||||
val xSVar = MstAlgebra.bindSymbol(x.identity).toSVar<KMathNumber<Double, DoubleField>>()
|
||||
val quadratic = "x^2-4*x-44".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
|
||||
val actualDerivative = quadratic.d(x).toMst().compileToExpression(DoubleField)
|
||||
val actualDerivative = quadratic.d(xSVar).toMst().compileToExpression(DoubleField)
|
||||
val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField)
|
||||
assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0))
|
||||
assertEquals(actualDerivative(x to 123.0), expectedDerivative(x to 123.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun moreComplexDerivative() {
|
||||
val x = MstAlgebra.bindSymbol("x").toSVar<KMathNumber<Double, DoubleField>>()
|
||||
val xSVar = MstAlgebra.bindSymbol(x.identity).toSVar<KMathNumber<Double, DoubleField>>()
|
||||
val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
|
||||
val actualDerivative = composition.d(x).toMst().compileToExpression(DoubleField)
|
||||
val actualDerivative = composition.d(xSVar).toMst().compileToExpression(DoubleField)
|
||||
|
||||
val expectedDerivative =
|
||||
"-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))".parseMath().compileToExpression(DoubleField)
|
||||
val expectedDerivative = "-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))"
|
||||
.parseMath()
|
||||
.compileToExpression(DoubleField)
|
||||
|
||||
assertEquals(actualDerivative(x to 0.1), expectedDerivative(x to 0.1))
|
||||
}
|
||||
|
||||
assertEquals(actualDerivative("x" to 0.1), expectedDerivative("x" to 0.1))
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions.
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-6`.
|
||||
The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-7`.
|
||||
|
||||
**Gradle:**
|
||||
```gradle
|
||||
@ -20,7 +20,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'space.kscience:kmath-nd4j:0.3.0-dev-6'
|
||||
implementation 'space.kscience:kmath-nd4j:0.3.0-dev-7'
|
||||
}
|
||||
```
|
||||
**Gradle Kotlin DSL:**
|
||||
@ -32,7 +32,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:kmath-nd4j:0.3.0-dev-6")
|
||||
implementation("space.kscience:kmath-nd4j:0.3.0-dev-7")
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -3,8 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("ru.mipt.npm.gradle.common")
|
||||
@ -20,7 +18,7 @@ dependencies {
|
||||
|
||||
readme {
|
||||
description = "ND4J NDStructure implementation and according NDAlgebra classes"
|
||||
maturity = Maturity.EXPERIMENTAL
|
||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||
|
||||
feature(
|
||||
|
@ -3,8 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("ru.mipt.npm.gradle.common")
|
||||
@ -30,5 +28,5 @@ kotlin.sourceSets {
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = Maturity.EXPERIMENTAL
|
||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||
}
|
@ -3,8 +3,6 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import ru.mipt.npm.gradle.Maturity
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("ru.mipt.npm.gradle.common")
|
||||
@ -18,5 +16,5 @@ dependencies {
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = Maturity.DEVELOPMENT
|
||||
maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT
|
||||
}
|
Loading…
Reference in New Issue
Block a user