forked from kscience/kmath
Merge dev
This commit is contained in:
commit
76b5cd0de5
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,7 +1,12 @@
|
|||||||
.gradle
|
.gradle
|
||||||
build/
|
build/
|
||||||
out/
|
out/
|
||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
!.idea/copyright/
|
||||||
|
!.idea/scopes/
|
||||||
|
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
|
6
.idea/copyright/kmath.xml
Normal file
6
.idea/copyright/kmath.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="CopyrightManager">
|
||||||
|
<copyright>
|
||||||
|
<option name="notice" value="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." />
|
||||||
|
<option name="myName" value="kmath" />
|
||||||
|
</copyright>
|
||||||
|
</component>
|
21
.idea/copyright/profiles_settings.xml
Normal file
21
.idea/copyright/profiles_settings.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<component name="CopyrightManager">
|
||||||
|
<settings default="kmath">
|
||||||
|
<module2copyright>
|
||||||
|
<element module="Apply copyright" copyright="kmath" />
|
||||||
|
</module2copyright>
|
||||||
|
<LanguageOptions name="Groovy">
|
||||||
|
<option name="fileTypeOverride" value="1" />
|
||||||
|
</LanguageOptions>
|
||||||
|
<LanguageOptions name="HTML">
|
||||||
|
<option name="fileTypeOverride" value="1" />
|
||||||
|
<option name="prefixLines" value="false" />
|
||||||
|
</LanguageOptions>
|
||||||
|
<LanguageOptions name="Properties">
|
||||||
|
<option name="fileTypeOverride" value="1" />
|
||||||
|
</LanguageOptions>
|
||||||
|
<LanguageOptions name="XML">
|
||||||
|
<option name="fileTypeOverride" value="1" />
|
||||||
|
<option name="prefixLines" value="false" />
|
||||||
|
</LanguageOptions>
|
||||||
|
</settings>
|
||||||
|
</component>
|
4
.idea/scopes/Apply_copyright.xml
Normal file
4
.idea/scopes/Apply_copyright.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<component name="DependencyValidationManager">
|
||||||
|
<scope name="Apply copyright"
|
||||||
|
pattern="!file[*]:*//testData//*&&!file[*]:testData//*&&!file[*]:*.gradle.kts&&!file[*]:*.gradle&&!file[group:kotlin-ultimate]:*/&&!file[kotlin.libraries]:stdlib/api//*"/>
|
||||||
|
</component>
|
@ -7,6 +7,10 @@
|
|||||||
- Basic integration API
|
- Basic integration API
|
||||||
- Basic MPP distributions and samplers
|
- Basic MPP distributions and samplers
|
||||||
- bindSymbolOrNull
|
- bindSymbolOrNull
|
||||||
|
- Blocking chains and Statistics
|
||||||
|
- Multiplatform integration
|
||||||
|
- Integration for any Field element
|
||||||
|
- Extendend operations for ND4J fields
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Exponential operations merged with hyperbolic functions
|
- Exponential operations merged with hyperbolic functions
|
||||||
@ -18,6 +22,8 @@
|
|||||||
- DataSets are moved from functions to core
|
- DataSets are moved from functions to core
|
||||||
- Redesign advanced Chain API
|
- Redesign advanced Chain API
|
||||||
- Redesign MST. Remove MSTExpression.
|
- Redesign MST. Remove MSTExpression.
|
||||||
|
- Move MST to core
|
||||||
|
- Separated benchmarks and examples
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
@ -28,6 +34,7 @@
|
|||||||
- MSTExpression
|
- MSTExpression
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- Ring inherits RingOperations, not GroupOperations
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
|
35
README.md
35
README.md
@ -11,6 +11,8 @@ Python's NumPy library. Later we found that kotlin is much more flexible languag
|
|||||||
designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
|
designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
|
||||||
be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
||||||
|
|
||||||
|
[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/)
|
||||||
|
|
||||||
## Publications and talks
|
## Publications and talks
|
||||||
|
|
||||||
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
|
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
|
||||||
@ -74,6 +76,12 @@ KMath is a modular library. Different modules provide different features with di
|
|||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
|
* ### [benchmarks](benchmarks)
|
||||||
|
>
|
||||||
|
>
|
||||||
|
> **Maturity**: EXPERIMENTAL
|
||||||
|
<hr/>
|
||||||
|
|
||||||
* ### [examples](examples)
|
* ### [examples](examples)
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
@ -86,12 +94,10 @@ KMath is a modular library. Different modules provide different features with di
|
|||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
>
|
>
|
||||||
> **Features:**
|
> **Features:**
|
||||||
> - [expression-language](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
> - [expression-language](kmath-ast/src/commonMain/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
|
|
||||||
> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
|
> - [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
|
> - [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/>
|
<hr/>
|
||||||
|
|
||||||
@ -169,15 +175,16 @@ One can still use generic algebras though.
|
|||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-functions](kmath-functions)
|
* ### [kmath-functions](kmath-functions)
|
||||||
> Functions and interpolation
|
> Functions, integration and interpolation
|
||||||
>
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: EXPERIMENTAL
|
||||||
>
|
>
|
||||||
> **Features:**
|
> **Features:**
|
||||||
> - [piecewise](kmath-functions/Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt
|
> - [piecewise](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt) : Piecewise functions.
|
||||||
> - [polynomials](kmath-functions/Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt
|
> - [polynomials](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt) : Polynomial functions.
|
||||||
> - [linear interpolation](kmath-functions/Linear XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt
|
> - [linear interpolation](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt) : Linear XY interpolator.
|
||||||
> - [spline interpolation](kmath-functions/Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt
|
> - [spline interpolation](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt) : Cubic spline XY interpolator.
|
||||||
|
> - [integration](kmath-functions/#) : Univariate and multivariate quadratures
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
@ -248,6 +255,10 @@ cases. We expect the worst KMath benchmarks will perform better than native Pyth
|
|||||||
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
|
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
|
||||||
better than SciPy.
|
better than SciPy.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for execution in order to get better performance.
|
||||||
|
|
||||||
### Repositories
|
### Repositories
|
||||||
|
|
||||||
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
||||||
@ -259,8 +270,8 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api("space.kscience:kmath-core:0.3.0-dev-4")
|
api("space.kscience:kmath-core:0.3.0-dev-7")
|
||||||
// api("kscience.kmath:kmath-core-jvm:0.3.0-dev-4") for jvm-specific version
|
// api("space.kscience:kmath-core-jvm:0.3.0-dev-7") for jvm-specific version
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
130
benchmarks/build.gradle.kts
Normal file
130
benchmarks/build.gradle.kts
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
kotlin("plugin.allopen")
|
||||||
|
id("org.jetbrains.kotlinx.benchmark")
|
||||||
|
}
|
||||||
|
|
||||||
|
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
||||||
|
sourceSets.register("benchmarks")
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
jcenter()
|
||||||
|
maven("https://repo.kotlin.link")
|
||||||
|
maven("https://clojars.org/repo")
|
||||||
|
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||||
|
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||||
|
maven("https://jitpack.io")
|
||||||
|
maven {
|
||||||
|
setUrl("http://logicrunch.research.it.uu.se/maven/")
|
||||||
|
isAllowInsecureProtocol = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvm()
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
val commonMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":kmath-ast"))
|
||||||
|
implementation(project(":kmath-core"))
|
||||||
|
implementation(project(":kmath-coroutines"))
|
||||||
|
implementation(project(":kmath-complex"))
|
||||||
|
implementation(project(":kmath-stat"))
|
||||||
|
implementation(project(":kmath-dimensions"))
|
||||||
|
implementation(project(":kmath-for-real"))
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val jvmMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":kmath-commons"))
|
||||||
|
implementation(project(":kmath-ejml"))
|
||||||
|
implementation(project(":kmath-nd4j"))
|
||||||
|
implementation(project(":kmath-kotlingrad"))
|
||||||
|
implementation(project(":kmath-viktor"))
|
||||||
|
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
|
||||||
|
|
||||||
|
// uncomment if your system supports AVX2
|
||||||
|
// val os = System.getProperty("os.name")
|
||||||
|
//
|
||||||
|
// if (System.getProperty("os.arch") in arrayOf("x86_64", "amd64")) when {
|
||||||
|
// os.startsWith("Windows") -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:windows-x86_64-avx2")
|
||||||
|
// os == "Linux" -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:linux-x86_64-avx2")
|
||||||
|
// os == "Mac OS X" -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:macosx-x86_64-avx2")
|
||||||
|
// } else
|
||||||
|
// implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure benchmark
|
||||||
|
benchmark {
|
||||||
|
// Setup configurations
|
||||||
|
targets {
|
||||||
|
register("jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
|
||||||
|
warmups = 1
|
||||||
|
iterations = 5
|
||||||
|
iterationTime = 1000
|
||||||
|
iterationTimeUnit = "ms"
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.register("buffer") {
|
||||||
|
commonConfiguration()
|
||||||
|
include("BufferBenchmark")
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.register("dot") {
|
||||||
|
commonConfiguration()
|
||||||
|
include("DotBenchmark")
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.register("expressions") {
|
||||||
|
commonConfiguration()
|
||||||
|
include("ExpressionsInterpretersBenchmark")
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.register("matrixInverse") {
|
||||||
|
commonConfiguration()
|
||||||
|
include("MatrixInverseBenchmark")
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.register("bigInt") {
|
||||||
|
commonConfiguration()
|
||||||
|
include("BigIntBenchmark")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix kotlinx-benchmarks bug
|
||||||
|
afterEvaluate {
|
||||||
|
val jvmBenchmarkJar by tasks.getting(org.gradle.jvm.tasks.Jar::class) {
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
kotlin.sourceSets.all {
|
||||||
|
with(languageSettings) {
|
||||||
|
useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
|
||||||
|
useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
|
||||||
|
useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "11"
|
||||||
|
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
readme {
|
||||||
|
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||||
|
}
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
import kotlinx.benchmark.Benchmark
|
import kotlinx.benchmark.Benchmark
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
|
|
||||||
|
import kotlinx.benchmark.Blackhole
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark
|
||||||
|
import org.openjdk.jmh.annotations.Scope
|
||||||
|
import org.openjdk.jmh.annotations.State
|
||||||
|
import space.kscience.kmath.operations.BigInt
|
||||||
|
import space.kscience.kmath.operations.BigIntField
|
||||||
|
import space.kscience.kmath.operations.JBigIntegerField
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
|
private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ZERO)
|
||||||
|
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
internal class BigIntBenchmark {
|
||||||
|
|
||||||
|
val kmNumber = BigIntField.number(Int.MAX_VALUE)
|
||||||
|
val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE)
|
||||||
|
val largeKmNumber = BigIntField { number(11).pow(100_000) }
|
||||||
|
val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) }
|
||||||
|
val bigExponent = 50_000
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun kmAdd(blackhole: Blackhole) = BigIntField {
|
||||||
|
blackhole.consume(kmNumber + kmNumber + kmNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun jvmAdd(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume(jvmNumber + jvmNumber + jvmNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun kmMultiply(blackhole: Blackhole) = BigIntField {
|
||||||
|
blackhole.consume(kmNumber * kmNumber * kmNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun kmMultiplyLarge(blackhole: Blackhole) = BigIntField {
|
||||||
|
blackhole.consume(largeKmNumber*largeKmNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun jvmMultiply(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume(jvmNumber * jvmNumber * jvmNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun jvmMultiplyLarge(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume(largeJvmNumber*largeJvmNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Benchmark
|
||||||
|
// fun kmPower(blackhole: Blackhole) = BigIntField {
|
||||||
|
// blackhole.consume(kmNumber.pow(bigExponent))
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Benchmark
|
||||||
|
// fun jvmPower(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
// blackhole.consume(jvmNumber.pow(bigExponent))
|
||||||
|
// }
|
||||||
|
}
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
import kotlinx.benchmark.Benchmark
|
import kotlinx.benchmark.Benchmark
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
import kotlinx.benchmark.Benchmark
|
import kotlinx.benchmark.Benchmark
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
|
import kotlinx.benchmark.Benchmark
|
||||||
|
import kotlinx.benchmark.Blackhole
|
||||||
|
import kotlinx.benchmark.Scope
|
||||||
|
import kotlinx.benchmark.State
|
||||||
|
import space.kscience.kmath.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
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
internal class ExpressionsInterpretersBenchmark {
|
||||||
|
@Benchmark
|
||||||
|
fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun asmExpression(blackhole: Blackhole) = invokeAndSum(asm, blackhole)
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole)
|
||||||
|
|
||||||
|
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
|
||||||
|
val random = Random(0)
|
||||||
|
var sum = 0.0
|
||||||
|
|
||||||
|
repeat(times) {
|
||||||
|
sum += expr(x to random.nextDouble())
|
||||||
|
}
|
||||||
|
|
||||||
|
blackhole.consume(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
import kotlinx.benchmark.Benchmark
|
import kotlinx.benchmark.Benchmark
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
import kotlinx.benchmark.Benchmark
|
import kotlinx.benchmark.Benchmark
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
import kotlinx.benchmark.Benchmark
|
import kotlinx.benchmark.Benchmark
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
import kotlinx.benchmark.Benchmark
|
import kotlinx.benchmark.Benchmark
|
@ -1,7 +1,3 @@
|
|||||||
import org.jetbrains.dokka.gradle.DokkaTask
|
|
||||||
import ru.mipt.npm.gradle.KSciencePublishingPlugin
|
|
||||||
import java.net.URL
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.project")
|
id("ru.mipt.npm.gradle.project")
|
||||||
}
|
}
|
||||||
@ -13,19 +9,21 @@ allprojects {
|
|||||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
maven("http://logicrunch.research.it.uu.se/maven/")
|
maven("http://logicrunch.research.it.uu.se/maven/") {
|
||||||
|
isAllowInsecureProtocol = true
|
||||||
|
}
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.3.0-dev-5"
|
version = "0.3.0-dev-7"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
if (name.startsWith("kmath")) apply<KSciencePublishingPlugin>()
|
if (name.startsWith("kmath")) apply<MavenPublishPlugin>()
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
tasks.withType<DokkaTask> {
|
tasks.withType<org.jetbrains.dokka.gradle.DokkaTask> {
|
||||||
dokkaSourceSets.all {
|
dokkaSourceSets.all {
|
||||||
val readmeFile = File(this@subprojects.projectDir, "./README.md")
|
val readmeFile = File(this@subprojects.projectDir, "./README.md")
|
||||||
if (readmeFile.exists())
|
if (readmeFile.exists())
|
||||||
@ -35,7 +33,7 @@ subprojects {
|
|||||||
"http://ejml.org/javadoc/",
|
"http://ejml.org/javadoc/",
|
||||||
"https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/",
|
"https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/",
|
||||||
"https://deeplearning4j.org/api/latest/"
|
"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 {
|
externalDocumentationLink {
|
||||||
packageListUrl.set(a)
|
packageListUrl.set(a)
|
||||||
url.set(b)
|
url.set(b)
|
||||||
|
8
docs/templates/README-TEMPLATE.md
vendored
8
docs/templates/README-TEMPLATE.md
vendored
@ -11,6 +11,8 @@ Python's NumPy library. Later we found that kotlin is much more flexible languag
|
|||||||
designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
|
designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
|
||||||
be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
||||||
|
|
||||||
|
[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/)
|
||||||
|
|
||||||
## Publications and talks
|
## Publications and talks
|
||||||
|
|
||||||
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
|
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
|
||||||
@ -92,6 +94,10 @@ cases. We expect the worst KMath benchmarks will perform better than native Pyth
|
|||||||
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
|
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
|
||||||
better than SciPy.
|
better than SciPy.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for execution in order to get better performance.
|
||||||
|
|
||||||
### Repositories
|
### Repositories
|
||||||
|
|
||||||
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
||||||
@ -104,7 +110,7 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api("${group}:kmath-core:$version")
|
api("${group}:kmath-core:$version")
|
||||||
// api("kscience.kmath:kmath-core-jvm:$version") for jvm-specific version
|
// api("${group}:kmath-core-jvm:$version") for jvm-specific version
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,27 +1,19 @@
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm")
|
kotlin("jvm")
|
||||||
kotlin("plugin.allopen")
|
|
||||||
id("kotlinx.benchmark")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
|
||||||
sourceSets.register("benchmarks")
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
jcenter()
|
jcenter()
|
||||||
maven("https://repo.kotlin.link")
|
maven("https://repo.kotlin.link")
|
||||||
maven("https://clojars.org/repo")
|
maven("https://clojars.org/repo")
|
||||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
|
||||||
maven("https://dl.bintray.com/kotlin/kotlinx")
|
|
||||||
maven("https://dl.bintray.com/mipt-npm/dev")
|
|
||||||
maven("https://dl.bintray.com/mipt-npm/kscience")
|
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
maven("http://logicrunch.research.it.uu.se/maven/")
|
maven{
|
||||||
mavenCentral()
|
setUrl("http://logicrunch.research.it.uu.se/maven/")
|
||||||
|
isAllowInsecureProtocol = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -39,7 +31,6 @@ dependencies {
|
|||||||
|
|
||||||
implementation(project(":kmath-for-real"))
|
implementation(project(":kmath-for-real"))
|
||||||
|
|
||||||
implementation("org.deeplearning4j:deeplearning4j-core:1.0.0-beta7")
|
|
||||||
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
|
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
|
||||||
|
|
||||||
// uncomment if your system supports AVX2
|
// uncomment if your system supports AVX2
|
||||||
@ -52,54 +43,9 @@ dependencies {
|
|||||||
// } else
|
// } else
|
||||||
implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
|
implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-io:0.2.0-npm-dev-11")
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20")
|
|
||||||
implementation("org.slf4j:slf4j-simple:1.7.30")
|
implementation("org.slf4j:slf4j-simple:1.7.30")
|
||||||
|
|
||||||
// plotting
|
// plotting
|
||||||
implementation("kscience.plotlykt:plotlykt-server:0.3.1-dev")
|
implementation("space.kscience:plotlykt-server:0.4.0-dev-2")
|
||||||
|
|
||||||
"benchmarksImplementation"("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-20")
|
|
||||||
"benchmarksImplementation"(sourceSets.main.get().output + sourceSets.main.get().runtimeClasspath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure benchmark
|
|
||||||
benchmark {
|
|
||||||
// Setup configurations
|
|
||||||
targets.register("benchmarks")
|
|
||||||
// This one matches sourceSet name above
|
|
||||||
|
|
||||||
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
|
|
||||||
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
|
|
||||||
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
|
|
||||||
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
|
|
||||||
include("MatrixInverseBenchmark")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin.sourceSets.all {
|
kotlin.sourceSets.all {
|
||||||
@ -110,8 +56,11 @@ kotlin.sourceSets.all {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<KotlinCompile> {
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||||
kotlinOptions.jvmTarget = "11"
|
kotlinOptions{
|
||||||
|
jvmTarget = "11"
|
||||||
|
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
package space.kscience.kmath.benchmarks
|
|
||||||
|
|
||||||
import kotlinx.benchmark.Benchmark
|
|
||||||
import kotlinx.benchmark.Blackhole
|
|
||||||
import kotlinx.benchmark.Scope
|
|
||||||
import kotlinx.benchmark.State
|
|
||||||
import space.kscience.kmath.asm.compileToExpression
|
|
||||||
import space.kscience.kmath.ast.MstField
|
|
||||||
import space.kscience.kmath.ast.toExpression
|
|
||||||
import space.kscience.kmath.expressions.Expression
|
|
||||||
import space.kscience.kmath.expressions.expressionInField
|
|
||||||
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
|
|
||||||
|
|
||||||
@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)
|
|
||||||
}
|
|
||||||
|
|
||||||
@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)
|
|
||||||
}
|
|
||||||
|
|
||||||
@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)
|
|
||||||
}
|
|
||||||
|
|
||||||
@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)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
|
|
||||||
val random = Random(0)
|
|
||||||
var sum = 0.0
|
|
||||||
|
|
||||||
repeat(1000000) {
|
|
||||||
sum += expr(x to random.nextDouble())
|
|
||||||
}
|
|
||||||
|
|
||||||
blackhole.consume(sum)
|
|
||||||
}
|
|
||||||
|
|
||||||
private companion object {
|
|
||||||
private val algebra = DoubleField
|
|
||||||
private val x by symbol
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess
|
import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess
|
||||||
|
@ -1,5 +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.kscience.kmath.ast
|
||||||
|
|
||||||
|
import space.kscience.kmath.expressions.MstField
|
||||||
|
import space.kscience.kmath.expressions.interpret
|
||||||
import space.kscience.kmath.misc.Symbol.Companion.x
|
import space.kscience.kmath.misc.Symbol.Companion.x
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
import space.kscience.kmath.asm.compileToExpression
|
import space.kscience.kmath.asm.compileToExpression
|
||||||
@ -20,5 +25,5 @@ fun main() {
|
|||||||
|
|
||||||
|
|
||||||
val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField)
|
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))
|
||||||
}
|
}
|
||||||
|
@ -1,10 +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.commons.fit
|
package space.kscience.kmath.commons.fit
|
||||||
|
|
||||||
import kotlinx.html.br
|
import kotlinx.html.br
|
||||||
import kotlinx.html.h3
|
import kotlinx.html.h3
|
||||||
import kscience.plotly.*
|
|
||||||
import kscience.plotly.models.ScatterMode
|
|
||||||
import kscience.plotly.models.TraceValues
|
|
||||||
import space.kscience.kmath.commons.optimization.chiSquared
|
import space.kscience.kmath.commons.optimization.chiSquared
|
||||||
import space.kscience.kmath.commons.optimization.minimize
|
import space.kscience.kmath.commons.optimization.minimize
|
||||||
import space.kscience.kmath.distributions.NormalDistribution
|
import space.kscience.kmath.distributions.NormalDistribution
|
||||||
@ -17,6 +19,9 @@ import space.kscience.kmath.real.step
|
|||||||
import space.kscience.kmath.stat.RandomGenerator
|
import space.kscience.kmath.stat.RandomGenerator
|
||||||
import space.kscience.kmath.structures.asIterable
|
import space.kscience.kmath.structures.asIterable
|
||||||
import space.kscience.kmath.structures.toList
|
import space.kscience.kmath.structures.toList
|
||||||
|
import space.kscience.plotly.*
|
||||||
|
import space.kscience.plotly.models.ScatterMode
|
||||||
|
import space.kscience.plotly.models.TraceValues
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
import space.kscience.kmath.integration.integrate
|
||||||
|
import space.kscience.kmath.integration.value
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
//Define a function
|
||||||
|
val function: UnivariateFunction<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 }
|
||||||
|
|
||||||
|
//get the result of the integration
|
||||||
|
val result = DoubleField.integrate(0.0..10.0, function = function)
|
||||||
|
|
||||||
|
//the value is nullable because in some cases the integration could not succeed
|
||||||
|
println(result.value)
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
import space.kscience.kmath.integration.integrate
|
||||||
|
import space.kscience.kmath.integration.value
|
||||||
|
import space.kscience.kmath.nd.StructureND
|
||||||
|
import space.kscience.kmath.nd.nd
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
|
fun main(): Unit = DoubleField {
|
||||||
|
nd(2, 2) {
|
||||||
|
|
||||||
|
//Produce a diagonal StructureND
|
||||||
|
fun diagonal(v: Double) = produce { (i, j) ->
|
||||||
|
if (i == j) v else 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
//Define a function in a nd space
|
||||||
|
val function: (Double) -> StructureND<Double> = { x: Double -> 3 * number(x).pow(2) + 2 * diagonal(x) + 1 }
|
||||||
|
|
||||||
|
//get the result of the integration
|
||||||
|
val result = integrate(0.0..10.0, function = function)
|
||||||
|
|
||||||
|
//the value is nullable because in some cases the integration could not succeed
|
||||||
|
println(result.value)
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.linear
|
package space.kscience.kmath.linear
|
||||||
|
|
||||||
import space.kscience.kmath.real.*
|
import space.kscience.kmath.real.*
|
||||||
@ -17,8 +22,8 @@ fun main() {
|
|||||||
return DoubleBuffer(x.size) { i ->
|
return DoubleBuffer(x.size) { i ->
|
||||||
val h = sigma[i] / 5
|
val h = sigma[i] / 5
|
||||||
val dVector = DoubleBuffer(x.size) { if (it == i) h else 0.0 }
|
val dVector = DoubleBuffer(x.size) { if (it == i) h else 0.0 }
|
||||||
val f1 = invoke(x + dVector / 2)
|
val f1 = this(x + dVector / 2)
|
||||||
val f0 = invoke(x - dVector / 2)
|
val f0 = this(x - dVector / 2)
|
||||||
(f1 - f0) / h
|
(f1 - f0) / h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.operations
|
package space.kscience.kmath.operations
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.operations
|
package space.kscience.kmath.operations
|
||||||
|
|
||||||
import space.kscience.kmath.complex.Complex
|
import space.kscience.kmath.complex.Complex
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.stat
|
package space.kscience.kmath.stat
|
||||||
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.apache.commons.rng.sampling.distribution.BoxMullerNormalizedGaussianSampler
|
||||||
import org.apache.commons.rng.simple.RandomSource
|
import org.apache.commons.rng.simple.RandomSource
|
||||||
import space.kscience.kmath.samplers.GaussianSampler
|
import space.kscience.kmath.samplers.GaussianSampler
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import org.apache.commons.rng.sampling.distribution.GaussianSampler as CMGaussianSampler
|
import org.apache.commons.rng.sampling.distribution.GaussianSampler as CMGaussianSampler
|
||||||
import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler as CMZigguratNormalizedGaussianSampler
|
|
||||||
|
|
||||||
private suspend fun runKMathChained(): Duration {
|
private suspend fun runKMathChained(): Duration {
|
||||||
val generator = RandomGenerator.fromSource(RandomSource.MT, 123L)
|
val generator = RandomGenerator.fromSource(RandomSource.MT, 123L)
|
||||||
@ -34,7 +39,7 @@ private fun runApacheDirect(): Duration {
|
|||||||
val rng = RandomSource.create(RandomSource.MT, 123L)
|
val rng = RandomSource.create(RandomSource.MT, 123L)
|
||||||
|
|
||||||
val sampler = CMGaussianSampler.of(
|
val sampler = CMGaussianSampler.of(
|
||||||
CMZigguratNormalizedGaussianSampler.of(rng),
|
BoxMullerNormalizedGaussianSampler.of(rng),
|
||||||
7.0,
|
7.0,
|
||||||
2.0
|
2.0
|
||||||
)
|
)
|
||||||
@ -59,8 +64,8 @@ private fun runApacheDirect(): Duration {
|
|||||||
* Comparing chain sampling performance with direct sampling performance
|
* Comparing chain sampling performance with direct sampling performance
|
||||||
*/
|
*/
|
||||||
fun main(): Unit = runBlocking(Dispatchers.Default) {
|
fun main(): Unit = runBlocking(Dispatchers.Default) {
|
||||||
val chainJob = async { runKMathChained() }
|
|
||||||
val directJob = async { runApacheDirect() }
|
val directJob = async { runApacheDirect() }
|
||||||
|
val chainJob = async { runKMathChained() }
|
||||||
println("KMath Chained: ${chainJob.await()}")
|
println("KMath Chained: ${chainJob.await()}")
|
||||||
println("Apache Direct: ${directJob.await()}")
|
println("Apache Direct: ${directJob.await()}")
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.stat
|
package space.kscience.kmath.stat
|
||||||
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
@file:Suppress("unused")
|
@file:Suppress("unused")
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
import space.kscience.kmath.nd.*
|
import space.kscience.kmath.nd.*
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
import space.kscience.kmath.nd.BufferND
|
import space.kscience.kmath.nd.BufferND
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
import space.kscience.kmath.nd.StructureND
|
import space.kscience.kmath.nd.StructureND
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
import space.kscience.kmath.dimensions.D2
|
import space.kscience.kmath.dimensions.D2
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2018-2021 KMath contributors.
|
||||||
|
# Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
#
|
||||||
|
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
||||||
kotlin.mpp.stability.nowarn=true
|
kotlin.mpp.stability.nowarn=true
|
||||||
kotlin.native.enableDependencyPropagation=false
|
kotlin.native.enableDependencyPropagation=false
|
||||||
kotlin.parallel.tasks.in.project=true
|
kotlin.parallel.tasks.in.project=true
|
||||||
org.gradle.configureondemand=true
|
org.gradle.configureondemand=true
|
||||||
org.gradle.jvmargs=-XX:MaxMetaspaceSize=9G
|
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -2,17 +2,15 @@
|
|||||||
|
|
||||||
Abstract syntax tree expression representation and related optimizations.
|
Abstract syntax tree expression representation and related optimizations.
|
||||||
|
|
||||||
- [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
- [expression-language](src/commonMain/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
|
|
||||||
- [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
|
- [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
|
- [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:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-4`.
|
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-7`.
|
||||||
|
|
||||||
**Gradle:**
|
**Gradle:**
|
||||||
```gradle
|
```gradle
|
||||||
@ -23,7 +21,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'space.kscience:kmath-ast:0.3.0-dev-4'
|
implementation 'space.kscience:kmath-ast:0.3.0-dev-7'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
@ -35,7 +33,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-ast:0.3.0-dev-4")
|
implementation("space.kscience:kmath-ast:0.3.0-dev-7")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -49,7 +47,7 @@ a special implementation of `Expression<T>` with implemented `invoke` function.
|
|||||||
For example, the following builder:
|
For example, the following builder:
|
||||||
|
|
||||||
```kotlin
|
```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:
|
||||||
@ -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
|
#### Known issues
|
||||||
|
|
||||||
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid
|
- 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.
|
A similar feature is also available on JS.
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
DoubleField.mstInField { symbol("x") + 2 }.compile()
|
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||||
```
|
```
|
||||||
|
|
||||||
The code above returns expression implemented with such a JS function:
|
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
|
#### 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
|
## 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:
|
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)
|
![](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>
|
<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).
|
(see API reference).
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import ru.mipt.npm.gradle.Maturity
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
kotlin("multiplatform")
|
||||||
|
id("ru.mipt.npm.gradle.common")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin.js {
|
kotlin.js {
|
||||||
@ -21,6 +20,7 @@ kotlin.js {
|
|||||||
kotlin.sourceSets {
|
kotlin.sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
api("com.github.h0tk3y.betterParse:better-parse:0.4.2")
|
||||||
api(project(":kmath-core"))
|
api(project(":kmath-core"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,13 +33,15 @@ kotlin.sourceSets {
|
|||||||
|
|
||||||
jsMain {
|
jsMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(npm("astring", "1.7.0"))
|
implementation(npm("astring", "1.7.4"))
|
||||||
|
implementation(npm("binaryen", "100.0"))
|
||||||
|
implementation(npm("js-base64", "3.6.0"))
|
||||||
|
implementation(npm("webassembly", "0.11.0"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jvmMain {
|
jvmMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api("com.github.h0tk3y.betterParse:better-parse:0.4.1")
|
|
||||||
implementation("org.ow2.asm:asm:9.1")
|
implementation("org.ow2.asm:asm:9.1")
|
||||||
implementation("org.ow2.asm:asm-commons:9.1")
|
implementation("org.ow2.asm:asm-commons:9.1")
|
||||||
}
|
}
|
||||||
@ -52,31 +54,13 @@ tasks.dokkaHtml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
maturity = Maturity.PROTOTYPE
|
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
||||||
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||||
|
|
||||||
feature(
|
feature(
|
||||||
id = "expression-language",
|
id = "expression-language",
|
||||||
description = "Expression language and its parser",
|
description = "Expression language and its parser",
|
||||||
ref = "src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt"
|
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt"
|
||||||
)
|
|
||||||
|
|
||||||
feature(
|
|
||||||
id = "mst",
|
|
||||||
description = "MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation",
|
|
||||||
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt"
|
|
||||||
)
|
|
||||||
|
|
||||||
feature(
|
|
||||||
id = "mst-building",
|
|
||||||
description = "MST building algebraic structure",
|
|
||||||
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt"
|
|
||||||
)
|
|
||||||
|
|
||||||
feature(
|
|
||||||
id = "mst-interpreter",
|
|
||||||
description = "MST interpreter",
|
|
||||||
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
feature(
|
feature(
|
||||||
@ -90,4 +74,10 @@ readme {
|
|||||||
description = "Dynamic MST to JS compiler",
|
description = "Dynamic MST to JS compiler",
|
||||||
ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt"
|
ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
feature(
|
||||||
|
id = "rendering",
|
||||||
|
description = "Extendable MST rendering",
|
||||||
|
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ a special implementation of `Expression<T>` with implemented `invoke` function.
|
|||||||
For example, the following builder:
|
For example, the following builder:
|
||||||
|
|
||||||
```kotlin
|
```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:
|
||||||
@ -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
|
#### Known issues
|
||||||
|
|
||||||
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid
|
- 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.
|
A similar feature is also available on JS.
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
DoubleField.mstInField { symbol("x") + 2 }.compile()
|
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||||
```
|
```
|
||||||
|
|
||||||
The code above returns expression implemented with such a JS function:
|
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
|
#### 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
|
## 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:
|
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)
|
![](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>
|
<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).
|
(see API reference).
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
// TODO move to common when https://github.com/h0tk3y/better-parse/pull/37 is merged
|
/*
|
||||||
|
* 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.kscience.kmath.ast
|
||||||
|
|
||||||
@ -13,6 +16,7 @@ import com.github.h0tk3y.betterParse.lexer.literalToken
|
|||||||
import com.github.h0tk3y.betterParse.lexer.regexToken
|
import com.github.h0tk3y.betterParse.lexer.regexToken
|
||||||
import com.github.h0tk3y.betterParse.parser.ParseResult
|
import com.github.h0tk3y.betterParse.parser.ParseResult
|
||||||
import com.github.h0tk3y.betterParse.parser.Parser
|
import com.github.h0tk3y.betterParse.parser.Parser
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
import space.kscience.kmath.operations.FieldOperations
|
import space.kscience.kmath.operations.FieldOperations
|
||||||
import space.kscience.kmath.operations.GroupOperations
|
import space.kscience.kmath.operations.GroupOperations
|
||||||
import space.kscience.kmath.operations.PowerOperations
|
import space.kscience.kmath.operations.PowerOperations
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,6 +71,15 @@ public object LatexSyntaxRenderer : SyntaxRenderer {
|
|||||||
append('}')
|
append('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is ExponentSyntax -> if (node.useOperatorForm) {
|
||||||
|
append("\\operatorname{exp}\\,")
|
||||||
|
render(node.operand)
|
||||||
|
} else {
|
||||||
|
append("e^{")
|
||||||
|
render(node.operand)
|
||||||
|
append('}')
|
||||||
|
}
|
||||||
|
|
||||||
is SuperscriptSyntax -> {
|
is SuperscriptSyntax -> {
|
||||||
render(node.left)
|
render(node.left)
|
||||||
append("^{")
|
append("^{")
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,6 +82,19 @@ public object MathMLSyntaxRenderer : SyntaxRenderer {
|
|||||||
|
|
||||||
is RadicalSyntax -> tag("msqrt") { render(node.operand) }
|
is RadicalSyntax -> tag("msqrt") { render(node.operand) }
|
||||||
|
|
||||||
|
is ExponentSyntax -> if (node.useOperatorForm) {
|
||||||
|
tag("mo") { append("exp") }
|
||||||
|
tag("mspace", "width" to "0.167em")
|
||||||
|
render(node.operand)
|
||||||
|
} else {
|
||||||
|
tag("msup") {
|
||||||
|
tag("mrow") {
|
||||||
|
tag("mi") { append("e") }
|
||||||
|
}
|
||||||
|
tag("mrow") { render(node.operand) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
is SuperscriptSyntax -> tag("msup") {
|
is SuperscriptSyntax -> tag("msup") {
|
||||||
tag("mrow") { render(node.left) }
|
tag("mrow") { render(node.left) }
|
||||||
tag("mrow") { render(node.right) }
|
tag("mrow") { render(node.right) }
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MST
|
import space.kscience.kmath.expressions.MST
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders [MST] to [MathSyntax].
|
* Renders [MST] to [MathSyntax].
|
||||||
@ -78,7 +83,7 @@ public open class FeaturedMathRendererWithPostProcess(
|
|||||||
Fraction.Default,
|
Fraction.Default,
|
||||||
Power.Default,
|
Power.Default,
|
||||||
SquareRoot.Default,
|
SquareRoot.Default,
|
||||||
Exponential.Default,
|
Exponent.Default,
|
||||||
InverseTrigonometricOperations.Default,
|
InverseTrigonometricOperations.Default,
|
||||||
|
|
||||||
// Fallback option for unknown operations - printing them as operator
|
// Fallback option for unknown operations - printing them as operator
|
||||||
@ -95,6 +100,7 @@ public open class FeaturedMathRendererWithPostProcess(
|
|||||||
PrintSymbolic,
|
PrintSymbolic,
|
||||||
),
|
),
|
||||||
listOf(
|
listOf(
|
||||||
|
BetterExponent,
|
||||||
SimplifyParentheses.Default,
|
SimplifyParentheses.Default,
|
||||||
BetterMultiplication,
|
BetterMultiplication,
|
||||||
),
|
),
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -184,6 +189,24 @@ public data class RadicalSyntax(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents exponential function.
|
||||||
|
*
|
||||||
|
* @property operand The argument of function.
|
||||||
|
* @property useOperatorForm `true` if operator form is used (*exp (x)*), `false` if exponentiation form is used
|
||||||
|
* (*e<sup>x</sup>*).
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
public data class ExponentSyntax(
|
||||||
|
public override val operation: String,
|
||||||
|
public override val operand: OperandSyntax,
|
||||||
|
public var useOperatorForm: Boolean,
|
||||||
|
) : UnarySyntax() {
|
||||||
|
init {
|
||||||
|
operand.parent = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a syntax node with superscript (usually, for exponentiation).
|
* Represents a syntax node with superscript (usually, for exponentiation).
|
||||||
*
|
*
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +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.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MST
|
|
||||||
import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature
|
import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
@ -51,10 +56,14 @@ private fun printSignedNumberString(s: String): MathSyntax {
|
|||||||
public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature {
|
public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature {
|
||||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
||||||
if (node !is MST.Numeric || node.value::class !in types) return null
|
if (node !is MST.Numeric || node.value::class !in types) return null
|
||||||
val toString = node.value.toString().removeSuffix(".0")
|
val toString = when (val v = node.value) {
|
||||||
|
is Float -> v.multiplatformToString()
|
||||||
|
is Double -> v.multiplatformToString()
|
||||||
|
else -> v.toString()
|
||||||
|
}.removeSuffix(".0")
|
||||||
|
|
||||||
if ('E' in toString) {
|
if (toString.contains('E', ignoreCase = true)) {
|
||||||
val (beforeE, afterE) = toString.split('E')
|
val (beforeE, afterE) = toString.split('E', ignoreCase = true)
|
||||||
val significand = beforeE.toDouble().toString().removeSuffix(".0")
|
val significand = beforeE.toDouble().toString().removeSuffix(".0")
|
||||||
val exponent = afterE.toDouble().toString().removeSuffix(".0")
|
val exponent = afterE.toDouble().toString().removeSuffix(".0")
|
||||||
|
|
||||||
@ -103,9 +112,7 @@ public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : Rend
|
|||||||
*/
|
*/
|
||||||
public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature {
|
public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature {
|
||||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
||||||
if (node !is MST.Numeric || node.value::class !in types)
|
if (node !is MST.Numeric || node.value::class !in types) return null
|
||||||
return null
|
|
||||||
|
|
||||||
return printSignedNumberString(node.value.toString())
|
return printSignedNumberString(node.value.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,15 +284,15 @@ public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Exponential(operations: Collection<String>?) : Unary(operations) {
|
public class Exponent(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = SuperscriptSyntax(
|
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
left = SymbolSyntax(string = "e"),
|
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||||
right = parent.render(node.value),
|
useOperatorForm = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public val Default: Exponential = Exponential(setOf(ExponentialOperations.EXP_OPERATION))
|
public val Default: Exponent = Exponent(setOf(ExponentialOperations.EXP_OPERATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
|
internal expect fun Double.multiplatformToString(): String
|
||||||
|
internal expect fun Float.multiplatformToString(): String
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
import space.kscience.kmath.operations.FieldOperations
|
import space.kscience.kmath.operations.FieldOperations
|
||||||
@ -11,69 +16,110 @@ import space.kscience.kmath.operations.RingOperations
|
|||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage {
|
public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage {
|
||||||
public override fun perform(node: MathSyntax) {
|
public override fun perform(node: MathSyntax): Unit = when (node) {
|
||||||
when (node) {
|
is NumberSyntax -> Unit
|
||||||
is NumberSyntax -> Unit
|
is SymbolSyntax -> Unit
|
||||||
is SymbolSyntax -> Unit
|
is OperatorNameSyntax -> Unit
|
||||||
is OperatorNameSyntax -> Unit
|
is SpecialSymbolSyntax -> Unit
|
||||||
is SpecialSymbolSyntax -> Unit
|
is OperandSyntax -> perform(node.operand)
|
||||||
is OperandSyntax -> perform(node.operand)
|
|
||||||
|
|
||||||
is UnaryOperatorSyntax -> {
|
is UnaryOperatorSyntax -> {
|
||||||
perform(node.prefix)
|
perform(node.prefix)
|
||||||
perform(node.operand)
|
perform(node.operand)
|
||||||
}
|
|
||||||
|
|
||||||
is UnaryPlusSyntax -> perform(node.operand)
|
|
||||||
is UnaryMinusSyntax -> perform(node.operand)
|
|
||||||
is RadicalSyntax -> perform(node.operand)
|
|
||||||
|
|
||||||
is SuperscriptSyntax -> {
|
|
||||||
perform(node.left)
|
|
||||||
perform(node.right)
|
|
||||||
}
|
|
||||||
|
|
||||||
is SubscriptSyntax -> {
|
|
||||||
perform(node.left)
|
|
||||||
perform(node.right)
|
|
||||||
}
|
|
||||||
|
|
||||||
is BinaryOperatorSyntax -> {
|
|
||||||
perform(node.prefix)
|
|
||||||
perform(node.left)
|
|
||||||
perform(node.right)
|
|
||||||
}
|
|
||||||
|
|
||||||
is BinaryPlusSyntax -> {
|
|
||||||
perform(node.left)
|
|
||||||
perform(node.right)
|
|
||||||
}
|
|
||||||
|
|
||||||
is BinaryMinusSyntax -> {
|
|
||||||
perform(node.left)
|
|
||||||
perform(node.right)
|
|
||||||
}
|
|
||||||
|
|
||||||
is FractionSyntax -> {
|
|
||||||
perform(node.left)
|
|
||||||
perform(node.right)
|
|
||||||
}
|
|
||||||
|
|
||||||
is RadicalWithIndexSyntax -> {
|
|
||||||
perform(node.left)
|
|
||||||
perform(node.right)
|
|
||||||
}
|
|
||||||
|
|
||||||
is MultiplicationSyntax -> {
|
|
||||||
node.times = node.right.operand is NumberSyntax && !node.right.parentheses
|
|
||||||
|| node.left.operand is NumberSyntax && node.right.operand is FractionSyntax
|
|
||||||
|| node.left.operand is NumberSyntax && node.right.operand is NumberSyntax
|
|
||||||
|| node.left.operand is NumberSyntax && node.right.operand is SuperscriptSyntax && node.right.operand.left is NumberSyntax
|
|
||||||
|
|
||||||
perform(node.left)
|
|
||||||
perform(node.right)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is UnaryPlusSyntax -> perform(node.operand)
|
||||||
|
is UnaryMinusSyntax -> perform(node.operand)
|
||||||
|
is RadicalSyntax -> perform(node.operand)
|
||||||
|
is ExponentSyntax -> perform(node.operand)
|
||||||
|
|
||||||
|
is SuperscriptSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is SubscriptSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is BinaryOperatorSyntax -> {
|
||||||
|
perform(node.prefix)
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is BinaryPlusSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is BinaryMinusSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is FractionSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is RadicalWithIndexSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is MultiplicationSyntax -> {
|
||||||
|
node.times = node.right.operand is NumberSyntax && !node.right.parentheses
|
||||||
|
|| node.left.operand is NumberSyntax && node.right.operand is FractionSyntax
|
||||||
|
|| node.left.operand is NumberSyntax && node.right.operand is NumberSyntax
|
||||||
|
|| node.left.operand is NumberSyntax && node.right.operand is SuperscriptSyntax && node.right.operand.left is NumberSyntax
|
||||||
|
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies [ExponentSyntax.useOperatorForm] to [ExponentSyntax] when the operand contains a fraction, a
|
||||||
|
* superscript or a subscript to improve readability.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage {
|
||||||
|
private fun perform0(node: MathSyntax): Boolean {
|
||||||
|
return when (node) {
|
||||||
|
is NumberSyntax -> false
|
||||||
|
is SymbolSyntax -> false
|
||||||
|
is OperatorNameSyntax -> false
|
||||||
|
is SpecialSymbolSyntax -> false
|
||||||
|
is OperandSyntax -> perform0(node.operand)
|
||||||
|
is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand)
|
||||||
|
is UnaryPlusSyntax -> perform0(node.operand)
|
||||||
|
is UnaryMinusSyntax -> perform0(node.operand)
|
||||||
|
is RadicalSyntax -> perform0(node.operand)
|
||||||
|
|
||||||
|
is ExponentSyntax -> {
|
||||||
|
val r = perform0(node.operand)
|
||||||
|
node.useOperatorForm = r
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
is SuperscriptSyntax -> true
|
||||||
|
is SubscriptSyntax -> true
|
||||||
|
is BinaryOperatorSyntax -> perform0(node.prefix) || perform0(node.left) || perform0(node.right)
|
||||||
|
is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right)
|
||||||
|
is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right)
|
||||||
|
is FractionSyntax -> true
|
||||||
|
is RadicalWithIndexSyntax -> perform0(node.left) || perform0(node.right)
|
||||||
|
is MultiplicationSyntax -> perform0(node.left) || perform0(node.right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun perform(node: MathSyntax) {
|
||||||
|
perform0(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,89 +131,89 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro
|
|||||||
*/
|
*/
|
||||||
public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) :
|
public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) :
|
||||||
FeaturedMathRendererWithPostProcess.PostProcessStage {
|
FeaturedMathRendererWithPostProcess.PostProcessStage {
|
||||||
public override fun perform(node: MathSyntax) {
|
public override fun perform(node: MathSyntax): Unit = when (node) {
|
||||||
when (node) {
|
is NumberSyntax -> Unit
|
||||||
is NumberSyntax -> Unit
|
is SymbolSyntax -> Unit
|
||||||
is SymbolSyntax -> Unit
|
is OperatorNameSyntax -> Unit
|
||||||
is OperatorNameSyntax -> Unit
|
is SpecialSymbolSyntax -> Unit
|
||||||
is SpecialSymbolSyntax -> Unit
|
|
||||||
|
|
||||||
is OperandSyntax -> {
|
is OperandSyntax -> {
|
||||||
val isRightOfSuperscript =
|
val isRightOfSuperscript =
|
||||||
(node.parent is SuperscriptSyntax) && (node.parent as SuperscriptSyntax).right === node
|
(node.parent is SuperscriptSyntax) && (node.parent as SuperscriptSyntax).right === node
|
||||||
|
|
||||||
val precedence = precedenceFunction(node.operand)
|
val precedence = precedenceFunction(node.operand)
|
||||||
|
|
||||||
val needParenthesesByPrecedence = when (val parent = node.parent) {
|
val needParenthesesByPrecedence = when (val parent = node.parent) {
|
||||||
null -> false
|
null -> false
|
||||||
|
|
||||||
is BinarySyntax -> {
|
is BinarySyntax -> {
|
||||||
val parentPrecedence = precedenceFunction(parent)
|
val parentPrecedence = precedenceFunction(parent)
|
||||||
|
|
||||||
parentPrecedence < precedence ||
|
parentPrecedence < precedence ||
|
||||||
parentPrecedence == precedence && parentPrecedence != 0 && node === parent.right
|
parentPrecedence == precedence && parentPrecedence != 0 && node === parent.right
|
||||||
}
|
|
||||||
|
|
||||||
else -> precedence > precedenceFunction(parent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node.parentheses = !isRightOfSuperscript
|
else -> precedence > precedenceFunction(parent)
|
||||||
&& (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax)
|
|
||||||
|
|
||||||
perform(node.operand)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is UnaryOperatorSyntax -> {
|
val isInsideExpOperator =
|
||||||
perform(node.prefix)
|
node.parent is ExponentSyntax && (node.parent as ExponentSyntax).useOperatorForm
|
||||||
perform(node.operand)
|
|
||||||
}
|
|
||||||
|
|
||||||
is UnaryPlusSyntax -> perform(node.operand)
|
node.parentheses = !isRightOfSuperscript
|
||||||
is UnaryMinusSyntax -> {
|
&& (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax || isInsideExpOperator)
|
||||||
perform(node.operand)
|
|
||||||
}
|
|
||||||
is RadicalSyntax -> perform(node.operand)
|
|
||||||
|
|
||||||
is SuperscriptSyntax -> {
|
perform(node.operand)
|
||||||
perform(node.left)
|
}
|
||||||
perform(node.right)
|
|
||||||
}
|
|
||||||
|
|
||||||
is SubscriptSyntax -> {
|
is UnaryOperatorSyntax -> {
|
||||||
perform(node.left)
|
perform(node.prefix)
|
||||||
perform(node.right)
|
perform(node.operand)
|
||||||
}
|
}
|
||||||
|
|
||||||
is BinaryOperatorSyntax -> {
|
is UnaryPlusSyntax -> perform(node.operand)
|
||||||
perform(node.prefix)
|
is UnaryMinusSyntax -> perform(node.operand)
|
||||||
perform(node.left)
|
is RadicalSyntax -> perform(node.operand)
|
||||||
perform(node.right)
|
is ExponentSyntax -> perform(node.operand)
|
||||||
}
|
|
||||||
|
|
||||||
is BinaryPlusSyntax -> {
|
is SuperscriptSyntax -> {
|
||||||
perform(node.left)
|
perform(node.left)
|
||||||
perform(node.right)
|
perform(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
is BinaryMinusSyntax -> {
|
is SubscriptSyntax -> {
|
||||||
perform(node.left)
|
perform(node.left)
|
||||||
perform(node.right)
|
perform(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
is FractionSyntax -> {
|
is BinaryOperatorSyntax -> {
|
||||||
perform(node.left)
|
perform(node.prefix)
|
||||||
perform(node.right)
|
perform(node.left)
|
||||||
}
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
is MultiplicationSyntax -> {
|
is BinaryPlusSyntax -> {
|
||||||
perform(node.left)
|
perform(node.left)
|
||||||
perform(node.right)
|
perform(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
is RadicalWithIndexSyntax -> {
|
is BinaryMinusSyntax -> {
|
||||||
perform(node.left)
|
perform(node.left)
|
||||||
perform(node.right)
|
perform(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is FractionSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is MultiplicationSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is RadicalWithIndexSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.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.DoubleField
|
||||||
import space.kscience.kmath.operations.Field
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class ParserPrecedenceTest {
|
internal class ParserPrecedenceTest {
|
||||||
private val f: Field<Double> = DoubleField
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath()))
|
fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath()))
|
||||||
|
|
||||||
@ -31,4 +35,8 @@ internal class ParserPrecedenceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test8(): Unit = assertEquals(18.0, f.evaluate("2*2^3+2".parseMath()))
|
fun test8(): Unit = assertEquals(18.0, f.evaluate("2*2^3+2".parseMath()))
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private val f = DoubleField
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,29 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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.kscience.kmath.ast
|
||||||
|
|
||||||
import space.kscience.kmath.complex.Complex
|
import space.kscience.kmath.complex.Complex
|
||||||
import space.kscience.kmath.complex.ComplexField
|
import space.kscience.kmath.complex.ComplexField
|
||||||
|
import space.kscience.kmath.expressions.evaluate
|
||||||
import space.kscience.kmath.operations.Algebra
|
import space.kscience.kmath.operations.Algebra
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class ParserTest {
|
internal class ParserTest {
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate MST`() {
|
fun evaluateParsedMst() {
|
||||||
val mst = "2+2*(2+2)".parseMath()
|
val mst = "2+2*(2+2)".parseMath()
|
||||||
val res = ComplexField.evaluate(mst)
|
val res = ComplexField.evaluate(mst)
|
||||||
assertEquals(Complex(10.0, 0.0), res)
|
assertEquals(Complex(10.0, 0.0), res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate MSTExpression`() {
|
fun evaluateMstSymbol() {
|
||||||
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`() {
|
|
||||||
val mst = "i".parseMath()
|
val mst = "i".parseMath()
|
||||||
val res = ComplexField.evaluate(mst)
|
val res = ComplexField.evaluate(mst)
|
||||||
assertEquals(ComplexField.i, res)
|
assertEquals(ComplexField.i, res)
|
||||||
@ -31,14 +30,14 @@ internal class ParserTest {
|
|||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate MST with unary function`() {
|
fun evaluateMstUnary() {
|
||||||
val mst = "sin(0)".parseMath()
|
val mst = "sin(0)".parseMath()
|
||||||
val res = DoubleField.evaluate(mst)
|
val res = DoubleField.evaluate(mst)
|
||||||
assertEquals(0.0, res)
|
assertEquals(0.0, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `evaluate MST with binary function`() {
|
fun evaluateMstBinary() {
|
||||||
val magicalAlgebra = object : Algebra<String> {
|
val magicalAlgebra = object : Algebra<String> {
|
||||||
override fun bindSymbolOrNull(value: String): String = value
|
override fun bindSymbolOrNull(value: String): String = value
|
||||||
|
|
@ -1,7 +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.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MST.Numeric
|
|
||||||
import space.kscience.kmath.ast.rendering.TestUtils.testLatex
|
import space.kscience.kmath.ast.rendering.TestUtils.testLatex
|
||||||
|
import space.kscience.kmath.expressions.MST.Numeric
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
|
||||||
internal class TestFeatures {
|
internal class TestFeatures {
|
||||||
@ -37,6 +42,22 @@ internal class TestFeatures {
|
|||||||
testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}")
|
testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}")
|
||||||
testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}")
|
testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}")
|
||||||
testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}")
|
testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}")
|
||||||
|
testLatex(Numeric(0.001), "0.001")
|
||||||
|
testLatex(Numeric(0.0000001), "1\\times10^{-7}")
|
||||||
|
|
||||||
|
testLatex(Numeric(Float.NaN), "NaN")
|
||||||
|
testLatex(Numeric(Float.POSITIVE_INFINITY), "\\infty")
|
||||||
|
testLatex(Numeric(Float.NEGATIVE_INFINITY), "-\\infty")
|
||||||
|
testLatex(Numeric(1.0f), "1")
|
||||||
|
testLatex(Numeric(-1.0f), "-1")
|
||||||
|
testLatex(Numeric(1.42f), "1.42")
|
||||||
|
testLatex(Numeric(-1.42f), "-1.42")
|
||||||
|
testLatex(Numeric(1e10f), "1\\times10^{10}")
|
||||||
|
testLatex(Numeric(1e-10f), "1\\times10^{-10}")
|
||||||
|
testLatex(Numeric(-1e-10f), "-1\\times10^{-10}")
|
||||||
|
testLatex(Numeric(-1e10f), "-1\\times10^{10}")
|
||||||
|
testLatex(Numeric(0.001f), "0.001")
|
||||||
|
testLatex(Numeric(0.0000001f), "1\\times10^{-7}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
@ -1,7 +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.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MST
|
|
||||||
import space.kscience.kmath.ast.rendering.TestUtils.testLatex
|
import space.kscience.kmath.ast.rendering.TestUtils.testLatex
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
import space.kscience.kmath.operations.GroupOperations
|
import space.kscience.kmath.operations.GroupOperations
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
|
@ -1,7 +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.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MST
|
|
||||||
import space.kscience.kmath.ast.rendering.TestUtils.testMathML
|
import space.kscience.kmath.ast.rendering.TestUtils.testMathML
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
import space.kscience.kmath.operations.GroupOperations
|
import space.kscience.kmath.operations.GroupOperations
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
import space.kscience.kmath.ast.rendering.TestUtils.testLatex
|
import space.kscience.kmath.ast.rendering.TestUtils.testLatex
|
||||||
@ -25,4 +30,11 @@ internal class TestStages {
|
|||||||
testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x")
|
testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x")
|
||||||
testLatex("x^(x+x)", "x^{x+x}")
|
testLatex("x^(x+x)", "x^{x+x}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun exponent() {
|
||||||
|
testLatex("exp(x)", "e^{x}")
|
||||||
|
testLatex("exp(x/2)", "\\operatorname{exp}\\,\\left(\\frac{x}{2}\\right)")
|
||||||
|
testLatex("exp(x^2)", "\\operatorname{exp}\\,\\left(x^{2}\\right)")
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,7 +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.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MST
|
|
||||||
import space.kscience.kmath.ast.parseMath
|
import space.kscience.kmath.ast.parseMath
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal object TestUtils {
|
internal object TestUtils {
|
@ -1,22 +0,0 @@
|
|||||||
package space.kscisnce.kmath.ast
|
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MstField
|
|
||||||
import space.kscience.kmath.ast.toExpression
|
|
||||||
import space.kscience.kmath.expressions.invoke
|
|
||||||
import space.kscience.kmath.misc.Symbol.Companion.x
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.test.Test
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
|
internal actual fun Double.multiplatformToString(): String {
|
||||||
|
val d = this
|
||||||
|
if (d >= 1e7 || d <= -1e7) return js("d.toExponential()") as String
|
||||||
|
return toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal actual fun Float.multiplatformToString(): String {
|
||||||
|
val d = this
|
||||||
|
if (d >= 1e7f || d <= -1e7f) return js("d.toExponential()") as String
|
||||||
|
return toString()
|
||||||
|
}
|
@ -1,11 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
package space.kscience.kmath.estree
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MST
|
|
||||||
import space.kscience.kmath.ast.MST.*
|
|
||||||
import space.kscience.kmath.estree.internal.ESTreeBuilder
|
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.Expression
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
|
import space.kscience.kmath.expressions.MST.*
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.internal.estree.BaseExpression
|
||||||
import space.kscience.kmath.misc.Symbol
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.operations.Algebra
|
import space.kscience.kmath.operations.Algebra
|
||||||
import space.kscience.kmath.operations.NumericAlgebra
|
import space.kscience.kmath.operations.NumericAlgebra
|
||||||
@ -26,16 +31,17 @@ internal fun <T> MST.compileWith(algebra: Algebra<T>): Expression<T> {
|
|||||||
|
|
||||||
is Unary -> when {
|
is Unary -> when {
|
||||||
algebra is NumericAlgebra && node.value is Numeric -> constant(
|
algebra is NumericAlgebra && node.value is Numeric -> constant(
|
||||||
algebra.unaryOperationFunction(node.operation)(algebra.number(node.value.value)))
|
algebra.unaryOperationFunction(node.operation)(algebra.number((node.value as Numeric).value)))
|
||||||
|
|
||||||
else -> call(algebra.unaryOperationFunction(node.operation), visit(node.value))
|
else -> call(algebra.unaryOperationFunction(node.operation), visit(node.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
is Binary -> when {
|
is Binary -> when {
|
||||||
algebra is NumericAlgebra && node.left is Numeric && node.right is Numeric -> constant(
|
algebra is NumericAlgebra && node.left is Numeric && node.right is Numeric -> constant(
|
||||||
algebra
|
algebra.binaryOperationFunction(node.operation).invoke(
|
||||||
.binaryOperationFunction(node.operation)
|
algebra.number((node.left as Numeric).value),
|
||||||
.invoke(algebra.number(node.left.value), algebra.number(node.right.value))
|
algebra.number((node.right as Numeric).value)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
algebra is NumericAlgebra && node.left is Numeric -> call(
|
algebra is NumericAlgebra && node.left is Numeric -> call(
|
||||||
@ -70,12 +76,12 @@ public fun <T : Any> MST.compileToExpression(algebra: Algebra<T>): Expression<T>
|
|||||||
/**
|
/**
|
||||||
* Compile given MST to expression and evaluate it against [arguments]
|
* Compile given MST to expression and evaluate it against [arguments]
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T: Any> MST.compile(algebra: Algebra<T>, arguments: Map<Symbol, T>): T =
|
public inline fun <reified T : Any> MST.compile(algebra: Algebra<T>, arguments: Map<Symbol, T>): T =
|
||||||
compileToExpression(algebra).invoke(arguments)
|
compileToExpression(algebra).invoke(arguments)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile given MST to expression and evaluate it against [arguments]
|
* Compile given MST to expression and evaluate it against [arguments]
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T: Any> MST.compile(algebra: Algebra<T>, vararg arguments: Pair<Symbol,T>): T =
|
public inline fun <reified T : Any> MST.compile(algebra: Algebra<T>, vararg arguments: Pair<Symbol, T>): T =
|
||||||
compileToExpression(algebra).invoke(*arguments)
|
compileToExpression(algebra).invoke(*arguments)
|
||||||
|
@ -1,8 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.estree.internal
|
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.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
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
|
||||||
internal class ESTreeBuilder<T>(val bodyCallback: ESTreeBuilder<T>.() -> BaseExpression) {
|
internal class ESTreeBuilder<T>(val bodyCallback: ESTreeBuilder<T>.() -> BaseExpression) {
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.estree.internal.astring
|
package space.kscience.kmath.estree.internal.astring
|
||||||
|
|
||||||
internal typealias Generator = Any
|
internal typealias Generator = Any
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,9 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
@file:JsModule("astring")
|
@file:JsModule("astring")
|
||||||
@file:JsNonModule
|
@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 {
|
internal external interface Options {
|
||||||
var indent: String?
|
var indent: String?
|
@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.internal.astring
|
||||||
|
|
||||||
|
internal typealias Generator = Any
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress(
|
||||||
|
"INTERFACE_WITH_SUPERCLASS",
|
||||||
|
"OVERRIDING_FINAL_MEMBER",
|
||||||
|
"RETURN_TYPE_MISMATCH_ON_OVERRIDE",
|
||||||
|
"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,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("PackageDirectoryMismatch", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation")
|
||||||
|
|
||||||
|
package space.kscience.kmath.internal.binaryen
|
||||||
|
|
||||||
|
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
|
@ -1,4 +1,9 @@
|
|||||||
package space.kscience.kmath.estree.internal.emitter
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.internal.emitter
|
||||||
|
|
||||||
internal open external class Emitter {
|
internal open external class Emitter {
|
||||||
constructor(obj: Any)
|
constructor(obj: Any)
|
@ -1,4 +1,9 @@
|
|||||||
package space.kscience.kmath.estree.internal.estree
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.internal.estree
|
||||||
|
|
||||||
internal fun Program(sourceType: String, vararg body: dynamic) = object : Program {
|
internal fun Program(sourceType: String, vararg body: dynamic) = object : Program {
|
||||||
override var type = "Program"
|
override var type = "Program"
|
@ -1,4 +1,9 @@
|
|||||||
package space.kscience.kmath.estree.internal.estree
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.internal.estree
|
||||||
|
|
||||||
import kotlin.js.RegExp
|
import kotlin.js.RegExp
|
||||||
|
|
@ -0,0 +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.internal.stream
|
||||||
|
|
||||||
|
import space.kscience.kmath.internal.emitter.Emitter
|
||||||
|
|
||||||
|
internal open external class Stream : Emitter {
|
||||||
|
open fun pipe(dest: Any, options: Any): Any
|
||||||
|
}
|
@ -1,4 +1,9 @@
|
|||||||
package space.kscience.kmath.estree.internal.tsstdlib
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.internal.tsstdlib
|
||||||
|
|
||||||
internal external interface IteratorYieldResult<TYield> {
|
internal external interface IteratorYieldResult<TYield> {
|
||||||
var done: Boolean?
|
var done: Boolean?
|
@ -1,6 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
@file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION")
|
@file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION")
|
||||||
|
|
||||||
package space.kscience.kmath.estree.internal.tsstdlib
|
package space.kscience.kmath.internal.tsstdlib
|
||||||
|
|
||||||
import kotlin.js.RegExp
|
import kotlin.js.RegExp
|
||||||
|
|
||||||
@ -33,6 +38,8 @@ internal external interface RegExpConstructor {
|
|||||||
var lastMatch: String
|
var lastMatch: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal typealias Record<K, T> = Any
|
||||||
|
|
||||||
internal external interface ConcatArray<T> {
|
internal external interface ConcatArray<T> {
|
||||||
var length: Number
|
var length: Number
|
||||||
|
|
||||||
@ -80,3 +87,10 @@ internal external interface ArrayLike<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal typealias Extract<T, U> = Any
|
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,236 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:JsQualifier("WebAssembly")
|
||||||
|
|
||||||
|
@file:Suppress(
|
||||||
|
"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,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("INTERFACE_WITH_SUPERCLASS",
|
||||||
|
"OVERRIDING_FINAL_MEMBER",
|
||||||
|
"RETURN_TYPE_MISMATCH_ON_OVERRIDE",
|
||||||
|
"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,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.wasm.internal
|
||||||
|
|
||||||
|
import space.kscience.kmath.expressions.Expression
|
||||||
|
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,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.wasm
|
||||||
|
|
||||||
|
import space.kscience.kmath.estree.compileWith
|
||||||
|
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,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
|
import space.kscience.kmath.expressions.*
|
||||||
|
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)
|
||||||
|
}
|
@ -1,20 +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.estree
|
package space.kscience.kmath.estree
|
||||||
|
|
||||||
import space.kscience.kmath.ast.*
|
|
||||||
import space.kscience.kmath.complex.ComplexField
|
import space.kscience.kmath.complex.ComplexField
|
||||||
import space.kscience.kmath.complex.toComplex
|
import space.kscience.kmath.complex.toComplex
|
||||||
import space.kscience.kmath.misc.Symbol
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.ByteRing
|
import space.kscience.kmath.operations.ByteRing
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class TestESTreeConsistencyWithInterpreter {
|
internal class TestESTreeConsistencyWithInterpreter {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun mstSpace() {
|
fun mstSpace() {
|
||||||
|
|
||||||
val mst = MstGroup {
|
val mst = MstGroup {
|
||||||
binaryOperationFunction("+")(
|
binaryOperationFunction("+")(
|
||||||
unaryOperationFunction("+")(
|
unaryOperationFunction("+")(
|
||||||
@ -25,12 +29,12 @@ internal class TestESTreeConsistencyWithInterpreter {
|
|||||||
),
|
),
|
||||||
|
|
||||||
number(1)
|
number(1)
|
||||||
) + bindSymbol("x") + zero
|
) + bindSymbol(x) + zero
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
mst.interpret(MstGroup, Symbol.x to MST.Numeric(2)),
|
mst.interpret(MstGroup, x to MST.Numeric(2)),
|
||||||
mst.compile(MstGroup, Symbol.x to MST.Numeric(2))
|
mst.compile(MstGroup, x to MST.Numeric(2))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +43,7 @@ internal class TestESTreeConsistencyWithInterpreter {
|
|||||||
val mst = MstRing {
|
val mst = MstRing {
|
||||||
binaryOperationFunction("+")(
|
binaryOperationFunction("+")(
|
||||||
unaryOperationFunction("+")(
|
unaryOperationFunction("+")(
|
||||||
(bindSymbol("x") - (2.toByte() + (scale(
|
(bindSymbol(x) - (2.toByte() + (scale(
|
||||||
add(number(1), number(1)),
|
add(number(1), number(1)),
|
||||||
2.0
|
2.0
|
||||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||||
@ -50,24 +54,24 @@ internal class TestESTreeConsistencyWithInterpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
mst.interpret(ByteRing, Symbol.x to 3.toByte()),
|
mst.interpret(ByteRing, x to 3.toByte()),
|
||||||
mst.compile(ByteRing, Symbol.x to 3.toByte())
|
mst.compile(ByteRing, x to 3.toByte())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun realField() {
|
fun doubleField() {
|
||||||
val mst = MstField {
|
val mst = MstField {
|
||||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
+(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),
|
||||||
number(1) / 2 + number(2.0) * one
|
number(1) / 2 + number(2.0) * one
|
||||||
) + zero
|
) + zero
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
mst.interpret(DoubleField, Symbol.x to 2.0),
|
mst.interpret(DoubleField, x to 2.0),
|
||||||
mst.compile(DoubleField, Symbol.x to 2.0)
|
mst.compile(DoubleField, x to 2.0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,15 +79,19 @@ internal class TestESTreeConsistencyWithInterpreter {
|
|||||||
fun complexField() {
|
fun complexField() {
|
||||||
val mst = MstField {
|
val mst = MstField {
|
||||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
+(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),
|
||||||
number(1) / 2 + number(2.0) * one
|
number(1) / 2 + number(2.0) * one
|
||||||
) + zero
|
) + zero
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
mst.interpret(ComplexField, Symbol.x to 2.0.toComplex()),
|
mst.interpret(ComplexField, x to 2.0.toComplex()),
|
||||||
mst.compile(ComplexField, Symbol.x to 2.0.toComplex())
|
mst.compile(ComplexField, x to 2.0.toComplex()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private val x by symbol
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,42 +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.estree
|
package space.kscience.kmath.estree
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MstExtendedField
|
import space.kscience.kmath.expressions.MstField
|
||||||
|
import space.kscience.kmath.expressions.MstGroup
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.random.Random
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class TestESTreeOperationsSupport {
|
internal class TestESTreeOperationsSupport {
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryOperationInvocation() {
|
fun testUnaryOperationInvocation() {
|
||||||
val expression = MstExtendedField { -bindSymbol("x") }.compileToExpression(DoubleField)
|
val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField)
|
||||||
val res = expression("x" to 2.0)
|
val res = expression(x to 2.0)
|
||||||
assertEquals(-2.0, res)
|
assertEquals(-2.0, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBinaryOperationInvocation() {
|
fun testBinaryOperationInvocation() {
|
||||||
val expression = MstExtendedField { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField)
|
val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField)
|
||||||
val res = expression("x" to 2.0)
|
val res = expression(x to 2.0)
|
||||||
assertEquals(-1.0, res)
|
assertEquals(-1.0, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testConstProductInvocation() {
|
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)
|
assertEquals(4.0, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private companion object {
|
||||||
fun testMultipleCalls() {
|
private val x by symbol
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.estree
|
package space.kscience.kmath.estree
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MstExtendedField
|
import space.kscience.kmath.expressions.MstExtendedField
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -10,55 +17,60 @@ import kotlin.test.assertEquals
|
|||||||
internal class TestESTreeSpecialization {
|
internal class TestESTreeSpecialization {
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryPlus() {
|
fun testUnaryPlus() {
|
||||||
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||||
assertEquals(2.0, expr("x" to 2.0))
|
assertEquals(2.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryMinus() {
|
fun testUnaryMinus() {
|
||||||
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||||
assertEquals(-2.0, expr("x" to 2.0))
|
assertEquals(-2.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAdd() {
|
fun testAdd() {
|
||||||
val expr = MstExtendedField {
|
val expr = MstExtendedField {
|
||||||
binaryOperationFunction("+")(bindSymbol("x"),
|
binaryOperationFunction("+")(
|
||||||
bindSymbol("x"))
|
bindSymbol(x),
|
||||||
|
bindSymbol(x),
|
||||||
|
)
|
||||||
}.compileToExpression(DoubleField)
|
}.compileToExpression(DoubleField)
|
||||||
assertEquals(4.0, expr("x" to 2.0))
|
assertEquals(4.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSine() {
|
fun testSine() {
|
||||||
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||||
assertEquals(0.0, expr("x" to 0.0))
|
assertEquals(0.0, expr(x to 0.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMinus() {
|
fun testSubtract() {
|
||||||
val expr = MstExtendedField {
|
val expr = MstExtendedField {
|
||||||
binaryOperationFunction("-")(bindSymbol("x"),
|
binaryOperationFunction("-")(bindSymbol(x),
|
||||||
bindSymbol("x"))
|
bindSymbol(x))
|
||||||
}.compileToExpression(DoubleField)
|
}.compileToExpression(DoubleField)
|
||||||
assertEquals(0.0, expr("x" to 2.0))
|
assertEquals(0.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDivide() {
|
fun testDivide() {
|
||||||
val expr = MstExtendedField {
|
val expr = MstExtendedField {
|
||||||
binaryOperationFunction("/")(bindSymbol("x"),
|
binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x))
|
||||||
bindSymbol("x"))
|
|
||||||
}.compileToExpression(DoubleField)
|
}.compileToExpression(DoubleField)
|
||||||
assertEquals(1.0, expr("x" to 2.0))
|
assertEquals(1.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPower() {
|
fun testPower() {
|
||||||
val expr = MstExtendedField {
|
val expr = MstExtendedField {
|
||||||
binaryOperationFunction("pow")(bindSymbol("x"), number(2))
|
binaryOperationFunction("pow")(bindSymbol(x), number(2))
|
||||||
}.compileToExpression(DoubleField)
|
}.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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.estree
|
package space.kscience.kmath.estree
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MstRing
|
import space.kscience.kmath.expressions.MstRing
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.ByteRing
|
import space.kscience.kmath.operations.ByteRing
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -11,13 +18,17 @@ import kotlin.test.assertFailsWith
|
|||||||
internal class TestESTreeVariables {
|
internal class TestESTreeVariables {
|
||||||
@Test
|
@Test
|
||||||
fun testVariable() {
|
fun testVariable() {
|
||||||
val expr = MstRing{ bindSymbol("x") }.compileToExpression(ByteRing)
|
val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing)
|
||||||
assertEquals(1.toByte(), expr("x" to 1.toByte()))
|
assertEquals(1.toByte(), expr(x to 1.toByte()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testUndefinedVariableFails() {
|
fun testUndefinedVariableFails() {
|
||||||
val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing)
|
val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing)
|
||||||
assertFailsWith<NoSuchElementException> { expr() }
|
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,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.asm
|
package space.kscience.kmath.asm
|
||||||
|
|
||||||
import space.kscience.kmath.asm.internal.AsmBuilder
|
import space.kscience.kmath.asm.internal.AsmBuilder
|
||||||
import space.kscience.kmath.asm.internal.buildName
|
import space.kscience.kmath.asm.internal.buildName
|
||||||
import space.kscience.kmath.ast.MST
|
|
||||||
import space.kscience.kmath.ast.MST.*
|
|
||||||
import space.kscience.kmath.expressions.Expression
|
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.expressions.invoke
|
||||||
import space.kscience.kmath.misc.Symbol
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.operations.Algebra
|
import space.kscience.kmath.operations.Algebra
|
||||||
@ -34,15 +39,17 @@ internal fun <T : Any> MST.compileWith(type: Class<T>, algebra: Algebra<T>): Exp
|
|||||||
|
|
||||||
is Unary -> when {
|
is Unary -> when {
|
||||||
algebra is NumericAlgebra && node.value is Numeric -> loadObjectConstant(
|
algebra is NumericAlgebra && node.value is Numeric -> loadObjectConstant(
|
||||||
algebra.unaryOperationFunction(node.operation)(algebra.number(node.value.value)))
|
algebra.unaryOperationFunction(node.operation)(algebra.number((node.value as Numeric).value)))
|
||||||
|
|
||||||
else -> buildCall(algebra.unaryOperationFunction(node.operation)) { visit(node.value) }
|
else -> buildCall(algebra.unaryOperationFunction(node.operation)) { visit(node.value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
is Binary -> when {
|
is Binary -> when {
|
||||||
algebra is NumericAlgebra && node.left is Numeric && node.right is Numeric -> loadObjectConstant(
|
algebra is NumericAlgebra && node.left is Numeric && node.right is Numeric -> loadObjectConstant(
|
||||||
algebra.binaryOperationFunction(node.operation)
|
algebra.binaryOperationFunction(node.operation).invoke(
|
||||||
.invoke(algebra.number(node.left.value), algebra.number(node.right.value))
|
algebra.number((node.left as Numeric).value),
|
||||||
|
algebra.number((node.right as Numeric).value)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
algebra is NumericAlgebra && node.left is Numeric -> buildCall(
|
algebra is NumericAlgebra && node.left is Numeric -> buildCall(
|
||||||
@ -71,18 +78,18 @@ internal fun <T : Any> MST.compileWith(type: Class<T>, algebra: Algebra<T>): Exp
|
|||||||
/**
|
/**
|
||||||
* Create a compiled expression with given [MST] and given [algebra].
|
* Create a compiled expression with given [MST] and given [algebra].
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T: Any> MST.compileToExpression(algebra: Algebra<T>): Expression<T> =
|
public inline fun <reified T : Any> MST.compileToExpression(algebra: Algebra<T>): Expression<T> =
|
||||||
compileWith(T::class.java, algebra)
|
compileWith(T::class.java, algebra)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile given MST to expression and evaluate it against [arguments]
|
* Compile given MST to expression and evaluate it against [arguments]
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T: Any> MST.compile(algebra: Algebra<T>, arguments: Map<Symbol, T>): T =
|
public inline fun <reified T : Any> MST.compile(algebra: Algebra<T>, arguments: Map<Symbol, T>): T =
|
||||||
compileToExpression(algebra).invoke(arguments)
|
compileToExpression(algebra).invoke(arguments)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile given MST to expression and evaluate it against [arguments]
|
* Compile given MST to expression and evaluate it against [arguments]
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T: Any> MST.compile(algebra: Algebra<T>, vararg arguments: Pair<Symbol,T>): T =
|
public inline fun <reified T : Any> MST.compile(algebra: Algebra<T>, vararg arguments: Pair<Symbol, T>): T =
|
||||||
compileToExpression(algebra).invoke(*arguments)
|
compileToExpression(algebra).invoke(*arguments)
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.asm.internal
|
package space.kscience.kmath.asm.internal
|
||||||
|
|
||||||
import org.objectweb.asm.*
|
import org.objectweb.asm.*
|
||||||
@ -5,8 +10,8 @@ import org.objectweb.asm.Opcodes.*
|
|||||||
import org.objectweb.asm.Type.*
|
import org.objectweb.asm.Type.*
|
||||||
import org.objectweb.asm.commons.InstructionAdapter
|
import org.objectweb.asm.commons.InstructionAdapter
|
||||||
import space.kscience.kmath.asm.internal.AsmBuilder.ClassLoader
|
import space.kscience.kmath.asm.internal.AsmBuilder.ClassLoader
|
||||||
import space.kscience.kmath.ast.MST
|
|
||||||
import space.kscience.kmath.expressions.Expression
|
import space.kscience.kmath.expressions.Expression
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
import java.lang.invoke.MethodHandles
|
import java.lang.invoke.MethodHandles
|
||||||
import java.lang.invoke.MethodType
|
import java.lang.invoke.MethodType
|
||||||
import java.util.stream.Collectors.toMap
|
import java.util.stream.Collectors.toMap
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.asm.internal
|
package space.kscience.kmath.asm.internal
|
||||||
|
|
||||||
import org.objectweb.asm.*
|
import org.objectweb.asm.*
|
||||||
import org.objectweb.asm.commons.InstructionAdapter
|
import org.objectweb.asm.commons.InstructionAdapter
|
||||||
import space.kscience.kmath.ast.MST
|
|
||||||
import space.kscience.kmath.expressions.Expression
|
import space.kscience.kmath.expressions.Expression
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
@file:JvmName("MapIntrinsics")
|
@file:JvmName("MapIntrinsics")
|
||||||
|
|
||||||
package space.kscience.kmath.asm.internal
|
package space.kscience.kmath.asm.internal
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
|
internal actual fun Double.multiplatformToString(): String = toString()
|
||||||
|
internal actual fun Float.multiplatformToString(): String = toString()
|
@ -1,20 +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.asm
|
package space.kscience.kmath.asm
|
||||||
|
|
||||||
import space.kscience.kmath.ast.*
|
|
||||||
import space.kscience.kmath.complex.ComplexField
|
import space.kscience.kmath.complex.ComplexField
|
||||||
import space.kscience.kmath.complex.toComplex
|
import space.kscience.kmath.complex.toComplex
|
||||||
import space.kscience.kmath.misc.Symbol.Companion.x
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.ByteRing
|
import space.kscience.kmath.operations.ByteRing
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class TestAsmConsistencyWithInterpreter {
|
internal class TestAsmConsistencyWithInterpreter {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun mstSpace() {
|
fun mstSpace() {
|
||||||
|
|
||||||
val mst = MstGroup {
|
val mst = MstGroup {
|
||||||
binaryOperationFunction("+")(
|
binaryOperationFunction("+")(
|
||||||
unaryOperationFunction("+")(
|
unaryOperationFunction("+")(
|
||||||
@ -25,7 +29,7 @@ internal class TestAsmConsistencyWithInterpreter {
|
|||||||
),
|
),
|
||||||
|
|
||||||
number(1)
|
number(1)
|
||||||
) + bindSymbol("x") + zero
|
) + bindSymbol(x) + zero
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@ -39,7 +43,7 @@ internal class TestAsmConsistencyWithInterpreter {
|
|||||||
val mst = MstRing {
|
val mst = MstRing {
|
||||||
binaryOperationFunction("+")(
|
binaryOperationFunction("+")(
|
||||||
unaryOperationFunction("+")(
|
unaryOperationFunction("+")(
|
||||||
(bindSymbol("x") - (2.toByte() + (scale(
|
(bindSymbol(x) - (2.toByte() + (scale(
|
||||||
add(number(1), number(1)),
|
add(number(1), number(1)),
|
||||||
2.0
|
2.0
|
||||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||||
@ -56,10 +60,10 @@ internal class TestAsmConsistencyWithInterpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun realField() {
|
fun doubleField() {
|
||||||
val mst = MstField {
|
val mst = MstField {
|
||||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
+(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),
|
||||||
number(1) / 2 + number(2.0) * one
|
number(1) / 2 + number(2.0) * one
|
||||||
) + zero
|
) + zero
|
||||||
@ -75,7 +79,7 @@ internal class TestAsmConsistencyWithInterpreter {
|
|||||||
fun complexField() {
|
fun complexField() {
|
||||||
val mst = MstField {
|
val mst = MstField {
|
||||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
+(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),
|
||||||
number(1) / 2 + number(2.0) * one
|
number(1) / 2 + number(2.0) * one
|
||||||
) + zero
|
) + zero
|
||||||
@ -86,4 +90,8 @@ internal class TestAsmConsistencyWithInterpreter {
|
|||||||
mst.compile(ComplexField, x to 2.0.toComplex())
|
mst.compile(ComplexField, x to 2.0.toComplex())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private val x by symbol
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,44 +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.asm
|
package space.kscience.kmath.asm
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MstExtendedField
|
import space.kscience.kmath.expressions.MstField
|
||||||
import space.kscience.kmath.ast.MstField
|
import space.kscience.kmath.expressions.MstGroup
|
||||||
import space.kscience.kmath.ast.MstGroup
|
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.random.Random
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class TestAsmOperationsSupport {
|
internal class TestAsmOperationsSupport {
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryOperationInvocation() {
|
fun testUnaryOperationInvocation() {
|
||||||
val expression = MstGroup { -bindSymbol("x") }.compileToExpression(DoubleField)
|
val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField)
|
||||||
val res = expression("x" to 2.0)
|
val res = expression(x to 2.0)
|
||||||
assertEquals(-2.0, res)
|
assertEquals(-2.0, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBinaryOperationInvocation() {
|
fun testBinaryOperationInvocation() {
|
||||||
val expression = MstGroup { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField)
|
val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField)
|
||||||
val res = expression("x" to 2.0)
|
val res = expression(x to 2.0)
|
||||||
assertEquals(-1.0, res)
|
assertEquals(-1.0, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testConstProductInvocation() {
|
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)
|
assertEquals(4.0, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private companion object {
|
||||||
fun testMultipleCalls() {
|
private val x by symbol
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.asm
|
package space.kscience.kmath.asm
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MstExtendedField
|
import space.kscience.kmath.expressions.MstExtendedField
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -10,55 +17,60 @@ import kotlin.test.assertEquals
|
|||||||
internal class TestAsmSpecialization {
|
internal class TestAsmSpecialization {
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryPlus() {
|
fun testUnaryPlus() {
|
||||||
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||||
assertEquals(2.0, expr("x" to 2.0))
|
assertEquals(2.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryMinus() {
|
fun testUnaryMinus() {
|
||||||
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||||
assertEquals(-2.0, expr("x" to 2.0))
|
assertEquals(-2.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAdd() {
|
fun testAdd() {
|
||||||
val expr = MstExtendedField {
|
val expr = MstExtendedField {
|
||||||
binaryOperationFunction("+")(bindSymbol("x"),
|
binaryOperationFunction("+")(
|
||||||
bindSymbol("x"))
|
bindSymbol(x),
|
||||||
|
bindSymbol(x),
|
||||||
|
)
|
||||||
}.compileToExpression(DoubleField)
|
}.compileToExpression(DoubleField)
|
||||||
assertEquals(4.0, expr("x" to 2.0))
|
assertEquals(4.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSine() {
|
fun testSine() {
|
||||||
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||||
assertEquals(0.0, expr("x" to 0.0))
|
assertEquals(0.0, expr(x to 0.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMinus() {
|
fun testSubtract() {
|
||||||
val expr = MstExtendedField {
|
val expr = MstExtendedField {
|
||||||
binaryOperationFunction("-")(bindSymbol("x"),
|
binaryOperationFunction("-")(bindSymbol(x),
|
||||||
bindSymbol("x"))
|
bindSymbol(x))
|
||||||
}.compileToExpression(DoubleField)
|
}.compileToExpression(DoubleField)
|
||||||
assertEquals(0.0, expr("x" to 2.0))
|
assertEquals(0.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDivide() {
|
fun testDivide() {
|
||||||
val expr = MstExtendedField {
|
val expr = MstExtendedField {
|
||||||
binaryOperationFunction("/")(bindSymbol("x"),
|
binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x))
|
||||||
bindSymbol("x"))
|
|
||||||
}.compileToExpression(DoubleField)
|
}.compileToExpression(DoubleField)
|
||||||
assertEquals(1.0, expr("x" to 2.0))
|
assertEquals(1.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPower() {
|
fun testPower() {
|
||||||
val expr = MstExtendedField {
|
val expr = MstExtendedField {
|
||||||
binaryOperationFunction("pow")(bindSymbol("x"), number(2))
|
binaryOperationFunction("pow")(bindSymbol(x), number(2))
|
||||||
}.compileToExpression(DoubleField)
|
}.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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.asm
|
package space.kscience.kmath.asm
|
||||||
|
|
||||||
import space.kscience.kmath.ast.MstRing
|
import space.kscience.kmath.expressions.MstRing
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.ByteRing
|
import space.kscience.kmath.operations.ByteRing
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -11,13 +18,17 @@ import kotlin.test.assertFailsWith
|
|||||||
internal class TestAsmVariables {
|
internal class TestAsmVariables {
|
||||||
@Test
|
@Test
|
||||||
fun testVariable() {
|
fun testVariable() {
|
||||||
val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing)
|
val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing)
|
||||||
assertEquals(1.toByte(), expr("x" to 1.toByte()))
|
assertEquals(1.toByte(), expr(x to 1.toByte()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testUndefinedVariableFails() {
|
fun testUndefinedVariableFails() {
|
||||||
val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing)
|
val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing)
|
||||||
assertFailsWith<NoSuchElementException> { expr() }
|
assertFailsWith<NoSuchElementException> { expr() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private val x by symbol
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.jvm")
|
kotlin("jvm")
|
||||||
|
id("ru.mipt.npm.gradle.common")
|
||||||
}
|
}
|
||||||
|
|
||||||
description = "Commons math binding for kmath"
|
description = "Commons math binding for kmath"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user