forked from kscience/kmath
Merge branch 'dev' into dev
This commit is contained in:
commit
a299003236
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@ -13,9 +13,11 @@ jobs:
|
|||||||
- name: Checkout the repo
|
- name: Checkout the repo
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Set up JDK 11
|
- name: Set up JDK 11
|
||||||
uses: actions/setup-java@v1
|
uses: DeLaGuardo/setup-graalvm@4.0
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
graalvm: 21.1.0
|
||||||
|
java: java11
|
||||||
|
arch: amd64
|
||||||
- name: Add msys to path
|
- name: Add msys to path
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
|
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
|
||||||
|
18
.github/workflows/pages.yml
vendored
18
.github/workflows/pages.yml
vendored
@ -15,24 +15,8 @@ jobs:
|
|||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
- name: Cache gradle
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }}
|
|
||||||
restore-keys: |
|
|
||||||
ubuntu-20.04-gradle-
|
|
||||||
- name: Cache konan
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.konan
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-gradle-
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
|
||||||
./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
|
|
||||||
mv build/dokka/htmlMultiModule/-modules.html build/dokka/htmlMultiModule/index.html
|
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
uses: JamesIves/github-pages-deploy-action@4.1.0
|
uses: JamesIves/github-pages-deploy-action@4.1.0
|
||||||
with:
|
with:
|
||||||
|
6
.github/workflows/publish.yml
vendored
6
.github/workflows/publish.yml
vendored
@ -18,9 +18,11 @@ jobs:
|
|||||||
- name: Checkout the repo
|
- name: Checkout the repo
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Set up JDK 11
|
- name: Set up JDK 11
|
||||||
uses: actions/setup-java@v1
|
uses: DeLaGuardo/setup-graalvm@4.0
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
graalvm: 21.1.0
|
||||||
|
java: java11
|
||||||
|
arch: amd64
|
||||||
- name: Add msys to path
|
- name: Add msys to path
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
|
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@ out/
|
|||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
!.idea/copyright/
|
!.idea/copyright/
|
||||||
|
!.idea/scopes/
|
||||||
|
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
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>
|
@ -10,6 +10,9 @@
|
|||||||
- Blocking chains and Statistics
|
- Blocking chains and Statistics
|
||||||
- Multiplatform integration
|
- Multiplatform integration
|
||||||
- Integration for any Field element
|
- Integration for any Field element
|
||||||
|
- Extended operations for ND4J fields
|
||||||
|
- Jupyter Notebook integration module (kmath-jupyter)
|
||||||
|
- `@PerformancePitfall` annotation to mark possibly slow API
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Exponential operations merged with hyperbolic functions
|
- Exponential operations merged with hyperbolic functions
|
||||||
@ -23,6 +26,8 @@
|
|||||||
- Redesign MST. Remove MSTExpression.
|
- Redesign MST. Remove MSTExpression.
|
||||||
- Move MST to core
|
- Move MST to core
|
||||||
- Separated benchmarks and examples
|
- Separated benchmarks and examples
|
||||||
|
- Rewritten EJML module without ejml-simple
|
||||||
|
- Stability of kmath-ast and kmath-kotilngrad promoted to EXPERIMENTAL.
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
@ -31,6 +36,8 @@
|
|||||||
- Number multiplication and division in main Algebra chain
|
- Number multiplication and division in main Algebra chain
|
||||||
- `contentEquals` from Buffer. It moved to the companion.
|
- `contentEquals` from Buffer. It moved to the companion.
|
||||||
- MSTExpression
|
- MSTExpression
|
||||||
|
- Expression algebra builders
|
||||||
|
- Complex and Quaternion no longer are elements.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Ring inherits RingOperations, not GroupOperations
|
- Ring inherits RingOperations, not GroupOperations
|
||||||
|
50
README.md
50
README.md
@ -76,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)
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
@ -85,15 +91,13 @@ KMath is a modular library. Different modules provide different features with di
|
|||||||
* ### [kmath-ast](kmath-ast)
|
* ### [kmath-ast](kmath-ast)
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: EXPERIMENTAL
|
||||||
>
|
>
|
||||||
> **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/>
|
||||||
|
|
||||||
@ -150,9 +154,9 @@ performance calculations to code generation.
|
|||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
>
|
>
|
||||||
> **Features:**
|
> **Features:**
|
||||||
> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix.
|
> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : Point implementations.
|
||||||
> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix.
|
> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : Matrix implementation.
|
||||||
> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix.
|
> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : LinearSpace implementations.
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
@ -196,12 +200,23 @@ One can still use generic algebras though.
|
|||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-kotlingrad](kmath-kotlingrad)
|
* ### [kmath-jupyter](kmath-jupyter)
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
|
* ### [kmath-kotlingrad](kmath-kotlingrad)
|
||||||
|
> Functions, integration and interpolation
|
||||||
|
>
|
||||||
|
> **Maturity**: EXPERIMENTAL
|
||||||
|
>
|
||||||
|
> **Features:**
|
||||||
|
> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : MST based DifferentiableExpression.
|
||||||
|
> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-memory](kmath-memory)
|
* ### [kmath-memory](kmath-memory)
|
||||||
> An API and basic implementation for arranging objects in a continous memory block.
|
> An API and basic implementation for arranging objects in a continous memory block.
|
||||||
>
|
>
|
||||||
@ -226,6 +241,19 @@ One can still use generic algebras though.
|
|||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
|
* ### [kmath-tensors](kmath-tensors)
|
||||||
|
>
|
||||||
|
>
|
||||||
|
> **Maturity**: PROTOTYPE
|
||||||
|
>
|
||||||
|
> **Features:**
|
||||||
|
> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.)
|
||||||
|
> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc.
|
||||||
|
> - [tensor algebra over Double](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s.
|
||||||
|
> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s.
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-viktor](kmath-viktor)
|
* ### [kmath-viktor](kmath-viktor)
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
@ -266,8 +294,8 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api("space.kscience:kmath-core:0.3.0-dev-6")
|
api("space.kscience:kmath-core:0.3.0-dev-8")
|
||||||
// api("space.kscience:kmath-core-jvm:0.3.0-dev-6") for jvm-specific version
|
// api("space.kscience:kmath-core-jvm:0.3.0-dev-8") for jvm-specific version
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import ru.mipt.npm.gradle.Maturity
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("multiplatform")
|
kotlin("multiplatform")
|
||||||
kotlin("plugin.allopen")
|
kotlin("plugin.allopen")
|
||||||
@ -14,18 +7,12 @@ plugins {
|
|||||||
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
||||||
sourceSets.register("benchmarks")
|
sourceSets.register("benchmarks")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
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/hotkeytlt/maven")
|
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
maven {
|
maven("http://logicrunch.research.it.uu.se/maven") {
|
||||||
setUrl("http://logicrunch.research.it.uu.se/maven/")
|
|
||||||
isAllowInsecureProtocol = true
|
isAllowInsecureProtocol = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,43 +64,35 @@ benchmark {
|
|||||||
register("jvm")
|
register("jvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
|
||||||
|
warmups = 1
|
||||||
|
iterations = 5
|
||||||
|
iterationTime = 1000
|
||||||
|
iterationTimeUnit = "ms"
|
||||||
|
}
|
||||||
|
|
||||||
configurations.register("buffer") {
|
configurations.register("buffer") {
|
||||||
warmups = 1 // number of warmup iterations
|
commonConfiguration()
|
||||||
iterations = 3 // number of iterations
|
|
||||||
iterationTime = 500 // time in seconds per iteration
|
|
||||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
|
||||||
include("BufferBenchmark")
|
include("BufferBenchmark")
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.register("dot") {
|
configurations.register("dot") {
|
||||||
warmups = 1 // number of warmup iterations
|
commonConfiguration()
|
||||||
iterations = 3 // number of iterations
|
|
||||||
iterationTime = 500 // time in seconds per iteration
|
|
||||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
|
||||||
include("DotBenchmark")
|
include("DotBenchmark")
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.register("expressions") {
|
configurations.register("expressions") {
|
||||||
warmups = 1 // number of warmup iterations
|
commonConfiguration()
|
||||||
iterations = 3 // number of iterations
|
|
||||||
iterationTime = 500 // time in seconds per iteration
|
|
||||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
|
||||||
include("ExpressionsInterpretersBenchmark")
|
include("ExpressionsInterpretersBenchmark")
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.register("matrixInverse") {
|
configurations.register("matrixInverse") {
|
||||||
warmups = 1 // number of warmup iterations
|
commonConfiguration()
|
||||||
iterations = 3 // number of iterations
|
|
||||||
iterationTime = 500 // time in seconds per iteration
|
|
||||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
|
||||||
include("MatrixInverseBenchmark")
|
include("MatrixInverseBenchmark")
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.register("bigInt") {
|
configurations.register("bigInt") {
|
||||||
warmups = 1 // number of warmup iterations
|
commonConfiguration()
|
||||||
iterations = 3 // number of iterations
|
|
||||||
iterationTime = 500 // time in seconds per iteration
|
|
||||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
|
||||||
include("BigIntBenchmark")
|
include("BigIntBenchmark")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,7 +100,7 @@ benchmark {
|
|||||||
// Fix kotlinx-benchmarks bug
|
// Fix kotlinx-benchmarks bug
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
val jvmBenchmarkJar by tasks.getting(org.gradle.jvm.tasks.Jar::class) {
|
val jvmBenchmarkJar by tasks.getting(org.gradle.jvm.tasks.Jar::class) {
|
||||||
duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.EXCLUDE
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,5 +122,5 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
|||||||
|
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
maturity = Maturity.EXPERIMENTAL
|
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole
|
|||||||
import kotlinx.benchmark.Scope
|
import kotlinx.benchmark.Scope
|
||||||
import kotlinx.benchmark.State
|
import kotlinx.benchmark.State
|
||||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
import space.kscience.kmath.commons.linear.CMLinearSpace
|
||||||
import space.kscience.kmath.ejml.EjmlLinearSpace
|
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
||||||
import space.kscience.kmath.linear.LinearSpace
|
import space.kscience.kmath.linear.LinearSpace
|
||||||
import space.kscience.kmath.linear.invoke
|
import space.kscience.kmath.linear.invoke
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
@ -29,8 +29,8 @@ internal class DotBenchmark {
|
|||||||
val cmMatrix1 = CMLinearSpace { matrix1.toCM() }
|
val cmMatrix1 = CMLinearSpace { matrix1.toCM() }
|
||||||
val cmMatrix2 = CMLinearSpace { matrix2.toCM() }
|
val cmMatrix2 = CMLinearSpace { matrix2.toCM() }
|
||||||
|
|
||||||
val ejmlMatrix1 = EjmlLinearSpace { matrix1.toEjml() }
|
val ejmlMatrix1 = EjmlLinearSpaceDDRM { matrix1.toEjml() }
|
||||||
val ejmlMatrix2 = EjmlLinearSpace { matrix2.toEjml() }
|
val ejmlMatrix2 = EjmlLinearSpaceDDRM { matrix2.toEjml() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@ -42,14 +42,14 @@ internal class DotBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun ejmlDot(blackhole: Blackhole) {
|
fun ejmlDot(blackhole: Blackhole) {
|
||||||
EjmlLinearSpace {
|
EjmlLinearSpaceDDRM {
|
||||||
blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
|
blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun ejmlDotWithConversion(blackhole: Blackhole) {
|
fun ejmlDotWithConversion(blackhole: Blackhole) {
|
||||||
EjmlLinearSpace {
|
EjmlLinearSpaceDDRM {
|
||||||
blackhole.consume(matrix1 dot matrix2)
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import kotlinx.benchmark.Scope
|
|||||||
import kotlinx.benchmark.State
|
import kotlinx.benchmark.State
|
||||||
import space.kscience.kmath.asm.compileToExpression
|
import space.kscience.kmath.asm.compileToExpression
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.misc.symbol
|
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.bindSymbol
|
||||||
@ -20,50 +21,22 @@ import kotlin.random.Random
|
|||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
internal class ExpressionsInterpretersBenchmark {
|
internal class ExpressionsInterpretersBenchmark {
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun functionalExpression(blackhole: Blackhole) {
|
fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
|
||||||
val expr = algebra.expressionInField {
|
|
||||||
val x = bindSymbol(x)
|
|
||||||
x * const(2.0) + const(2.0) / x - const(16.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
invokeAndSum(expr, blackhole)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun mstExpression(blackhole: Blackhole) {
|
fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
|
||||||
val expr = MstField {
|
|
||||||
val x = bindSymbol(x)
|
|
||||||
x * 2.0 + number(2.0) / x - 16.0
|
|
||||||
}.toExpression(algebra)
|
|
||||||
|
|
||||||
invokeAndSum(expr, blackhole)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun asmExpression(blackhole: Blackhole) {
|
fun asmExpression(blackhole: Blackhole) = invokeAndSum(asm, blackhole)
|
||||||
val expr = MstField {
|
|
||||||
val x = bindSymbol(x)
|
|
||||||
x * 2.0 + number(2.0) / x - 16.0
|
|
||||||
}.compileToExpression(algebra)
|
|
||||||
|
|
||||||
invokeAndSum(expr, blackhole)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun rawExpression(blackhole: Blackhole) {
|
fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, 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) {
|
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
|
||||||
val random = Random(0)
|
val random = Random(0)
|
||||||
var sum = 0.0
|
var sum = 0.0
|
||||||
|
|
||||||
repeat(1000000) {
|
repeat(times) {
|
||||||
sum += expr(x to random.nextDouble())
|
sum += expr(x to random.nextDouble())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +44,23 @@ internal class ExpressionsInterpretersBenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private val algebra = DoubleField
|
private val x: Symbol by symbol
|
||||||
private val x 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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,25 +11,26 @@ import kotlinx.benchmark.Scope
|
|||||||
import kotlinx.benchmark.State
|
import kotlinx.benchmark.State
|
||||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
import space.kscience.kmath.commons.linear.CMLinearSpace
|
||||||
import space.kscience.kmath.commons.linear.inverse
|
import space.kscience.kmath.commons.linear.inverse
|
||||||
import space.kscience.kmath.ejml.EjmlLinearSpace
|
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
||||||
import space.kscience.kmath.ejml.inverse
|
import space.kscience.kmath.linear.InverseMatrixFeature
|
||||||
import space.kscience.kmath.linear.LinearSpace
|
import space.kscience.kmath.linear.LinearSpace
|
||||||
import space.kscience.kmath.linear.inverseWithLup
|
import space.kscience.kmath.linear.inverseWithLup
|
||||||
import space.kscience.kmath.linear.invoke
|
import space.kscience.kmath.linear.invoke
|
||||||
|
import space.kscience.kmath.nd.getFeature
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
internal class MatrixInverseBenchmark {
|
internal class MatrixInverseBenchmark {
|
||||||
companion object {
|
private companion object {
|
||||||
val random = Random(1224)
|
private val random = Random(1224)
|
||||||
const val dim = 100
|
private const val dim = 100
|
||||||
|
|
||||||
private val space = LinearSpace.real
|
private val space = LinearSpace.real
|
||||||
|
|
||||||
//creating invertible matrix
|
//creating invertible matrix
|
||||||
val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
private val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
||||||
val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
|
private val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
|
||||||
val matrix = space { l dot u }
|
private val matrix = space { l dot u }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@ -46,8 +47,8 @@ internal class MatrixInverseBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun ejmlInverse(blackhole: Blackhole) {
|
fun ejmlInverse(blackhole: Blackhole) {
|
||||||
with(EjmlLinearSpace) {
|
with(EjmlLinearSpaceDDRM) {
|
||||||
blackhole.consume(inverse(matrix))
|
blackhole.consume(matrix.getFeature<InverseMatrixFeature<Double>>()?.inverse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,53 +1,37 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import org.jetbrains.dokka.gradle.DokkaTask
|
|
||||||
import java.net.URL
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.project")
|
id("ru.mipt.npm.gradle.project")
|
||||||
|
kotlin("jupyter.api") apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
|
||||||
maven("https://clojars.org/repo")
|
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("https://jitpack.io")
|
||||||
maven{
|
maven("http://logicrunch.research.it.uu.se/maven") {
|
||||||
setUrl("http://logicrunch.research.it.uu.se/maven/")
|
|
||||||
isAllowInsecureProtocol = true
|
isAllowInsecureProtocol = true
|
||||||
}
|
}
|
||||||
|
maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.3.0-dev-7"
|
version = "0.3.0-dev-8"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
if (name.startsWith("kmath")) apply<MavenPublishPlugin>()
|
if (name.startsWith("kmath")) apply<MavenPublishPlugin>()
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
tasks.withType<DokkaTask> {
|
tasks.withType<org.jetbrains.dokka.gradle.DokkaTaskPartial> {
|
||||||
dokkaSourceSets.all {
|
dependsOn(tasks.getByName("assemble"))
|
||||||
val readmeFile = File(this@subprojects.projectDir, "./README.md")
|
|
||||||
if (readmeFile.exists())
|
|
||||||
includes.setFrom(includes + readmeFile.absolutePath)
|
|
||||||
|
|
||||||
arrayOf(
|
dokkaSourceSets.all {
|
||||||
"http://ejml.org/javadoc/",
|
val readmeFile = File(this@subprojects.projectDir, "README.md")
|
||||||
"https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/",
|
if (readmeFile.exists()) includes.setFrom(includes + readmeFile.absolutePath)
|
||||||
"https://deeplearning4j.org/api/latest/"
|
externalDocumentationLink("http://ejml.org/javadoc/")
|
||||||
).map { URL("${it}package-list") to URL(it) }.forEach { (a, b) ->
|
externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/")
|
||||||
externalDocumentationLink {
|
externalDocumentationLink("https://deeplearning4j.org/api/latest/")
|
||||||
packageListUrl.set(a)
|
externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/")
|
||||||
url.set(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
6
docs/templates/ARTIFACT-TEMPLATE.md
vendored
6
docs/templates/ARTIFACT-TEMPLATE.md
vendored
@ -6,8 +6,7 @@ The Maven coordinates of this project are `${group}:${name}:${version}`.
|
|||||||
```gradle
|
```gradle
|
||||||
repositories {
|
repositories {
|
||||||
maven { url 'https://repo.kotlin.link' }
|
maven { url 'https://repo.kotlin.link' }
|
||||||
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
mavenCentral()
|
||||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -18,8 +17,7 @@ dependencies {
|
|||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://repo.kotlin.link")
|
maven("https://repo.kotlin.link")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
mavenCentral()
|
||||||
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -1,25 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
||||||
import ru.mipt.npm.gradle.Maturity
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm")
|
kotlin("jvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
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/hotkeytlt/maven")
|
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
maven{
|
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers")
|
||||||
setUrl("http://logicrunch.research.it.uu.se/maven/")
|
maven("http://logicrunch.research.it.uu.se/maven") {
|
||||||
isAllowInsecureProtocol = true
|
isAllowInsecureProtocol = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,6 +25,7 @@ dependencies {
|
|||||||
implementation(project(":kmath-dimensions"))
|
implementation(project(":kmath-dimensions"))
|
||||||
implementation(project(":kmath-ejml"))
|
implementation(project(":kmath-ejml"))
|
||||||
implementation(project(":kmath-nd4j"))
|
implementation(project(":kmath-nd4j"))
|
||||||
|
implementation(project(":kmath-tensors"))
|
||||||
|
|
||||||
implementation(project(":kmath-for-real"))
|
implementation(project(":kmath-for-real"))
|
||||||
|
|
||||||
@ -64,7 +54,7 @@ kotlin.sourceSets.all {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<KotlinCompile> {
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||||
kotlinOptions{
|
kotlinOptions{
|
||||||
jvmTarget = "11"
|
jvmTarget = "11"
|
||||||
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
|
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
|
||||||
@ -72,5 +62,5 @@ tasks.withType<KotlinCompile> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
maturity = Maturity.EXPERIMENTAL
|
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||||
}
|
}
|
||||||
|
@ -25,5 +25,5 @@ fun main() {
|
|||||||
|
|
||||||
|
|
||||||
val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField)
|
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,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.integration.integrate
|
import space.kscience.kmath.integration.integrate
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.integration.integrate
|
import space.kscience.kmath.integration.integrate
|
||||||
|
@ -22,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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import org.nd4j.linalg.factory.Nd4j
|
import org.nd4j.linalg.factory.Nd4j
|
||||||
import space.kscience.kmath.nd.*
|
import space.kscience.kmath.nd.*
|
||||||
@ -22,6 +23,7 @@ internal inline fun measureAndPrint(title: String, block: () -> Unit) {
|
|||||||
println("$title completed in $time millis")
|
println("$title completed in $time millis")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
fun main() {
|
fun main() {
|
||||||
// initializing Nd4j
|
// initializing Nd4j
|
||||||
Nd4j.zeros(0)
|
Nd4j.zeros(0)
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
||||||
|
|
||||||
|
|
||||||
|
// Dataset normalization
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
|
||||||
|
// work in context with broadcast methods
|
||||||
|
BroadcastDoubleTensorAlgebra {
|
||||||
|
// take dataset of 5-element vectors from normal distribution
|
||||||
|
val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5)
|
||||||
|
|
||||||
|
dataset += fromArray(
|
||||||
|
intArrayOf(5),
|
||||||
|
doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// find out mean and standard deviation of each column
|
||||||
|
val mean = dataset.mean(0, false)
|
||||||
|
val std = dataset.std(0, false)
|
||||||
|
|
||||||
|
println("Mean:\n$mean")
|
||||||
|
println("Standard deviation:\n$std")
|
||||||
|
|
||||||
|
// also we can calculate other statistic as minimum and maximum of rows
|
||||||
|
println("Minimum:\n${dataset.min(0, false)}")
|
||||||
|
println("Maximum:\n${dataset.max(0, false)}")
|
||||||
|
|
||||||
|
// now we can scale dataset with mean normalization
|
||||||
|
val datasetScaled = (dataset - mean) / std
|
||||||
|
|
||||||
|
// find out mean and std of scaled dataset
|
||||||
|
|
||||||
|
println("Mean of scaled:\n${datasetScaled.mean(0, false)}")
|
||||||
|
println("Mean of scaled:\n${datasetScaled.std(0, false)}")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import space.kscience.kmath.tensors.core.DoubleTensor
|
||||||
|
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
||||||
|
|
||||||
|
// solving linear system with LUP decomposition
|
||||||
|
|
||||||
|
fun main () {
|
||||||
|
|
||||||
|
// work in context with linear operations
|
||||||
|
BroadcastDoubleTensorAlgebra {
|
||||||
|
|
||||||
|
// set true value of x
|
||||||
|
val trueX = fromArray(
|
||||||
|
intArrayOf(4),
|
||||||
|
doubleArrayOf(-2.0, 1.5, 6.8, -2.4)
|
||||||
|
)
|
||||||
|
|
||||||
|
// and A matrix
|
||||||
|
val a = fromArray(
|
||||||
|
intArrayOf(4, 4),
|
||||||
|
doubleArrayOf(
|
||||||
|
0.5, 10.5, 4.5, 1.0,
|
||||||
|
8.5, 0.9, 12.8, 0.1,
|
||||||
|
5.56, 9.19, 7.62, 5.45,
|
||||||
|
1.0, 2.0, -3.0, -2.5
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// calculate y value
|
||||||
|
val b = a dot trueX
|
||||||
|
|
||||||
|
// check out A and b
|
||||||
|
println("A:\n$a")
|
||||||
|
println("b:\n$b")
|
||||||
|
|
||||||
|
// solve `Ax = b` system using LUP decomposition
|
||||||
|
|
||||||
|
// get P, L, U such that PA = LU
|
||||||
|
val (p, l, u) = a.lu()
|
||||||
|
|
||||||
|
// check that P is permutation matrix
|
||||||
|
println("P:\n$p")
|
||||||
|
// L is lower triangular matrix and U is upper triangular matrix
|
||||||
|
println("L:\n$l")
|
||||||
|
println("U:\n$u")
|
||||||
|
// and PA = LU
|
||||||
|
println("PA:\n${p dot a}")
|
||||||
|
println("LU:\n${l dot u}")
|
||||||
|
|
||||||
|
/* Ax = b;
|
||||||
|
PAx = Pb;
|
||||||
|
LUx = Pb;
|
||||||
|
let y = Ux, then
|
||||||
|
Ly = Pb -- this system can be easily solved, since the matrix L is lower triangular;
|
||||||
|
Ux = y can be solved the same way, since the matrix L is upper triangular
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// this function returns solution x of a system lx = b, l should be lower triangular
|
||||||
|
fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor {
|
||||||
|
val n = l.shape[0]
|
||||||
|
val x = zeros(intArrayOf(n))
|
||||||
|
for (i in 0 until n){
|
||||||
|
x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)]
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
val y = solveLT(l, p dot b)
|
||||||
|
|
||||||
|
// solveLT(l, b) function can be easily adapted for upper triangular matrix by the permutation matrix revMat
|
||||||
|
// create it by placing ones on side diagonal
|
||||||
|
val revMat = u.zeroesLike()
|
||||||
|
val n = revMat.shape[0]
|
||||||
|
for (i in 0 until n) {
|
||||||
|
revMat[intArrayOf(i, n - 1 - i)] = 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// solution of system ux = b, u should be upper triangular
|
||||||
|
fun solveUT(u: DoubleTensor, b: DoubleTensor): DoubleTensor = revMat dot solveLT(
|
||||||
|
revMat dot u dot revMat, revMat dot b
|
||||||
|
)
|
||||||
|
|
||||||
|
val x = solveUT(u, y)
|
||||||
|
|
||||||
|
println("True x:\n$trueX")
|
||||||
|
println("x founded with LU method:\n$x")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,241 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
||||||
|
import space.kscience.kmath.tensors.core.DoubleTensor
|
||||||
|
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
||||||
|
import space.kscience.kmath.tensors.core.toDoubleArray
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
const val seed = 100500L
|
||||||
|
|
||||||
|
// Simple feedforward neural network with backpropagation training
|
||||||
|
|
||||||
|
// interface of network layer
|
||||||
|
interface Layer {
|
||||||
|
fun forward(input: DoubleTensor): DoubleTensor
|
||||||
|
fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor
|
||||||
|
}
|
||||||
|
|
||||||
|
// activation layer
|
||||||
|
open class Activation(
|
||||||
|
val activation: (DoubleTensor) -> DoubleTensor,
|
||||||
|
val activationDer: (DoubleTensor) -> DoubleTensor
|
||||||
|
) : Layer {
|
||||||
|
override fun forward(input: DoubleTensor): DoubleTensor {
|
||||||
|
return activation(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor {
|
||||||
|
return DoubleTensorAlgebra { outputError * activationDer(input) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun relu(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra {
|
||||||
|
x.map { if (it > 0) it else 0.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reluDer(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra {
|
||||||
|
x.map { if (it > 0) 1.0 else 0.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
// activation layer with relu activator
|
||||||
|
class ReLU : Activation(::relu, ::reluDer)
|
||||||
|
|
||||||
|
fun sigmoid(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra {
|
||||||
|
1.0 / (1.0 + (-x).exp())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sigmoidDer(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra {
|
||||||
|
sigmoid(x) * (1.0 - sigmoid(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
// activation layer with sigmoid activator
|
||||||
|
class Sigmoid : Activation(::sigmoid, ::sigmoidDer)
|
||||||
|
|
||||||
|
// dense layer
|
||||||
|
class Dense(
|
||||||
|
private val inputUnits: Int,
|
||||||
|
private val outputUnits: Int,
|
||||||
|
private val learningRate: Double = 0.1
|
||||||
|
) : Layer {
|
||||||
|
|
||||||
|
private val weights: DoubleTensor = DoubleTensorAlgebra {
|
||||||
|
randomNormal(
|
||||||
|
intArrayOf(inputUnits, outputUnits),
|
||||||
|
seed
|
||||||
|
) * sqrt(2.0 / (inputUnits + outputUnits))
|
||||||
|
}
|
||||||
|
|
||||||
|
private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(intArrayOf(outputUnits)) }
|
||||||
|
|
||||||
|
override fun forward(input: DoubleTensor): DoubleTensor {
|
||||||
|
return BroadcastDoubleTensorAlgebra { (input dot weights) + bias }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor = DoubleTensorAlgebra {
|
||||||
|
val gradInput = outputError dot weights.transpose()
|
||||||
|
|
||||||
|
val gradW = input.transpose() dot outputError
|
||||||
|
val gradBias = outputError.mean(dim = 0, keepDim = false) * input.shape[0].toDouble()
|
||||||
|
|
||||||
|
weights -= learningRate * gradW
|
||||||
|
bias -= learningRate * gradBias
|
||||||
|
|
||||||
|
gradInput
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// simple accuracy equal to the proportion of correct answers
|
||||||
|
fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double {
|
||||||
|
check(yPred.shape contentEquals yTrue.shape)
|
||||||
|
val n = yPred.shape[0]
|
||||||
|
var correctCnt = 0
|
||||||
|
for (i in 0 until n) {
|
||||||
|
if (yPred[intArrayOf(i, 0)] == yTrue[intArrayOf(i, 0)]) {
|
||||||
|
correctCnt += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return correctCnt.toDouble() / n.toDouble()
|
||||||
|
}
|
||||||
|
|
||||||
|
// neural network class
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
class NeuralNetwork(private val layers: List<Layer>) {
|
||||||
|
private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra {
|
||||||
|
|
||||||
|
val onesForAnswers = yPred.zeroesLike()
|
||||||
|
yTrue.toDoubleArray().forEachIndexed { index, labelDouble ->
|
||||||
|
val label = labelDouble.toInt()
|
||||||
|
onesForAnswers[intArrayOf(index, label)] = 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
val softmaxValue = yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true)
|
||||||
|
|
||||||
|
(-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun forward(x: DoubleTensor): List<DoubleTensor> {
|
||||||
|
var input = x
|
||||||
|
|
||||||
|
return buildList {
|
||||||
|
layers.forEach { layer ->
|
||||||
|
val output = layer.forward(input)
|
||||||
|
add(output)
|
||||||
|
input = output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun train(xTrain: DoubleTensor, yTrain: DoubleTensor) {
|
||||||
|
val layerInputs = buildList {
|
||||||
|
add(xTrain)
|
||||||
|
addAll(forward(xTrain))
|
||||||
|
}
|
||||||
|
|
||||||
|
var lossGrad = softMaxLoss(layerInputs.last(), yTrain)
|
||||||
|
|
||||||
|
layers.zip(layerInputs).reversed().forEach { (layer, input) ->
|
||||||
|
lossGrad = layer.backward(input, lossGrad)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fit(xTrain: DoubleTensor, yTrain: DoubleTensor, batchSize: Int, epochs: Int) = DoubleTensorAlgebra {
|
||||||
|
fun iterBatch(x: DoubleTensor, y: DoubleTensor): Sequence<Pair<DoubleTensor, DoubleTensor>> = sequence {
|
||||||
|
val n = x.shape[0]
|
||||||
|
val shuffledIndices = (0 until n).shuffled()
|
||||||
|
for (i in 0 until n step batchSize) {
|
||||||
|
val excerptIndices = shuffledIndices.drop(i).take(batchSize).toIntArray()
|
||||||
|
val batch = x.rowsByIndices(excerptIndices) to y.rowsByIndices(excerptIndices)
|
||||||
|
yield(batch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (epoch in 0 until epochs) {
|
||||||
|
println("Epoch ${epoch + 1}/$epochs")
|
||||||
|
for ((xBatch, yBatch) in iterBatch(xTrain, yTrain)) {
|
||||||
|
train(xBatch, yBatch)
|
||||||
|
}
|
||||||
|
println("Accuracy:${accuracy(yTrain, predict(xTrain).argMax(1, true))}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun predict(x: DoubleTensor): DoubleTensor {
|
||||||
|
return forward(x).last()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
fun main() {
|
||||||
|
BroadcastDoubleTensorAlgebra {
|
||||||
|
val features = 5
|
||||||
|
val sampleSize = 250
|
||||||
|
val trainSize = 180
|
||||||
|
//val testSize = sampleSize - trainSize
|
||||||
|
|
||||||
|
// take sample of features from normal distribution
|
||||||
|
val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5
|
||||||
|
|
||||||
|
x += fromArray(
|
||||||
|
intArrayOf(5),
|
||||||
|
doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// define class like '1' if the sum of features > 0 and '0' otherwise
|
||||||
|
val y = fromArray(
|
||||||
|
intArrayOf(sampleSize, 1),
|
||||||
|
DoubleArray(sampleSize) { i ->
|
||||||
|
if (x[i].sum() > 0.0) {
|
||||||
|
1.0
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// split train ans test
|
||||||
|
val trainIndices = (0 until trainSize).toList().toIntArray()
|
||||||
|
val testIndices = (trainSize until sampleSize).toList().toIntArray()
|
||||||
|
|
||||||
|
val xTrain = x.rowsByIndices(trainIndices)
|
||||||
|
val yTrain = y.rowsByIndices(trainIndices)
|
||||||
|
|
||||||
|
val xTest = x.rowsByIndices(testIndices)
|
||||||
|
val yTest = y.rowsByIndices(testIndices)
|
||||||
|
|
||||||
|
// build model
|
||||||
|
val layers = buildList {
|
||||||
|
add(Dense(features, 64))
|
||||||
|
add(ReLU())
|
||||||
|
add(Dense(64, 16))
|
||||||
|
add(ReLU())
|
||||||
|
add(Dense(16, 2))
|
||||||
|
add(Sigmoid())
|
||||||
|
}
|
||||||
|
val model = NeuralNetwork(layers)
|
||||||
|
|
||||||
|
// fit it with train data
|
||||||
|
model.fit(xTrain, yTrain, batchSize = 20, epochs = 10)
|
||||||
|
|
||||||
|
// make prediction
|
||||||
|
val prediction = model.predict(xTest)
|
||||||
|
|
||||||
|
// process raw prediction via argMax
|
||||||
|
val predictionLabels = prediction.argMax(1, true)
|
||||||
|
|
||||||
|
// find out accuracy
|
||||||
|
val acc = accuracy(yTest, predictionLabels)
|
||||||
|
println("Test accuracy:$acc")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import space.kscience.kmath.tensors.core.DoubleTensor
|
||||||
|
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
||||||
|
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
// OLS estimator using SVD
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
//seed for random
|
||||||
|
val randSeed = 100500L
|
||||||
|
|
||||||
|
// work in context with linear operations
|
||||||
|
DoubleTensorAlgebra {
|
||||||
|
// take coefficient vector from normal distribution
|
||||||
|
val alpha = randomNormal(
|
||||||
|
intArrayOf(5),
|
||||||
|
randSeed
|
||||||
|
) + fromArray(
|
||||||
|
intArrayOf(5),
|
||||||
|
doubleArrayOf(1.0, 2.5, 3.4, 5.0, 10.1)
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Real alpha:\n$alpha")
|
||||||
|
|
||||||
|
// also take sample of size 20 from normal distribution for x
|
||||||
|
val x = randomNormal(
|
||||||
|
intArrayOf(20, 5),
|
||||||
|
randSeed
|
||||||
|
)
|
||||||
|
|
||||||
|
// calculate y and add gaussian noise (N(0, 0.05))
|
||||||
|
val y = x dot alpha
|
||||||
|
y += y.randomNormalLike(randSeed) * 0.05
|
||||||
|
|
||||||
|
// now restore the coefficient vector with OSL estimator with SVD
|
||||||
|
val (u, singValues, v) = x.svd()
|
||||||
|
|
||||||
|
// we have to make sure the singular values of the matrix are not close to zero
|
||||||
|
println("Singular values:\n$singValues")
|
||||||
|
|
||||||
|
|
||||||
|
// inverse Sigma matrix can be restored from singular values with diagonalEmbedding function
|
||||||
|
val sigma = diagonalEmbedding(singValues.map{ if (abs(it) < 1e-3) 0.0 else 1.0/it })
|
||||||
|
|
||||||
|
val alphaOLS = v dot sigma dot u.transpose() dot y
|
||||||
|
println("Estimated alpha:\n" +
|
||||||
|
"$alphaOLS")
|
||||||
|
|
||||||
|
// figure out MSE of approximation
|
||||||
|
fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double {
|
||||||
|
require(yTrue.shape.size == 1)
|
||||||
|
require(yTrue.shape contentEquals yPred.shape)
|
||||||
|
|
||||||
|
val diff = yTrue - yPred
|
||||||
|
return diff.dot(diff).sqrt().value()
|
||||||
|
}
|
||||||
|
|
||||||
|
println("MSE: ${mse(alpha, alphaOLS)}")
|
||||||
|
}
|
||||||
|
}
|
78
examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt
Normal file
78
examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
||||||
|
|
||||||
|
|
||||||
|
// simple PCA
|
||||||
|
|
||||||
|
fun main(){
|
||||||
|
val seed = 100500L
|
||||||
|
|
||||||
|
// work in context with broadcast methods
|
||||||
|
BroadcastDoubleTensorAlgebra {
|
||||||
|
|
||||||
|
// assume x is range from 0 until 10
|
||||||
|
val x = fromArray(
|
||||||
|
intArrayOf(10),
|
||||||
|
(0 until 10).toList().map { it.toDouble() }.toDoubleArray()
|
||||||
|
)
|
||||||
|
|
||||||
|
// take y dependent on x with noise
|
||||||
|
val y = 2.0 * x + (3.0 + x.randomNormalLike(seed) * 1.5)
|
||||||
|
|
||||||
|
println("x:\n$x")
|
||||||
|
println("y:\n$y")
|
||||||
|
|
||||||
|
// stack them into single dataset
|
||||||
|
val dataset = stack(listOf(x, y)).transpose()
|
||||||
|
|
||||||
|
// normalize both x and y
|
||||||
|
val xMean = x.mean()
|
||||||
|
val yMean = y.mean()
|
||||||
|
|
||||||
|
val xStd = x.std()
|
||||||
|
val yStd = y.std()
|
||||||
|
|
||||||
|
val xScaled = (x - xMean) / xStd
|
||||||
|
val yScaled = (y - yMean) / yStd
|
||||||
|
|
||||||
|
// save means ans standard deviations for further recovery
|
||||||
|
val mean = fromArray(
|
||||||
|
intArrayOf(2),
|
||||||
|
doubleArrayOf(xMean, yMean)
|
||||||
|
)
|
||||||
|
println("Means:\n$mean")
|
||||||
|
|
||||||
|
val std = fromArray(
|
||||||
|
intArrayOf(2),
|
||||||
|
doubleArrayOf(xStd, yStd)
|
||||||
|
)
|
||||||
|
println("Standard deviations:\n$std")
|
||||||
|
|
||||||
|
// calculate the covariance matrix of scaled x and y
|
||||||
|
val covMatrix = cov(listOf(xScaled, yScaled))
|
||||||
|
println("Covariance matrix:\n$covMatrix")
|
||||||
|
|
||||||
|
// and find out eigenvector of it
|
||||||
|
val (_, evecs) = covMatrix.symEig()
|
||||||
|
val v = evecs[0]
|
||||||
|
println("Eigenvector:\n$v")
|
||||||
|
|
||||||
|
// reduce dimension of dataset
|
||||||
|
val datasetReduced = v dot stack(listOf(xScaled, yScaled))
|
||||||
|
println("Reduced data:\n$datasetReduced")
|
||||||
|
|
||||||
|
// we can restore original data from reduced data.
|
||||||
|
// for example, find 7th element of dataset
|
||||||
|
val n = 7
|
||||||
|
val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean
|
||||||
|
println("Original value:\n${dataset[n]}")
|
||||||
|
println("Restored value:\n$restored")
|
||||||
|
}
|
||||||
|
}
|
15
gradlew
vendored
15
gradlew
vendored
@ -1,8 +1,19 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright 2018-2021 KMath contributors.
|
# Copyright 2015 the original author or authors.
|
||||||
# Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
@ -1,41 +1,37 @@
|
|||||||
# Module kmath-ast
|
# Module kmath-ast
|
||||||
|
|
||||||
Abstract syntax tree expression representation and related optimizations.
|
Performance and visualization extensions to MST API.
|
||||||
|
|
||||||
- [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-6`.
|
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-8`.
|
||||||
|
|
||||||
**Gradle:**
|
**Gradle:**
|
||||||
```gradle
|
```gradle
|
||||||
repositories {
|
repositories {
|
||||||
maven { url 'https://repo.kotlin.link' }
|
maven { url 'https://repo.kotlin.link' }
|
||||||
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
mavenCentral()
|
||||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'space.kscience:kmath-ast:0.3.0-dev-6'
|
implementation 'space.kscience:kmath-ast:0.3.0-dev-8'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://repo.kotlin.link")
|
maven("https://repo.kotlin.link")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
mavenCentral()
|
||||||
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-ast:0.3.0-dev-6")
|
implementation("space.kscience:kmath-ast:0.3.0-dev-8")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -43,21 +39,26 @@ dependencies {
|
|||||||
|
|
||||||
### On JVM
|
### On JVM
|
||||||
|
|
||||||
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds
|
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a
|
||||||
a special implementation of `Expression<T>` with implemented `invoke` function.
|
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()
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
import space.kscience.kmath.asm.*
|
||||||
|
|
||||||
|
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||||
```
|
```
|
||||||
|
|
||||||
… leads to generation of bytecode, which can be decompiled to the following Java class:
|
... leads to generation of bytecode, which can be decompiled to the following Java class:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package space.kscience.kmath.asm.generated;
|
package space.kscience.kmath.asm.generated;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import kotlin.jvm.functions.Function2;
|
import kotlin.jvm.functions.Function2;
|
||||||
import space.kscience.kmath.asm.internal.MapIntrinsics;
|
import space.kscience.kmath.asm.internal.MapIntrinsics;
|
||||||
import space.kscience.kmath.expressions.Expression;
|
import space.kscience.kmath.expressions.Expression;
|
||||||
@ -67,7 +68,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
|||||||
private final Object[] constants;
|
private final Object[] constants;
|
||||||
|
|
||||||
public final Double invoke(Map<Symbol, ? extends Double> arguments) {
|
public final Double invoke(Map<Symbol, ? extends Double> arguments) {
|
||||||
return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2);
|
return (Double) ((Function2) this.constants[0]).invoke((Double) MapIntrinsics.getOrFail(arguments, "x"), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsmCompiledExpression_45045_0(Object[] constants) {
|
public AsmCompiledExpression_45045_0(Object[] constants) {
|
||||||
@ -77,19 +78,10 @@ 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 class
|
||||||
class loading overhead.
|
loading overhead.
|
||||||
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
|
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
|
||||||
|
|
||||||
### On JS
|
### On JS
|
||||||
@ -97,33 +89,62 @@ 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()
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
import space.kscience.kmath.estree.*
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var executable = function (constants, arguments) {
|
var executable = function (constants, arguments) {
|
||||||
return constants[1](constants[0](arguments, "x"), 2);
|
return constants[1](constants[0](arguments, "x"), 2);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
|
||||||
|
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
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:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
import space.kscience.kmath.ast.*
|
import space.kscience.kmath.ast.*
|
||||||
import space.kscience.kmath.ast.rendering.*
|
import space.kscience.kmath.ast.rendering.*
|
||||||
|
import space.kscience.kmath.misc.*
|
||||||
|
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public fun main() {
|
public fun main() {
|
||||||
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath()
|
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(12)+x^(2/3)".parseMath()
|
||||||
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
|
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
|
||||||
val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax)
|
val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax)
|
||||||
println("LaTeX:")
|
println("LaTeX:")
|
||||||
@ -135,15 +156,80 @@ 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)
|
![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3})
|
||||||
|
|
||||||
Result MathML (embedding MathML is not allowed by GitHub Markdown):
|
Result MathML (can be used with MathJax or other renderers):
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<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>
|
<math xmlns="https://www.w3.org/1998/Math/MathML">
|
||||||
|
<mrow>
|
||||||
|
<mo>exp</mo>
|
||||||
|
<mspace width="0.167em"></mspace>
|
||||||
|
<mfenced open="(" close=")" separators="">
|
||||||
|
<msqrt>
|
||||||
|
<mi>x</mi>
|
||||||
|
</msqrt>
|
||||||
|
</mfenced>
|
||||||
|
<mo>-</mo>
|
||||||
|
<mfrac>
|
||||||
|
<mrow>
|
||||||
|
<mfrac>
|
||||||
|
<mrow>
|
||||||
|
<mo>arcsin</mo>
|
||||||
|
<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>
|
||||||
|
<mn>12</mn>
|
||||||
|
</mrow>
|
||||||
|
</mfrac>
|
||||||
|
<mo>+</mo>
|
||||||
|
<msup>
|
||||||
|
<mrow>
|
||||||
|
<mi>x</mi>
|
||||||
|
</mrow>
|
||||||
|
<mrow>
|
||||||
|
<mn>2</mn>
|
||||||
|
<mo>/</mo>
|
||||||
|
<mn>3</mn>
|
||||||
|
</mrow>
|
||||||
|
</msup>
|
||||||
|
</mrow>
|
||||||
|
</math>
|
||||||
```
|
```
|
||||||
|
|
||||||
It is also possible to create custom algorithms of render, and even add support of other markup languages
|
</details>
|
||||||
|
|
||||||
|
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,10 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import ru.mipt.npm.gradle.Maturity
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("multiplatform")
|
kotlin("multiplatform")
|
||||||
id("ru.mipt.npm.gradle.common")
|
id("ru.mipt.npm.gradle.common")
|
||||||
@ -25,8 +18,13 @@ kotlin.js {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kotlin.sourceSets {
|
kotlin.sourceSets {
|
||||||
|
filter { it.name.contains("test", true) }
|
||||||
|
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
|
||||||
|
.forEach { it.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") }
|
||||||
|
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
api("com.github.h0tk3y.betterParse:better-parse:0.4.2")
|
||||||
api(project(":kmath-core"))
|
api(project(":kmath-core"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,13 +37,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")
|
||||||
}
|
}
|
||||||
@ -58,31 +58,13 @@ tasks.dokkaHtml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
maturity = Maturity.PROTOTYPE
|
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||||
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(
|
||||||
@ -96,4 +78,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"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Module kmath-ast
|
# Module kmath-ast
|
||||||
|
|
||||||
Abstract syntax tree expression representation and related optimizations.
|
Performance and visualization extensions to MST API.
|
||||||
|
|
||||||
${features}
|
${features}
|
||||||
|
|
||||||
@ -10,21 +10,26 @@ ${artifact}
|
|||||||
|
|
||||||
### On JVM
|
### On JVM
|
||||||
|
|
||||||
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds
|
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a
|
||||||
a special implementation of `Expression<T>` with implemented `invoke` function.
|
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()
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
import space.kscience.kmath.asm.*
|
||||||
|
|
||||||
|
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||||
```
|
```
|
||||||
|
|
||||||
… leads to generation of bytecode, which can be decompiled to the following Java class:
|
... leads to generation of bytecode, which can be decompiled to the following Java class:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package space.kscience.kmath.asm.generated;
|
package space.kscience.kmath.asm.generated;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import kotlin.jvm.functions.Function2;
|
import kotlin.jvm.functions.Function2;
|
||||||
import space.kscience.kmath.asm.internal.MapIntrinsics;
|
import space.kscience.kmath.asm.internal.MapIntrinsics;
|
||||||
import space.kscience.kmath.expressions.Expression;
|
import space.kscience.kmath.expressions.Expression;
|
||||||
@ -34,7 +39,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
|||||||
private final Object[] constants;
|
private final Object[] constants;
|
||||||
|
|
||||||
public final Double invoke(Map<Symbol, ? extends Double> arguments) {
|
public final Double invoke(Map<Symbol, ? extends Double> arguments) {
|
||||||
return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2);
|
return (Double) ((Function2) this.constants[0]).invoke((Double) MapIntrinsics.getOrFail(arguments, "x"), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsmCompiledExpression_45045_0(Object[] constants) {
|
public AsmCompiledExpression_45045_0(Object[] constants) {
|
||||||
@ -44,19 +49,10 @@ 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 class
|
||||||
class loading overhead.
|
loading overhead.
|
||||||
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
|
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
|
||||||
|
|
||||||
### On JS
|
### On JS
|
||||||
@ -64,33 +60,62 @@ 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()
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
import space.kscience.kmath.estree.*
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var executable = function (constants, arguments) {
|
var executable = function (constants, arguments) {
|
||||||
return constants[1](constants[0](arguments, "x"), 2);
|
return constants[1](constants[0](arguments, "x"), 2);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
|
||||||
|
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
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:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
import space.kscience.kmath.ast.*
|
import space.kscience.kmath.ast.*
|
||||||
import space.kscience.kmath.ast.rendering.*
|
import space.kscience.kmath.ast.rendering.*
|
||||||
|
import space.kscience.kmath.misc.*
|
||||||
|
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public fun main() {
|
public fun main() {
|
||||||
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath()
|
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(12)+x^(2/3)".parseMath()
|
||||||
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
|
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
|
||||||
val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax)
|
val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax)
|
||||||
println("LaTeX:")
|
println("LaTeX:")
|
||||||
@ -102,15 +127,80 @@ 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)
|
![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3})
|
||||||
|
|
||||||
Result MathML (embedding MathML is not allowed by GitHub Markdown):
|
Result MathML (can be used with MathJax or other renderers):
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<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>
|
<math xmlns="https://www.w3.org/1998/Math/MathML">
|
||||||
|
<mrow>
|
||||||
|
<mo>exp</mo>
|
||||||
|
<mspace width="0.167em"></mspace>
|
||||||
|
<mfenced open="(" close=")" separators="">
|
||||||
|
<msqrt>
|
||||||
|
<mi>x</mi>
|
||||||
|
</msqrt>
|
||||||
|
</mfenced>
|
||||||
|
<mo>-</mo>
|
||||||
|
<mfrac>
|
||||||
|
<mrow>
|
||||||
|
<mfrac>
|
||||||
|
<mrow>
|
||||||
|
<mo>arcsin</mo>
|
||||||
|
<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>
|
||||||
|
<mn>12</mn>
|
||||||
|
</mrow>
|
||||||
|
</mfrac>
|
||||||
|
<mo>+</mo>
|
||||||
|
<msup>
|
||||||
|
<mrow>
|
||||||
|
<mi>x</mi>
|
||||||
|
</mrow>
|
||||||
|
<mrow>
|
||||||
|
<mn>2</mn>
|
||||||
|
<mo>/</mo>
|
||||||
|
<mn>3</mn>
|
||||||
|
</mrow>
|
||||||
|
</msup>
|
||||||
|
</mrow>
|
||||||
|
</math>
|
||||||
```
|
```
|
||||||
|
|
||||||
It is also possible to create custom algorithms of render, and even add support of other markup languages
|
</details>
|
||||||
|
|
||||||
|
It is also possible to create custom algorithms of render, and even add support of other markup languages
|
||||||
(see API reference).
|
(see API reference).
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO move to common when https://github.com/h0tk3y/better-parse/pull/37 is merged
|
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
import com.github.h0tk3y.betterParse.combinators.*
|
import com.github.h0tk3y.betterParse.combinators.*
|
||||||
@ -31,7 +29,6 @@ import space.kscience.kmath.operations.RingOperations
|
|||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public object ArithmeticsEvaluator : Grammar<MST>() {
|
public object ArithmeticsEvaluator : Grammar<MST>() {
|
||||||
// TODO replace with "...".toRegex() when better-parse 0.4.1 is released
|
|
||||||
private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?".toRegex())
|
private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?".toRegex())
|
||||||
private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*".toRegex())
|
private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*".toRegex())
|
||||||
private val lpar: Token by literalToken("(")
|
private val lpar: Token by literalToken("(")
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [SyntaxRenderer] implementation for LaTeX.
|
* [SyntaxRenderer] implementation for LaTeX.
|
||||||
*
|
*
|
||||||
@ -23,6 +25,7 @@ package space.kscience.kmath.ast.rendering
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public object LatexSyntaxRenderer : SyntaxRenderer {
|
public object LatexSyntaxRenderer : SyntaxRenderer {
|
||||||
public override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
|
public override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
|
||||||
fun render(syntax: MathSyntax) = render(syntax, output)
|
fun render(syntax: MathSyntax) = render(syntax, output)
|
||||||
@ -71,6 +74,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("^{")
|
||||||
@ -106,7 +118,11 @@ public object LatexSyntaxRenderer : SyntaxRenderer {
|
|||||||
render(node.right)
|
render(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
is FractionSyntax -> {
|
is FractionSyntax -> if (node.infix) {
|
||||||
|
render(node.left)
|
||||||
|
append('/')
|
||||||
|
render(node.right)
|
||||||
|
} else {
|
||||||
append("\\frac{")
|
append("\\frac{")
|
||||||
render(node.left)
|
render(node.left)
|
||||||
append("}{")
|
append("}{")
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [SyntaxRenderer] implementation for MathML.
|
* [SyntaxRenderer] implementation for MathML.
|
||||||
*
|
*
|
||||||
@ -12,14 +14,18 @@ package space.kscience.kmath.ast.rendering
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public object MathMLSyntaxRenderer : SyntaxRenderer {
|
public object MathMLSyntaxRenderer : SyntaxRenderer {
|
||||||
public override fun render(node: MathSyntax, output: Appendable) {
|
public override fun render(node: MathSyntax, output: Appendable) {
|
||||||
output.append("<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>")
|
output.append("<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>")
|
||||||
render0(node, output)
|
renderPart(node, output)
|
||||||
output.append("</mrow></math>")
|
output.append("</mrow></math>")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun render0(node: MathSyntax, output: Appendable): Unit = output.run {
|
/**
|
||||||
|
* Renders a part of syntax returning a correct MathML tag not the whole MathML instance.
|
||||||
|
*/
|
||||||
|
public fun renderPart(node: MathSyntax, output: Appendable): Unit = output.run {
|
||||||
fun tag(tagName: String, vararg attr: Pair<String, String>, block: () -> Unit = {}) {
|
fun tag(tagName: String, vararg attr: Pair<String, String>, block: () -> Unit = {}) {
|
||||||
append('<')
|
append('<')
|
||||||
append(tagName)
|
append(tagName)
|
||||||
@ -44,7 +50,7 @@ public object MathMLSyntaxRenderer : SyntaxRenderer {
|
|||||||
append('>')
|
append('>')
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(syntax: MathSyntax) = render0(syntax, output)
|
fun render(syntax: MathSyntax) = renderPart(syntax, output)
|
||||||
|
|
||||||
when (node) {
|
when (node) {
|
||||||
is NumberSyntax -> tag("mn") { append(node.string) }
|
is NumberSyntax -> tag("mn") { append(node.string) }
|
||||||
@ -82,6 +88,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) }
|
||||||
@ -114,14 +133,13 @@ public object MathMLSyntaxRenderer : SyntaxRenderer {
|
|||||||
render(node.right)
|
render(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
is FractionSyntax -> tag("mfrac") {
|
is FractionSyntax -> if (node.infix) {
|
||||||
tag("mrow") {
|
render(node.left)
|
||||||
render(node.left)
|
tag("mo") { append('/') }
|
||||||
}
|
render(node.right)
|
||||||
|
} else tag("mfrac") {
|
||||||
tag("mrow") {
|
tag("mrow") { render(node.left) }
|
||||||
render(node.right)
|
tag("mrow") { render(node.right) }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is RadicalWithIndexSyntax -> tag("mroot") {
|
is RadicalWithIndexSyntax -> tag("mroot") {
|
||||||
|
@ -6,12 +6,14 @@
|
|||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.MST
|
import space.kscience.kmath.expressions.MST
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders [MST] to [MathSyntax].
|
* Renders [MST] to [MathSyntax].
|
||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public fun interface MathRenderer {
|
public fun interface MathRenderer {
|
||||||
/**
|
/**
|
||||||
* Renders [MST] to [MathSyntax].
|
* Renders [MST] to [MathSyntax].
|
||||||
@ -25,6 +27,7 @@ public fun interface MathRenderer {
|
|||||||
* @property features The applied features.
|
* @property features The applied features.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public open class FeaturedMathRenderer(public val features: List<RenderFeature>) : MathRenderer {
|
public open class FeaturedMathRenderer(public val features: List<RenderFeature>) : MathRenderer {
|
||||||
public override fun render(mst: MST): MathSyntax {
|
public override fun render(mst: MST): MathSyntax {
|
||||||
for (feature in features) feature.render(this, mst)?.let { return it }
|
for (feature in features) feature.render(this, mst)?.let { return it }
|
||||||
@ -48,6 +51,7 @@ public open class FeaturedMathRenderer(public val features: List<RenderFeature>)
|
|||||||
* @property stages The applied stages.
|
* @property stages The applied stages.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public open class FeaturedMathRendererWithPostProcess(
|
public open class FeaturedMathRendererWithPostProcess(
|
||||||
features: List<RenderFeature>,
|
features: List<RenderFeature>,
|
||||||
public val stages: List<PostProcessStage>,
|
public val stages: List<PostProcessStage>,
|
||||||
@ -83,8 +87,9 @@ public open class FeaturedMathRendererWithPostProcess(
|
|||||||
Fraction.Default,
|
Fraction.Default,
|
||||||
Power.Default,
|
Power.Default,
|
||||||
SquareRoot.Default,
|
SquareRoot.Default,
|
||||||
Exponential.Default,
|
Exponent.Default,
|
||||||
InverseTrigonometricOperations.Default,
|
InverseTrigonometricOperations.Default,
|
||||||
|
InverseHyperbolicOperations.Default,
|
||||||
|
|
||||||
// Fallback option for unknown operations - printing them as operator
|
// Fallback option for unknown operations - printing them as operator
|
||||||
BinaryOperator.Default,
|
BinaryOperator.Default,
|
||||||
@ -100,6 +105,8 @@ public open class FeaturedMathRendererWithPostProcess(
|
|||||||
PrintSymbolic,
|
PrintSymbolic,
|
||||||
),
|
),
|
||||||
listOf(
|
listOf(
|
||||||
|
BetterExponent,
|
||||||
|
BetterFraction,
|
||||||
SimplifyParentheses.Default,
|
SimplifyParentheses.Default,
|
||||||
BetterMultiplication,
|
BetterMultiplication,
|
||||||
),
|
),
|
||||||
|
@ -5,11 +5,14 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mathematical typography syntax node.
|
* Mathematical typography syntax node.
|
||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public sealed class MathSyntax {
|
public sealed class MathSyntax {
|
||||||
/**
|
/**
|
||||||
* The parent node of this syntax node.
|
* The parent node of this syntax node.
|
||||||
@ -22,6 +25,7 @@ public sealed class MathSyntax {
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public sealed class TerminalSyntax : MathSyntax()
|
public sealed class TerminalSyntax : MathSyntax()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,6 +33,7 @@ public sealed class TerminalSyntax : MathSyntax()
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public sealed class OperationSyntax : MathSyntax() {
|
public sealed class OperationSyntax : MathSyntax() {
|
||||||
/**
|
/**
|
||||||
* The operation token.
|
* The operation token.
|
||||||
@ -41,6 +46,7 @@ public sealed class OperationSyntax : MathSyntax() {
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public sealed class UnarySyntax : OperationSyntax() {
|
public sealed class UnarySyntax : OperationSyntax() {
|
||||||
/**
|
/**
|
||||||
* The operand of this node.
|
* The operand of this node.
|
||||||
@ -53,6 +59,7 @@ public sealed class UnarySyntax : OperationSyntax() {
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public sealed class BinarySyntax : OperationSyntax() {
|
public sealed class BinarySyntax : OperationSyntax() {
|
||||||
/**
|
/**
|
||||||
* The left-hand side operand.
|
* The left-hand side operand.
|
||||||
@ -71,6 +78,7 @@ public sealed class BinarySyntax : OperationSyntax() {
|
|||||||
* @property string The digits of number.
|
* @property string The digits of number.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class NumberSyntax(public var string: String) : TerminalSyntax()
|
public data class NumberSyntax(public var string: String) : TerminalSyntax()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,6 +87,7 @@ public data class NumberSyntax(public var string: String) : TerminalSyntax()
|
|||||||
* @property string The symbol.
|
* @property string The symbol.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class SymbolSyntax(public var string: String) : TerminalSyntax()
|
public data class SymbolSyntax(public var string: String) : TerminalSyntax()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,14 +98,16 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax()
|
|||||||
* @see UnaryOperatorSyntax
|
* @see UnaryOperatorSyntax
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class OperatorNameSyntax(public var name: String) : TerminalSyntax()
|
public data class OperatorNameSyntax(public var name: String) : TerminalSyntax()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a usage of special symbols.
|
* Represents a usage of special symbols (e.g., *∞*).
|
||||||
*
|
*
|
||||||
* @property kind The kind of symbol.
|
* @property kind The kind of symbol.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() {
|
public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() {
|
||||||
/**
|
/**
|
||||||
* The kind of symbol.
|
* The kind of symbol.
|
||||||
@ -121,6 +132,7 @@ public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax()
|
|||||||
* @property parentheses Whether the operand should be wrapped with parentheses.
|
* @property parentheses Whether the operand should be wrapped with parentheses.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class OperandSyntax(
|
public data class OperandSyntax(
|
||||||
public val operand: MathSyntax,
|
public val operand: MathSyntax,
|
||||||
public var parentheses: Boolean,
|
public var parentheses: Boolean,
|
||||||
@ -131,11 +143,12 @@ public data class OperandSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents unary, prefix operator syntax (like f x).
|
* Represents unary, prefix operator syntax (like *f(x)*).
|
||||||
*
|
*
|
||||||
* @property prefix The prefix.
|
* @property prefix The prefix.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class UnaryOperatorSyntax(
|
public data class UnaryOperatorSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public var prefix: MathSyntax,
|
public var prefix: MathSyntax,
|
||||||
@ -147,10 +160,11 @@ public data class UnaryOperatorSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents prefix, unary plus operator.
|
* Represents prefix, unary plus operator (*+x*).
|
||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class UnaryPlusSyntax(
|
public data class UnaryPlusSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public override val operand: OperandSyntax,
|
public override val operand: OperandSyntax,
|
||||||
@ -161,10 +175,11 @@ public data class UnaryPlusSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents prefix, unary minus operator.
|
* Represents prefix, unary minus operator (*-x*).
|
||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class UnaryMinusSyntax(
|
public data class UnaryMinusSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public override val operand: OperandSyntax,
|
public override val operand: OperandSyntax,
|
||||||
@ -175,11 +190,12 @@ public data class UnaryMinusSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents radical with a node inside it.
|
* Represents radical with a node inside it (*√x*).
|
||||||
*
|
*
|
||||||
* @property operand The radicand.
|
* @property operand The radicand.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class RadicalSyntax(
|
public data class RadicalSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public override val operand: MathSyntax,
|
public override val operand: MathSyntax,
|
||||||
@ -190,12 +206,32 @@ public data class RadicalSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a syntax node with superscript (usually, for exponentiation).
|
* 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
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
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 (*x<sup>2</sup>*).
|
||||||
*
|
*
|
||||||
* @property left The node.
|
* @property left The node.
|
||||||
* @property right The superscript.
|
* @property right The superscript.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class SuperscriptSyntax(
|
public data class SuperscriptSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public override val left: MathSyntax,
|
public override val left: MathSyntax,
|
||||||
@ -208,12 +244,13 @@ public data class SuperscriptSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a syntax node with subscript.
|
* Represents a syntax node with subscript (*x<sub>i</sup>*).
|
||||||
*
|
*
|
||||||
* @property left The node.
|
* @property left The node.
|
||||||
* @property right The subscript.
|
* @property right The subscript.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class SubscriptSyntax(
|
public data class SubscriptSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public override val left: MathSyntax,
|
public override val left: MathSyntax,
|
||||||
@ -226,11 +263,12 @@ public data class SubscriptSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents binary, prefix operator syntax (like f(a, b)).
|
* Represents binary, prefix operator syntax (like *f(a, b)*).
|
||||||
*
|
*
|
||||||
* @property prefix The prefix.
|
* @property prefix The prefix.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class BinaryOperatorSyntax(
|
public data class BinaryOperatorSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public var prefix: MathSyntax,
|
public var prefix: MathSyntax,
|
||||||
@ -244,12 +282,13 @@ public data class BinaryOperatorSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents binary, infix addition.
|
* Represents binary, infix addition (*42 + 42*).
|
||||||
*
|
*
|
||||||
* @param left The augend.
|
* @param left The augend.
|
||||||
* @param right The addend.
|
* @param right The addend.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class BinaryPlusSyntax(
|
public data class BinaryPlusSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public override val left: OperandSyntax,
|
public override val left: OperandSyntax,
|
||||||
@ -262,12 +301,13 @@ public data class BinaryPlusSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents binary, infix subtraction.
|
* Represents binary, infix subtraction (*42 - 42*).
|
||||||
*
|
*
|
||||||
* @param left The minuend.
|
* @param left The minuend.
|
||||||
* @param right The subtrahend.
|
* @param right The subtrahend.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class BinaryMinusSyntax(
|
public data class BinaryMinusSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public override val left: OperandSyntax,
|
public override val left: OperandSyntax,
|
||||||
@ -284,12 +324,15 @@ public data class BinaryMinusSyntax(
|
|||||||
*
|
*
|
||||||
* @property left The numerator.
|
* @property left The numerator.
|
||||||
* @property right The denominator.
|
* @property right The denominator.
|
||||||
|
* @property infix Whether infix (*1 / 2*) or normal (*½*) fraction should be made.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class FractionSyntax(
|
public data class FractionSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public override val left: MathSyntax,
|
public override val left: OperandSyntax,
|
||||||
public override val right: MathSyntax,
|
public override val right: OperandSyntax,
|
||||||
|
public var infix: Boolean,
|
||||||
) : BinarySyntax() {
|
) : BinarySyntax() {
|
||||||
init {
|
init {
|
||||||
left.parent = this
|
left.parent = this
|
||||||
@ -298,12 +341,13 @@ public data class FractionSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents radical syntax with index.
|
* Represents radical syntax with index (*<sup>3</sup>√x*).
|
||||||
*
|
*
|
||||||
* @property left The index.
|
* @property left The index.
|
||||||
* @property right The radicand.
|
* @property right The radicand.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class RadicalWithIndexSyntax(
|
public data class RadicalWithIndexSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public override val left: MathSyntax,
|
public override val left: MathSyntax,
|
||||||
@ -316,13 +360,14 @@ public data class RadicalWithIndexSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents binary, infix multiplication in the form of coefficient (2 x) or with operator (x×2).
|
* Represents binary, infix multiplication in the form of coefficient (*2 x*) or with operator (*x × 2*).
|
||||||
*
|
*
|
||||||
* @property left The multiplicand.
|
* @property left The multiplicand.
|
||||||
* @property right The multiplier.
|
* @property right The multiplier.
|
||||||
* @property times whether the times (×) symbol should be used.
|
* @property times Whether the times (×) symbol should be used.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public data class MultiplicationSyntax(
|
public data class MultiplicationSyntax(
|
||||||
public override val operation: String,
|
public override val operation: String,
|
||||||
public override val left: OperandSyntax,
|
public override val left: OperandSyntax,
|
||||||
|
@ -5,12 +5,15 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should
|
* Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should
|
||||||
* involve traversal of MathSyntax with handling each its subtype.
|
* involve traversal of MathSyntax with handling each its subtype.
|
||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public fun interface SyntaxRenderer {
|
public fun interface SyntaxRenderer {
|
||||||
/**
|
/**
|
||||||
* Renders the [MathSyntax] to [output].
|
* Renders the [MathSyntax] to [output].
|
||||||
@ -23,6 +26,7 @@ public fun interface SyntaxRenderer {
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String {
|
public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String {
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
render(node, sb)
|
render(node, sb)
|
||||||
|
@ -7,6 +7,7 @@ package space.kscience.kmath.ast.rendering
|
|||||||
|
|
||||||
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.expressions.MST
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
@ -15,11 +16,12 @@ import kotlin.reflect.KClass
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public object PrintSymbolic : RenderFeature {
|
public object PrintSymbolic : RenderFeature {
|
||||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? =
|
||||||
if (node !is MST.Symbolic) return null
|
if (node !is MST.Symbolic) null
|
||||||
return SymbolSyntax(string = node.value)
|
else
|
||||||
}
|
SymbolSyntax(string = node.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,39 +29,46 @@ public object PrintSymbolic : RenderFeature {
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public object PrintNumeric : RenderFeature {
|
public object PrintNumeric : RenderFeature {
|
||||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
public override fun render(renderer: FeaturedMathRenderer, node: MST): NumberSyntax? = if (node !is MST.Numeric)
|
||||||
if (node !is MST.Numeric) return null
|
null
|
||||||
return NumberSyntax(string = node.value.toString())
|
else
|
||||||
}
|
NumberSyntax(string = node.value.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun printSignedNumberString(s: String): MathSyntax {
|
@UnstableKMathAPI
|
||||||
if (s.startsWith('-'))
|
private fun printSignedNumberString(s: String): MathSyntax = if (s.startsWith('-'))
|
||||||
return UnaryMinusSyntax(
|
UnaryMinusSyntax(
|
||||||
operation = GroupOperations.MINUS_OPERATION,
|
operation = GroupOperations.MINUS_OPERATION,
|
||||||
operand = OperandSyntax(
|
operand = OperandSyntax(
|
||||||
operand = NumberSyntax(string = s.removePrefix("-")),
|
operand = NumberSyntax(string = s.removePrefix("-")),
|
||||||
parentheses = true,
|
parentheses = true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
else
|
||||||
return NumberSyntax(string = s)
|
NumberSyntax(string = s)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special printing for numeric types which are printed in form of
|
* Special printing for numeric types which are printed in form of
|
||||||
* *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*.
|
* *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*.
|
||||||
*
|
*
|
||||||
* @property types The suitable types.
|
* @property types The suitable types.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
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")
|
|
||||||
|
|
||||||
if ('E' in toString) {
|
val toString = when (val v = node.value) {
|
||||||
val (beforeE, afterE) = toString.split('E')
|
is Float -> v.multiplatformToString()
|
||||||
|
is Double -> v.multiplatformToString()
|
||||||
|
else -> v.toString()
|
||||||
|
}.removeSuffix(".0")
|
||||||
|
|
||||||
|
if (toString.contains('E', ignoreCase = true)) {
|
||||||
|
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")
|
||||||
|
|
||||||
@ -105,14 +114,15 @@ public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : Rend
|
|||||||
* Special printing for numeric types which are printed in form of *'-'? DIGIT+*.
|
* Special printing for numeric types which are printed in form of *'-'? DIGIT+*.
|
||||||
*
|
*
|
||||||
* @property types The suitable types.
|
* @property types The suitable types.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
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
|
null
|
||||||
|
else
|
||||||
return printSignedNumberString(node.value.toString())
|
printSignedNumberString(node.value.toString())
|
||||||
}
|
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
/**
|
/**
|
||||||
@ -127,12 +137,15 @@ public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : Re
|
|||||||
* Special printing for symbols meaning Pi.
|
* Special printing for symbols meaning Pi.
|
||||||
*
|
*
|
||||||
* @property symbols The allowed symbols.
|
* @property symbols The allowed symbols.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
|
public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
|
||||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? =
|
||||||
if (node !is MST.Symbolic || node.value !in symbols) return null
|
if (node !is MST.Symbolic || node.value !in symbols)
|
||||||
return SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI)
|
null
|
||||||
}
|
else
|
||||||
|
SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
/**
|
/**
|
||||||
@ -147,17 +160,20 @@ public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
|
|||||||
* not [MST.Unary].
|
* not [MST.Unary].
|
||||||
*
|
*
|
||||||
* @param operations the allowed operations. If `null`, any operation is accepted.
|
* @param operations the allowed operations. If `null`, any operation is accepted.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public abstract class Unary(public val operations: Collection<String>?) : RenderFeature {
|
public abstract class Unary(public val operations: Collection<String>?) : RenderFeature {
|
||||||
/**
|
/**
|
||||||
* The actual render function.
|
* The actual render function specialized for [MST.Unary].
|
||||||
*/
|
*/
|
||||||
protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax?
|
protected abstract fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax?
|
||||||
|
|
||||||
public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
|
||||||
if (node !is MST.Unary || operations != null && node.operation !in operations) return null
|
if (node !is MST.Unary || operations != null && node.operation !in operations)
|
||||||
return render0(renderer, node)
|
null
|
||||||
}
|
else
|
||||||
|
renderUnary(renderer, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,169 +181,301 @@ public abstract class Unary(public val operations: Collection<String>?) : Render
|
|||||||
* not [MST.Binary].
|
* not [MST.Binary].
|
||||||
*
|
*
|
||||||
* @property operations the allowed operations. If `null`, any operation is accepted.
|
* @property operations the allowed operations. If `null`, any operation is accepted.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public abstract class Binary(public val operations: Collection<String>?) : RenderFeature {
|
public abstract class Binary(public val operations: Collection<String>?) : RenderFeature {
|
||||||
/**
|
/**
|
||||||
* The actual render function.
|
* The actual render function specialized for [MST.Binary].
|
||||||
*/
|
*/
|
||||||
protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax?
|
protected abstract fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax?
|
||||||
|
|
||||||
public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
||||||
if (node !is MST.Binary || operations != null && node.operation !in operations) return null
|
if (node !is MST.Binary || operations != null && node.operation !in operations) return null
|
||||||
return render0(renderer, node)
|
return renderBinary(renderer, node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles binary nodes by producing [BinaryPlusSyntax].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
|
public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryPlusSyntax(
|
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryPlusSyntax =
|
||||||
operation = node.operation,
|
BinaryPlusSyntax(
|
||||||
left = OperandSyntax(parent.render(node.left), true),
|
operation = node.operation,
|
||||||
right = OperandSyntax(parent.render(node.right), true),
|
left = OperandSyntax(parent.render(node.left), true),
|
||||||
)
|
right = OperandSyntax(parent.render(node.right), true),
|
||||||
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [GroupOperations.PLUS_OPERATION].
|
||||||
|
*/
|
||||||
public val Default: BinaryPlus = BinaryPlus(setOf(GroupOperations.PLUS_OPERATION))
|
public val Default: BinaryPlus = BinaryPlus(setOf(GroupOperations.PLUS_OPERATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles binary nodes by producing [BinaryMinusSyntax].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
|
public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryMinusSyntax(
|
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryMinusSyntax =
|
||||||
operation = node.operation,
|
BinaryMinusSyntax(
|
||||||
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
operation = node.operation,
|
||||||
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
|
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
||||||
)
|
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
|
||||||
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [GroupOperations.MINUS_OPERATION].
|
||||||
|
*/
|
||||||
public val Default: BinaryMinus = BinaryMinus(setOf(GroupOperations.MINUS_OPERATION))
|
public val Default: BinaryMinus = BinaryMinus(setOf(GroupOperations.MINUS_OPERATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles unary nodes by producing [UnaryPlusSyntax].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
|
public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax(
|
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryPlusSyntax = UnaryPlusSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||||
)
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [GroupOperations.PLUS_OPERATION].
|
||||||
|
*/
|
||||||
public val Default: UnaryPlus = UnaryPlus(setOf(GroupOperations.PLUS_OPERATION))
|
public val Default: UnaryPlus = UnaryPlus(setOf(GroupOperations.PLUS_OPERATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles binary nodes by producing [UnaryMinusSyntax].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
|
public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax(
|
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryMinusSyntax = UnaryMinusSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||||
)
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [GroupOperations.MINUS_OPERATION].
|
||||||
|
*/
|
||||||
public val Default: UnaryMinus = UnaryMinus(setOf(GroupOperations.MINUS_OPERATION))
|
public val Default: UnaryMinus = UnaryMinus(setOf(GroupOperations.MINUS_OPERATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles binary nodes by producing [FractionSyntax].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public class Fraction(operations: Collection<String>?) : Binary(operations) {
|
public class Fraction(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax(
|
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
left = parent.render(node.left),
|
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
||||||
right = parent.render(node.right),
|
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
|
||||||
|
infix = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [FieldOperations.DIV_OPERATION].
|
||||||
|
*/
|
||||||
public val Default: Fraction = Fraction(setOf(FieldOperations.DIV_OPERATION))
|
public val Default: Fraction = Fraction(setOf(FieldOperations.DIV_OPERATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles binary nodes by producing [BinaryOperatorSyntax].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public class BinaryOperator(operations: Collection<String>?) : Binary(operations) {
|
public class BinaryOperator(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryOperatorSyntax(
|
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryOperatorSyntax =
|
||||||
operation = node.operation,
|
BinaryOperatorSyntax(
|
||||||
prefix = OperatorNameSyntax(name = node.operation),
|
operation = node.operation,
|
||||||
left = parent.render(node.left),
|
prefix = OperatorNameSyntax(name = node.operation),
|
||||||
right = parent.render(node.right),
|
left = parent.render(node.left),
|
||||||
)
|
right = parent.render(node.right),
|
||||||
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with `null`.
|
||||||
|
*/
|
||||||
public val Default: BinaryOperator = BinaryOperator(null)
|
public val Default: BinaryOperator = BinaryOperator(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles unary nodes by producing [UnaryOperatorSyntax].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public class UnaryOperator(operations: Collection<String>?) : Unary(operations) {
|
public class UnaryOperator(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax(
|
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
|
||||||
operation = node.operation,
|
UnaryOperatorSyntax(
|
||||||
prefix = OperatorNameSyntax(node.operation),
|
operation = node.operation,
|
||||||
operand = OperandSyntax(parent.render(node.value), true),
|
prefix = OperatorNameSyntax(node.operation),
|
||||||
)
|
operand = OperandSyntax(parent.render(node.value), true),
|
||||||
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with `null`.
|
||||||
|
*/
|
||||||
public val Default: UnaryOperator = UnaryOperator(null)
|
public val Default: UnaryOperator = UnaryOperator(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles binary nodes by producing [SuperscriptSyntax].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public class Power(operations: Collection<String>?) : Binary(operations) {
|
public class Power(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = SuperscriptSyntax(
|
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): SuperscriptSyntax =
|
||||||
operation = node.operation,
|
SuperscriptSyntax(
|
||||||
left = OperandSyntax(parent.render(node.left), true),
|
operation = node.operation,
|
||||||
right = OperandSyntax(parent.render(node.right), true),
|
left = OperandSyntax(parent.render(node.left), true),
|
||||||
)
|
right = OperandSyntax(parent.render(node.right), true),
|
||||||
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [PowerOperations.POW_OPERATION].
|
||||||
|
*/
|
||||||
public val Default: Power = Power(setOf(PowerOperations.POW_OPERATION))
|
public val Default: Power = Power(setOf(PowerOperations.POW_OPERATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles binary nodes by producing [RadicalSyntax] with no index.
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
|
public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
|
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): RadicalSyntax =
|
||||||
RadicalSyntax(operation = node.operation, operand = parent.render(node.value))
|
RadicalSyntax(operation = node.operation, operand = parent.render(node.value))
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [PowerOperations.SQRT_OPERATION].
|
||||||
|
*/
|
||||||
public val Default: SquareRoot = SquareRoot(setOf(PowerOperations.SQRT_OPERATION))
|
public val Default: SquareRoot = SquareRoot(setOf(PowerOperations.SQRT_OPERATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Exponential(operations: Collection<String>?) : Unary(operations) {
|
/**
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = SuperscriptSyntax(
|
* Handles unary nodes by producing [ExponentSyntax].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public class Exponent(operations: Collection<String>?) : Unary(operations) {
|
||||||
|
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): ExponentSyntax = ExponentSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
left = SymbolSyntax(string = "e"),
|
|
||||||
right = parent.render(node.value),
|
|
||||||
)
|
|
||||||
|
|
||||||
public companion object {
|
|
||||||
public val Default: Exponential = Exponential(setOf(ExponentialOperations.EXP_OPERATION))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Multiplication(operations: Collection<String>?) : Binary(operations) {
|
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = MultiplicationSyntax(
|
|
||||||
operation = node.operation,
|
|
||||||
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
|
||||||
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
|
|
||||||
times = true,
|
|
||||||
)
|
|
||||||
|
|
||||||
public companion object {
|
|
||||||
public val Default: Multiplication = Multiplication(setOf(
|
|
||||||
RingOperations.TIMES_OPERATION,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class InverseTrigonometricOperations(operations: Collection<String>?) : Unary(operations) {
|
|
||||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax(
|
|
||||||
operation = node.operation,
|
|
||||||
prefix = SuperscriptSyntax(
|
|
||||||
operation = PowerOperations.POW_OPERATION,
|
|
||||||
left = OperatorNameSyntax(name = node.operation.removePrefix("a")),
|
|
||||||
right = UnaryMinusSyntax(
|
|
||||||
operation = GroupOperations.MINUS_OPERATION,
|
|
||||||
operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||||
|
useOperatorForm = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [ExponentialOperations.EXP_OPERATION].
|
||||||
|
*/
|
||||||
|
public val Default: Exponent = Exponent(setOf(ExponentialOperations.EXP_OPERATION))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles binary nodes by producing [MultiplicationSyntax].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public class Multiplication(operations: Collection<String>?) : Binary(operations) {
|
||||||
|
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MultiplicationSyntax =
|
||||||
|
MultiplicationSyntax(
|
||||||
|
operation = node.operation,
|
||||||
|
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
||||||
|
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
|
||||||
|
times = true,
|
||||||
|
)
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [RingOperations.TIMES_OPERATION].
|
||||||
|
*/
|
||||||
|
public val Default: Multiplication = Multiplication(setOf(RingOperations.TIMES_OPERATION))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles binary nodes by producing inverse [UnaryOperatorSyntax] with *arc* prefix instead of *a*.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public class InverseTrigonometricOperations(operations: Collection<String>?) : Unary(operations) {
|
||||||
|
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
|
||||||
|
UnaryOperatorSyntax(
|
||||||
|
operation = node.operation,
|
||||||
|
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "arc")),
|
||||||
|
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||||
|
)
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [TrigonometricOperations.ACOS_OPERATION],
|
||||||
|
* [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION].
|
||||||
|
*/
|
||||||
public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf(
|
public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf(
|
||||||
TrigonometricOperations.ACOS_OPERATION,
|
TrigonometricOperations.ACOS_OPERATION,
|
||||||
TrigonometricOperations.ASIN_OPERATION,
|
TrigonometricOperations.ASIN_OPERATION,
|
||||||
TrigonometricOperations.ATAN_OPERATION,
|
TrigonometricOperations.ATAN_OPERATION,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles binary nodes by producing inverse [UnaryOperatorSyntax] with *ar* prefix instead of *a*.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public class InverseHyperbolicOperations(operations: Collection<String>?) : Unary(operations) {
|
||||||
|
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
|
||||||
|
UnaryOperatorSyntax(
|
||||||
|
operation = node.operation,
|
||||||
|
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "ar")),
|
||||||
|
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||||
|
)
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
/**
|
||||||
|
* The default instance configured with [ExponentialOperations.ACOSH_OPERATION],
|
||||||
|
* [ExponentialOperations.ASINH_OPERATION], and [ExponentialOperations.ATANH_OPERATION].
|
||||||
|
*/
|
||||||
|
public val Default: InverseHyperbolicOperations = InverseHyperbolicOperations(setOf(
|
||||||
ExponentialOperations.ACOSH_OPERATION,
|
ExponentialOperations.ACOSH_OPERATION,
|
||||||
ExponentialOperations.ASINH_OPERATION,
|
ExponentialOperations.ASINH_OPERATION,
|
||||||
ExponentialOperations.ATANH_OPERATION,
|
ExponentialOperations.ATANH_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
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
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
|
||||||
@ -15,70 +16,182 @@ import space.kscience.kmath.operations.RingOperations
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chooses [FractionSyntax.infix] depending on the context.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public object BetterFraction : FeaturedMathRendererWithPostProcess.PostProcessStage {
|
||||||
|
private fun perform0(node: MathSyntax, infix: Boolean = false): Unit = when (node) {
|
||||||
|
is NumberSyntax -> Unit
|
||||||
|
is SymbolSyntax -> Unit
|
||||||
|
is OperatorNameSyntax -> Unit
|
||||||
|
is SpecialSymbolSyntax -> Unit
|
||||||
|
is OperandSyntax -> perform0(node.operand, infix)
|
||||||
|
|
||||||
|
is UnaryOperatorSyntax -> {
|
||||||
|
perform0(node.prefix, infix)
|
||||||
|
perform0(node.operand, infix)
|
||||||
|
}
|
||||||
|
|
||||||
|
is UnaryPlusSyntax -> perform0(node.operand, infix)
|
||||||
|
is UnaryMinusSyntax -> perform0(node.operand, infix)
|
||||||
|
is RadicalSyntax -> perform0(node.operand, infix)
|
||||||
|
is ExponentSyntax -> perform0(node.operand, infix)
|
||||||
|
|
||||||
|
is SuperscriptSyntax -> {
|
||||||
|
perform0(node.left, true)
|
||||||
|
perform0(node.right, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
is SubscriptSyntax -> {
|
||||||
|
perform0(node.left, true)
|
||||||
|
perform0(node.right, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
is BinaryOperatorSyntax -> {
|
||||||
|
perform0(node.prefix, infix)
|
||||||
|
perform0(node.left, infix)
|
||||||
|
perform0(node.right, infix)
|
||||||
|
}
|
||||||
|
|
||||||
|
is BinaryPlusSyntax -> {
|
||||||
|
perform0(node.left, infix)
|
||||||
|
perform0(node.right, infix)
|
||||||
|
}
|
||||||
|
|
||||||
|
is BinaryMinusSyntax -> {
|
||||||
|
perform0(node.left, infix)
|
||||||
|
perform0(node.right, infix)
|
||||||
|
}
|
||||||
|
|
||||||
|
is FractionSyntax -> {
|
||||||
|
node.infix = infix
|
||||||
|
perform0(node.left, infix)
|
||||||
|
perform0(node.right, infix)
|
||||||
|
}
|
||||||
|
|
||||||
|
is RadicalWithIndexSyntax -> {
|
||||||
|
perform0(node.left, true)
|
||||||
|
perform0(node.right, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
is MultiplicationSyntax -> {
|
||||||
|
perform0(node.left, infix)
|
||||||
|
perform0(node.right, infix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun perform(node: MathSyntax): Unit = perform0(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies [ExponentSyntax.useOperatorForm] to [ExponentSyntax] when the operand contains a fraction, a
|
||||||
|
* superscript or a subscript to improve readability.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
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 -> true
|
||||||
|
|
||||||
|
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 -> true
|
||||||
|
is MultiplicationSyntax -> perform0(node.left) || perform0(node.right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun perform(node: MathSyntax) {
|
||||||
|
perform0(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,91 +201,95 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro
|
|||||||
* @property precedenceFunction Returns the precedence number for syntax node. Higher number is lower priority.
|
* @property precedenceFunction Returns the precedence number for syntax node. Higher number is lower priority.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
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)
|
val isOnOrUnderNormalFraction = node.parent is FractionSyntax && !((node.parent as FractionSyntax).infix)
|
||||||
is UnaryMinusSyntax -> {
|
|
||||||
perform(node.operand)
|
|
||||||
}
|
|
||||||
is RadicalSyntax -> perform(node.operand)
|
|
||||||
|
|
||||||
is SuperscriptSyntax -> {
|
node.parentheses = !isRightOfSuperscript
|
||||||
perform(node.left)
|
&& (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax || isInsideExpOperator)
|
||||||
perform(node.right)
|
&& !isOnOrUnderNormalFraction
|
||||||
}
|
|
||||||
|
|
||||||
is SubscriptSyntax -> {
|
perform(node.operand)
|
||||||
perform(node.left)
|
}
|
||||||
perform(node.right)
|
|
||||||
}
|
|
||||||
|
|
||||||
is BinaryOperatorSyntax -> {
|
is UnaryOperatorSyntax -> {
|
||||||
perform(node.prefix)
|
perform(node.prefix)
|
||||||
perform(node.left)
|
perform(node.operand)
|
||||||
perform(node.right)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
is BinaryPlusSyntax -> {
|
is UnaryPlusSyntax -> perform(node.operand)
|
||||||
perform(node.left)
|
is UnaryMinusSyntax -> perform(node.operand)
|
||||||
perform(node.right)
|
is RadicalSyntax -> perform(node.operand)
|
||||||
}
|
is ExponentSyntax -> perform(node.operand)
|
||||||
|
|
||||||
is BinaryMinusSyntax -> {
|
is SuperscriptSyntax -> {
|
||||||
perform(node.left)
|
perform(node.left)
|
||||||
perform(node.right)
|
perform(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
is FractionSyntax -> {
|
is SubscriptSyntax -> {
|
||||||
perform(node.left)
|
perform(node.left)
|
||||||
perform(node.right)
|
perform(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
is MultiplicationSyntax -> {
|
is BinaryOperatorSyntax -> {
|
||||||
perform(node.left)
|
perform(node.prefix)
|
||||||
perform(node.right)
|
perform(node.left)
|
||||||
}
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
is RadicalWithIndexSyntax -> {
|
is BinaryPlusSyntax -> {
|
||||||
perform(node.left)
|
perform(node.left)
|
||||||
perform(node.right)
|
perform(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is BinaryMinusSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is FractionSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is MultiplicationSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
is RadicalWithIndexSyntax -> {
|
||||||
|
perform(node.left)
|
||||||
|
perform(node.right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.MstField
|
||||||
|
import space.kscience.kmath.expressions.MstRing
|
||||||
|
import space.kscience.kmath.expressions.interpret
|
||||||
|
import space.kscience.kmath.misc.Symbol.Companion.x
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.IntRing
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
internal class TestCompilerConsistencyWithInterpreter {
|
||||||
|
@Test
|
||||||
|
fun intRing() = runCompilerTest {
|
||||||
|
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() = runCompilerTest {
|
||||||
|
val mst = MstField {
|
||||||
|
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||||
|
(3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||||
|
+ number(1),
|
||||||
|
number(1) / 2 + number(2.0) * one,
|
||||||
|
) + zero
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
mst.interpret(DoubleField, x to 2.0),
|
||||||
|
mst.compile(DoubleField, x to 2.0),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
|
import space.kscience.kmath.expressions.MstExtendedField
|
||||||
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.misc.Symbol.Companion.x
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
internal class TestCompilerOperations {
|
||||||
|
@Test
|
||||||
|
fun testUnaryPlus() = runCompilerTest {
|
||||||
|
val expr = MstExtendedField { +bindSymbol(x) }.compileToExpression(DoubleField)
|
||||||
|
assertEquals(2.0, expr(x to 2.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUnaryMinus() = runCompilerTest {
|
||||||
|
val expr = MstExtendedField { -bindSymbol(x) }.compileToExpression(DoubleField)
|
||||||
|
assertEquals(-2.0, expr(x to 2.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAdd() = runCompilerTest {
|
||||||
|
val expr = MstExtendedField { bindSymbol(x) + bindSymbol(x) }.compileToExpression(DoubleField)
|
||||||
|
assertEquals(4.0, expr(x to 2.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSine() = runCompilerTest {
|
||||||
|
val expr = MstExtendedField { sin(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||||
|
assertEquals(0.0, expr(x to 0.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCosine() = runCompilerTest {
|
||||||
|
val expr = MstExtendedField { cos(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||||
|
assertEquals(1.0, expr(x to 0.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSubtract() = runCompilerTest {
|
||||||
|
val expr = MstExtendedField { bindSymbol(x) - bindSymbol(x) }.compileToExpression(DoubleField)
|
||||||
|
assertEquals(0.0, expr(x to 2.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDivide() = runCompilerTest {
|
||||||
|
val expr = MstExtendedField { bindSymbol(x) / bindSymbol(x) }.compileToExpression(DoubleField)
|
||||||
|
assertEquals(1.0, expr(x to 2.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPower() = runCompilerTest {
|
||||||
|
val expr = MstExtendedField { bindSymbol(x) pow 2 }.compileToExpression(DoubleField)
|
||||||
|
assertEquals(4.0, expr(x to 2.0))
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.MstRing
|
||||||
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.misc.Symbol.Companion.x
|
||||||
|
import space.kscience.kmath.operations.IntRing
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
|
internal class TestCompilerVariables {
|
||||||
|
@Test
|
||||||
|
fun testVariable() = runCompilerTest {
|
||||||
|
val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
|
||||||
|
assertEquals(1, expr(x to 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUndefinedVariableFails() = runCompilerTest {
|
||||||
|
val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
|
||||||
|
assertFailsWith<NoSuchElementException> { expr() }
|
||||||
|
}
|
||||||
|
}
|
@ -7,31 +7,22 @@ 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.MstField
|
|
||||||
import space.kscience.kmath.expressions.evaluate
|
import space.kscience.kmath.expressions.evaluate
|
||||||
import space.kscience.kmath.expressions.interpret
|
|
||||||
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 TestParser {
|
||||||
@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)
|
||||||
@ -39,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
|
||||||
|
|
@ -7,13 +7,10 @@ package space.kscience.kmath.ast
|
|||||||
|
|
||||||
import space.kscience.kmath.expressions.evaluate
|
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 TestParserPrecedence {
|
||||||
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()))
|
||||||
|
|
||||||
@ -37,4 +34,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
|
||||||
|
}
|
||||||
}
|
}
|
@ -42,6 +42,22 @@ internal class TestFeatures {
|
|||||||
testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}")
|
testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}")
|
||||||
testLatex(Numeric(-1.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
|
||||||
@ -83,13 +99,17 @@ internal class TestFeatures {
|
|||||||
fun multiplication() = testLatex("x*1", "x\\times1")
|
fun multiplication() = testLatex("x*1", "x\\times1")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun inverseTrigonometry() {
|
fun inverseTrigonometric() {
|
||||||
testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)")
|
testLatex("asin(x)", "\\operatorname{arcsin}\\,\\left(x\\right)")
|
||||||
testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)")
|
testLatex("acos(x)", "\\operatorname{arccos}\\,\\left(x\\right)")
|
||||||
testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)")
|
testLatex("atan(x)", "\\operatorname{arctan}\\,\\left(x\\right)")
|
||||||
testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)")
|
}
|
||||||
testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)")
|
|
||||||
testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)")
|
@Test
|
||||||
|
fun inverseHyperbolic() {
|
||||||
|
testLatex("asinh(x)", "\\operatorname{arsinh}\\,\\left(x\\right)")
|
||||||
|
testLatex("acosh(x)", "\\operatorname{arcosh}\\,\\left(x\\right)")
|
||||||
|
testLatex("atanh(x)", "\\operatorname{artanh}\\,\\left(x\\right)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
// @Test
|
@ -30,4 +30,17 @@ 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)")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun fraction() {
|
||||||
|
testLatex("x/y", "\\frac{x}{y}")
|
||||||
|
testLatex("x^(x/y)", "x^{x/y}")
|
||||||
|
}
|
||||||
}
|
}
|
@ -30,17 +30,17 @@ internal object TestUtils {
|
|||||||
)
|
)
|
||||||
|
|
||||||
internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals(
|
internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals(
|
||||||
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
|
expected = "<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
|
||||||
actual = mathML(mst),
|
actual = mathML(mst),
|
||||||
)
|
)
|
||||||
|
|
||||||
internal fun testMathML(expression: String, expectedMathML: String) = assertEquals(
|
internal fun testMathML(expression: String, expectedMathML: String) = assertEquals(
|
||||||
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
|
expected = "<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
|
||||||
actual = mathML(expression.parseMath()),
|
actual = mathML(expression.parseMath()),
|
||||||
)
|
)
|
||||||
|
|
||||||
internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals(
|
internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals(
|
||||||
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
|
expected = "<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
|
||||||
actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression),
|
actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression),
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
|
import space.kscience.kmath.expressions.Expression
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.IntRing
|
||||||
|
|
||||||
|
internal interface CompilerTestContext {
|
||||||
|
fun MST.compileToExpression(algebra: IntRing): Expression<Int>
|
||||||
|
fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int
|
||||||
|
fun MST.compile(algebra: IntRing, vararg arguments: Pair<Symbol, Int>): Int = compile(algebra, mapOf(*arguments))
|
||||||
|
fun MST.compileToExpression(algebra: DoubleField): Expression<Double>
|
||||||
|
fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double
|
||||||
|
|
||||||
|
fun MST.compile(algebra: DoubleField, vararg arguments: Pair<Symbol, Double>): Double =
|
||||||
|
compile(algebra, mapOf(*arguments))
|
||||||
|
}
|
||||||
|
|
||||||
|
internal expect inline fun runCompilerTest(action: CompilerTestContext.() -> Unit)
|
@ -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()
|
||||||
|
}
|
@ -6,11 +6,11 @@
|
|||||||
package space.kscience.kmath.estree
|
package space.kscience.kmath.estree
|
||||||
|
|
||||||
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.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
|
||||||
|
@ -5,9 +5,14 @@
|
|||||||
|
|
||||||
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) {
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
@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?
|
@ -1,4 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 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.
|
* Use of this 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
|
@ -3,7 +3,7 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.estree.internal.emitter
|
package space.kscience.kmath.internal.emitter
|
||||||
|
|
||||||
internal open external class Emitter {
|
internal open external class Emitter {
|
||||||
constructor(obj: Any)
|
constructor(obj: Any)
|
@ -3,7 +3,7 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.estree.internal.estree
|
package space.kscience.kmath.internal.estree
|
||||||
|
|
||||||
internal fun Program(sourceType: String, vararg body: dynamic) = object : Program {
|
internal fun Program(sourceType: String, vararg body: dynamic) = object : Program {
|
||||||
override var type = "Program"
|
override var type = "Program"
|
@ -3,7 +3,7 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.estree.internal.estree
|
package space.kscience.kmath.internal.estree
|
||||||
|
|
||||||
import kotlin.js.RegExp
|
import kotlin.js.RegExp
|
||||||
|
|
@ -3,9 +3,9 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.estree.internal.stream
|
package space.kscience.kmath.internal.stream
|
||||||
|
|
||||||
import space.kscience.kmath.estree.internal.emitter.Emitter
|
import space.kscience.kmath.internal.emitter.Emitter
|
||||||
|
|
||||||
internal open external class Stream : Emitter {
|
internal open external class Stream : Emitter {
|
||||||
open fun pipe(dest: Any, options: Any): Any
|
open fun pipe(dest: Any, options: Any): Any
|
@ -3,7 +3,7 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.estree.internal.tsstdlib
|
package space.kscience.kmath.internal.tsstdlib
|
||||||
|
|
||||||
internal external interface IteratorYieldResult<TYield> {
|
internal external interface IteratorYieldResult<TYield> {
|
||||||
var done: Boolean?
|
var done: Boolean?
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
@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
|
||||||
|
|
||||||
@ -38,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
|
||||||
|
|
||||||
@ -85,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,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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@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: 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,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.IntRing
|
||||||
|
import space.kscience.kmath.wasm.internal.DoubleWasmBuilder
|
||||||
|
import space.kscience.kmath.wasm.internal.IntWasmBuilder
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles an [MST] to WASM in the context of reals.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public fun DoubleField.expression(mst: MST): Expression<Double> =
|
||||||
|
DoubleWasmBuilder(mst).instance
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles an [MST] to WASM in the context of integers.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public fun IntRing.expression(mst: MST): Expression<Int> =
|
||||||
|
IntWasmBuilder(mst).instance
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a compiled expression with given [MST] and given [algebra].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public fun MST.compileToExpression(algebra: IntRing): Expression<Int> = compileWith(algebra)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile given MST to expression and evaluate it against [arguments].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = compileWith(algebra)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile given MST to expression and evaluate it against [arguments].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
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)
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
|
import space.kscience.kmath.expressions.Expression
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.IntRing
|
||||||
|
import space.kscience.kmath.estree.compile as estreeCompile
|
||||||
|
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
|
||||||
|
import space.kscience.kmath.wasm.compile as wasmCompile
|
||||||
|
import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
|
||||||
|
|
||||||
|
private object WasmCompilerTestContext : CompilerTestContext {
|
||||||
|
override fun MST.compileToExpression(algebra: IntRing): Expression<Int> = wasmCompileToExpression(algebra)
|
||||||
|
override fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int = wasmCompile(algebra, arguments)
|
||||||
|
override fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = wasmCompileToExpression(algebra)
|
||||||
|
|
||||||
|
override fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double =
|
||||||
|
wasmCompile(algebra, arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
private object ESTreeCompilerTestContext : CompilerTestContext {
|
||||||
|
override fun MST.compileToExpression(algebra: IntRing): Expression<Int> = estreeCompileToExpression(algebra)
|
||||||
|
override fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int = estreeCompile(algebra, arguments)
|
||||||
|
override fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = estreeCompileToExpression(algebra)
|
||||||
|
|
||||||
|
override fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double =
|
||||||
|
estreeCompile(algebra, arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) {
|
||||||
|
action(WasmCompilerTestContext)
|
||||||
|
action(ESTreeCompilerTestContext)
|
||||||
|
}
|
@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.estree
|
|
||||||
|
|
||||||
import space.kscience.kmath.complex.ComplexField
|
|
||||||
import space.kscience.kmath.complex.toComplex
|
|
||||||
import space.kscience.kmath.expressions.*
|
|
||||||
import space.kscience.kmath.misc.Symbol
|
|
||||||
import space.kscience.kmath.operations.ByteRing
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
internal class TestESTreeConsistencyWithInterpreter {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun mstSpace() {
|
|
||||||
|
|
||||||
val mst = MstGroup {
|
|
||||||
binaryOperationFunction("+")(
|
|
||||||
unaryOperationFunction("+")(
|
|
||||||
number(3.toByte()) - (number(2.toByte()) + (scale(
|
|
||||||
add(number(1), number(1)),
|
|
||||||
2.0
|
|
||||||
) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
|
|
||||||
),
|
|
||||||
|
|
||||||
number(1)
|
|
||||||
) + bindSymbol("x") + zero
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
mst.interpret(MstGroup, Symbol.x to MST.Numeric(2)),
|
|
||||||
mst.compile(MstGroup, Symbol.x to MST.Numeric(2))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun byteRing() {
|
|
||||||
val mst = MstRing {
|
|
||||||
binaryOperationFunction("+")(
|
|
||||||
unaryOperationFunction("+")(
|
|
||||||
(bindSymbol("x") - (2.toByte() + (scale(
|
|
||||||
add(number(1), number(1)),
|
|
||||||
2.0
|
|
||||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
|
||||||
),
|
|
||||||
|
|
||||||
number(1)
|
|
||||||
) * number(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
mst.interpret(ByteRing, Symbol.x to 3.toByte()),
|
|
||||||
mst.compile(ByteRing, Symbol.x to 3.toByte())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun realField() {
|
|
||||||
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, Symbol.x to 2.0),
|
|
||||||
mst.compile(DoubleField, Symbol.x to 2.0)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun complexField() {
|
|
||||||
val mst = MstField {
|
|
||||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
|
||||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
|
||||||
+ number(1),
|
|
||||||
number(1) / 2 + number(2.0) * one
|
|
||||||
) + zero
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
mst.interpret(ComplexField, Symbol.x to 2.0.toComplex()),
|
|
||||||
mst.compile(ComplexField, Symbol.x to 2.0.toComplex())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.estree
|
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.MstExtendedField
|
|
||||||
import space.kscience.kmath.expressions.invoke
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.random.Random
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
internal class TestESTreeOperationsSupport {
|
|
||||||
@Test
|
|
||||||
fun testUnaryOperationInvocation() {
|
|
||||||
val expression = MstExtendedField { -bindSymbol("x") }.compileToExpression(DoubleField)
|
|
||||||
val res = expression("x" to 2.0)
|
|
||||||
assertEquals(-2.0, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testBinaryOperationInvocation() {
|
|
||||||
val expression = MstExtendedField { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField)
|
|
||||||
val res = expression("x" to 2.0)
|
|
||||||
assertEquals(-1.0, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testConstProductInvocation() {
|
|
||||||
val res = MstExtendedField { bindSymbol("x") * 2 }.compileToExpression(DoubleField)("x" to 2.0)
|
|
||||||
assertEquals(4.0, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testMultipleCalls() {
|
|
||||||
val e =
|
|
||||||
MstExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }
|
|
||||||
.compileToExpression(DoubleField)
|
|
||||||
val r = Random(0)
|
|
||||||
var s = 0.0
|
|
||||||
repeat(1000000) { s += e("x" to r.nextDouble()) }
|
|
||||||
println(s)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.estree
|
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.MstExtendedField
|
|
||||||
import space.kscience.kmath.expressions.invoke
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
internal class TestESTreeSpecialization {
|
|
||||||
@Test
|
|
||||||
fun testUnaryPlus() {
|
|
||||||
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
|
||||||
assertEquals(2.0, expr("x" to 2.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testUnaryMinus() {
|
|
||||||
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
|
||||||
assertEquals(-2.0, expr("x" to 2.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testAdd() {
|
|
||||||
val expr = MstExtendedField {
|
|
||||||
binaryOperationFunction("+")(bindSymbol("x"),
|
|
||||||
bindSymbol("x"))
|
|
||||||
}.compileToExpression(DoubleField)
|
|
||||||
assertEquals(4.0, expr("x" to 2.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSine() {
|
|
||||||
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
|
||||||
assertEquals(0.0, expr("x" to 0.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testMinus() {
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.estree
|
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.MstRing
|
|
||||||
import space.kscience.kmath.expressions.invoke
|
|
||||||
import space.kscience.kmath.operations.ByteRing
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertFailsWith
|
|
||||||
|
|
||||||
internal class TestESTreeVariables {
|
|
||||||
@Test
|
|
||||||
fun testVariable() {
|
|
||||||
val expr = MstRing{ bindSymbol("x") }.compileToExpression(ByteRing)
|
|
||||||
assertEquals(1.toByte(), expr("x" to 1.toByte()))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testUndefinedVariableFails() {
|
|
||||||
val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing)
|
|
||||||
assertFailsWith<NoSuchElementException> { expr() }
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -342,8 +342,8 @@ internal class AsmBuilder<T>(
|
|||||||
val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") }
|
val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM Type for [kscience.kmath.expressions.Symbol].
|
* ASM Type for [space.kscience.kmath.misc.Symbol].
|
||||||
*/
|
*/
|
||||||
val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") }
|
val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/misc/Symbol") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.(
|
|||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) }
|
internal fun MethodVisitor.label(): Label = Label().also(::visitLabel)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a class name for [Expression] subclassed to implement [mst] provided.
|
* Creates a class name for [Expression] subclassed to implement [mst] provided.
|
||||||
|
@ -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,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.asm
|
|
||||||
|
|
||||||
import space.kscience.kmath.complex.ComplexField
|
|
||||||
import space.kscience.kmath.complex.toComplex
|
|
||||||
import space.kscience.kmath.expressions.*
|
|
||||||
import space.kscience.kmath.misc.Symbol.Companion.x
|
|
||||||
import space.kscience.kmath.operations.ByteRing
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
internal class TestAsmConsistencyWithInterpreter {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun mstSpace() {
|
|
||||||
|
|
||||||
val mst = MstGroup {
|
|
||||||
binaryOperationFunction("+")(
|
|
||||||
unaryOperationFunction("+")(
|
|
||||||
number(3.toByte()) - (number(2.toByte()) + (scale(
|
|
||||||
add(number(1), number(1)),
|
|
||||||
2.0
|
|
||||||
) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
|
|
||||||
),
|
|
||||||
|
|
||||||
number(1)
|
|
||||||
) + bindSymbol("x") + zero
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
mst.interpret(MstGroup, x to MST.Numeric(2)),
|
|
||||||
mst.compile(MstGroup, x to MST.Numeric(2))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun byteRing() {
|
|
||||||
val mst = MstRing {
|
|
||||||
binaryOperationFunction("+")(
|
|
||||||
unaryOperationFunction("+")(
|
|
||||||
(bindSymbol("x") - (2.toByte() + (scale(
|
|
||||||
add(number(1), number(1)),
|
|
||||||
2.0
|
|
||||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
|
||||||
),
|
|
||||||
|
|
||||||
number(1)
|
|
||||||
) * number(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
mst.interpret(ByteRing, x to 3.toByte()),
|
|
||||||
mst.compile(ByteRing, x to 3.toByte())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun realField() {
|
|
||||||
val mst = MstField {
|
|
||||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
|
||||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
|
||||||
+ number(1),
|
|
||||||
number(1) / 2 + number(2.0) * one
|
|
||||||
) + zero
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
mst.interpret(DoubleField, x to 2.0),
|
|
||||||
mst.compile(DoubleField, x to 2.0)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun complexField() {
|
|
||||||
val mst = MstField {
|
|
||||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
|
||||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
|
||||||
+ number(1),
|
|
||||||
number(1) / 2 + number(2.0) * one
|
|
||||||
) + zero
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
mst.interpret(ComplexField, x to 2.0.toComplex()),
|
|
||||||
mst.compile(ComplexField, x to 2.0.toComplex())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.asm
|
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.MstExtendedField
|
|
||||||
import space.kscience.kmath.expressions.MstField
|
|
||||||
import space.kscience.kmath.expressions.MstGroup
|
|
||||||
import space.kscience.kmath.expressions.invoke
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.random.Random
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
internal class TestAsmOperationsSupport {
|
|
||||||
@Test
|
|
||||||
fun testUnaryOperationInvocation() {
|
|
||||||
val expression = MstGroup { -bindSymbol("x") }.compileToExpression(DoubleField)
|
|
||||||
val res = expression("x" to 2.0)
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testMultipleCalls() {
|
|
||||||
val e =
|
|
||||||
MstExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }
|
|
||||||
.compileToExpression(DoubleField)
|
|
||||||
val r = Random(0)
|
|
||||||
var s = 0.0
|
|
||||||
repeat(1000000) { s += e("x" to r.nextDouble()) }
|
|
||||||
println(s)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.asm
|
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.MstExtendedField
|
|
||||||
import space.kscience.kmath.expressions.invoke
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
internal class TestAsmSpecialization {
|
|
||||||
@Test
|
|
||||||
fun testUnaryPlus() {
|
|
||||||
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
|
||||||
assertEquals(2.0, expr("x" to 2.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testUnaryMinus() {
|
|
||||||
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
|
||||||
assertEquals(-2.0, expr("x" to 2.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testAdd() {
|
|
||||||
val expr = MstExtendedField {
|
|
||||||
binaryOperationFunction("+")(bindSymbol("x"),
|
|
||||||
bindSymbol("x"))
|
|
||||||
}.compileToExpression(DoubleField)
|
|
||||||
assertEquals(4.0, expr("x" to 2.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSine() {
|
|
||||||
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField)
|
|
||||||
assertEquals(0.0, expr("x" to 0.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testMinus() {
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.asm
|
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.MstRing
|
|
||||||
import space.kscience.kmath.expressions.invoke
|
|
||||||
import space.kscience.kmath.operations.ByteRing
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertFailsWith
|
|
||||||
|
|
||||||
internal class TestAsmVariables {
|
|
||||||
@Test
|
|
||||||
fun testVariable() {
|
|
||||||
val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing)
|
|
||||||
assertEquals(1.toByte(), expr("x" to 1.toByte()))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testUndefinedVariableFails() {
|
|
||||||
val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing)
|
|
||||||
assertFailsWith<NoSuchElementException> { expr() }
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
|
import space.kscience.kmath.expressions.Expression
|
||||||
|
import space.kscience.kmath.expressions.MST
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.IntRing
|
||||||
|
import space.kscience.kmath.asm.compile as asmCompile
|
||||||
|
import space.kscience.kmath.asm.compileToExpression as asmCompileToExpression
|
||||||
|
|
||||||
|
private object AsmCompilerTestContext : CompilerTestContext {
|
||||||
|
override fun MST.compileToExpression(algebra: IntRing): Expression<Int> = asmCompileToExpression(algebra)
|
||||||
|
override fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int = asmCompile(algebra, arguments)
|
||||||
|
override fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = asmCompileToExpression(algebra)
|
||||||
|
|
||||||
|
override fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double =
|
||||||
|
asmCompile(algebra, arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) = action(AsmCompilerTestContext)
|
@ -1,12 +1,8 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm")
|
kotlin("jvm")
|
||||||
id("ru.mipt.npm.gradle.common")
|
id("ru.mipt.npm.gradle.common")
|
||||||
}
|
}
|
||||||
|
|
||||||
description = "Commons math binding for kmath"
|
description = "Commons math binding for kmath"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -28,7 +28,7 @@ public class CMIntegrator(
|
|||||||
val integrator = integratorBuilder(integrand)
|
val integrator = integratorBuilder(integrand)
|
||||||
val maxCalls = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: defaultMaxCalls
|
val maxCalls = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: defaultMaxCalls
|
||||||
val remainingCalls = maxCalls - integrand.calls
|
val remainingCalls = maxCalls - integrand.calls
|
||||||
val range = integrand.getFeature<IntegrationRange<Double>>()?.range
|
val range = integrand.getFeature<IntegrationRange>()?.range
|
||||||
?: error("Integration range is not provided")
|
?: error("Integration range is not provided")
|
||||||
val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive)
|
val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive)
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ public class GaussRuleIntegrator(
|
|||||||
) : UnivariateIntegrator<Double> {
|
) : UnivariateIntegrator<Double> {
|
||||||
|
|
||||||
override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||||
val range = integrand.getFeature<IntegrationRange<Double>>()?.range
|
val range = integrand.getFeature<IntegrationRange>()?.range
|
||||||
?: error("Integration range is not provided")
|
?: error("Integration range is not provided")
|
||||||
val integrator: GaussIntegrator = getIntegrator(range)
|
val integrator: GaussIntegrator = getIntegrator(range)
|
||||||
//TODO check performance
|
//TODO check performance
|
||||||
|
@ -19,16 +19,16 @@ internal class IntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun simpson() {
|
fun simpson() {
|
||||||
val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function)
|
val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function = function)
|
||||||
assertTrue { abs(res) < 1e-3 }
|
assertTrue { abs(res) < 1e-3 }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun customSimpson() {
|
fun customSimpson() {
|
||||||
val res = CMIntegrator.simpson().integrate(0.0..PI, function) {
|
val res = CMIntegrator.simpson().integrate(0.0..PI, {
|
||||||
targetRelativeAccuracy = 1e-4
|
targetRelativeAccuracy = 1e-4
|
||||||
targetAbsoluteAccuracy = 1e-4
|
targetAbsoluteAccuracy = 1e-4
|
||||||
}
|
}, function)
|
||||||
assertTrue { abs(res - 2) < 1e-3 }
|
assertTrue { abs(res - 2) < 1e-3 }
|
||||||
assertTrue { abs(res - 2) > 1e-12 }
|
assertTrue { abs(res - 2) > 1e-12 }
|
||||||
}
|
}
|
||||||
|
@ -8,29 +8,27 @@ Complex and hypercomplex number systems in KMath.
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-6`.
|
The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-8`.
|
||||||
|
|
||||||
**Gradle:**
|
**Gradle:**
|
||||||
```gradle
|
```gradle
|
||||||
repositories {
|
repositories {
|
||||||
maven { url 'https://repo.kotlin.link' }
|
maven { url 'https://repo.kotlin.link' }
|
||||||
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
mavenCentral()
|
||||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'space.kscience:kmath-complex:0.3.0-dev-6'
|
implementation 'space.kscience:kmath-complex:0.3.0-dev-8'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://repo.kotlin.link")
|
maven("https://repo.kotlin.link")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
mavenCentral()
|
||||||
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-complex:0.3.0-dev-6")
|
implementation("space.kscience:kmath-complex:0.3.0-dev-8")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
import ru.mipt.npm.gradle.Maturity
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("multiplatform")
|
kotlin("multiplatform")
|
||||||
id("ru.mipt.npm.gradle.common")
|
id("ru.mipt.npm.gradle.common")
|
||||||
@ -21,7 +14,7 @@ kotlin.sourceSets {
|
|||||||
|
|
||||||
readme {
|
readme {
|
||||||
description = "Complex numbers and quaternions."
|
description = "Complex numbers and quaternions."
|
||||||
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(
|
||||||
|
@ -9,7 +9,10 @@ import space.kscience.kmath.memory.MemoryReader
|
|||||||
import space.kscience.kmath.memory.MemorySpec
|
import space.kscience.kmath.memory.MemorySpec
|
||||||
import space.kscience.kmath.memory.MemoryWriter
|
import space.kscience.kmath.memory.MemoryWriter
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.ExtendedField
|
||||||
|
import space.kscience.kmath.operations.Norm
|
||||||
|
import space.kscience.kmath.operations.NumbersAddOperations
|
||||||
|
import space.kscience.kmath.operations.ScaleOperations
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.MemoryBuffer
|
import space.kscience.kmath.structures.MemoryBuffer
|
||||||
import space.kscience.kmath.structures.MutableBuffer
|
import space.kscience.kmath.structures.MutableBuffer
|
||||||
@ -180,13 +183,11 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, Num
|
|||||||
* @property im The imaginary part.
|
* @property im The imaginary part.
|
||||||
*/
|
*/
|
||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public data class Complex(val re: Double, val im: Double) : FieldElement<Complex, ComplexField> {
|
public data class Complex(val re: Double, val im: Double) {
|
||||||
public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble())
|
public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble())
|
||||||
public constructor(re: Number) : this(re.toDouble(), 0.0)
|
public constructor(re: Number) : this(re.toDouble(), 0.0)
|
||||||
|
|
||||||
public override val context: ComplexField get() = ComplexField
|
public override fun toString(): String = "($re + i * $im)"
|
||||||
|
|
||||||
public override fun toString(): String = "($re + i*$im)"
|
|
||||||
|
|
||||||
public companion object : MemorySpec<Complex> {
|
public companion object : MemorySpec<Complex> {
|
||||||
public override val objectSize: Int
|
public override val objectSize: Int
|
||||||
|
@ -27,8 +27,10 @@ public val Quaternion.conjugate: Quaternion
|
|||||||
*/
|
*/
|
||||||
public val Quaternion.reciprocal: Quaternion
|
public val Quaternion.reciprocal: Quaternion
|
||||||
get() {
|
get() {
|
||||||
val n = QuaternionField { norm(this@reciprocal) }
|
QuaternionField {
|
||||||
return conjugate / (n * n)
|
val n = norm(this@reciprocal)
|
||||||
|
return conjugate / (n * n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -198,7 +200,7 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
|
|||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public data class Quaternion(
|
public data class Quaternion(
|
||||||
val w: Double, val x: Double, val y: Double, val z: Double,
|
val w: Double, val x: Double, val y: Double, val z: Double,
|
||||||
) : FieldElement<Quaternion, QuaternionField> {
|
) {
|
||||||
public constructor(w: Number, x: Number, y: Number, z: Number) : this(
|
public constructor(w: Number, x: Number, y: Number, z: Number) : this(
|
||||||
w.toDouble(),
|
w.toDouble(),
|
||||||
x.toDouble(),
|
x.toDouble(),
|
||||||
@ -219,8 +221,6 @@ public data class Quaternion(
|
|||||||
require(!z.isNaN()) { "x-component of quaternion is not-a-number" }
|
require(!z.isNaN()) { "x-component of quaternion is not-a-number" }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override val context: QuaternionField get() = QuaternionField
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string representation of this quaternion.
|
* Returns a string representation of this quaternion.
|
||||||
*/
|
*/
|
||||||
|
@ -15,29 +15,27 @@ performance calculations to code generation.
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-6`.
|
The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-8`.
|
||||||
|
|
||||||
**Gradle:**
|
**Gradle:**
|
||||||
```gradle
|
```gradle
|
||||||
repositories {
|
repositories {
|
||||||
maven { url 'https://repo.kotlin.link' }
|
maven { url 'https://repo.kotlin.link' }
|
||||||
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
mavenCentral()
|
||||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'space.kscience:kmath-core:0.3.0-dev-6'
|
implementation 'space.kscience:kmath-core:0.3.0-dev-8'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://repo.kotlin.link")
|
maven("https://repo.kotlin.link")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
mavenCentral()
|
||||||
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-core:0.3.0-dev-6")
|
implementation("space.kscience:kmath-core:0.3.0-dev-8")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -45,13 +45,6 @@ public abstract interface class space/kscience/kmath/expressions/ExpressionAlgeb
|
|||||||
public abstract fun const (Ljava/lang/Object;)Ljava/lang/Object;
|
public abstract fun const (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/expressions/ExpressionBuildersKt {
|
|
||||||
public static final fun extendedFieldExpression (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
|
|
||||||
public static final fun fieldExpression (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
|
|
||||||
public static final fun ringExpression (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
|
|
||||||
public static final fun spaceExpression (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/kmath/expressions/ExpressionKt {
|
public final class space/kscience/kmath/expressions/ExpressionKt {
|
||||||
public static final fun binding (Lspace/kscience/kmath/expressions/ExpressionAlgebra;)Lkotlin/properties/ReadOnlyProperty;
|
public static final fun binding (Lspace/kscience/kmath/expressions/ExpressionAlgebra;)Lkotlin/properties/ReadOnlyProperty;
|
||||||
public static final fun callByString (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object;
|
public static final fun callByString (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object;
|
||||||
@ -272,6 +265,8 @@ public final class space/kscience/kmath/expressions/MstExtendedField : space/ksc
|
|||||||
public fun sin (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
|
public fun sin (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
|
||||||
public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
|
public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
public fun sinh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
|
public fun sinh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
|
||||||
|
public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
|
public fun sqrt (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST;
|
||||||
public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
|
public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
public fun tan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
|
public fun tan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
|
||||||
public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
|
public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
@ -679,6 +674,9 @@ public final class space/kscience/kmath/misc/CumulativeKt {
|
|||||||
public static final fun cumulativeSumOfLong (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
|
public static final fun cumulativeSumOfLong (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract interface annotation class space/kscience/kmath/misc/PerformancePitfall : java/lang/annotation/Annotation {
|
||||||
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/misc/StringSymbol : space/kscience/kmath/misc/Symbol {
|
public final class space/kscience/kmath/misc/StringSymbol : space/kscience/kmath/misc/Symbol {
|
||||||
public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/misc/StringSymbol;
|
public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/misc/StringSymbol;
|
||||||
public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String;
|
public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String;
|
||||||
@ -705,7 +703,11 @@ public final class space/kscience/kmath/misc/Symbol$Companion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/misc/SymbolKt {
|
public final class space/kscience/kmath/misc/SymbolKt {
|
||||||
|
public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object;
|
||||||
|
public static final fun get (Ljava/util/Map;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty;
|
public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty;
|
||||||
|
public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V
|
||||||
|
public static final fun set (Ljava/util/Map;Lspace/kscience/kmath/misc/Symbol;Ljava/lang/Object;)V
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation {
|
public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation {
|
||||||
@ -748,7 +750,7 @@ public final class space/kscience/kmath/nd/BufferAlgebraNDKt {
|
|||||||
public static final fun ring (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedRingND;
|
public static final fun ring (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedRingND;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND {
|
public class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND {
|
||||||
public fun <init> (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V
|
public fun <init> (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V
|
||||||
public fun elements ()Lkotlin/sequences/Sequence;
|
public fun elements ()Lkotlin/sequences/Sequence;
|
||||||
public fun get ([I)Ljava/lang/Object;
|
public fun get ([I)Ljava/lang/Object;
|
||||||
@ -789,10 +791,9 @@ public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath
|
|||||||
public fun equals (Ljava/lang/Object;)Z
|
public fun equals (Ljava/lang/Object;)Z
|
||||||
public fun getLinearSize ()I
|
public fun getLinearSize ()I
|
||||||
public fun getShape ()[I
|
public fun getShape ()[I
|
||||||
public fun getStrides ()Ljava/util/List;
|
public fun getStrides ()[I
|
||||||
public fun hashCode ()I
|
public fun hashCode ()I
|
||||||
public fun index (I)[I
|
public fun index (I)[I
|
||||||
public fun offset ([I)I
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/nd/DefaultStrides$Companion {
|
public final class space/kscience/kmath/nd/DefaultStrides$Companion {
|
||||||
@ -876,6 +877,22 @@ public abstract interface class space/kscience/kmath/nd/GroupND : space/kscience
|
|||||||
public final class space/kscience/kmath/nd/GroupND$Companion {
|
public final class space/kscience/kmath/nd/GroupND$Companion {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/kmath/nd/MutableBufferND : space/kscience/kmath/nd/BufferND, space/kscience/kmath/nd/MutableStructureND {
|
||||||
|
public fun <init> (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/MutableBuffer;)V
|
||||||
|
public final fun getMutableBuffer ()Lspace/kscience/kmath/structures/MutableBuffer;
|
||||||
|
public fun set ([ILjava/lang/Object;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface class space/kscience/kmath/nd/MutableStructure1D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure1D, space/kscience/kmath/structures/MutableBuffer {
|
||||||
|
public fun set ([ILjava/lang/Object;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface class space/kscience/kmath/nd/MutableStructure2D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure2D {
|
||||||
|
public fun getColumns ()Ljava/util/List;
|
||||||
|
public fun getRows ()Ljava/util/List;
|
||||||
|
public abstract fun set (IILjava/lang/Object;)V
|
||||||
|
}
|
||||||
|
|
||||||
public abstract interface class space/kscience/kmath/nd/MutableStructureND : space/kscience/kmath/nd/StructureND {
|
public abstract interface class space/kscience/kmath/nd/MutableStructureND : space/kscience/kmath/nd/StructureND {
|
||||||
public abstract fun set ([ILjava/lang/Object;)V
|
public abstract fun set ([ILjava/lang/Object;)V
|
||||||
}
|
}
|
||||||
@ -915,10 +932,10 @@ public final class space/kscience/kmath/nd/ShortRingNDKt {
|
|||||||
public abstract interface class space/kscience/kmath/nd/Strides {
|
public abstract interface class space/kscience/kmath/nd/Strides {
|
||||||
public abstract fun getLinearSize ()I
|
public abstract fun getLinearSize ()I
|
||||||
public abstract fun getShape ()[I
|
public abstract fun getShape ()[I
|
||||||
public abstract fun getStrides ()Ljava/util/List;
|
public abstract fun getStrides ()[I
|
||||||
public abstract fun index (I)[I
|
public abstract fun index (I)[I
|
||||||
public fun indices ()Lkotlin/sequences/Sequence;
|
public fun indices ()Lkotlin/sequences/Sequence;
|
||||||
public abstract fun offset ([I)I
|
public fun offset ([I)I
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer {
|
public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer {
|
||||||
@ -932,6 +949,7 @@ public final class space/kscience/kmath/nd/Structure1D$Companion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/nd/Structure1DKt {
|
public final class space/kscience/kmath/nd/Structure1DKt {
|
||||||
|
public static final fun as1D (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructure1D;
|
||||||
public static final fun as1D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure1D;
|
public static final fun as1D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure1D;
|
||||||
public static final fun asND (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/nd/Structure1D;
|
public static final fun asND (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/nd/Structure1D;
|
||||||
}
|
}
|
||||||
@ -952,6 +970,7 @@ public final class space/kscience/kmath/nd/Structure2D$Companion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/nd/Structure2DKt {
|
public final class space/kscience/kmath/nd/Structure2DKt {
|
||||||
|
public static final fun as2D (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructure2D;
|
||||||
public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D;
|
public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -991,14 +1010,7 @@ public abstract interface class space/kscience/kmath/operations/Algebra {
|
|||||||
public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface class space/kscience/kmath/operations/AlgebraElement {
|
|
||||||
public abstract fun getContext ()Lspace/kscience/kmath/operations/Algebra;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/kmath/operations/AlgebraElementsKt {
|
public final class space/kscience/kmath/operations/AlgebraElementsKt {
|
||||||
public static final fun div (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
|
|
||||||
public static final fun plus (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
|
|
||||||
public static final fun times (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/operations/AlgebraExtensionsKt {
|
public final class space/kscience/kmath/operations/AlgebraExtensionsKt {
|
||||||
@ -1209,7 +1221,6 @@ public abstract interface class space/kscience/kmath/operations/ExtendedField :
|
|||||||
public fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
|
public fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
public fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
|
public fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
public fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
|
public fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
|
|
||||||
public fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
|
public fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
||||||
public fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
|
public fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import ru.mipt.npm.gradle.Maturity
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("multiplatform")
|
kotlin("multiplatform")
|
||||||
id("ru.mipt.npm.gradle.common")
|
id("ru.mipt.npm.gradle.common")
|
||||||
@ -21,7 +14,7 @@ kotlin.sourceSets {
|
|||||||
|
|
||||||
readme {
|
readme {
|
||||||
description = "Core classes, algebra definitions, basic linear algebra"
|
description = "Core classes, algebra definitions, basic linear algebra"
|
||||||
maturity = Maturity.DEVELOPMENT
|
maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT
|
||||||
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||||
|
|
||||||
feature(
|
feature(
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.data
|
package space.kscience.kmath.data
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.misc.Symbol
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.nd.Structure2D
|
import space.kscience.kmath.nd.Structure2D
|
||||||
@ -25,6 +26,7 @@ public interface ColumnarData<out T> {
|
|||||||
* A zero-copy method to represent a [Structure2D] as a two-column x-y data.
|
* A zero-copy method to represent a [Structure2D] as a two-column x-y data.
|
||||||
* There could more than two columns in the structure.
|
* There could more than two columns in the structure.
|
||||||
*/
|
*/
|
||||||
|
@OptIn(PerformancePitfall::class)
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public fun <T> Structure2D<T>.asColumnarData(mapping: Map<Symbol, Int>): ColumnarData<T> {
|
public fun <T> Structure2D<T>.asColumnarData(mapping: Map<Symbol, Int>): ColumnarData<T> {
|
||||||
require(shape[1] >= mapping.maxOf { it.value }) { "Column index out of bounds" }
|
require(shape[1] >= mapping.maxOf { it.value }) { "Column index out of bounds" }
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.data
|
package space.kscience.kmath.data
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.misc.Symbol
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.nd.Structure2D
|
import space.kscience.kmath.nd.Structure2D
|
||||||
@ -49,6 +50,7 @@ public fun <T, X : T, Y : T> XYColumnarData(x: Buffer<X>, y: Buffer<Y>): XYColum
|
|||||||
* A zero-copy method to represent a [Structure2D] as a two-column x-y data.
|
* A zero-copy method to represent a [Structure2D] as a two-column x-y data.
|
||||||
* There could more than two columns in the structure.
|
* There could more than two columns in the structure.
|
||||||
*/
|
*/
|
||||||
|
@OptIn(PerformancePitfall::class)
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public fun <T> Structure2D<T>.asXYData(xIndex: Int = 0, yIndex: Int = 1): XYColumnarData<T, T, T> {
|
public fun <T> Structure2D<T>.asXYData(xIndex: Int = 0, yIndex: Int = 1): XYColumnarData<T, T, T> {
|
||||||
require(shape[1] >= max(xIndex, yIndex)) { "Column index out of bounds" }
|
require(shape[1] >= max(xIndex, yIndex)) { "Column index out of bounds" }
|
||||||
|
@ -135,6 +135,7 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
|
|||||||
public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg)
|
public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg)
|
||||||
public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg)
|
public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg)
|
||||||
public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b)
|
public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b)
|
||||||
|
public override fun sqrt(arg: MST): MST = unaryOperationFunction(PowerOperations.SQRT_OPERATION)(arg)
|
||||||
|
|
||||||
public override fun scale(a: MST, value: Double): MST =
|
public override fun scale(a: MST, value: Double): MST =
|
||||||
binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value))
|
binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value))
|
||||||
|
@ -33,12 +33,12 @@ public interface SymbolIndexer {
|
|||||||
|
|
||||||
public operator fun DoubleArray.get(symbol: Symbol): Double {
|
public operator fun DoubleArray.get(symbol: Symbol): Double {
|
||||||
require(size == symbols.size) { "The input array size for indexer should be ${symbols.size} but $size found" }
|
require(size == symbols.size) { "The input array size for indexer should be ${symbols.size} but $size found" }
|
||||||
return get(this@SymbolIndexer.indexOf(symbol))
|
return get(indexOf(symbol))
|
||||||
}
|
}
|
||||||
|
|
||||||
public operator fun <T> Point<T>.get(symbol: Symbol): T {
|
public operator fun <T> Point<T>.get(symbol: Symbol): T {
|
||||||
require(size == symbols.size) { "The input buffer size for indexer should be ${symbols.size} but $size found" }
|
require(size == symbols.size) { "The input buffer size for indexer should be ${symbols.size} but $size found" }
|
||||||
return get(this@SymbolIndexer.indexOf(symbol))
|
return get(indexOf(symbol))
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun DoubleArray.toMap(): Map<Symbol, Double> {
|
public fun DoubleArray.toMap(): Map<Symbol, Double> {
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.expressions
|
|
||||||
|
|
||||||
import space.kscience.kmath.operations.ExtendedField
|
|
||||||
import space.kscience.kmath.operations.Field
|
|
||||||
import space.kscience.kmath.operations.Ring
|
|
||||||
import kotlin.contracts.InvocationKind
|
|
||||||
import kotlin.contracts.contract
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a functional expression with this [Ring].
|
|
||||||
*/
|
|
||||||
public inline fun <T> Ring<T>.spaceExpression(block: FunctionalExpressionGroup<T, Ring<T>>.() -> Expression<T>): Expression<T> {
|
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
|
||||||
return FunctionalExpressionGroup(this).block()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a functional expression with this [Ring].
|
|
||||||
*/
|
|
||||||
public inline fun <T> Ring<T>.ringExpression(block: FunctionalExpressionRing<T, Ring<T>>.() -> Expression<T>): Expression<T> {
|
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
|
||||||
return FunctionalExpressionRing(this).block()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a functional expression with this [Field].
|
|
||||||
*/
|
|
||||||
public inline fun <T> Field<T>.fieldExpression(block: FunctionalExpressionField<T, Field<T>>.() -> Expression<T>): Expression<T> {
|
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
|
||||||
return FunctionalExpressionField(this).block()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a functional expression with this [ExtendedField].
|
|
||||||
*/
|
|
||||||
public inline fun <T> ExtendedField<T>.extendedFieldExpression(block: FunctionalExpressionExtendedField<T, ExtendedField<T>>.() -> Expression<T>): Expression<T> {
|
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
|
||||||
return FunctionalExpressionExtendedField(this).block()
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user