Merge branch 'dev' into feature/advanced-optimization
# Conflicts: # examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt # examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt # kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt # kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt # kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt # kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt # kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt # kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt # kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt # kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt # kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt # kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt # kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt # kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt
This commit is contained in:
commit
3ec674c61b
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@ -13,9 +13,11 @@ jobs:
|
||||
- name: Checkout the repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
uses: DeLaGuardo/setup-graalvm@4.0
|
||||
with:
|
||||
java-version: 11
|
||||
graalvm: 21.1.0
|
||||
java: java11
|
||||
arch: amd64
|
||||
- name: Add msys to path
|
||||
if: matrix.os == 'windows-latest'
|
||||
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
|
||||
with:
|
||||
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
|
||||
run: |
|
||||
./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
|
||||
mv build/dokka/htmlMultiModule/-modules.html build/dokka/htmlMultiModule/index.html
|
||||
run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: JamesIves/github-pages-deploy-action@4.1.0
|
||||
with:
|
||||
|
6
.github/workflows/publish.yml
vendored
6
.github/workflows/publish.yml
vendored
@ -18,9 +18,11 @@ jobs:
|
||||
- name: Checkout the repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
uses: DeLaGuardo/setup-graalvm@4.0
|
||||
with:
|
||||
java-version: 11
|
||||
graalvm: 21.1.0
|
||||
java: java11
|
||||
arch: amd64
|
||||
- name: Add msys to path
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
|
||||
|
22
CHANGELOG.md
22
CHANGELOG.md
@ -10,20 +10,31 @@
|
||||
- Blocking chains and Statistics
|
||||
- Multiplatform integration
|
||||
- Integration for any Field element
|
||||
- Extendend operations for ND4J fields
|
||||
- Extended operations for ND4J fields
|
||||
- Jupyter Notebook integration module (kmath-jupyter)
|
||||
- `@PerformancePitfall` annotation to mark possibly slow API
|
||||
- BigInt operation performance improvement and fixes by @zhelenskiy (#328)
|
||||
|
||||
### Changed
|
||||
- Exponential operations merged with hyperbolic functions
|
||||
- Space is replaced by Group. Space is reserved for vector spaces.
|
||||
- VectorSpace is now a vector space
|
||||
- Buffer factories for primitives moved to MutableBuffer.Companion
|
||||
- NDStructure and NDAlgebra to StructureND and AlgebraND respectively
|
||||
- Real -> Double
|
||||
- Rename `NDStructure` and `NDAlgebra` to `StructureND` and `AlgebraND` respectively
|
||||
- `Real` -> `Double`
|
||||
- DataSets are moved from functions to core
|
||||
- Redesign advanced Chain API
|
||||
- Redesign MST. Remove MSTExpression.
|
||||
- Move MST to core
|
||||
- Redesign `MST`. Remove `MstExpression`.
|
||||
- Move `MST` to core
|
||||
- Separated benchmarks and examples
|
||||
- Rewrite `kmath-ejml` without `ejml-simple` artifact, support sparse matrices
|
||||
- Promote stability of kmath-ast and kmath-kotlingrad to EXPERIMENTAL.
|
||||
- ColumnarData returns nullable column
|
||||
- `MST` is made sealed interface
|
||||
- Replace `MST.Symbolic` by `Symbol`, `Symbol` now implements MST
|
||||
- Remove Any restriction on polynomials
|
||||
- Add `out` variance to type parameters of `StructureND` and its implementations where possible
|
||||
- Rename `DifferentiableMstExpression` to `KotlingradExpression`
|
||||
|
||||
### Deprecated
|
||||
|
||||
@ -33,6 +44,7 @@
|
||||
- `contentEquals` from Buffer. It moved to the companion.
|
||||
- MSTExpression
|
||||
- Expression algebra builders
|
||||
- Complex and Quaternion no longer are elements.
|
||||
|
||||
### Fixed
|
||||
- Ring inherits RingOperations, not GroupOperations
|
||||
|
39
README.md
39
README.md
@ -40,7 +40,7 @@ KMath is a modular library. Different modules provide different features with di
|
||||
|
||||
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
|
||||
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations.
|
||||
* **DEVELOPMENT**. API breaking genrally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
||||
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
||||
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
|
||||
|
||||
<!--Current feature list is [here](/docs/features.md)-->
|
||||
@ -91,7 +91,7 @@ KMath is a modular library. Different modules provide different features with di
|
||||
* ### [kmath-ast](kmath-ast)
|
||||
>
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
>
|
||||
> **Features:**
|
||||
> - [expression-language](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||
@ -154,9 +154,9 @@ performance calculations to code generation.
|
||||
> **Maturity**: PROTOTYPE
|
||||
>
|
||||
> **Features:**
|
||||
> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix.
|
||||
> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix.
|
||||
> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace 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) : Matrix implementation.
|
||||
> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : LinearSpace implementations.
|
||||
|
||||
<hr/>
|
||||
|
||||
@ -200,12 +200,23 @@ One can still use generic algebras though.
|
||||
> **Maturity**: PROTOTYPE
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-kotlingrad](kmath-kotlingrad)
|
||||
* ### [kmath-jupyter](kmath-jupyter)
|
||||
>
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
<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)
|
||||
> An API and basic implementation for arranging objects in a continous memory block.
|
||||
>
|
||||
@ -230,6 +241,18 @@ One can still use generic algebras though.
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-tensors](kmath-tensors)
|
||||
>
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
>
|
||||
> **Features:**
|
||||
> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.)
|
||||
> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting.
|
||||
> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc.
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-viktor](kmath-viktor)
|
||||
>
|
||||
>
|
||||
@ -270,8 +293,8 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("space.kscience:kmath-core:0.3.0-dev-7")
|
||||
// api("space.kscience:kmath-core-jvm:0.3.0-dev-7") for jvm-specific version
|
||||
api("space.kscience:kmath-core:0.3.0-dev-11")
|
||||
// api("space.kscience:kmath-core-jvm:0.3.0-dev-11") for jvm-specific version
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -9,14 +9,10 @@ sourceSets.register("benchmarks")
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://clojars.org/repo")
|
||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||
maven("https://jitpack.io")
|
||||
maven {
|
||||
setUrl("http://logicrunch.research.it.uu.se/maven/")
|
||||
maven("http://logicrunch.research.it.uu.se/maven") {
|
||||
isAllowInsecureProtocol = true
|
||||
}
|
||||
}
|
||||
|
@ -10,20 +10,19 @@ import kotlinx.benchmark.Blackhole
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import space.kscience.kmath.operations.BigInt
|
||||
import space.kscience.kmath.operations.BigIntField
|
||||
import space.kscience.kmath.operations.JBigIntegerField
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.*
|
||||
import java.math.BigInteger
|
||||
|
||||
private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ZERO)
|
||||
|
||||
@UnstableKMathAPI
|
||||
@State(Scope.Benchmark)
|
||||
internal class BigIntBenchmark {
|
||||
|
||||
val kmNumber = BigIntField.number(Int.MAX_VALUE)
|
||||
val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE)
|
||||
val largeKmNumber = BigIntField { number(11).pow(100_000) }
|
||||
val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) }
|
||||
val largeKmNumber = BigIntField { number(11).pow(100_000U) }
|
||||
val largeJvmNumber: BigInteger = JBigIntegerField { number(11).pow(100_000) }
|
||||
val bigExponent = 50_000
|
||||
|
||||
@Benchmark
|
||||
@ -36,6 +35,16 @@ internal class BigIntBenchmark {
|
||||
blackhole.consume(jvmNumber + jvmNumber + jvmNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmAddLarge(blackhole: Blackhole) = BigIntField {
|
||||
blackhole.consume(largeKmNumber + largeKmNumber + largeKmNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmAddLarge(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume(largeJvmNumber + largeJvmNumber + largeJvmNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmMultiply(blackhole: Blackhole) = BigIntField {
|
||||
blackhole.consume(kmNumber * kmNumber * kmNumber)
|
||||
@ -56,13 +65,33 @@ internal class BigIntBenchmark {
|
||||
blackhole.consume(largeJvmNumber*largeJvmNumber)
|
||||
}
|
||||
|
||||
// @Benchmark
|
||||
// fun kmPower(blackhole: Blackhole) = BigIntField {
|
||||
// blackhole.consume(kmNumber.pow(bigExponent))
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// fun jvmPower(blackhole: Blackhole) = JBigIntegerField {
|
||||
// blackhole.consume(jvmNumber.pow(bigExponent))
|
||||
// }
|
||||
@Benchmark
|
||||
fun kmPower(blackhole: Blackhole) = BigIntField {
|
||||
blackhole.consume(kmNumber.pow(bigExponent.toUInt()))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmPower(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume(jvmNumber.pow(bigExponent))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmParsing16(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume("0x7f57ed8b89c29a3b9a85c7a5b84ca3929c7b7488593".parseBigInteger())
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmParsing10(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume("236656783929183747565738292847574838922010".parseBigInteger())
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmParsing10(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume("236656783929183747565738292847574838922010".toBigInteger(10))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmParsing16(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume("7f57ed8b89c29a3b9a85c7a5b84ca3929c7b7488593".toBigInteger(16))
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
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.invoke
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
@ -29,8 +29,8 @@ internal class DotBenchmark {
|
||||
val cmMatrix1 = CMLinearSpace { matrix1.toCM() }
|
||||
val cmMatrix2 = CMLinearSpace { matrix2.toCM() }
|
||||
|
||||
val ejmlMatrix1 = EjmlLinearSpace { matrix1.toEjml() }
|
||||
val ejmlMatrix2 = EjmlLinearSpace { matrix2.toEjml() }
|
||||
val ejmlMatrix1 = EjmlLinearSpaceDDRM { matrix1.toEjml() }
|
||||
val ejmlMatrix2 = EjmlLinearSpaceDDRM { matrix2.toEjml() }
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@ -42,14 +42,14 @@ internal class DotBenchmark {
|
||||
|
||||
@Benchmark
|
||||
fun ejmlDot(blackhole: Blackhole) {
|
||||
EjmlLinearSpace {
|
||||
EjmlLinearSpaceDDRM {
|
||||
blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun ejmlDotWithConversion(blackhole: Blackhole) {
|
||||
EjmlLinearSpace {
|
||||
EjmlLinearSpaceDDRM {
|
||||
blackhole.consume(matrix1 dot matrix2)
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,6 @@ import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import space.kscience.kmath.asm.compileToExpression
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
|
@ -11,25 +11,26 @@ import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
||||
import space.kscience.kmath.commons.linear.inverse
|
||||
import space.kscience.kmath.ejml.EjmlLinearSpace
|
||||
import space.kscience.kmath.ejml.inverse
|
||||
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
||||
import space.kscience.kmath.linear.InverseMatrixFeature
|
||||
import space.kscience.kmath.linear.LinearSpace
|
||||
import space.kscience.kmath.linear.inverseWithLup
|
||||
import space.kscience.kmath.linear.invoke
|
||||
import space.kscience.kmath.nd.getFeature
|
||||
import kotlin.random.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class MatrixInverseBenchmark {
|
||||
companion object {
|
||||
val random = Random(1224)
|
||||
const val dim = 100
|
||||
private companion object {
|
||||
private val random = Random(1224)
|
||||
private const val dim = 100
|
||||
|
||||
private val space = LinearSpace.real
|
||||
|
||||
//creating invertible matrix
|
||||
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 }
|
||||
val matrix = space { l dot u }
|
||||
private val u = 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 }
|
||||
private val matrix = space { l dot u }
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@ -46,8 +47,8 @@ internal class MatrixInverseBenchmark {
|
||||
|
||||
@Benchmark
|
||||
fun ejmlInverse(blackhole: Blackhole) {
|
||||
with(EjmlLinearSpace) {
|
||||
blackhole.consume(inverse(matrix))
|
||||
with(EjmlLinearSpaceDDRM) {
|
||||
blackhole.consume(matrix.getFeature<InverseMatrixFeature<Double>>()?.inverse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +1,37 @@
|
||||
plugins {
|
||||
id("ru.mipt.npm.gradle.project")
|
||||
kotlin("jupyter.api") apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven("https://clojars.org/repo")
|
||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||
maven("https://jitpack.io")
|
||||
maven("http://logicrunch.research.it.uu.se/maven/") {
|
||||
maven("http://logicrunch.research.it.uu.se/maven") {
|
||||
isAllowInsecureProtocol = true
|
||||
}
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
group = "space.kscience"
|
||||
version = "0.3.0-dev-7"
|
||||
version = "0.3.0-dev-13"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
if (name.startsWith("kmath")) apply<MavenPublishPlugin>()
|
||||
|
||||
afterEvaluate {
|
||||
tasks.withType<org.jetbrains.dokka.gradle.DokkaTask> {
|
||||
dokkaSourceSets.all {
|
||||
val readmeFile = File(this@subprojects.projectDir, "./README.md")
|
||||
if (readmeFile.exists())
|
||||
includes.setFrom(includes + readmeFile.absolutePath)
|
||||
tasks.withType<org.jetbrains.dokka.gradle.DokkaTaskPartial> {
|
||||
dependsOn(tasks.getByName("assemble"))
|
||||
|
||||
arrayOf(
|
||||
"http://ejml.org/javadoc/",
|
||||
"https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/",
|
||||
"https://deeplearning4j.org/api/latest/"
|
||||
).map { java.net.URL("${it}package-list") to java.net.URL(it) }.forEach { (a, b) ->
|
||||
externalDocumentationLink {
|
||||
packageListUrl.set(a)
|
||||
url.set(b)
|
||||
}
|
||||
}
|
||||
dokkaSourceSets.all {
|
||||
val readmeFile = File(this@subprojects.projectDir, "README.md")
|
||||
if (readmeFile.exists()) includes.setFrom(includes + readmeFile.absolutePath)
|
||||
externalDocumentationLink("http://ejml.org/javadoc/")
|
||||
externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/")
|
||||
externalDocumentationLink("https://deeplearning4j.org/api/latest/")
|
||||
externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
buildSrc/build.gradle.kts
Normal file
5
buildSrc/build.gradle.kts
Normal file
@ -0,0 +1,5 @@
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
}
|
||||
|
||||
repositories.mavenCentral()
|
@ -0,0 +1,425 @@
|
||||
/*
|
||||
* 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("KDocUnresolvedReference")
|
||||
|
||||
package space.kscience.kmath.ejml.codegen
|
||||
|
||||
import org.intellij.lang.annotations.Language
|
||||
import java.io.File
|
||||
|
||||
private fun Appendable.appendEjmlVector(type: String, ejmlMatrixType: String) {
|
||||
@Language("kotlin") val text = """/**
|
||||
* [EjmlVector] specialization for [$type].
|
||||
*/
|
||||
public class Ejml${type}Vector<out M : $ejmlMatrixType>(public override val origin: M) : EjmlVector<$type, M>(origin) {
|
||||
init {
|
||||
require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" }
|
||||
}
|
||||
|
||||
public override operator fun get(index: Int): $type = origin[0, index]
|
||||
}"""
|
||||
appendLine(text)
|
||||
appendLine()
|
||||
}
|
||||
|
||||
private fun Appendable.appendEjmlMatrix(type: String, ejmlMatrixType: String) {
|
||||
val text = """/**
|
||||
* [EjmlMatrix] specialization for [$type].
|
||||
*/
|
||||
public class Ejml${type}Matrix<out M : $ejmlMatrixType>(public override val origin: M) : EjmlMatrix<$type, M>(origin) {
|
||||
public override operator fun get(i: Int, j: Int): $type = origin[i, j]
|
||||
}"""
|
||||
appendLine(text)
|
||||
appendLine()
|
||||
}
|
||||
|
||||
private fun Appendable.appendEjmlLinearSpace(
|
||||
type: String,
|
||||
kmathAlgebra: String,
|
||||
ejmlMatrixParentTypeMatrix: String,
|
||||
ejmlMatrixType: String,
|
||||
ejmlMatrixDenseType: String,
|
||||
ops: String,
|
||||
denseOps: String,
|
||||
isDense: Boolean,
|
||||
) {
|
||||
@Language("kotlin") val text = """/**
|
||||
* [EjmlLinearSpace] implementation based on [CommonOps_$ops], [DecompositionFactory_${ops}] operations and
|
||||
* [${ejmlMatrixType}] matrices.
|
||||
*/
|
||||
public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra}, $ejmlMatrixType>() {
|
||||
/**
|
||||
* The [${kmathAlgebra}] reference.
|
||||
*/
|
||||
public override val elementAlgebra: $kmathAlgebra get() = $kmathAlgebra
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public override fun Matrix<${type}>.toEjml(): Ejml${type}Matrix<${ejmlMatrixType}> = when {
|
||||
this is Ejml${type}Matrix<*> && origin is $ejmlMatrixType -> this as Ejml${type}Matrix<${ejmlMatrixType}>
|
||||
else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) }
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public override fun Point<${type}>.toEjml(): Ejml${type}Vector<${ejmlMatrixType}> = when {
|
||||
this is Ejml${type}Vector<*> && origin is $ejmlMatrixType -> this as Ejml${type}Vector<${ejmlMatrixType}>
|
||||
else -> Ejml${type}Vector(${ejmlMatrixType}(size, 1).also {
|
||||
(0 until it.numRows).forEach { row -> it[row, 0] = get(row) }
|
||||
})
|
||||
}
|
||||
|
||||
public override fun buildMatrix(
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
initializer: ${kmathAlgebra}.(i: Int, j: Int) -> ${type},
|
||||
): Ejml${type}Matrix<${ejmlMatrixType}> = ${ejmlMatrixType}(rows, columns).also {
|
||||
(0 until rows).forEach { row ->
|
||||
(0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) }
|
||||
}
|
||||
}.wrapMatrix()
|
||||
|
||||
public override fun buildVector(
|
||||
size: Int,
|
||||
initializer: ${kmathAlgebra}.(Int) -> ${type},
|
||||
): Ejml${type}Vector<${ejmlMatrixType}> = Ejml${type}Vector(${ejmlMatrixType}(size, 1).also {
|
||||
(0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) }
|
||||
})
|
||||
|
||||
private fun <T : ${ejmlMatrixParentTypeMatrix}> T.wrapMatrix() = Ejml${type}Matrix(this)
|
||||
private fun <T : ${ejmlMatrixParentTypeMatrix}> T.wrapVector() = Ejml${type}Vector(this)
|
||||
|
||||
public override fun Matrix<${type}>.unaryMinus(): Matrix<${type}> = this * elementAlgebra { -one }
|
||||
|
||||
public override fun Matrix<${type}>.dot(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||
val out = ${ejmlMatrixType}(1, 1)
|
||||
CommonOps_${ops}.mult(toEjml().origin, other.toEjml().origin, out)
|
||||
return out.wrapMatrix()
|
||||
}
|
||||
|
||||
public override fun Matrix<${type}>.dot(vector: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||
val out = ${ejmlMatrixType}(1, 1)
|
||||
CommonOps_${ops}.mult(toEjml().origin, vector.toEjml().origin, out)
|
||||
return out.wrapVector()
|
||||
}
|
||||
|
||||
public override operator fun Matrix<${type}>.minus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||
val out = ${ejmlMatrixType}(1, 1)
|
||||
|
||||
CommonOps_${ops}.add(
|
||||
elementAlgebra.one,
|
||||
toEjml().origin,
|
||||
elementAlgebra { -one },
|
||||
other.toEjml().origin,
|
||||
out,${
|
||||
if (isDense) "" else
|
||||
"""
|
||||
null,
|
||||
null,"""
|
||||
}
|
||||
)
|
||||
|
||||
return out.wrapMatrix()
|
||||
}
|
||||
|
||||
public override operator fun Matrix<${type}>.times(value: ${type}): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||
val res = ${ejmlMatrixType}(1, 1)
|
||||
CommonOps_${ops}.scale(value, toEjml().origin, res)
|
||||
return res.wrapMatrix()
|
||||
}
|
||||
|
||||
public override fun Point<${type}>.unaryMinus(): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||
val res = ${ejmlMatrixType}(1, 1)
|
||||
CommonOps_${ops}.changeSign(toEjml().origin, res)
|
||||
return res.wrapVector()
|
||||
}
|
||||
|
||||
public override fun Matrix<${type}>.plus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||
val out = ${ejmlMatrixType}(1, 1)
|
||||
|
||||
CommonOps_${ops}.add(
|
||||
elementAlgebra.one,
|
||||
toEjml().origin,
|
||||
elementAlgebra.one,
|
||||
other.toEjml().origin,
|
||||
out,${
|
||||
if (isDense) "" else
|
||||
"""
|
||||
null,
|
||||
null,"""
|
||||
}
|
||||
)
|
||||
|
||||
return out.wrapMatrix()
|
||||
}
|
||||
|
||||
public override fun Point<${type}>.plus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||
val out = ${ejmlMatrixType}(1, 1)
|
||||
|
||||
CommonOps_${ops}.add(
|
||||
elementAlgebra.one,
|
||||
toEjml().origin,
|
||||
elementAlgebra.one,
|
||||
other.toEjml().origin,
|
||||
out,${
|
||||
if (isDense) "" else
|
||||
"""
|
||||
null,
|
||||
null,"""
|
||||
}
|
||||
)
|
||||
|
||||
return out.wrapVector()
|
||||
}
|
||||
|
||||
public override fun Point<${type}>.minus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||
val out = ${ejmlMatrixType}(1, 1)
|
||||
|
||||
CommonOps_${ops}.add(
|
||||
elementAlgebra.one,
|
||||
toEjml().origin,
|
||||
elementAlgebra { -one },
|
||||
other.toEjml().origin,
|
||||
out,${
|
||||
if (isDense) "" else
|
||||
"""
|
||||
null,
|
||||
null,"""
|
||||
}
|
||||
)
|
||||
|
||||
return out.wrapVector()
|
||||
}
|
||||
|
||||
public override fun ${type}.times(m: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> = m * this
|
||||
|
||||
public override fun Point<${type}>.times(value: ${type}): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||
val res = ${ejmlMatrixType}(1, 1)
|
||||
CommonOps_${ops}.scale(value, toEjml().origin, res)
|
||||
return res.wrapVector()
|
||||
}
|
||||
|
||||
public override fun ${type}.times(v: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> = v * this
|
||||
|
||||
@UnstableKMathAPI
|
||||
public override fun <F : StructureFeature> getFeature(structure: Matrix<${type}>, type: KClass<out F>): F? {
|
||||
structure.getFeature(type)?.let { return it }
|
||||
val origin = structure.toEjml().origin
|
||||
|
||||
return when (type) {
|
||||
${
|
||||
if (isDense)
|
||||
""" InverseMatrixFeature::class -> object : InverseMatrixFeature<${type}> {
|
||||
override val inverse: Matrix<${type}> by lazy {
|
||||
val res = origin.copy()
|
||||
CommonOps_${ops}.invert(res)
|
||||
res.wrapMatrix()
|
||||
}
|
||||
}
|
||||
|
||||
DeterminantFeature::class -> object : DeterminantFeature<${type}> {
|
||||
override val determinant: $type by lazy { CommonOps_${ops}.det(origin) }
|
||||
}
|
||||
|
||||
SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<${type}> {
|
||||
private val svd by lazy {
|
||||
DecompositionFactory_${ops}.svd(origin.numRows, origin.numCols, true, true, false)
|
||||
.apply { decompose(origin.copy()) }
|
||||
}
|
||||
|
||||
override val u: Matrix<${type}> by lazy { svd.getU(null, false).wrapMatrix() }
|
||||
override val s: Matrix<${type}> by lazy { svd.getW(null).wrapMatrix() }
|
||||
override val v: Matrix<${type}> by lazy { svd.getV(null, false).wrapMatrix() }
|
||||
override val singularValues: Point<${type}> by lazy { ${type}Buffer(svd.singularValues) }
|
||||
}
|
||||
|
||||
QRDecompositionFeature::class -> object : QRDecompositionFeature<${type}> {
|
||||
private val qr by lazy {
|
||||
DecompositionFactory_${ops}.qr().apply { decompose(origin.copy()) }
|
||||
}
|
||||
|
||||
override val q: Matrix<${type}> by lazy {
|
||||
qr.getQ(null, false).wrapMatrix() + OrthogonalFeature
|
||||
}
|
||||
|
||||
override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix() + UFeature }
|
||||
}
|
||||
|
||||
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<${type}> {
|
||||
override val l: Matrix<${type}> by lazy {
|
||||
val cholesky =
|
||||
DecompositionFactory_${ops}.chol(structure.rowNum, true).apply { decompose(origin.copy()) }
|
||||
|
||||
cholesky.getT(null).wrapMatrix() + LFeature
|
||||
}
|
||||
}
|
||||
|
||||
LupDecompositionFeature::class -> object : LupDecompositionFeature<${type}> {
|
||||
private val lup by lazy {
|
||||
DecompositionFactory_${ops}.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) }
|
||||
}
|
||||
|
||||
override val l: Matrix<${type}> by lazy {
|
||||
lup.getLower(null).wrapMatrix() + LFeature
|
||||
}
|
||||
|
||||
override val u: Matrix<${type}> by lazy {
|
||||
lup.getUpper(null).wrapMatrix() + UFeature
|
||||
}
|
||||
|
||||
override val p: Matrix<${type}> by lazy { lup.getRowPivot(null).wrapMatrix() }
|
||||
}""" else """ QRDecompositionFeature::class -> object : QRDecompositionFeature<$type> {
|
||||
private val qr by lazy {
|
||||
DecompositionFactory_${ops}.qr(FillReducing.NONE).apply { decompose(origin.copy()) }
|
||||
}
|
||||
|
||||
override val q: Matrix<${type}> by lazy {
|
||||
qr.getQ(null, false).wrapMatrix() + OrthogonalFeature
|
||||
}
|
||||
|
||||
override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix() + UFeature }
|
||||
}
|
||||
|
||||
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<${type}> {
|
||||
override val l: Matrix<${type}> by lazy {
|
||||
val cholesky =
|
||||
DecompositionFactory_${ops}.cholesky().apply { decompose(origin.copy()) }
|
||||
|
||||
(cholesky.getT(null) as ${ejmlMatrixParentTypeMatrix}).wrapMatrix() + LFeature
|
||||
}
|
||||
}
|
||||
|
||||
LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object :
|
||||
LUDecompositionFeature<${type}>, DeterminantFeature<${type}>, InverseMatrixFeature<${type}> {
|
||||
private val lu by lazy {
|
||||
DecompositionFactory_${ops}.lu(FillReducing.NONE).apply { decompose(origin.copy()) }
|
||||
}
|
||||
|
||||
override val l: Matrix<${type}> by lazy {
|
||||
lu.getLower(null).wrapMatrix() + LFeature
|
||||
}
|
||||
|
||||
override val u: Matrix<${type}> by lazy {
|
||||
lu.getUpper(null).wrapMatrix() + UFeature
|
||||
}
|
||||
|
||||
override val inverse: Matrix<${type}> by lazy {
|
||||
var a = origin
|
||||
val inverse = ${ejmlMatrixDenseType}(1, 1)
|
||||
val solver = LinearSolverFactory_${ops}.lu(FillReducing.NONE)
|
||||
if (solver.modifiesA()) a = a.copy()
|
||||
val i = CommonOps_${denseOps}.identity(a.numRows)
|
||||
solver.solve(i, inverse)
|
||||
inverse.wrapMatrix()
|
||||
}
|
||||
|
||||
override val determinant: $type by lazy { elementAlgebra.number(lu.computeDeterminant().real) }
|
||||
}"""
|
||||
}
|
||||
|
||||
else -> null
|
||||
}?.let(type::cast)
|
||||
}
|
||||
|
||||
/**
|
||||
* Solves for *x* in the following equation: *x = [a] <sup>-1</sup> · [b]*.
|
||||
*
|
||||
* @param a the base matrix.
|
||||
* @param b n by p matrix.
|
||||
* @return the solution for *x* that is n by p.
|
||||
*/
|
||||
public fun solve(a: Matrix<${type}>, b: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||
val res = ${ejmlMatrixType}(1, 1)
|
||||
CommonOps_${ops}.solve(${ejmlMatrixType}(a.toEjml().origin), ${ejmlMatrixType}(b.toEjml().origin), res)
|
||||
return res.wrapMatrix()
|
||||
}
|
||||
|
||||
/**
|
||||
* Solves for *x* in the following equation: *x = [a] <sup>-1</sup> · [b]*.
|
||||
*
|
||||
* @param a the base matrix.
|
||||
* @param b n by p vector.
|
||||
* @return the solution for *x* that is n by p.
|
||||
*/
|
||||
public fun solve(a: Matrix<${type}>, b: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||
val res = ${ejmlMatrixType}(1, 1)
|
||||
CommonOps_${ops}.solve(${ejmlMatrixType}(a.toEjml().origin), ${ejmlMatrixType}(b.toEjml().origin), res)
|
||||
return Ejml${type}Vector(res)
|
||||
}
|
||||
}"""
|
||||
appendLine(text)
|
||||
appendLine()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates routine EJML classes.
|
||||
*/
|
||||
fun ejmlCodegen(outputFile: String): Unit = File(outputFile).run {
|
||||
parentFile.mkdirs()
|
||||
|
||||
writer().use {
|
||||
it.appendLine("/*")
|
||||
it.appendLine(" * Copyright 2018-2021 KMath contributors.")
|
||||
it.appendLine(" * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.")
|
||||
it.appendLine(" */")
|
||||
it.appendLine()
|
||||
it.appendLine("/* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */")
|
||||
it.appendLine()
|
||||
it.appendLine("package space.kscience.kmath.ejml")
|
||||
it.appendLine()
|
||||
it.appendLine("""import org.ejml.data.*
|
||||
import org.ejml.dense.row.CommonOps_DDRM
|
||||
import org.ejml.dense.row.CommonOps_FDRM
|
||||
import org.ejml.dense.row.factory.DecompositionFactory_DDRM
|
||||
import org.ejml.dense.row.factory.DecompositionFactory_FDRM
|
||||
import org.ejml.sparse.FillReducing
|
||||
import org.ejml.sparse.csc.CommonOps_DSCC
|
||||
import org.ejml.sparse.csc.CommonOps_FSCC
|
||||
import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC
|
||||
import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC
|
||||
import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC
|
||||
import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC
|
||||
import space.kscience.kmath.linear.*
|
||||
import space.kscience.kmath.linear.Matrix
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.StructureFeature
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.FloatField
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.structures.DoubleBuffer
|
||||
import space.kscience.kmath.structures.FloatBuffer
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.cast""")
|
||||
it.appendLine()
|
||||
it.appendEjmlVector("Double", "DMatrix")
|
||||
it.appendEjmlVector("Float", "FMatrix")
|
||||
it.appendEjmlMatrix("Double", "DMatrix")
|
||||
it.appendEjmlMatrix("Float", "FMatrix")
|
||||
it.appendEjmlLinearSpace("Double", "DoubleField", "DMatrix", "DMatrixRMaj", "DMatrixRMaj", "DDRM", "DDRM", true)
|
||||
it.appendEjmlLinearSpace("Float", "FloatField", "FMatrix", "FMatrixRMaj", "FMatrixRMaj", "FDRM", "FDRM", true)
|
||||
|
||||
it.appendEjmlLinearSpace(
|
||||
type = "Double",
|
||||
kmathAlgebra = "DoubleField",
|
||||
ejmlMatrixParentTypeMatrix = "DMatrix",
|
||||
ejmlMatrixType = "DMatrixSparseCSC",
|
||||
ejmlMatrixDenseType = "DMatrixRMaj",
|
||||
ops = "DSCC",
|
||||
denseOps = "DDRM",
|
||||
isDense = false,
|
||||
)
|
||||
|
||||
it.appendEjmlLinearSpace(
|
||||
type = "Float",
|
||||
kmathAlgebra = "FloatField",
|
||||
ejmlMatrixParentTypeMatrix = "FMatrix",
|
||||
ejmlMatrixType = "FMatrixSparseCSC",
|
||||
ejmlMatrixDenseType = "FMatrixRMaj",
|
||||
ops = "FSCC",
|
||||
denseOps = "FDRM",
|
||||
isDense = false,
|
||||
)
|
||||
}
|
||||
}
|
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
|
||||
repositories {
|
||||
maven { url 'https://repo.kotlin.link' }
|
||||
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -18,8 +17,7 @@ dependencies {
|
||||
```kotlin
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
2
docs/templates/README-TEMPLATE.md
vendored
2
docs/templates/README-TEMPLATE.md
vendored
@ -40,7 +40,7 @@ KMath is a modular library. Different modules provide different features with di
|
||||
|
||||
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
|
||||
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations.
|
||||
* **DEVELOPMENT**. API breaking genrally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
||||
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
||||
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
|
||||
|
||||
<!--Current feature list is [here](/docs/features.md)-->
|
||||
|
@ -4,14 +4,11 @@ plugins {
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://clojars.org/repo")
|
||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||
maven("https://jitpack.io")
|
||||
maven{
|
||||
setUrl("http://logicrunch.research.it.uu.se/maven/")
|
||||
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers")
|
||||
maven("http://logicrunch.research.it.uu.se/maven") {
|
||||
isAllowInsecureProtocol = true
|
||||
}
|
||||
}
|
||||
@ -28,6 +25,7 @@ dependencies {
|
||||
implementation(project(":kmath-dimensions"))
|
||||
implementation(project(":kmath-ejml"))
|
||||
implementation(project(":kmath-nd4j"))
|
||||
implementation(project(":kmath-tensors"))
|
||||
|
||||
implementation(project(":kmath-for-real"))
|
||||
|
||||
@ -45,7 +43,7 @@ dependencies {
|
||||
|
||||
implementation("org.slf4j:slf4j-simple:1.7.30")
|
||||
// plotting
|
||||
implementation("space.kscience:plotlykt-server:0.4.0-dev-2")
|
||||
implementation("space.kscience:plotlykt-server:0.4.0")
|
||||
}
|
||||
|
||||
kotlin.sourceSets.all {
|
||||
@ -59,7 +57,7 @@ kotlin.sourceSets.all {
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions{
|
||||
jvmTarget = "11"
|
||||
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
|
||||
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
package space.kscience.kmath.ast
|
||||
|
||||
import space.kscience.kmath.expressions.MstField
|
||||
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||
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.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
|
@ -8,8 +8,8 @@ package space.kscience.kmath.ast
|
||||
import space.kscience.kmath.asm.compileToExpression
|
||||
import space.kscience.kmath.expressions.derivative
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.expressions.symbol
|
||||
import space.kscience.kmath.kotlingrad.toDiffExpression
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
|
||||
/**
|
||||
|
@ -10,7 +10,7 @@ import kotlinx.html.h3
|
||||
import space.kscience.kmath.commons.optimization.chiSquared
|
||||
import space.kscience.kmath.commons.optimization.minimize
|
||||
import space.kscience.kmath.distributions.NormalDistribution
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.expressions.symbol
|
||||
import space.kscience.kmath.optimization.FunctionOptimization
|
||||
import space.kscience.kmath.optimization.OptimizationResult
|
||||
import space.kscience.kmath.real.DoubleVector
|
||||
|
@ -5,7 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.integration.process
|
||||
import space.kscience.kmath.integration.gaussIntegrator
|
||||
import space.kscience.kmath.integration.integrate
|
||||
import space.kscience.kmath.integration.value
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import kotlin.math.pow
|
||||
@ -15,7 +16,7 @@ fun main() {
|
||||
val function: UnivariateFunction<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 }
|
||||
|
||||
//get the result of the integration
|
||||
val result = DoubleField.process(0.0..10.0, function = function)
|
||||
val result = DoubleField.gaussIntegrator.integrate(0.0..10.0, function = function)
|
||||
|
||||
//the value is nullable because in some cases the integration could not succeed
|
||||
println(result.value)
|
||||
|
@ -0,0 +1,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.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.interpolation.SplineInterpolator
|
||||
import space.kscience.kmath.interpolation.interpolatePolynomials
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.structures.DoubleBuffer
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.UnstablePlotlyAPI
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.functionXY
|
||||
import space.kscience.plotly.scatter
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.sin
|
||||
|
||||
@OptIn(UnstablePlotlyAPI::class)
|
||||
fun main() {
|
||||
val data = (0..10).map {
|
||||
val x = it.toDouble() / 5 * PI
|
||||
x to sin(x)
|
||||
}
|
||||
|
||||
val polynomial: PiecewisePolynomial<Double> = SplineInterpolator(
|
||||
DoubleField, ::DoubleBuffer
|
||||
).interpolatePolynomials(data)
|
||||
|
||||
val function = polynomial.asFunction(DoubleField, 0.0)
|
||||
|
||||
val cmInterpolate = org.apache.commons.math3.analysis.interpolation.SplineInterpolator().interpolate(
|
||||
data.map { it.first }.toDoubleArray(),
|
||||
data.map { it.second }.toDoubleArray()
|
||||
)
|
||||
|
||||
Plotly.plot {
|
||||
scatter {
|
||||
name = "interpolated"
|
||||
x.numbers = data.map { it.first }
|
||||
y.numbers = x.doubles.map { function(it) }
|
||||
}
|
||||
scatter {
|
||||
name = "original"
|
||||
functionXY(0.0..(2 * PI), 0.1) { sin(it) }
|
||||
}
|
||||
scatter {
|
||||
name = "cm"
|
||||
x.numbers = data.map { it.first }
|
||||
y.numbers = x.doubles.map { cmInterpolate.value(it) }
|
||||
}
|
||||
}.makeFile()
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.interpolation.SplineInterpolator
|
||||
import space.kscience.kmath.interpolation.interpolatePolynomials
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.real.step
|
||||
import space.kscience.kmath.structures.map
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.UnstablePlotlyAPI
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.functionXY
|
||||
import space.kscience.plotly.scatter
|
||||
|
||||
@OptIn(UnstablePlotlyAPI::class)
|
||||
fun main() {
|
||||
val function: UnivariateFunction<Double> = { x ->
|
||||
if (x in 30.0..50.0) {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
val xs = 0.0..100.0 step 0.5
|
||||
val ys = xs.map(function)
|
||||
|
||||
val polynomial: PiecewisePolynomial<Double> = SplineInterpolator.double.interpolatePolynomials(xs, ys)
|
||||
|
||||
val polyFunction = polynomial.asFunction(DoubleField, 0.0)
|
||||
|
||||
Plotly.plot {
|
||||
scatter {
|
||||
name = "interpolated"
|
||||
functionXY(25.0..55.0, 0.1) { polyFunction(it) }
|
||||
}
|
||||
scatter {
|
||||
name = "original"
|
||||
functionXY(25.0..55.0, 0.1) { function(it) }
|
||||
}
|
||||
}.makeFile()
|
||||
}
|
@ -5,7 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.integration.process
|
||||
import space.kscience.kmath.integration.gaussIntegrator
|
||||
import space.kscience.kmath.integration.integrate
|
||||
import space.kscience.kmath.integration.value
|
||||
import space.kscience.kmath.nd.StructureND
|
||||
import space.kscience.kmath.nd.nd
|
||||
@ -24,7 +25,7 @@ fun main(): Unit = DoubleField {
|
||||
val function: (Double) -> StructureND<Double> = { x: Double -> 3 * number(x).pow(2) + 2 * diagonal(x) + 1 }
|
||||
|
||||
//get the result of the integration
|
||||
val result = process(0.0..10.0, function = function)
|
||||
val result = gaussIntegrator.integrate(0.0..10.0, function = function)
|
||||
|
||||
//the value is nullable because in some cases the integration could not succeed
|
||||
println(result.value)
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import org.nd4j.linalg.factory.Nd4j
|
||||
import space.kscience.kmath.nd.*
|
||||
@ -22,6 +23,7 @@ internal inline fun measureAndPrint(title: String, block: () -> Unit) {
|
||||
println("$title completed in $time millis")
|
||||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun main() {
|
||||
// initializing Nd4j
|
||||
Nd4j.zeros(0)
|
||||
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.tensors
|
||||
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
||||
|
||||
|
||||
// Dataset normalization
|
||||
|
||||
fun main() = BroadcastDoubleTensorAlgebra { // work in context with broadcast methods
|
||||
// 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,93 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.tensors
|
||||
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
||||
import space.kscience.kmath.tensors.core.DoubleTensor
|
||||
|
||||
// solving linear system with LUP decomposition
|
||||
|
||||
fun main() = BroadcastDoubleTensorAlgebra {// work in context with linear operations
|
||||
|
||||
// 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,239 @@
|
||||
/*
|
||||
* 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 = 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)}")
|
||||
}
|
||||
}
|
74
examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt
Normal file
74
examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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(): Unit = BroadcastDoubleTensorAlgebra { // work in context with broadcast methods
|
||||
val seed = 100500L
|
||||
|
||||
// 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")
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
# Module kmath-ast
|
||||
|
||||
Abstract syntax tree expression representation and related optimizations.
|
||||
Performance and visualization extensions to MST API.
|
||||
|
||||
- [expression-language](src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||
- [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
|
||||
@ -10,30 +10,28 @@ Abstract syntax tree expression representation and related optimizations.
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-7`.
|
||||
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-11`.
|
||||
|
||||
**Gradle:**
|
||||
```gradle
|
||||
repositories {
|
||||
maven { url 'https://repo.kotlin.link' }
|
||||
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'space.kscience:kmath-ast:0.3.0-dev-7'
|
||||
implementation 'space.kscience:kmath-ast:0.3.0-dev-11'
|
||||
}
|
||||
```
|
||||
**Gradle Kotlin DSL:**
|
||||
```kotlin
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:kmath-ast:0.3.0-dev-7")
|
||||
implementation("space.kscience:kmath-ast:0.3.0-dev-11")
|
||||
}
|
||||
```
|
||||
|
||||
@ -41,21 +39,26 @@ dependencies {
|
||||
|
||||
### On JVM
|
||||
|
||||
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds
|
||||
a special implementation of `Expression<T>` with implemented `invoke` function.
|
||||
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a
|
||||
special implementation of `Expression<T>` with implemented `invoke` function.
|
||||
|
||||
For example, the following builder:
|
||||
|
||||
```kotlin
|
||||
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
|
||||
package space.kscience.kmath.asm.generated;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import kotlin.jvm.functions.Function2;
|
||||
import space.kscience.kmath.asm.internal.MapIntrinsics;
|
||||
import space.kscience.kmath.expressions.Expression;
|
||||
@ -65,7 +68,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
||||
private final Object[] constants;
|
||||
|
||||
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) {
|
||||
@ -77,8 +80,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
||||
|
||||
#### Known issues
|
||||
|
||||
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid
|
||||
class loading overhead.
|
||||
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class
|
||||
loading overhead.
|
||||
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
|
||||
|
||||
### On JS
|
||||
@ -86,6 +89,10 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
||||
A similar feature is also available on JS.
|
||||
|
||||
```kotlin
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.estree.*
|
||||
|
||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||
```
|
||||
|
||||
@ -93,18 +100,22 @@ The code above returns expression implemented with such a JS function:
|
||||
|
||||
```js
|
||||
var executable = function (constants, arguments) {
|
||||
return constants[1](constants[0](arguments, "x"), 2);
|
||||
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:
|
||||
An example of emitted Wasm IR in the form of WAT:
|
||||
|
||||
```lisp
|
||||
(func $executable (param $0 f64) (result f64)
|
||||
@ -129,9 +140,11 @@ Example usage:
|
||||
```kotlin
|
||||
import space.kscience.kmath.ast.*
|
||||
import space.kscience.kmath.ast.rendering.*
|
||||
import space.kscience.kmath.misc.*
|
||||
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
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 latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax)
|
||||
println("LaTeX:")
|
||||
@ -145,13 +158,78 @@ public fun main() {
|
||||
|
||||
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
|
||||
<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>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
It is also possible to create custom algorithms of render, and even add support of other markup languages
|
||||
(see API reference).
|
||||
|
@ -18,6 +18,10 @@ kotlin.js {
|
||||
}
|
||||
|
||||
kotlin.sourceSets {
|
||||
filter { it.name.contains("test", true) }
|
||||
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
|
||||
.forEach { it.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") }
|
||||
|
||||
commonMain {
|
||||
dependencies {
|
||||
api("com.github.h0tk3y.betterParse:better-parse:0.4.2")
|
||||
@ -54,7 +58,7 @@ tasks.dokkaHtml {
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||
|
||||
feature(
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Module kmath-ast
|
||||
|
||||
Abstract syntax tree expression representation and related optimizations.
|
||||
Performance and visualization extensions to MST API.
|
||||
|
||||
${features}
|
||||
|
||||
@ -10,21 +10,26 @@ ${artifact}
|
||||
|
||||
### On JVM
|
||||
|
||||
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds
|
||||
a special implementation of `Expression<T>` with implemented `invoke` function.
|
||||
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a
|
||||
special implementation of `Expression<T>` with implemented `invoke` function.
|
||||
|
||||
For example, the following builder:
|
||||
|
||||
```kotlin
|
||||
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
|
||||
package space.kscience.kmath.asm.generated;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import kotlin.jvm.functions.Function2;
|
||||
import space.kscience.kmath.asm.internal.MapIntrinsics;
|
||||
import space.kscience.kmath.expressions.Expression;
|
||||
@ -34,7 +39,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
||||
private final Object[] constants;
|
||||
|
||||
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) {
|
||||
@ -46,8 +51,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
||||
|
||||
#### Known issues
|
||||
|
||||
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid
|
||||
class loading overhead.
|
||||
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class
|
||||
loading overhead.
|
||||
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
|
||||
|
||||
### On JS
|
||||
@ -55,6 +60,10 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
||||
A similar feature is also available on JS.
|
||||
|
||||
```kotlin
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.estree.*
|
||||
|
||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
||||
```
|
||||
|
||||
@ -62,18 +71,22 @@ The code above returns expression implemented with such a JS function:
|
||||
|
||||
```js
|
||||
var executable = function (constants, arguments) {
|
||||
return constants[1](constants[0](arguments, "x"), 2);
|
||||
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:
|
||||
An example of emitted Wasm IR in the form of WAT:
|
||||
|
||||
```lisp
|
||||
(func \$executable (param \$0 f64) (result f64)
|
||||
@ -98,9 +111,11 @@ Example usage:
|
||||
```kotlin
|
||||
import space.kscience.kmath.ast.*
|
||||
import space.kscience.kmath.ast.rendering.*
|
||||
import space.kscience.kmath.misc.*
|
||||
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
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 latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax)
|
||||
println("LaTeX:")
|
||||
@ -114,13 +129,78 @@ public fun main() {
|
||||
|
||||
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
|
||||
<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>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
It is also possible to create custom algorithms of render, and even add support of other markup languages
|
||||
(see API reference).
|
||||
|
@ -17,6 +17,7 @@ import com.github.h0tk3y.betterParse.lexer.regexToken
|
||||
import com.github.h0tk3y.betterParse.parser.ParseResult
|
||||
import com.github.h0tk3y.betterParse.parser.Parser
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.expressions.StringSymbol
|
||||
import space.kscience.kmath.operations.FieldOperations
|
||||
import space.kscience.kmath.operations.GroupOperations
|
||||
import space.kscience.kmath.operations.PowerOperations
|
||||
@ -29,7 +30,6 @@ import space.kscience.kmath.operations.RingOperations
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
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 id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*".toRegex())
|
||||
private val lpar: Token by literalToken("(")
|
||||
@ -43,7 +43,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
|
||||
private val ws: Token by regexToken("\\s+".toRegex(), ignore = true)
|
||||
|
||||
private val number: Parser<MST> by num use { MST.Numeric(text.toDouble()) }
|
||||
private val singular: Parser<MST> by id use { MST.Symbolic(text) }
|
||||
private val singular: Parser<MST> by id use { StringSymbol(text) }
|
||||
|
||||
private val unaryFunction: Parser<MST> by (id and -lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
|
||||
.map { (id, term) -> MST.Unary(id.text, term) }
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
|
||||
/**
|
||||
* [SyntaxRenderer] implementation for LaTeX.
|
||||
*
|
||||
@ -23,6 +25,7 @@ package space.kscience.kmath.ast.rendering
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public object LatexSyntaxRenderer : SyntaxRenderer {
|
||||
public override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
|
||||
fun render(syntax: MathSyntax) = render(syntax, output)
|
||||
@ -115,7 +118,11 @@ public object LatexSyntaxRenderer : SyntaxRenderer {
|
||||
render(node.right)
|
||||
}
|
||||
|
||||
is FractionSyntax -> {
|
||||
is FractionSyntax -> if (node.infix) {
|
||||
render(node.left)
|
||||
append('/')
|
||||
render(node.right)
|
||||
} else {
|
||||
append("\\frac{")
|
||||
render(node.left)
|
||||
append("}{")
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
|
||||
/**
|
||||
* [SyntaxRenderer] implementation for MathML.
|
||||
*
|
||||
@ -12,14 +14,18 @@ package space.kscience.kmath.ast.rendering
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public object MathMLSyntaxRenderer : SyntaxRenderer {
|
||||
public override fun render(node: MathSyntax, output: Appendable) {
|
||||
output.append("<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>")
|
||||
render0(node, output)
|
||||
output.append("<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>")
|
||||
renderPart(node, output)
|
||||
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 = {}) {
|
||||
append('<')
|
||||
append(tagName)
|
||||
@ -44,7 +50,7 @@ public object MathMLSyntaxRenderer : SyntaxRenderer {
|
||||
append('>')
|
||||
}
|
||||
|
||||
fun render(syntax: MathSyntax) = render0(syntax, output)
|
||||
fun render(syntax: MathSyntax) = renderPart(syntax, output)
|
||||
|
||||
when (node) {
|
||||
is NumberSyntax -> tag("mn") { append(node.string) }
|
||||
@ -127,14 +133,13 @@ public object MathMLSyntaxRenderer : SyntaxRenderer {
|
||||
render(node.right)
|
||||
}
|
||||
|
||||
is FractionSyntax -> tag("mfrac") {
|
||||
tag("mrow") {
|
||||
render(node.left)
|
||||
}
|
||||
|
||||
tag("mrow") {
|
||||
render(node.right)
|
||||
}
|
||||
is FractionSyntax -> if (node.infix) {
|
||||
render(node.left)
|
||||
tag("mo") { append('/') }
|
||||
render(node.right)
|
||||
} else tag("mfrac") {
|
||||
tag("mrow") { render(node.left) }
|
||||
tag("mrow") { render(node.right) }
|
||||
}
|
||||
|
||||
is RadicalWithIndexSyntax -> tag("mroot") {
|
||||
|
@ -6,12 +6,14 @@
|
||||
package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
|
||||
/**
|
||||
* Renders [MST] to [MathSyntax].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun interface MathRenderer {
|
||||
/**
|
||||
* Renders [MST] to [MathSyntax].
|
||||
@ -25,6 +27,7 @@ public fun interface MathRenderer {
|
||||
* @property features The applied features.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public open class FeaturedMathRenderer(public val features: List<RenderFeature>) : MathRenderer {
|
||||
public override fun render(mst: MST): MathSyntax {
|
||||
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.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public open class FeaturedMathRendererWithPostProcess(
|
||||
features: List<RenderFeature>,
|
||||
public val stages: List<PostProcessStage>,
|
||||
@ -85,6 +89,7 @@ public open class FeaturedMathRendererWithPostProcess(
|
||||
SquareRoot.Default,
|
||||
Exponent.Default,
|
||||
InverseTrigonometricOperations.Default,
|
||||
InverseHyperbolicOperations.Default,
|
||||
|
||||
// Fallback option for unknown operations - printing them as operator
|
||||
BinaryOperator.Default,
|
||||
@ -101,6 +106,7 @@ public open class FeaturedMathRendererWithPostProcess(
|
||||
),
|
||||
listOf(
|
||||
BetterExponent,
|
||||
BetterFraction,
|
||||
SimplifyParentheses.Default,
|
||||
BetterMultiplication,
|
||||
),
|
||||
|
@ -5,11 +5,14 @@
|
||||
|
||||
package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
|
||||
/**
|
||||
* Mathematical typography syntax node.
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public sealed class MathSyntax {
|
||||
/**
|
||||
* The parent node of this syntax node.
|
||||
@ -22,6 +25,7 @@ public sealed class MathSyntax {
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public sealed class TerminalSyntax : MathSyntax()
|
||||
|
||||
/**
|
||||
@ -29,6 +33,7 @@ public sealed class TerminalSyntax : MathSyntax()
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public sealed class OperationSyntax : MathSyntax() {
|
||||
/**
|
||||
* The operation token.
|
||||
@ -41,6 +46,7 @@ public sealed class OperationSyntax : MathSyntax() {
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public sealed class UnarySyntax : OperationSyntax() {
|
||||
/**
|
||||
* The operand of this node.
|
||||
@ -53,6 +59,7 @@ public sealed class UnarySyntax : OperationSyntax() {
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public sealed class BinarySyntax : OperationSyntax() {
|
||||
/**
|
||||
* The left-hand side operand.
|
||||
@ -71,6 +78,7 @@ public sealed class BinarySyntax : OperationSyntax() {
|
||||
* @property string The digits of number.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
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.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class SymbolSyntax(public var string: String) : TerminalSyntax()
|
||||
|
||||
/**
|
||||
@ -89,14 +98,16 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax()
|
||||
* @see UnaryOperatorSyntax
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
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.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() {
|
||||
/**
|
||||
* 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.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class OperandSyntax(
|
||||
public val operand: MathSyntax,
|
||||
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.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class UnaryOperatorSyntax(
|
||||
public override val operation: String,
|
||||
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
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class UnaryPlusSyntax(
|
||||
public override val operation: String,
|
||||
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
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class UnaryMinusSyntax(
|
||||
public override val operation: String,
|
||||
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.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class RadicalSyntax(
|
||||
public override val operation: String,
|
||||
public override val operand: MathSyntax,
|
||||
@ -197,6 +213,7 @@ public data class RadicalSyntax(
|
||||
* (*e<sup>x</sup>*).
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class ExponentSyntax(
|
||||
public override val operation: String,
|
||||
public override val operand: OperandSyntax,
|
||||
@ -208,12 +225,13 @@ public data class ExponentSyntax(
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a syntax node with superscript (usually, for exponentiation).
|
||||
* Represents a syntax node with superscript (*x<sup>2</sup>*).
|
||||
*
|
||||
* @property left The node.
|
||||
* @property right The superscript.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class SuperscriptSyntax(
|
||||
public override val operation: String,
|
||||
public override val left: MathSyntax,
|
||||
@ -226,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 right The subscript.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class SubscriptSyntax(
|
||||
public override val operation: String,
|
||||
public override val left: MathSyntax,
|
||||
@ -244,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.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class BinaryOperatorSyntax(
|
||||
public override val operation: String,
|
||||
public var prefix: MathSyntax,
|
||||
@ -262,12 +282,13 @@ public data class BinaryOperatorSyntax(
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents binary, infix addition.
|
||||
* Represents binary, infix addition (*42 + 42*).
|
||||
*
|
||||
* @param left The augend.
|
||||
* @param right The addend.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class BinaryPlusSyntax(
|
||||
public override val operation: String,
|
||||
public override val left: OperandSyntax,
|
||||
@ -280,12 +301,13 @@ public data class BinaryPlusSyntax(
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents binary, infix subtraction.
|
||||
* Represents binary, infix subtraction (*42 - 42*).
|
||||
*
|
||||
* @param left The minuend.
|
||||
* @param right The subtrahend.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class BinaryMinusSyntax(
|
||||
public override val operation: String,
|
||||
public override val left: OperandSyntax,
|
||||
@ -302,12 +324,15 @@ public data class BinaryMinusSyntax(
|
||||
*
|
||||
* @property left The numerator.
|
||||
* @property right The denominator.
|
||||
* @property infix Whether infix (*1 / 2*) or normal (*½*) fraction should be made.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class FractionSyntax(
|
||||
public override val operation: String,
|
||||
public override val left: MathSyntax,
|
||||
public override val right: MathSyntax,
|
||||
public override val left: OperandSyntax,
|
||||
public override val right: OperandSyntax,
|
||||
public var infix: Boolean,
|
||||
) : BinarySyntax() {
|
||||
init {
|
||||
left.parent = this
|
||||
@ -316,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 right The radicand.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class RadicalWithIndexSyntax(
|
||||
public override val operation: String,
|
||||
public override val left: MathSyntax,
|
||||
@ -334,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 right The multiplier.
|
||||
* @property times whether the times (×) symbol should be used.
|
||||
* @property times Whether the times (×) symbol should be used.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public data class MultiplicationSyntax(
|
||||
public override val operation: String,
|
||||
public override val left: OperandSyntax,
|
||||
|
@ -5,12 +5,15 @@
|
||||
|
||||
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
|
||||
* involve traversal of MathSyntax with handling each its subtype.
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun interface SyntaxRenderer {
|
||||
/**
|
||||
* Renders the [MathSyntax] to [output].
|
||||
@ -23,6 +26,7 @@ public fun interface SyntaxRenderer {
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String {
|
||||
val sb = StringBuilder()
|
||||
render(node, sb)
|
||||
|
@ -7,6 +7,8 @@ package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@ -15,11 +17,11 @@ import kotlin.reflect.KClass
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public object PrintSymbolic : RenderFeature {
|
||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
||||
if (node !is MST.Symbolic) return null
|
||||
return SymbolSyntax(string = node.value)
|
||||
}
|
||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? =
|
||||
if (node !is Symbol) null
|
||||
else SymbolSyntax(string = node.identity)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -27,35 +29,38 @@ public object PrintSymbolic : RenderFeature {
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public object PrintNumeric : RenderFeature {
|
||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
||||
if (node !is MST.Numeric) return null
|
||||
return NumberSyntax(string = node.value.toString())
|
||||
}
|
||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): NumberSyntax? = if (node !is MST.Numeric)
|
||||
null
|
||||
else
|
||||
NumberSyntax(string = node.value.toString())
|
||||
}
|
||||
|
||||
private fun printSignedNumberString(s: String): MathSyntax {
|
||||
if (s.startsWith('-'))
|
||||
return UnaryMinusSyntax(
|
||||
operation = GroupOperations.MINUS_OPERATION,
|
||||
operand = OperandSyntax(
|
||||
operand = NumberSyntax(string = s.removePrefix("-")),
|
||||
parentheses = true,
|
||||
),
|
||||
)
|
||||
|
||||
return NumberSyntax(string = s)
|
||||
}
|
||||
@UnstableKMathAPI
|
||||
private fun printSignedNumberString(s: String): MathSyntax = if (s.startsWith('-'))
|
||||
UnaryMinusSyntax(
|
||||
operation = GroupOperations.MINUS_OPERATION,
|
||||
operand = OperandSyntax(
|
||||
operand = NumberSyntax(string = s.removePrefix("-")),
|
||||
parentheses = true,
|
||||
),
|
||||
)
|
||||
else
|
||||
NumberSyntax(string = s)
|
||||
|
||||
/**
|
||||
* Special printing for numeric types which are printed in form of
|
||||
* *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*.
|
||||
*
|
||||
* @property types The suitable types.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature {
|
||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
||||
if (node !is MST.Numeric || node.value::class !in types) return null
|
||||
|
||||
val toString = when (val v = node.value) {
|
||||
is Float -> v.multiplatformToString()
|
||||
is Double -> v.multiplatformToString()
|
||||
@ -109,12 +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+*.
|
||||
*
|
||||
* @property types The suitable types.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature {
|
||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
||||
if (node !is MST.Numeric || node.value::class !in types) return null
|
||||
return printSignedNumberString(node.value.toString())
|
||||
}
|
||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
|
||||
if (node !is MST.Numeric || node.value::class !in types)
|
||||
null
|
||||
else
|
||||
printSignedNumberString(node.value.toString())
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
@ -129,12 +137,15 @@ public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : Re
|
||||
* Special printing for symbols meaning Pi.
|
||||
*
|
||||
* @property symbols The allowed symbols.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
|
||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
||||
if (node !is MST.Symbolic || node.value !in symbols) return null
|
||||
return SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI)
|
||||
}
|
||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? =
|
||||
if (node !is Symbol || node.identity !in symbols)
|
||||
null
|
||||
else
|
||||
SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
@ -149,17 +160,20 @@ public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
|
||||
* not [MST.Unary].
|
||||
*
|
||||
* @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 {
|
||||
/**
|
||||
* 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? {
|
||||
if (node !is MST.Unary || operations != null && node.operation !in operations) return null
|
||||
return render0(renderer, node)
|
||||
}
|
||||
public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
|
||||
if (node !is MST.Unary || operations != null && node.operation !in operations)
|
||||
null
|
||||
else
|
||||
renderUnary(renderer, node)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,169 +181,301 @@ public abstract class Unary(public val operations: Collection<String>?) : Render
|
||||
* not [MST.Binary].
|
||||
*
|
||||
* @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 {
|
||||
/**
|
||||
* 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? {
|
||||
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 override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryPlusSyntax(
|
||||
operation = node.operation,
|
||||
left = OperandSyntax(parent.render(node.left), true),
|
||||
right = OperandSyntax(parent.render(node.right), true),
|
||||
)
|
||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryPlusSyntax =
|
||||
BinaryPlusSyntax(
|
||||
operation = node.operation,
|
||||
left = OperandSyntax(parent.render(node.left), true),
|
||||
right = OperandSyntax(parent.render(node.right), true),
|
||||
)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The default instance configured with [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 override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryMinusSyntax(
|
||||
operation = node.operation,
|
||||
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
||||
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
|
||||
)
|
||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryMinusSyntax =
|
||||
BinaryMinusSyntax(
|
||||
operation = node.operation,
|
||||
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
||||
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
|
||||
)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The default instance configured with [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 override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax(
|
||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryPlusSyntax = UnaryPlusSyntax(
|
||||
operation = node.operation,
|
||||
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||
)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The default instance configured with [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 override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax(
|
||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryMinusSyntax = UnaryMinusSyntax(
|
||||
operation = node.operation,
|
||||
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||
)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The default instance configured with [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 override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax(
|
||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax(
|
||||
operation = node.operation,
|
||||
left = parent.render(node.left),
|
||||
right = parent.render(node.right),
|
||||
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
||||
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
|
||||
infix = true,
|
||||
)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The default instance configured with [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 override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryOperatorSyntax(
|
||||
operation = node.operation,
|
||||
prefix = OperatorNameSyntax(name = node.operation),
|
||||
left = parent.render(node.left),
|
||||
right = parent.render(node.right),
|
||||
)
|
||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryOperatorSyntax =
|
||||
BinaryOperatorSyntax(
|
||||
operation = node.operation,
|
||||
prefix = OperatorNameSyntax(name = node.operation),
|
||||
left = parent.render(node.left),
|
||||
right = parent.render(node.right),
|
||||
)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The default instance configured with `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 override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax(
|
||||
operation = node.operation,
|
||||
prefix = OperatorNameSyntax(node.operation),
|
||||
operand = OperandSyntax(parent.render(node.value), true),
|
||||
)
|
||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
|
||||
UnaryOperatorSyntax(
|
||||
operation = node.operation,
|
||||
prefix = OperatorNameSyntax(node.operation),
|
||||
operand = OperandSyntax(parent.render(node.value), true),
|
||||
)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The default instance configured with `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 override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = SuperscriptSyntax(
|
||||
operation = node.operation,
|
||||
left = OperandSyntax(parent.render(node.left), true),
|
||||
right = OperandSyntax(parent.render(node.right), true),
|
||||
)
|
||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): SuperscriptSyntax =
|
||||
SuperscriptSyntax(
|
||||
operation = node.operation,
|
||||
left = OperandSyntax(parent.render(node.left), true),
|
||||
right = OperandSyntax(parent.render(node.right), true),
|
||||
)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The default instance configured with [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 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))
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The default instance configured with [PowerOperations.SQRT_OPERATION].
|
||||
*/
|
||||
public val Default: SquareRoot = SquareRoot(setOf(PowerOperations.SQRT_OPERATION))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles unary nodes by producing [ExponentSyntax].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public class Exponent(operations: Collection<String>?) : Unary(operations) {
|
||||
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax(
|
||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): ExponentSyntax = ExponentSyntax(
|
||||
operation = node.operation,
|
||||
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||
useOperatorForm = true,
|
||||
)
|
||||
|
||||
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 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 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 {
|
||||
public val Default: Multiplication = Multiplication(setOf(
|
||||
RingOperations.TIMES_OPERATION,
|
||||
))
|
||||
/**
|
||||
* 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 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),
|
||||
)
|
||||
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(
|
||||
TrigonometricOperations.ACOS_OPERATION,
|
||||
TrigonometricOperations.ASIN_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.ASINH_OPERATION,
|
||||
ExponentialOperations.ATANH_OPERATION,
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package space.kscience.kmath.ast.rendering
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.FieldOperations
|
||||
import space.kscience.kmath.operations.GroupOperations
|
||||
import space.kscience.kmath.operations.PowerOperations
|
||||
@ -15,6 +16,7 @@ import space.kscience.kmath.operations.RingOperations
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage {
|
||||
public override fun perform(node: MathSyntax): Unit = when (node) {
|
||||
is NumberSyntax -> Unit
|
||||
@ -81,6 +83,75 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -88,6 +159,7 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage {
|
||||
private fun perform0(node: MathSyntax): Boolean {
|
||||
return when (node) {
|
||||
@ -99,7 +171,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt
|
||||
is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand)
|
||||
is UnaryPlusSyntax -> perform0(node.operand)
|
||||
is UnaryMinusSyntax -> perform0(node.operand)
|
||||
is RadicalSyntax -> perform0(node.operand)
|
||||
is RadicalSyntax -> true
|
||||
|
||||
is ExponentSyntax -> {
|
||||
val r = perform0(node.operand)
|
||||
@ -113,7 +185,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt
|
||||
is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right)
|
||||
is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right)
|
||||
is FractionSyntax -> true
|
||||
is RadicalWithIndexSyntax -> perform0(node.left) || perform0(node.right)
|
||||
is RadicalWithIndexSyntax -> true
|
||||
is MultiplicationSyntax -> perform0(node.left) || perform0(node.right)
|
||||
}
|
||||
}
|
||||
@ -129,6 +201,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt
|
||||
* @property precedenceFunction Returns the precedence number for syntax node. Higher number is lower priority.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) :
|
||||
FeaturedMathRendererWithPostProcess.PostProcessStage {
|
||||
public override fun perform(node: MathSyntax): Unit = when (node) {
|
||||
@ -159,8 +232,11 @@ public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) ->
|
||||
val isInsideExpOperator =
|
||||
node.parent is ExponentSyntax && (node.parent as ExponentSyntax).useOperatorForm
|
||||
|
||||
val isOnOrUnderNormalFraction = node.parent is FractionSyntax && !((node.parent as FractionSyntax).infix)
|
||||
|
||||
node.parentheses = !isRightOfSuperscript
|
||||
&& (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax || isInsideExpOperator)
|
||||
&& !isOnOrUnderNormalFraction
|
||||
|
||||
perform(node.operand)
|
||||
}
|
||||
|
@ -3,12 +3,12 @@
|
||||
* 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
|
||||
package space.kscience.kmath.ast
|
||||
|
||||
import space.kscience.kmath.expressions.MstField
|
||||
import space.kscience.kmath.expressions.MstRing
|
||||
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||
import space.kscience.kmath.expressions.interpret
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.IntRing
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
@ -16,45 +16,41 @@ import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestWasmConsistencyWithInterpreter {
|
||||
internal class TestCompilerConsistencyWithInterpreter {
|
||||
@Test
|
||||
fun intRing() {
|
||||
fun intRing() = runCompilerTest {
|
||||
val mst = MstRing {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
(bindSymbol(x) - (2.toByte() + (scale(
|
||||
add(number(1), number(1)),
|
||||
2.0
|
||||
2.0,
|
||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||
),
|
||||
|
||||
number(1)
|
||||
number(1),
|
||||
) * number(2)
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
mst.interpret(IntRing, x to 3),
|
||||
mst.compile(IntRing, x to 3)
|
||||
mst.compile(IntRing, x to 3),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleField() {
|
||||
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
|
||||
number(1) / 2 + number(2.0) * one,
|
||||
) + zero
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
mst.interpret(DoubleField, x to 2.0),
|
||||
mst.compile(DoubleField, x to 2.0)
|
||||
mst.compile(DoubleField, x to 2.0),
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -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.Symbol.Companion.x
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
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 { +x }.compileToExpression(DoubleField)
|
||||
assertEquals(2.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUnaryMinus() = runCompilerTest {
|
||||
val expr = MstExtendedField { -x }.compileToExpression(DoubleField)
|
||||
assertEquals(-2.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAdd() = runCompilerTest {
|
||||
val expr = MstExtendedField { x + x }.compileToExpression(DoubleField)
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSine() = runCompilerTest {
|
||||
val expr = MstExtendedField { sin(x) }.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr(x to 0.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCosine() = runCompilerTest {
|
||||
val expr = MstExtendedField { cos(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))
|
||||
}
|
||||
}
|
@ -3,11 +3,11 @@
|
||||
* 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
|
||||
package space.kscience.kmath.ast
|
||||
|
||||
import space.kscience.kmath.expressions.MstRing
|
||||
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.IntRing
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
@ -15,20 +15,16 @@ import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
internal class TestWasmVariables {
|
||||
internal class TestCompilerVariables {
|
||||
@Test
|
||||
fun testVariable() {
|
||||
fun testVariable() = runCompilerTest {
|
||||
val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
|
||||
assertEquals(1, expr(x to 1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUndefinedVariableFails() {
|
||||
fun testUndefinedVariableFails() = runCompilerTest {
|
||||
val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
|
||||
assertFailsWith<NoSuchElementException> { expr() }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ import space.kscience.kmath.operations.DoubleField
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class ParserTest {
|
||||
internal class TestParser {
|
||||
@Test
|
||||
fun evaluateParsedMst() {
|
||||
val mst = "2+2*(2+2)".parseMath()
|
@ -5,13 +5,12 @@
|
||||
|
||||
package space.kscience.kmath.ast
|
||||
|
||||
import space.kscience.kmath.ast.parseMath
|
||||
import space.kscience.kmath.expressions.evaluate
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class ParserPrecedenceTest {
|
||||
internal class TestParserPrecedence {
|
||||
@Test
|
||||
fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath()))
|
||||
|
@ -99,13 +99,17 @@ internal class TestFeatures {
|
||||
fun multiplication() = testLatex("x*1", "x\\times1")
|
||||
|
||||
@Test
|
||||
fun inverseTrigonometry() {
|
||||
testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)")
|
||||
testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)")
|
||||
testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)")
|
||||
testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)")
|
||||
testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)")
|
||||
testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)")
|
||||
fun inverseTrigonometric() {
|
||||
testLatex("asin(x)", "\\operatorname{arcsin}\\,\\left(x\\right)")
|
||||
testLatex("acos(x)", "\\operatorname{arccos}\\,\\left(x\\right)")
|
||||
testLatex("atan(x)", "\\operatorname{arctan}\\,\\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
|
||||
|
@ -37,4 +37,10 @@ internal class TestStages {
|
||||
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(
|
||||
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),
|
||||
)
|
||||
|
||||
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()),
|
||||
)
|
||||
|
||||
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),
|
||||
)
|
||||
}
|
||||
|
@ -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.expressions.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)
|
@ -9,22 +9,23 @@ import space.kscience.kmath.estree.internal.ESTreeBuilder
|
||||
import space.kscience.kmath.expressions.Expression
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.expressions.MST.*
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.internal.estree.BaseExpression
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.operations.Algebra
|
||||
import space.kscience.kmath.operations.NumericAlgebra
|
||||
import space.kscience.kmath.operations.bindSymbolOrNull
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T> MST.compileWith(algebra: Algebra<T>): Expression<T> {
|
||||
fun ESTreeBuilder<T>.visit(node: MST): BaseExpression = when (node) {
|
||||
is Symbolic -> {
|
||||
val symbol = algebra.bindSymbolOrNull(node.value)
|
||||
is Symbol -> {
|
||||
val symbol = algebra.bindSymbolOrNull(node)
|
||||
|
||||
if (symbol != null)
|
||||
constant(symbol)
|
||||
else
|
||||
variable(node.value)
|
||||
variable(node.identity)
|
||||
}
|
||||
|
||||
is Numeric -> constant(node.value)
|
||||
|
@ -6,14 +6,9 @@
|
||||
package space.kscience.kmath.estree.internal
|
||||
|
||||
import space.kscience.kmath.expressions.Expression
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
import space.kscience.kmath.internal.astring.generate
|
||||
import space.kscience.kmath.internal.estree.*
|
||||
import space.kscience.kmath.internal.estree.BaseExpression
|
||||
import space.kscience.kmath.internal.estree.BlockStatement
|
||||
import space.kscience.kmath.internal.estree.Program
|
||||
import space.kscience.kmath.internal.estree.VariableDeclaration
|
||||
import space.kscience.kmath.internal.estree.VariableDeclarator
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
|
||||
internal class ESTreeBuilder<T>(val bodyCallback: ESTreeBuilder<T>.() -> BaseExpression) {
|
||||
private class GeneratedExpression<T>(val executable: dynamic, val constants: Array<dynamic>) : Expression<T> {
|
||||
|
@ -3,7 +3,8 @@
|
||||
* 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",
|
||||
@file:Suppress(
|
||||
"INTERFACE_WITH_SUPERCLASS",
|
||||
"OVERRIDING_FINAL_MEMBER",
|
||||
"RETURN_TYPE_MISMATCH_ON_OVERRIDE",
|
||||
"CONFLICTING_OVERLOADS",
|
||||
|
@ -8,9 +8,9 @@ package space.kscience.kmath.wasm.internal
|
||||
import space.kscience.kmath.expressions.Expression
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.expressions.MST.*
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
import space.kscience.kmath.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
|
||||
@ -23,20 +23,20 @@ internal sealed class WasmBuilder<T>(
|
||||
val algebra: Algebra<T>,
|
||||
val target: MST,
|
||||
) where T : Number {
|
||||
val keys: MutableList<String> = mutableListOf()
|
||||
val keys: MutableList<Symbol> = mutableListOf()
|
||||
lateinit var ctx: BinaryenModule
|
||||
|
||||
open fun visitSymbolic(mst: MST.Symbolic): ExpressionRef {
|
||||
open fun visitSymbolic(mst: Symbol): ExpressionRef {
|
||||
try {
|
||||
algebra.bindSymbol(mst.value)
|
||||
algebra.bindSymbol(mst)
|
||||
} catch (ignored: Throwable) {
|
||||
null
|
||||
}?.let { return visitNumeric(Numeric(it)) }
|
||||
|
||||
var idx = keys.indexOf(mst.value)
|
||||
var idx = keys.indexOf(mst)
|
||||
|
||||
if (idx == -1) {
|
||||
keys += mst.value
|
||||
keys += mst
|
||||
idx = keys.lastIndex
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ internal sealed class WasmBuilder<T>(
|
||||
open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()")
|
||||
|
||||
fun visit(mst: MST): ExpressionRef = when (mst) {
|
||||
is Symbolic -> visitSymbolic(mst)
|
||||
is Symbol -> visitSymbolic(mst)
|
||||
is Numeric -> visitNumeric(mst)
|
||||
|
||||
is Unary -> when {
|
||||
@ -96,7 +96,7 @@ internal sealed class WasmBuilder<T>(
|
||||
})
|
||||
|
||||
val i = Instance(c, js("{}") as Any)
|
||||
val symbols = keys.map(::StringSymbol)
|
||||
val symbols = keys
|
||||
keys.clear()
|
||||
|
||||
Expression<T> { args ->
|
||||
|
@ -8,8 +8,9 @@ package space.kscience.kmath.wasm
|
||||
import space.kscience.kmath.estree.compileWith
|
||||
import space.kscience.kmath.expressions.Expression
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.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
|
||||
@ -20,6 +21,7 @@ import space.kscience.kmath.wasm.internal.IntWasmBuilder
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun DoubleField.expression(mst: MST): Expression<Double> =
|
||||
DoubleWasmBuilder(mst).instance
|
||||
|
||||
@ -28,6 +30,7 @@ public fun DoubleField.expression(mst: MST): Expression<Double> =
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun IntRing.expression(mst: MST): Expression<Int> =
|
||||
IntWasmBuilder(mst).instance
|
||||
|
||||
@ -36,6 +39,7 @@ public fun IntRing.expression(mst: MST): Expression<Int> =
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun MST.compileToExpression(algebra: IntRing): Expression<Int> = compileWith(algebra)
|
||||
|
||||
|
||||
@ -44,6 +48,7 @@ public fun MST.compileToExpression(algebra: IntRing): Expression<Int> = compileW
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int =
|
||||
compileToExpression(algebra).invoke(arguments)
|
||||
|
||||
@ -53,6 +58,7 @@ public fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int =
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun MST.compile(algebra: IntRing, vararg arguments: Pair<Symbol, Int>): Int =
|
||||
compileToExpression(algebra)(*arguments)
|
||||
|
||||
@ -61,6 +67,7 @@ public fun MST.compile(algebra: IntRing, vararg arguments: Pair<Symbol, Int>): I
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = compileWith(algebra)
|
||||
|
||||
|
||||
@ -69,6 +76,7 @@ public fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = c
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double =
|
||||
compileToExpression(algebra).invoke(arguments)
|
||||
|
||||
@ -78,5 +86,6 @@ public fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Do
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun MST.compile(algebra: DoubleField, vararg arguments: Pair<Symbol, Double>): Double =
|
||||
compileToExpression(algebra).invoke(*arguments)
|
||||
|
@ -6,7 +6,6 @@
|
||||
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
|
||||
|
@ -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.expressions.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,97 +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.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestESTreeConsistencyWithInterpreter {
|
||||
@Test
|
||||
fun mstSpace() {
|
||||
val mst = MstGroup {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
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 doubleField() {
|
||||
val mst = MstField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
mst.interpret(DoubleField, x to 2.0),
|
||||
mst.compile(DoubleField, x to 2.0)
|
||||
)
|
||||
}
|
||||
|
||||
@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()),
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -1,42 +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.MstField
|
||||
import space.kscience.kmath.expressions.MstGroup
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestESTreeOperationsSupport {
|
||||
@Test
|
||||
fun testUnaryOperationInvocation() {
|
||||
val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField)
|
||||
val res = expression(x to 2.0)
|
||||
assertEquals(-2.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBinaryOperationInvocation() {
|
||||
val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField)
|
||||
val res = expression(x to 2.0)
|
||||
assertEquals(-1.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testConstProductInvocation() {
|
||||
val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0)
|
||||
assertEquals(4.0, res)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -1,76 +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.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class 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 testSubtract() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("-")(bindSymbol(x),
|
||||
bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDivide() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(1.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPower() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("pow")(bindSymbol(x), number(2))
|
||||
}.compileToExpression(DoubleField)
|
||||
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -1,34 +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.misc.symbol
|
||||
import space.kscience.kmath.operations.ByteRing
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
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() }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -1,42 +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.wasm
|
||||
|
||||
import space.kscience.kmath.expressions.MstField
|
||||
import space.kscience.kmath.expressions.MstGroup
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestWasmOperationsSupport {
|
||||
@Test
|
||||
fun testUnaryOperationInvocation() {
|
||||
val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField)
|
||||
val res = expression(x to 2.0)
|
||||
assertEquals(-2.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBinaryOperationInvocation() {
|
||||
val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField)
|
||||
val res = expression(x to 2.0)
|
||||
assertEquals(-1.0, res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testConstProductInvocation() {
|
||||
val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0)
|
||||
assertEquals(4.0, res)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -1,76 +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.wasm
|
||||
|
||||
import space.kscience.kmath.expressions.MstExtendedField
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestWasmSpecialization {
|
||||
@Test
|
||||
fun testUnaryPlus() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(2.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUnaryMinus() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(-2.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAdd() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("+")(
|
||||
bindSymbol(x),
|
||||
bindSymbol(x),
|
||||
)
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSine() {
|
||||
val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr(x to 0.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSubtract() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("-")(bindSymbol(x),
|
||||
bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDivide() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(1.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPower() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("pow")(bindSymbol(x), number(2))
|
||||
}.compileToExpression(DoubleField)
|
||||
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ 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.expressions.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.IntRing
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
|
@ -10,10 +10,11 @@ import space.kscience.kmath.asm.internal.buildName
|
||||
import space.kscience.kmath.expressions.Expression
|
||||
import space.kscience.kmath.expressions.MST
|
||||
import space.kscience.kmath.expressions.MST.*
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.operations.Algebra
|
||||
import space.kscience.kmath.operations.NumericAlgebra
|
||||
import space.kscience.kmath.operations.bindSymbolOrNull
|
||||
|
||||
/**
|
||||
* Compiles given MST to an Expression using AST compiler.
|
||||
@ -26,13 +27,13 @@ import space.kscience.kmath.operations.NumericAlgebra
|
||||
@PublishedApi
|
||||
internal fun <T : Any> MST.compileWith(type: Class<T>, algebra: Algebra<T>): Expression<T> {
|
||||
fun AsmBuilder<T>.visit(node: MST): Unit = when (node) {
|
||||
is Symbolic -> {
|
||||
val symbol = algebra.bindSymbolOrNull(node.value)
|
||||
is Symbol -> {
|
||||
val symbol = algebra.bindSymbolOrNull(node)
|
||||
|
||||
if (symbol != null)
|
||||
loadObjectConstant(symbol as Any)
|
||||
else
|
||||
loadVariable(node.value)
|
||||
loadVariable(node.identity)
|
||||
}
|
||||
|
||||
is Numeric -> loadNumberConstant(node.value)
|
||||
|
@ -342,7 +342,7 @@ internal class AsmBuilder<T>(
|
||||
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.expressions.Symbol].
|
||||
*/
|
||||
val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") }
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.(
|
||||
*
|
||||
* @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.
|
||||
|
@ -7,8 +7,8 @@
|
||||
|
||||
package space.kscience.kmath.asm.internal
|
||||
|
||||
import space.kscience.kmath.misc.StringSymbol
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.expressions.StringSymbol
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
|
||||
/**
|
||||
* Gets value with given [key] or throws [NoSuchElementException] whenever it is not present.
|
||||
|
@ -1,97 +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
|
||||
import space.kscience.kmath.operations.ByteRing
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestAsmConsistencyWithInterpreter {
|
||||
@Test
|
||||
fun mstSpace() {
|
||||
val mst = MstGroup {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
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 doubleField() {
|
||||
val mst = MstField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
mst.interpret(DoubleField, x to 2.0),
|
||||
mst.compile(DoubleField, x to 2.0)
|
||||
)
|
||||
}
|
||||
|
||||
@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())
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -1,42 +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.MstField
|
||||
import space.kscience.kmath.expressions.MstGroup
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class 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)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -1,76 +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.misc.symbol
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class 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 testSubtract() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("-")(bindSymbol(x),
|
||||
bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(0.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDivide() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x))
|
||||
}.compileToExpression(DoubleField)
|
||||
assertEquals(1.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPower() {
|
||||
val expr = MstExtendedField {
|
||||
binaryOperationFunction("pow")(bindSymbol(x), number(2))
|
||||
}.compileToExpression(DoubleField)
|
||||
|
||||
assertEquals(4.0, expr(x to 2.0))
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -1,34 +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.misc.symbol
|
||||
import space.kscience.kmath.operations.ByteRing
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
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() }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
}
|
||||
}
|
@ -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.expressions.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)
|
@ -7,7 +7,6 @@ package space.kscience.kmath.commons.expressions
|
||||
|
||||
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.NumbersAddOperations
|
||||
|
@ -11,12 +11,12 @@ import space.kscience.kmath.integration.*
|
||||
/**
|
||||
* A simple one-pass integrator based on Gauss rule
|
||||
*/
|
||||
public class GaussRuleIntegrator(
|
||||
public class CMGaussRuleIntegrator(
|
||||
private val numpoints: Int,
|
||||
private var type: GaussRule = GaussRule.LEGANDRE,
|
||||
) : UnivariateIntegrator<Double> {
|
||||
|
||||
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||
override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||
val range = integrand.getFeature<IntegrationRange>()?.range
|
||||
?: error("Integration range is not provided")
|
||||
val integrator: GaussIntegrator = getIntegrator(range)
|
||||
@ -76,8 +76,8 @@ public class GaussRuleIntegrator(
|
||||
numPoints: Int = 100,
|
||||
type: GaussRule = GaussRule.LEGANDRE,
|
||||
function: (Double) -> Double,
|
||||
): Double = GaussRuleIntegrator(numPoints, type).process(
|
||||
): Double = CMGaussRuleIntegrator(numPoints, type).integrate(
|
||||
UnivariateIntegrand(function, IntegrationRange(range))
|
||||
).value!!
|
||||
).valueOrNull!!
|
||||
}
|
||||
}
|
@ -18,13 +18,7 @@ public class CMIntegrator(
|
||||
public val integratorBuilder: (Integrand) -> org.apache.commons.math3.analysis.integration.UnivariateIntegrator,
|
||||
) : UnivariateIntegrator<Double> {
|
||||
|
||||
public class TargetRelativeAccuracy(public val value: Double) : IntegrandFeature
|
||||
public class TargetAbsoluteAccuracy(public val value: Double) : IntegrandFeature
|
||||
|
||||
public class MinIterations(public val value: Int) : IntegrandFeature
|
||||
public class MaxIterations(public val value: Int) : IntegrandFeature
|
||||
|
||||
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||
override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||
val integrator = integratorBuilder(integrand)
|
||||
val maxCalls = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: defaultMaxCalls
|
||||
val remainingCalls = maxCalls - integrand.calls
|
||||
@ -32,12 +26,11 @@ public class CMIntegrator(
|
||||
?: error("Integration range is not provided")
|
||||
val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive)
|
||||
|
||||
return integrand.with(
|
||||
IntegrandValue(res),
|
||||
IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy),
|
||||
IntegrandRelativeAccuracy(integrator.relativeAccuracy),
|
||||
IntegrandCallsPerformed(integrator.evaluations + integrand.calls)
|
||||
)
|
||||
return integrand +
|
||||
IntegrandValue(res) +
|
||||
IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy) +
|
||||
IntegrandRelativeAccuracy(integrator.relativeAccuracy) +
|
||||
IntegrandCallsPerformed(integrator.evaluations + integrand.calls)
|
||||
}
|
||||
|
||||
|
||||
@ -46,16 +39,15 @@ public class CMIntegrator(
|
||||
* Create a Simpson integrator based on [SimpsonIntegrator]
|
||||
*/
|
||||
public fun simpson(defaultMaxCalls: Int = 200): CMIntegrator = CMIntegrator(defaultMaxCalls) { integrand ->
|
||||
val absoluteAccuracy = integrand.getFeature<TargetAbsoluteAccuracy>()?.value
|
||||
val absoluteAccuracy = integrand.getFeature<IntegrandAbsoluteAccuracy>()?.accuracy
|
||||
?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
||||
val relativeAccuracy = integrand.getFeature<TargetRelativeAccuracy>()?.value
|
||||
val relativeAccuracy = integrand.getFeature<IntegrandRelativeAccuracy>()?.accuracy
|
||||
?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
||||
val minIterations = integrand.getFeature<MinIterations>()?.value
|
||||
?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT
|
||||
val maxIterations = integrand.getFeature<MaxIterations>()?.value
|
||||
?: SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT
|
||||
val iterations = integrand.getFeature<IntegrandIterationsRange>()?.range
|
||||
?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT
|
||||
|
||||
SimpsonIntegrator(relativeAccuracy, absoluteAccuracy, minIterations, maxIterations)
|
||||
|
||||
SimpsonIntegrator(relativeAccuracy, absoluteAccuracy, iterations.first, iterations.last)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,21 +55,19 @@ public class CMIntegrator(
|
||||
*/
|
||||
public fun legandre(numPoints: Int, defaultMaxCalls: Int = numPoints * 5): CMIntegrator =
|
||||
CMIntegrator(defaultMaxCalls) { integrand ->
|
||||
val absoluteAccuracy = integrand.getFeature<TargetAbsoluteAccuracy>()?.value
|
||||
val absoluteAccuracy = integrand.getFeature<IntegrandAbsoluteAccuracy>()?.accuracy
|
||||
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
||||
val relativeAccuracy = integrand.getFeature<TargetRelativeAccuracy>()?.value
|
||||
val relativeAccuracy = integrand.getFeature<IntegrandRelativeAccuracy>()?.accuracy
|
||||
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
||||
val minIterations = integrand.getFeature<MinIterations>()?.value
|
||||
?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT
|
||||
val maxIterations = integrand.getFeature<MaxIterations>()?.value
|
||||
?: IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT
|
||||
val iterations = integrand.getFeature<IntegrandIterationsRange>()?.range
|
||||
?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT
|
||||
|
||||
IterativeLegendreGaussIntegrator(
|
||||
numPoints,
|
||||
relativeAccuracy,
|
||||
absoluteAccuracy,
|
||||
minIterations,
|
||||
maxIterations
|
||||
iterations.first,
|
||||
iterations.last
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -85,14 +75,14 @@ public class CMIntegrator(
|
||||
|
||||
@UnstableKMathAPI
|
||||
public var MutableList<IntegrandFeature>.targetAbsoluteAccuracy: Double?
|
||||
get() = filterIsInstance<CMIntegrator.TargetAbsoluteAccuracy>().lastOrNull()?.value
|
||||
get() = filterIsInstance<IntegrandAbsoluteAccuracy>().lastOrNull()?.accuracy
|
||||
set(value) {
|
||||
value?.let { add(CMIntegrator.TargetAbsoluteAccuracy(value)) }
|
||||
value?.let { add(IntegrandAbsoluteAccuracy(value)) }
|
||||
}
|
||||
|
||||
@UnstableKMathAPI
|
||||
public var MutableList<IntegrandFeature>.targetRelativeAccuracy: Double?
|
||||
get() = filterIsInstance<CMIntegrator.TargetRelativeAccuracy>().lastOrNull()?.value
|
||||
get() = filterIsInstance<IntegrandRelativeAccuracy>().lastOrNull()?.accuracy
|
||||
set(value) {
|
||||
value?.let { add(CMIntegrator.TargetRelativeAccuracy(value)) }
|
||||
value?.let { add(IntegrandRelativeAccuracy(value)) }
|
||||
}
|
@ -5,11 +5,7 @@
|
||||
|
||||
package space.kscience.kmath.commons.expressions
|
||||
|
||||
import space.kscience.kmath.expressions.binding
|
||||
import space.kscience.kmath.expressions.derivative
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.expressions.*
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.test.Test
|
||||
|
@ -7,6 +7,7 @@ package space.kscience.kmath.commons.integration
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import space.kscience.kmath.integration.integrate
|
||||
import space.kscience.kmath.integration.value
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.DoubleField.sin
|
||||
import kotlin.math.PI
|
||||
@ -19,16 +20,16 @@ internal class IntegrationTest {
|
||||
|
||||
@Test
|
||||
fun simpson() {
|
||||
val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function)
|
||||
val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function = function).value
|
||||
assertTrue { abs(res) < 1e-3 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun customSimpson() {
|
||||
val res = CMIntegrator.simpson().integrate(0.0..PI, function) {
|
||||
val res = CMIntegrator.simpson().integrate(0.0..PI, {
|
||||
targetRelativeAccuracy = 1e-4
|
||||
targetAbsoluteAccuracy = 1e-4
|
||||
}
|
||||
}, function).value
|
||||
assertTrue { abs(res - 2) < 1e-3 }
|
||||
assertTrue { abs(res - 2) > 1e-12 }
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ package space.kscience.kmath.commons.optimization
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import space.kscience.kmath.commons.expressions.DerivativeStructureExpression
|
||||
import space.kscience.kmath.distributions.NormalDistribution
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.expressions.symbol
|
||||
import space.kscience.kmath.optimization.FunctionOptimization
|
||||
import space.kscience.kmath.stat.RandomGenerator
|
||||
import kotlin.math.pow
|
||||
|
@ -8,29 +8,27 @@ Complex and hypercomplex number systems in KMath.
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-7`.
|
||||
The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-11`.
|
||||
|
||||
**Gradle:**
|
||||
```gradle
|
||||
repositories {
|
||||
maven { url 'https://repo.kotlin.link' }
|
||||
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'space.kscience:kmath-complex:0.3.0-dev-7'
|
||||
implementation 'space.kscience:kmath-complex:0.3.0-dev-11'
|
||||
}
|
||||
```
|
||||
**Gradle Kotlin DSL:**
|
||||
```kotlin
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:kmath-complex:0.3.0-dev-7")
|
||||
implementation("space.kscience:kmath-complex:0.3.0-dev-11")
|
||||
}
|
||||
```
|
||||
|
@ -9,7 +9,10 @@ import space.kscience.kmath.memory.MemoryReader
|
||||
import space.kscience.kmath.memory.MemorySpec
|
||||
import space.kscience.kmath.memory.MemoryWriter
|
||||
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.MemoryBuffer
|
||||
import space.kscience.kmath.structures.MutableBuffer
|
||||
@ -180,13 +183,11 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, Num
|
||||
* @property im The imaginary part.
|
||||
*/
|
||||
@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) : 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 override val objectSize: Int
|
||||
|
@ -27,8 +27,10 @@ public val Quaternion.conjugate: Quaternion
|
||||
*/
|
||||
public val Quaternion.reciprocal: Quaternion
|
||||
get() {
|
||||
val n = QuaternionField { norm(this@reciprocal) }
|
||||
return conjugate / (n * n)
|
||||
QuaternionField {
|
||||
val n = norm(this@reciprocal)
|
||||
return conjugate / (n * n)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,7 +200,7 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
public data class Quaternion(
|
||||
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(
|
||||
w.toDouble(),
|
||||
x.toDouble(),
|
||||
@ -219,8 +221,6 @@ public data class Quaternion(
|
||||
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.
|
||||
*/
|
||||
|
@ -7,7 +7,7 @@ package space.kscience.kmath.complex
|
||||
|
||||
import space.kscience.kmath.expressions.FunctionalExpressionField
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.misc.symbol
|
||||
import space.kscience.kmath.expressions.symbol
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
@ -15,29 +15,27 @@ performance calculations to code generation.
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-7`.
|
||||
The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-11`.
|
||||
|
||||
**Gradle:**
|
||||
```gradle
|
||||
repositories {
|
||||
maven { url 'https://repo.kotlin.link' }
|
||||
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'space.kscience:kmath-core:0.3.0-dev-7'
|
||||
implementation 'space.kscience:kmath-core:0.3.0-dev-11'
|
||||
}
|
||||
```
|
||||
**Gradle Kotlin DSL:**
|
||||
```kotlin
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:kmath-core:0.3.0-dev-7")
|
||||
implementation("space.kscience:kmath-core:0.3.0-dev-11")
|
||||
}
|
||||
```
|
||||
|
@ -21,7 +21,7 @@ public class space/kscience/kmath/expressions/AutoDiffValue {
|
||||
|
||||
public final class space/kscience/kmath/expressions/DerivationResult {
|
||||
public fun <init> (Ljava/lang/Object;Ljava/util/Map;Lspace/kscience/kmath/operations/Field;)V
|
||||
public final fun derivative (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||
public final fun derivative (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
||||
public final fun div ()Ljava/lang/Object;
|
||||
public final fun getContext ()Lspace/kscience/kmath/operations/Field;
|
||||
public final fun getValue ()Ljava/lang/Object;
|
||||
@ -34,7 +34,7 @@ public abstract interface class space/kscience/kmath/expressions/DifferentiableE
|
||||
public final class space/kscience/kmath/expressions/DifferentiableExpressionKt {
|
||||
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression;
|
||||
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression;
|
||||
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;[Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
||||
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/kmath/expressions/Expression {
|
||||
@ -55,7 +55,7 @@ public final class space/kscience/kmath/expressions/ExpressionKt {
|
||||
public abstract class space/kscience/kmath/expressions/FirstDerivativeExpression : space/kscience/kmath/expressions/DifferentiableExpression {
|
||||
public fun <init> ()V
|
||||
public final fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression;
|
||||
public abstract fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
||||
public abstract fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
||||
}
|
||||
|
||||
public abstract class space/kscience/kmath/expressions/FunctionalExpressionAlgebra : space/kscience/kmath/expressions/ExpressionAlgebra {
|
||||
@ -146,7 +146,7 @@ public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/k
|
||||
public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
||||
}
|
||||
|
||||
public abstract class space/kscience/kmath/expressions/MST {
|
||||
public abstract interface class space/kscience/kmath/expressions/MST {
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/MST$Binary : space/kscience/kmath/expressions/MST {
|
||||
@ -175,17 +175,6 @@ public final class space/kscience/kmath/expressions/MST$Numeric : space/kscience
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/MST$Symbolic : space/kscience/kmath/expressions/MST {
|
||||
public fun <init> (Ljava/lang/String;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun copy (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
|
||||
public static synthetic fun copy$default (Lspace/kscience/kmath/expressions/MST$Symbolic;Ljava/lang/String;ILjava/lang/Object;)Lspace/kscience/kmath/expressions/MST$Symbolic;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getValue ()Ljava/lang/String;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/MST$Unary : space/kscience/kmath/expressions/MST {
|
||||
public fun <init> (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
@ -206,18 +195,6 @@ public final class space/kscience/kmath/expressions/MSTKt {
|
||||
public static final fun toExpression (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/operations/Algebra;)Lspace/kscience/kmath/expressions/Expression;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/MstAlgebra : space/kscience/kmath/operations/NumericAlgebra {
|
||||
public static final field INSTANCE Lspace/kscience/kmath/expressions/MstAlgebra;
|
||||
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
||||
public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
|
||||
public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
|
||||
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
|
||||
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
|
||||
public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
|
||||
public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric;
|
||||
public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/MstExtendedField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumericAlgebra {
|
||||
public static final field INSTANCE Lspace/kscience/kmath/expressions/MstExtendedField;
|
||||
public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
@ -236,7 +213,7 @@ public final class space/kscience/kmath/expressions/MstExtendedField : space/ksc
|
||||
public fun atanh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
|
||||
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
||||
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
|
||||
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
|
||||
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
|
||||
public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun cos (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
|
||||
public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
@ -265,6 +242,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 synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
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 fun tan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
|
||||
public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
@ -282,7 +261,7 @@ public final class space/kscience/kmath/expressions/MstField : space/kscience/km
|
||||
public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary;
|
||||
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
||||
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
|
||||
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
|
||||
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
|
||||
public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun divide (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary;
|
||||
public synthetic fun getOne ()Ljava/lang/Object;
|
||||
@ -310,7 +289,7 @@ public final class space/kscience/kmath/expressions/MstGroup : space/kscience/km
|
||||
public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary;
|
||||
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
||||
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
|
||||
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
|
||||
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
|
||||
public synthetic fun getZero ()Ljava/lang/Object;
|
||||
public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric;
|
||||
public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
@ -326,13 +305,25 @@ public final class space/kscience/kmath/expressions/MstGroup : space/kscience/km
|
||||
public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/MstNumericAlgebra : space/kscience/kmath/operations/NumericAlgebra {
|
||||
public static final field INSTANCE Lspace/kscience/kmath/expressions/MstNumericAlgebra;
|
||||
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
||||
public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
|
||||
public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
|
||||
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
|
||||
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
|
||||
public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
|
||||
public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric;
|
||||
public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/MstRing : space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/Ring, space/kscience/kmath/operations/ScaleOperations {
|
||||
public static final field INSTANCE Lspace/kscience/kmath/expressions/MstRing;
|
||||
public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary;
|
||||
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
||||
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
|
||||
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
|
||||
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
|
||||
public synthetic fun getOne ()Ljava/lang/Object;
|
||||
public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric;
|
||||
public synthetic fun getZero ()Ljava/lang/Object;
|
||||
@ -354,7 +345,7 @@ public final class space/kscience/kmath/expressions/MstRing : space/kscience/kma
|
||||
|
||||
public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : space/kscience/kmath/expressions/FirstDerivativeExpression {
|
||||
public fun <init> (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V
|
||||
public fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
||||
public fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
||||
public final fun getField ()Lspace/kscience/kmath/operations/Field;
|
||||
public final fun getFunction ()Lkotlin/jvm/functions/Function1;
|
||||
public fun invoke (Ljava/util/Map;)Ljava/lang/Object;
|
||||
@ -443,7 +434,7 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt {
|
||||
public static final fun cos (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||
public static final fun cosh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||
public static final fun exp (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||
public static final fun grad (Lspace/kscience/kmath/expressions/DerivationResult;[Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer;
|
||||
public static final fun grad (Lspace/kscience/kmath/expressions/DerivationResult;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer;
|
||||
public static final fun ln (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||
public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||
public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;I)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||
@ -459,9 +450,42 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt {
|
||||
public static final fun tanh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/StringSymbol : space/kscience/kmath/expressions/Symbol {
|
||||
public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/expressions/StringSymbol;
|
||||
public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z
|
||||
public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z
|
||||
public fun getIdentity ()Ljava/lang/String;
|
||||
public fun hashCode ()I
|
||||
public static fun hashCode-impl (Ljava/lang/String;)I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String;
|
||||
public final synthetic fun unbox-impl ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/kmath/expressions/Symbol : space/kscience/kmath/expressions/MST {
|
||||
public static final field Companion Lspace/kscience/kmath/expressions/Symbol$Companion;
|
||||
public abstract fun getIdentity ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/Symbol$Companion {
|
||||
public final fun getX-uKgCeAI ()Ljava/lang/String;
|
||||
public final fun getY-uKgCeAI ()Ljava/lang/String;
|
||||
public final fun getZ-uKgCeAI ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/SymbolIndexerKt {
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/expressions/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/expressions/Symbol;)Ljava/lang/Object;
|
||||
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/expressions/Symbol;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscience/kmath/linear/LinearSpace {
|
||||
public fun <init> (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V
|
||||
public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D;
|
||||
@ -498,6 +522,11 @@ public final class space/kscience/kmath/linear/LFeature : space/kscience/kmath/l
|
||||
public static final field INSTANCE Lspace/kscience/kmath/linear/LFeature;
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/kmath/linear/LUDecompositionFeature : space/kscience/kmath/linear/MatrixFeature {
|
||||
public abstract fun getL ()Lspace/kscience/kmath/nd/Structure2D;
|
||||
public abstract fun getU ()Lspace/kscience/kmath/nd/Structure2D;
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/kmath/linear/LinearSolver {
|
||||
public abstract fun inverse (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
|
||||
public abstract fun solve (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
|
||||
@ -672,37 +701,7 @@ public final class space/kscience/kmath/misc/CumulativeKt {
|
||||
public static final fun cumulativeSumOfLong (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
|
||||
}
|
||||
|
||||
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 fun constructor-impl (Ljava/lang/String;)Ljava/lang/String;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z
|
||||
public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z
|
||||
public fun getIdentity ()Ljava/lang/String;
|
||||
public fun hashCode ()I
|
||||
public static fun hashCode-impl (Ljava/lang/String;)I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String;
|
||||
public final synthetic fun unbox-impl ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/kmath/misc/Symbol {
|
||||
public static final field Companion Lspace/kscience/kmath/misc/Symbol$Companion;
|
||||
public abstract fun getIdentity ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/misc/Symbol$Companion {
|
||||
public final fun getX-tWtZOCg ()Ljava/lang/String;
|
||||
public final fun getY-tWtZOCg ()Ljava/lang/String;
|
||||
public final fun getZ-tWtZOCg ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
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 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/PerformancePitfall : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation {
|
||||
@ -745,7 +744,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 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 elements ()Lkotlin/sequences/Sequence;
|
||||
public fun get ([I)Ljava/lang/Object;
|
||||
@ -786,10 +785,9 @@ public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getLinearSize ()I
|
||||
public fun getShape ()[I
|
||||
public fun getStrides ()Ljava/util/List;
|
||||
public fun getStrides ()[I
|
||||
public fun hashCode ()I
|
||||
public fun index (I)[I
|
||||
public fun offset ([I)I
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/nd/DefaultStrides$Companion {
|
||||
@ -873,6 +871,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/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 fun set ([ILjava/lang/Object;)V
|
||||
}
|
||||
@ -912,10 +926,10 @@ public final class space/kscience/kmath/nd/ShortRingNDKt {
|
||||
public abstract interface class space/kscience/kmath/nd/Strides {
|
||||
public abstract fun getLinearSize ()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 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 {
|
||||
@ -929,6 +943,7 @@ public final class space/kscience/kmath/nd/Structure1D$Companion {
|
||||
}
|
||||
|
||||
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 asND (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/nd/Structure1D;
|
||||
}
|
||||
@ -949,6 +964,7 @@ public final class space/kscience/kmath/nd/Structure2D$Companion {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -988,14 +1004,7 @@ public abstract interface class space/kscience/kmath/operations/Algebra {
|
||||
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 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 {
|
||||
@ -1005,7 +1014,7 @@ public final class space/kscience/kmath/operations/AlgebraExtensionsKt {
|
||||
public static final fun averageWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Object;
|
||||
public static final fun averageWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Object;
|
||||
public static final fun power (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;I)Ljava/lang/Object;
|
||||
public static final fun power (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;I)Ljava/lang/Object;
|
||||
public static final fun power-jXDDuk8 (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;I)Ljava/lang/Object;
|
||||
public static final fun sum (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Iterable;)Ljava/lang/Object;
|
||||
public static final fun sum (Lspace/kscience/kmath/operations/Ring;Lkotlin/sequences/Sequence;)Ljava/lang/Object;
|
||||
public static final fun sumWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Object;
|
||||
@ -1013,8 +1022,8 @@ public final class space/kscience/kmath/operations/AlgebraExtensionsKt {
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/operations/AlgebraKt {
|
||||
public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||
public static final fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||
public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
||||
public static final fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
||||
public static final fun invoke (Lspace/kscience/kmath/operations/Algebra;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
@ -1035,6 +1044,7 @@ public final class space/kscience/kmath/operations/BigInt : java/lang/Comparable
|
||||
public final fun modPow (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
|
||||
public final fun or (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
|
||||
public final fun plus (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
|
||||
public final fun pow-WZ4Q5Ns (I)Lspace/kscience/kmath/operations/BigInt;
|
||||
public final fun rem (I)I
|
||||
public final fun rem (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
|
||||
public final fun shl (I)Lspace/kscience/kmath/operations/BigInt;
|
||||
@ -1398,6 +1408,11 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci
|
||||
public abstract interface annotation class space/kscience/kmath/operations/KMathContext : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/operations/LogicAlgebra$Companion {
|
||||
public final fun getFALSE ()Lspace/kscience/kmath/expressions/Symbol;
|
||||
public final fun getTRUE ()Lspace/kscience/kmath/expressions/Symbol;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/operations/LongRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring {
|
||||
public static final field INSTANCE Lspace/kscience/kmath/operations/LongRing;
|
||||
public fun add (JJ)Ljava/lang/Long;
|
||||
|
@ -5,7 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.data
|
||||
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
import space.kscience.kmath.misc.PerformancePitfall
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.Structure2D
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
@ -18,13 +19,17 @@ import space.kscience.kmath.structures.Buffer
|
||||
public interface ColumnarData<out T> {
|
||||
public val size: Int
|
||||
|
||||
public operator fun get(symbol: Symbol): Buffer<T>
|
||||
/**
|
||||
* Provide a column by symbol or null if column with given symbol is not defined
|
||||
*/
|
||||
public operator fun get(symbol: Symbol): Buffer<T>?
|
||||
}
|
||||
|
||||
/**
|
||||
* A zero-copy method to represent a [Structure2D] as a two-column x-y data.
|
||||
* There could more than two columns in the structure.
|
||||
*/
|
||||
@OptIn(PerformancePitfall::class)
|
||||
@UnstableKMathAPI
|
||||
public fun <T> Structure2D<T>.asColumnarData(mapping: Map<Symbol, Int>): ColumnarData<T> {
|
||||
require(shape[1] >= mapping.maxOf { it.value }) { "Column index out of bounds" }
|
||||
|
@ -5,7 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.data
|
||||
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
import space.kscience.kmath.misc.PerformancePitfall
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.Structure2D
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
@ -26,10 +27,10 @@ public interface XYColumnarData<T, out X : T, out Y : T> : ColumnarData<T> {
|
||||
*/
|
||||
public val y: Buffer<Y>
|
||||
|
||||
override fun get(symbol: Symbol): Buffer<T> = when (symbol) {
|
||||
override fun get(symbol: Symbol): Buffer<T>? = when (symbol) {
|
||||
Symbol.x -> x
|
||||
Symbol.y -> y
|
||||
else -> error("A column for symbol $symbol not found")
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
* There could more than two columns in the structure.
|
||||
*/
|
||||
@OptIn(PerformancePitfall::class)
|
||||
@UnstableKMathAPI
|
||||
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" }
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
package space.kscience.kmath.data
|
||||
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
|
||||
@ -17,10 +17,10 @@ import space.kscience.kmath.structures.Buffer
|
||||
public interface XYZColumnarData<T, out X : T, out Y : T, out Z : T> : XYColumnarData<T, X, Y> {
|
||||
public val z: Buffer<Z>
|
||||
|
||||
override fun get(symbol: Symbol): Buffer<T> = when (symbol) {
|
||||
override fun get(symbol: Symbol): Buffer<T>? = when (symbol) {
|
||||
Symbol.x -> x
|
||||
Symbol.y -> y
|
||||
Symbol.z -> z
|
||||
else -> error("A column for symbol $symbol not found")
|
||||
else -> null
|
||||
}
|
||||
}
|
@ -5,9 +5,6 @@
|
||||
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import space.kscience.kmath.misc.StringSymbol
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
|
||||
/**
|
||||
* Represents expression which structure can be differentiated.
|
||||
*
|
||||
|
@ -5,8 +5,6 @@
|
||||
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import space.kscience.kmath.misc.StringSymbol
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.operations.Algebra
|
||||
import kotlin.jvm.JvmName
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import space.kscience.kmath.misc.StringSymbol
|
||||
import space.kscience.kmath.operations.*
|
||||
|
||||
/**
|
||||
|
@ -5,30 +5,23 @@
|
||||
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import space.kscience.kmath.misc.StringSymbol
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.operations.Algebra
|
||||
import space.kscience.kmath.operations.NumericAlgebra
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
|
||||
/**
|
||||
* A Mathematical Syntax Tree (MST) node for mathematical expressions.
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
public sealed class MST {
|
||||
/**
|
||||
* A node containing raw string.
|
||||
*
|
||||
* @property value the value of this node.
|
||||
*/
|
||||
public data class Symbolic(val value: String) : MST()
|
||||
public sealed interface MST {
|
||||
|
||||
/**
|
||||
* A node containing a numeric value or scalar.
|
||||
*
|
||||
* @property value the value of this number.
|
||||
*/
|
||||
public data class Numeric(val value: Number) : MST()
|
||||
public data class Numeric(val value: Number) : MST
|
||||
|
||||
/**
|
||||
* A node containing an unary operation.
|
||||
@ -36,7 +29,7 @@ public sealed class MST {
|
||||
* @property operation the identifier of operation.
|
||||
* @property value the argument of this operation.
|
||||
*/
|
||||
public data class Unary(val operation: String, val value: MST) : MST()
|
||||
public data class Unary(val operation: String, val value: MST) : MST
|
||||
|
||||
/**
|
||||
* A node containing binary operation.
|
||||
@ -45,7 +38,7 @@ public sealed class MST {
|
||||
* @property left the left operand.
|
||||
* @property right the right operand.
|
||||
*/
|
||||
public data class Binary(val operation: String, val left: MST, val right: MST) : MST()
|
||||
public data class Binary(val operation: String, val left: MST, val right: MST) : MST
|
||||
}
|
||||
|
||||
// TODO add a function with named arguments
|
||||
@ -62,7 +55,7 @@ public fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
|
||||
is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value)
|
||||
?: error("Numeric nodes are not supported by $this")
|
||||
|
||||
is MST.Symbolic -> bindSymbol(node.value)
|
||||
is Symbol -> bindSymbol(node)
|
||||
|
||||
is MST.Unary -> when {
|
||||
this is NumericAlgebra && node.value is MST.Numeric -> unaryOperationFunction(node.operation)(number(node.value.value))
|
||||
@ -83,7 +76,7 @@ public fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
|
||||
}
|
||||
}
|
||||
|
||||
internal class InnerAlgebra<T : Any>(val algebra: Algebra<T>, val arguments: Map<Symbol, T>) : NumericAlgebra<T> {
|
||||
internal class InnerAlgebra<T>(val algebra: Algebra<T>, val arguments: Map<Symbol, T>) : NumericAlgebra<T> {
|
||||
override fun bindSymbolOrNull(value: String): T? = algebra.bindSymbolOrNull(value) ?: arguments[StringSymbol(value)]
|
||||
|
||||
override fun unaryOperation(operation: String, arg: T): T =
|
||||
@ -108,7 +101,7 @@ internal class InnerAlgebra<T : Any>(val algebra: Algebra<T>, val arguments: Map
|
||||
/**
|
||||
* Interprets the [MST] node with this [Algebra] and optional [arguments]
|
||||
*/
|
||||
public fun <T : Any> MST.interpret(algebra: Algebra<T>, arguments: Map<Symbol, T>): T =
|
||||
public fun <T> MST.interpret(algebra: Algebra<T>, arguments: Map<Symbol, T>): T =
|
||||
InnerAlgebra(algebra, arguments).evaluate(this)
|
||||
|
||||
/**
|
||||
@ -118,7 +111,7 @@ public fun <T : Any> MST.interpret(algebra: Algebra<T>, arguments: Map<Symbol, T
|
||||
* @param algebra the algebra that provides operations.
|
||||
* @return the value of expression.
|
||||
*/
|
||||
public fun <T : Any> MST.interpret(algebra: Algebra<T>, vararg arguments: Pair<Symbol, T>): T =
|
||||
public fun <T> MST.interpret(algebra: Algebra<T>, vararg arguments: Pair<Symbol, T>): T =
|
||||
interpret(algebra, mapOf(*arguments))
|
||||
|
||||
/**
|
||||
|
@ -11,10 +11,10 @@ import space.kscience.kmath.operations.*
|
||||
/**
|
||||
* [Algebra] over [MST] nodes.
|
||||
*/
|
||||
public object MstAlgebra : NumericAlgebra<MST> {
|
||||
public object MstNumericAlgebra : NumericAlgebra<MST> {
|
||||
public override fun number(value: Number): MST.Numeric = MST.Numeric(value)
|
||||
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MST.Symbolic(value)
|
||||
override fun bindSymbol(value: String): MST.Symbolic = bindSymbolOrNull(value)
|
||||
public override fun bindSymbolOrNull(value: String): Symbol = StringSymbol(value)
|
||||
override fun bindSymbol(value: String): Symbol = bindSymbolOrNull(value)
|
||||
|
||||
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
|
||||
{ arg -> MST.Unary(operation, arg) }
|
||||
@ -29,8 +29,8 @@ public object MstAlgebra : NumericAlgebra<MST> {
|
||||
public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
|
||||
public override val zero: MST.Numeric = number(0.0)
|
||||
|
||||
public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value)
|
||||
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value)
|
||||
public override fun number(value: Number): MST.Numeric = MstNumericAlgebra.number(value)
|
||||
public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
|
||||
public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(GroupOperations.PLUS_OPERATION)(a, b)
|
||||
public override operator fun MST.unaryPlus(): MST.Unary =
|
||||
unaryOperationFunction(GroupOperations.PLUS_OPERATION)(this)
|
||||
@ -45,10 +45,10 @@ public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
|
||||
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(value))
|
||||
|
||||
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
||||
MstAlgebra.binaryOperationFunction(operation)
|
||||
MstNumericAlgebra.binaryOperationFunction(operation)
|
||||
|
||||
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
|
||||
MstAlgebra.unaryOperationFunction(operation)
|
||||
MstNumericAlgebra.unaryOperationFunction(operation)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,7 +61,7 @@ public object MstRing : Ring<MST>, NumbersAddOperations<MST>, ScaleOperations<MS
|
||||
public override val one: MST.Numeric = number(1.0)
|
||||
|
||||
public override fun number(value: Number): MST.Numeric = MstGroup.number(value)
|
||||
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value)
|
||||
public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
|
||||
public override fun add(a: MST, b: MST): MST.Binary = MstGroup.add(a, b)
|
||||
|
||||
public override fun scale(a: MST, value: Double): MST.Binary =
|
||||
@ -78,7 +78,7 @@ public object MstRing : Ring<MST>, NumbersAddOperations<MST>, ScaleOperations<MS
|
||||
MstGroup.binaryOperationFunction(operation)
|
||||
|
||||
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
|
||||
MstAlgebra.unaryOperationFunction(operation)
|
||||
MstNumericAlgebra.unaryOperationFunction(operation)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,7 +90,7 @@ public object MstField : Field<MST>, NumbersAddOperations<MST>, ScaleOperations<
|
||||
public override inline val zero: MST.Numeric get() = MstRing.zero
|
||||
public override inline val one: MST.Numeric get() = MstRing.one
|
||||
|
||||
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value)
|
||||
public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
|
||||
public override fun number(value: Number): MST.Numeric = MstRing.number(value)
|
||||
public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b)
|
||||
|
||||
@ -120,7 +120,7 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
|
||||
public override inline val zero: MST.Numeric get() = MstField.zero
|
||||
public override inline val one: MST.Numeric get() = MstField.one
|
||||
|
||||
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value)
|
||||
public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
|
||||
public override fun number(value: Number): MST.Numeric = MstRing.number(value)
|
||||
public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg)
|
||||
public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg)
|
||||
@ -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 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 sqrt(arg: MST): MST = unaryOperationFunction(PowerOperations.SQRT_OPERATION)(arg)
|
||||
|
||||
public override fun scale(a: MST, value: Double): MST =
|
||||
binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value))
|
||||
@ -157,3 +158,25 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
|
||||
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
|
||||
MstField.unaryOperationFunction(operation)
|
||||
}
|
||||
|
||||
/**
|
||||
* Logic algebra for [MST]
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public object MstLogicAlgebra : LogicAlgebra<MST> {
|
||||
public override fun bindSymbolOrNull(value: String): MST = super.bindSymbolOrNull(value) ?: StringSymbol(value)
|
||||
|
||||
override fun const(boolean: Boolean): Symbol = if (boolean) {
|
||||
LogicAlgebra.TRUE
|
||||
} else {
|
||||
LogicAlgebra.FALSE
|
||||
}
|
||||
|
||||
override fun MST.not(): MST = MST.Unary(Boolean::not.name, this)
|
||||
|
||||
override fun MST.and(other: MST): MST = MST.Binary(Boolean::and.name, this, other)
|
||||
|
||||
override fun MST.or(other: MST): MST = MST.Binary(Boolean::or.name, this, other)
|
||||
|
||||
override fun MST.xor(other: MST): MST = MST.Binary(Boolean::xor.name, this, other)
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.asBuffer
|
||||
|
@ -3,21 +3,22 @@
|
||||
* 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.misc
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import kotlin.jvm.JvmInline
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
|
||||
/**
|
||||
* A marker interface for a symbol. A symbol mus have an identity
|
||||
* A marker interface for a symbol. A symbol must have an identity.
|
||||
* Ic
|
||||
*/
|
||||
public interface Symbol {
|
||||
public interface Symbol : MST {
|
||||
/**
|
||||
* Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol.
|
||||
*/
|
||||
public val identity: String
|
||||
|
||||
public companion object{
|
||||
public companion object {
|
||||
public val x: StringSymbol = StringSymbol("x")
|
||||
public val y: StringSymbol = StringSymbol("y")
|
||||
public val z: StringSymbol = StringSymbol("z")
|
||||
@ -47,7 +48,7 @@ public operator fun <T> Map<String, T>.get(symbol: Symbol): T? = get(symbol.iden
|
||||
/**
|
||||
* Set a value of [String]-keyed map by a [Symbol]
|
||||
*/
|
||||
public operator fun <T> MutableMap<String, T>.set(symbol: Symbol, value: T){
|
||||
public operator fun <T> MutableMap<String, T>.set(symbol: Symbol, value: T) {
|
||||
set(symbol.identity, value)
|
||||
}
|
||||
|
||||
@ -59,6 +60,6 @@ public operator fun <T> Map<Symbol, T>.get(string: String): T? = get(StringSymbo
|
||||
/**
|
||||
* Set a value of [String]-keyed map by a [Symbol]
|
||||
*/
|
||||
public operator fun <T> MutableMap<Symbol, T>.set(string: String, value: T){
|
||||
public operator fun <T> MutableMap<Symbol, T>.set(string: String, value: T) {
|
||||
set(StringSymbol(string), value)
|
||||
}
|
@ -6,7 +6,6 @@
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.misc.Symbol
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.Structure2D
|
||||
import space.kscience.kmath.structures.BufferFactory
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.kmath.misc.PerformancePitfall
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import space.kscience.kmath.operations.invoke
|
||||
@ -50,6 +51,7 @@ public class BufferedLinearSpace<T : Any, A : Ring<T>>(
|
||||
this
|
||||
}
|
||||
|
||||
@OptIn(PerformancePitfall::class)
|
||||
override fun Matrix<T>.dot(other: Matrix<T>): Matrix<T> {
|
||||
require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
|
||||
return elementAlgebra {
|
||||
@ -67,6 +69,7 @@ public class BufferedLinearSpace<T : Any, A : Ring<T>>(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(PerformancePitfall::class)
|
||||
override fun Matrix<T>.dot(vector: Point<T>): Point<T> {
|
||||
require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
|
||||
return elementAlgebra {
|
||||
|
@ -19,6 +19,7 @@ import kotlin.reflect.KClass
|
||||
* @param T the type of items.
|
||||
*/
|
||||
public typealias Matrix<T> = Structure2D<T>
|
||||
public typealias MutableMatrix<T> = MutableStructure2D<T>
|
||||
|
||||
/**
|
||||
* Alias or using [Buffer] as a point/vector in a many-dimensional space.
|
||||
|
@ -8,7 +8,7 @@ package space.kscience.kmath.linear
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.Ring
|
||||
|
||||
public class MatrixBuilder<T : Any, A : Ring<T>>(
|
||||
public class MatrixBuilder<T : Any, out A : Ring<T>>(
|
||||
public val linearSpace: LinearSpace<T, A>,
|
||||
public val rows: Int,
|
||||
public val columns: Int,
|
||||
|
@ -75,6 +75,23 @@ public object LFeature : MatrixFeature
|
||||
*/
|
||||
public object UFeature : MatrixFeature
|
||||
|
||||
/**
|
||||
* Matrices with this feature support LU factorization: *a = [l] · [u]* where *a* is the owning matrix.
|
||||
*
|
||||
* @param T the type of matrices' items.
|
||||
*/
|
||||
public interface LUDecompositionFeature<T : Any> : MatrixFeature {
|
||||
/**
|
||||
* The lower triangular matrix in this decomposition. It may have [LFeature].
|
||||
*/
|
||||
public val l: Matrix<T>
|
||||
|
||||
/**
|
||||
* The upper triangular matrix in this decomposition. It may have [UFeature].
|
||||
*/
|
||||
public val u: Matrix<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* Matrices with this feature support LU factorization with partial pivoting: *[p] · a = [l] · [u]* where
|
||||
* *a* is the owning matrix.
|
||||
|
@ -16,7 +16,7 @@ import kotlin.reflect.KClass
|
||||
*
|
||||
* @param T the type of items.
|
||||
*/
|
||||
public class MatrixWrapper<T : Any> internal constructor(
|
||||
public class MatrixWrapper<out T : Any> internal constructor(
|
||||
public val origin: Matrix<T>,
|
||||
public val features: Set<MatrixFeature>,
|
||||
) : Matrix<T> by origin {
|
||||
@ -26,12 +26,11 @@ public class MatrixWrapper<T : Any> internal constructor(
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <F : StructureFeature> getFeature(type: KClass<out F>): F? = features.singleOrNull { type.isInstance(it) } as? F
|
||||
?: origin.getFeature(type)
|
||||
public override fun <F : StructureFeature> getFeature(type: KClass<out F>): F? =
|
||||
features.singleOrNull(type::isInstance) as? F
|
||||
?: origin.getFeature(type)
|
||||
|
||||
override fun toString(): String {
|
||||
return "MatrixWrapper(matrix=$origin, features=$features)"
|
||||
}
|
||||
public override fun toString(): String = "MatrixWrapper(matrix=$origin, features=$features)"
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,7 +81,7 @@ public fun <T : Any> LinearSpace<T, Ring<T>>.zero(
|
||||
elementAlgebra.zero
|
||||
} + ZeroFeature
|
||||
|
||||
public class TransposedFeature<T : Any>(public val original: Matrix<T>) : MatrixFeature
|
||||
public class TransposedFeature<out T : Any>(public val original: Matrix<T>) : MatrixFeature
|
||||
|
||||
/**
|
||||
* Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A`
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user