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:
Alexander Nozik 2021-05-24 14:44:08 +03:00
commit 3ec674c61b
218 changed files with 8520 additions and 3157 deletions

View File

@ -13,9 +13,11 @@ jobs:
- name: Checkout the repo - name: Checkout the repo
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up JDK 11 - name: Set up JDK 11
uses: actions/setup-java@v1 uses: DeLaGuardo/setup-graalvm@4.0
with: with:
java-version: 11 graalvm: 21.1.0
java: java11
arch: amd64
- name: Add msys to path - name: Add msys to path
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"

View File

@ -15,24 +15,8 @@ jobs:
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 11 java-version: 11
- name: Cache gradle
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
ubuntu-20.04-gradle-
- name: Cache konan
uses: actions/cache@v2
with:
path: ~/.konan
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build - name: Build
run: | run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
mv build/dokka/htmlMultiModule/-modules.html build/dokka/htmlMultiModule/index.html
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@4.1.0 uses: JamesIves/github-pages-deploy-action@4.1.0
with: with:

View File

@ -18,9 +18,11 @@ jobs:
- name: Checkout the repo - name: Checkout the repo
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up JDK 11 - name: Set up JDK 11
uses: actions/setup-java@v1 uses: DeLaGuardo/setup-graalvm@4.0
with: with:
java-version: 11 graalvm: 21.1.0
java: java11
arch: amd64
- name: Add msys to path - name: Add msys to path
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"

View File

@ -10,20 +10,31 @@
- Blocking chains and Statistics - Blocking chains and Statistics
- Multiplatform integration - Multiplatform integration
- Integration for any Field element - 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 ### Changed
- Exponential operations merged with hyperbolic functions - Exponential operations merged with hyperbolic functions
- Space is replaced by Group. Space is reserved for vector spaces. - Space is replaced by Group. Space is reserved for vector spaces.
- VectorSpace is now a vector space - VectorSpace is now a vector space
- Buffer factories for primitives moved to MutableBuffer.Companion - Buffer factories for primitives moved to MutableBuffer.Companion
- NDStructure and NDAlgebra to StructureND and AlgebraND respectively - Rename `NDStructure` and `NDAlgebra` to `StructureND` and `AlgebraND` respectively
- Real -> Double - `Real` -> `Double`
- DataSets are moved from functions to core - DataSets are moved from functions to core
- Redesign advanced Chain API - Redesign advanced Chain API
- Redesign MST. Remove MSTExpression. - Redesign `MST`. Remove `MstExpression`.
- Move MST to core - Move `MST` to core
- Separated benchmarks and examples - 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 ### Deprecated
@ -33,6 +44,7 @@
- `contentEquals` from Buffer. It moved to the companion. - `contentEquals` from Buffer. It moved to the companion.
- MSTExpression - MSTExpression
- Expression algebra builders - Expression algebra builders
- Complex and Quaternion no longer are elements.
### Fixed ### Fixed
- Ring inherits RingOperations, not GroupOperations - Ring inherits RingOperations, not GroupOperations

View File

@ -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. * **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. * **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. * **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
<!--Current feature list is [here](/docs/features.md)--> <!--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) * ### [kmath-ast](kmath-ast)
> >
> >
> **Maturity**: PROTOTYPE > **Maturity**: EXPERIMENTAL
> >
> **Features:** > **Features:**
> - [expression-language](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser > - [expression-language](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
@ -154,9 +154,9 @@ performance calculations to code generation.
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
> >
> **Features:** > **Features:**
> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix. > - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : Point implementations.
> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix. > - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : Matrix implementation.
> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix. > - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : LinearSpace implementations.
<hr/> <hr/>
@ -200,12 +200,23 @@ One can still use generic algebras though.
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
<hr/> <hr/>
* ### [kmath-kotlingrad](kmath-kotlingrad) * ### [kmath-jupyter](kmath-jupyter)
> >
> >
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
<hr/> <hr/>
* ### [kmath-kotlingrad](kmath-kotlingrad)
> Functions, integration and interpolation
>
> **Maturity**: EXPERIMENTAL
>
> **Features:**
> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : MST based DifferentiableExpression.
> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST
<hr/>
* ### [kmath-memory](kmath-memory) * ### [kmath-memory](kmath-memory)
> An API and basic implementation for arranging objects in a continous memory block. > An API and basic implementation for arranging objects in a continous memory block.
> >
@ -230,6 +241,18 @@ One can still use generic algebras though.
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
<hr/> <hr/>
* ### [kmath-tensors](kmath-tensors)
>
>
> **Maturity**: PROTOTYPE
>
> **Features:**
> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : 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) * ### [kmath-viktor](kmath-viktor)
> >
> >
@ -270,8 +293,8 @@ repositories {
} }
dependencies { dependencies {
api("space.kscience:kmath-core:0.3.0-dev-7") api("space.kscience:kmath-core:0.3.0-dev-11")
// api("space.kscience:kmath-core-jvm:0.3.0-dev-7") for jvm-specific version // api("space.kscience:kmath-core-jvm:0.3.0-dev-11") for jvm-specific version
} }
``` ```

View File

@ -9,14 +9,10 @@ sourceSets.register("benchmarks")
repositories { repositories {
mavenCentral() mavenCentral()
jcenter()
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
maven("https://clojars.org/repo") maven("https://clojars.org/repo")
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
maven("https://dl.bintray.com/hotkeytlt/maven")
maven("https://jitpack.io") maven("https://jitpack.io")
maven { maven("http://logicrunch.research.it.uu.se/maven") {
setUrl("http://logicrunch.research.it.uu.se/maven/")
isAllowInsecureProtocol = true isAllowInsecureProtocol = true
} }
} }

View File

@ -10,20 +10,19 @@ import kotlinx.benchmark.Blackhole
import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State import org.openjdk.jmh.annotations.State
import space.kscience.kmath.operations.BigInt import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.BigIntField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.JBigIntegerField import java.math.BigInteger
import space.kscience.kmath.operations.invoke
private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ZERO)
@UnstableKMathAPI
@State(Scope.Benchmark) @State(Scope.Benchmark)
internal class BigIntBenchmark { internal class BigIntBenchmark {
val kmNumber = BigIntField.number(Int.MAX_VALUE) val kmNumber = BigIntField.number(Int.MAX_VALUE)
val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE) val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE)
val largeKmNumber = BigIntField { number(11).pow(100_000) } val largeKmNumber = BigIntField { number(11).pow(100_000U) }
val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) } val largeJvmNumber: BigInteger = JBigIntegerField { number(11).pow(100_000) }
val bigExponent = 50_000 val bigExponent = 50_000
@Benchmark @Benchmark
@ -36,6 +35,16 @@ internal class BigIntBenchmark {
blackhole.consume(jvmNumber + jvmNumber + jvmNumber) 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 @Benchmark
fun kmMultiply(blackhole: Blackhole) = BigIntField { fun kmMultiply(blackhole: Blackhole) = BigIntField {
blackhole.consume(kmNumber * kmNumber * kmNumber) blackhole.consume(kmNumber * kmNumber * kmNumber)
@ -56,13 +65,33 @@ internal class BigIntBenchmark {
blackhole.consume(largeJvmNumber*largeJvmNumber) blackhole.consume(largeJvmNumber*largeJvmNumber)
} }
// @Benchmark @Benchmark
// fun kmPower(blackhole: Blackhole) = BigIntField { fun kmPower(blackhole: Blackhole) = BigIntField {
// blackhole.consume(kmNumber.pow(bigExponent)) blackhole.consume(kmNumber.pow(bigExponent.toUInt()))
// } }
//
// @Benchmark @Benchmark
// fun jvmPower(blackhole: Blackhole) = JBigIntegerField { fun jvmPower(blackhole: Blackhole) = JBigIntegerField {
// blackhole.consume(jvmNumber.pow(bigExponent)) 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))
}
} }

View File

@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope import kotlinx.benchmark.Scope
import kotlinx.benchmark.State import kotlinx.benchmark.State
import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.commons.linear.CMLinearSpace
import space.kscience.kmath.ejml.EjmlLinearSpace import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.LinearSpace
import space.kscience.kmath.linear.invoke import space.kscience.kmath.linear.invoke
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
@ -29,8 +29,8 @@ internal class DotBenchmark {
val cmMatrix1 = CMLinearSpace { matrix1.toCM() } val cmMatrix1 = CMLinearSpace { matrix1.toCM() }
val cmMatrix2 = CMLinearSpace { matrix2.toCM() } val cmMatrix2 = CMLinearSpace { matrix2.toCM() }
val ejmlMatrix1 = EjmlLinearSpace { matrix1.toEjml() } val ejmlMatrix1 = EjmlLinearSpaceDDRM { matrix1.toEjml() }
val ejmlMatrix2 = EjmlLinearSpace { matrix2.toEjml() } val ejmlMatrix2 = EjmlLinearSpaceDDRM { matrix2.toEjml() }
} }
@Benchmark @Benchmark
@ -42,14 +42,14 @@ internal class DotBenchmark {
@Benchmark @Benchmark
fun ejmlDot(blackhole: Blackhole) { fun ejmlDot(blackhole: Blackhole) {
EjmlLinearSpace { EjmlLinearSpaceDDRM {
blackhole.consume(ejmlMatrix1 dot ejmlMatrix2) blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
} }
} }
@Benchmark @Benchmark
fun ejmlDotWithConversion(blackhole: Blackhole) { fun ejmlDotWithConversion(blackhole: Blackhole) {
EjmlLinearSpace { EjmlLinearSpaceDDRM {
blackhole.consume(matrix1 dot matrix2) blackhole.consume(matrix1 dot matrix2)
} }
} }

View File

@ -11,8 +11,6 @@ import kotlinx.benchmark.Scope
import kotlinx.benchmark.State import kotlinx.benchmark.State
import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.asm.compileToExpression
import space.kscience.kmath.expressions.* import space.kscience.kmath.expressions.*
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke

View File

@ -11,25 +11,26 @@ import kotlinx.benchmark.Scope
import kotlinx.benchmark.State import kotlinx.benchmark.State
import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.commons.linear.CMLinearSpace
import space.kscience.kmath.commons.linear.inverse import space.kscience.kmath.commons.linear.inverse
import space.kscience.kmath.ejml.EjmlLinearSpace import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
import space.kscience.kmath.ejml.inverse import space.kscience.kmath.linear.InverseMatrixFeature
import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.LinearSpace
import space.kscience.kmath.linear.inverseWithLup import space.kscience.kmath.linear.inverseWithLup
import space.kscience.kmath.linear.invoke import space.kscience.kmath.linear.invoke
import space.kscience.kmath.nd.getFeature
import kotlin.random.Random import kotlin.random.Random
@State(Scope.Benchmark) @State(Scope.Benchmark)
internal class MatrixInverseBenchmark { internal class MatrixInverseBenchmark {
companion object { private companion object {
val random = Random(1224) private val random = Random(1224)
const val dim = 100 private const val dim = 100
private val space = LinearSpace.real private val space = LinearSpace.real
//creating invertible matrix //creating invertible matrix
val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } private val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 } private val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
val matrix = space { l dot u } private val matrix = space { l dot u }
} }
@Benchmark @Benchmark
@ -46,8 +47,8 @@ internal class MatrixInverseBenchmark {
@Benchmark @Benchmark
fun ejmlInverse(blackhole: Blackhole) { fun ejmlInverse(blackhole: Blackhole) {
with(EjmlLinearSpace) { with(EjmlLinearSpaceDDRM) {
blackhole.consume(inverse(matrix)) blackhole.consume(matrix.getFeature<InverseMatrixFeature<Double>>()?.inverse)
} }
} }
} }

View File

@ -1,44 +1,37 @@
plugins { plugins {
id("ru.mipt.npm.gradle.project") id("ru.mipt.npm.gradle.project")
kotlin("jupyter.api") apply false
} }
allprojects { allprojects {
repositories { repositories {
jcenter()
maven("https://clojars.org/repo") maven("https://clojars.org/repo")
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
maven("https://dl.bintray.com/hotkeytlt/maven")
maven("https://jitpack.io") maven("https://jitpack.io")
maven("http://logicrunch.research.it.uu.se/maven/") { maven("http://logicrunch.research.it.uu.se/maven") {
isAllowInsecureProtocol = true isAllowInsecureProtocol = true
} }
maven("https://oss.sonatype.org/content/repositories/snapshots")
mavenCentral() mavenCentral()
} }
group = "space.kscience" group = "space.kscience"
version = "0.3.0-dev-7" version = "0.3.0-dev-13"
} }
subprojects { subprojects {
if (name.startsWith("kmath")) apply<MavenPublishPlugin>() if (name.startsWith("kmath")) apply<MavenPublishPlugin>()
afterEvaluate { afterEvaluate {
tasks.withType<org.jetbrains.dokka.gradle.DokkaTask> { tasks.withType<org.jetbrains.dokka.gradle.DokkaTaskPartial> {
dokkaSourceSets.all { dependsOn(tasks.getByName("assemble"))
val readmeFile = File(this@subprojects.projectDir, "./README.md")
if (readmeFile.exists())
includes.setFrom(includes + readmeFile.absolutePath)
arrayOf( dokkaSourceSets.all {
"http://ejml.org/javadoc/", val readmeFile = File(this@subprojects.projectDir, "README.md")
"https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/", if (readmeFile.exists()) includes.setFrom(includes + readmeFile.absolutePath)
"https://deeplearning4j.org/api/latest/" externalDocumentationLink("http://ejml.org/javadoc/")
).map { java.net.URL("${it}package-list") to java.net.URL(it) }.forEach { (a, b) -> externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/")
externalDocumentationLink { externalDocumentationLink("https://deeplearning4j.org/api/latest/")
packageListUrl.set(a) externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/")
url.set(b)
}
}
} }
} }
} }

View File

@ -0,0 +1,5 @@
plugins {
`kotlin-dsl`
}
repositories.mavenCentral()

View File

@ -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> &middot; [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> &middot; [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,
)
}
}

View File

@ -6,8 +6,7 @@ The Maven coordinates of this project are `${group}:${name}:${version}`.
```gradle ```gradle
repositories { repositories {
maven { url 'https://repo.kotlin.link' } maven { url 'https://repo.kotlin.link' }
maven { url 'https://dl.bintray.com/hotkeytlt/maven' } mavenCentral()
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
} }
dependencies { dependencies {
@ -18,8 +17,7 @@ dependencies {
```kotlin ```kotlin
repositories { repositories {
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap mavenCentral()
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
} }
dependencies { dependencies {

View File

@ -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. * **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. * **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. * **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
<!--Current feature list is [here](/docs/features.md)--> <!--Current feature list is [here](/docs/features.md)-->

View File

@ -4,14 +4,11 @@ plugins {
repositories { repositories {
mavenCentral() mavenCentral()
jcenter()
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
maven("https://clojars.org/repo") maven("https://clojars.org/repo")
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
maven("https://dl.bintray.com/hotkeytlt/maven")
maven("https://jitpack.io") maven("https://jitpack.io")
maven{ maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers")
setUrl("http://logicrunch.research.it.uu.se/maven/") maven("http://logicrunch.research.it.uu.se/maven") {
isAllowInsecureProtocol = true isAllowInsecureProtocol = true
} }
} }
@ -28,6 +25,7 @@ dependencies {
implementation(project(":kmath-dimensions")) implementation(project(":kmath-dimensions"))
implementation(project(":kmath-ejml")) implementation(project(":kmath-ejml"))
implementation(project(":kmath-nd4j")) implementation(project(":kmath-nd4j"))
implementation(project(":kmath-tensors"))
implementation(project(":kmath-for-real")) implementation(project(":kmath-for-real"))
@ -45,7 +43,7 @@ dependencies {
implementation("org.slf4j:slf4j-simple:1.7.30") implementation("org.slf4j:slf4j-simple:1.7.30")
// plotting // plotting
implementation("space.kscience:plotlykt-server:0.4.0-dev-2") implementation("space.kscience:plotlykt-server:0.4.0")
} }
kotlin.sourceSets.all { kotlin.sourceSets.all {
@ -59,7 +57,7 @@ kotlin.sourceSets.all {
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> { tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions{ kotlinOptions{
jvmTarget = "11" jvmTarget = "11"
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn"
} }
} }

View File

@ -6,8 +6,8 @@
package space.kscience.kmath.ast package space.kscience.kmath.ast
import space.kscience.kmath.expressions.MstField import space.kscience.kmath.expressions.MstField
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.interpret 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.DoubleField
import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke

View File

@ -8,8 +8,8 @@ package space.kscience.kmath.ast
import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.asm.compileToExpression
import space.kscience.kmath.expressions.derivative import space.kscience.kmath.expressions.derivative
import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.kotlingrad.toDiffExpression import space.kscience.kmath.kotlingrad.toDiffExpression
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
/** /**

View File

@ -10,7 +10,7 @@ import kotlinx.html.h3
import space.kscience.kmath.commons.optimization.chiSquared import space.kscience.kmath.commons.optimization.chiSquared
import space.kscience.kmath.commons.optimization.minimize import space.kscience.kmath.commons.optimization.minimize
import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.misc.symbol import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.optimization.FunctionOptimization
import space.kscience.kmath.optimization.OptimizationResult import space.kscience.kmath.optimization.OptimizationResult
import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.DoubleVector

View File

@ -5,7 +5,8 @@
package space.kscience.kmath.functions 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.integration.value
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import kotlin.math.pow import kotlin.math.pow
@ -15,7 +16,7 @@ fun main() {
val function: UnivariateFunction<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 } val function: UnivariateFunction<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 }
//get the result of the integration //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 //the value is nullable because in some cases the integration could not succeed
println(result.value) println(result.value)

View File

@ -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()
}

View File

@ -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()
}

View File

@ -5,7 +5,8 @@
package space.kscience.kmath.functions 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.integration.value
import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.nd.nd 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 } val function: (Double) -> StructureND<Double> = { x: Double -> 3 * number(x).pow(2) + 2 * diagonal(x) + 1 }
//get the result of the integration //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 //the value is nullable because in some cases the integration could not succeed
println(result.value) println(result.value)

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import org.nd4j.linalg.factory.Nd4j import org.nd4j.linalg.factory.Nd4j
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.*
@ -22,6 +23,7 @@ internal inline fun measureAndPrint(title: String, block: () -> Unit) {
println("$title completed in $time millis") println("$title completed in $time millis")
} }
@OptIn(DelicateCoroutinesApi::class)
fun main() { fun main() {
// initializing Nd4j // initializing Nd4j
Nd4j.zeros(0) Nd4j.zeros(0)

View File

@ -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)}")
}

View File

@ -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")
}

View File

@ -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")
}

View File

@ -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)}")
}
}

View 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")
}

View File

@ -1,6 +1,6 @@
# Module kmath-ast # Module kmath-ast
Abstract syntax tree expression representation and related optimizations. Performance and visualization extensions to MST API.
- [expression-language](src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser - [expression-language](src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
- [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler - [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
@ -10,30 +10,28 @@ Abstract syntax tree expression representation and related optimizations.
## Artifact: ## 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:**
```gradle ```gradle
repositories { repositories {
maven { url 'https://repo.kotlin.link' } maven { url 'https://repo.kotlin.link' }
maven { url 'https://dl.bintray.com/hotkeytlt/maven' } mavenCentral()
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
} }
dependencies { dependencies {
implementation 'space.kscience:kmath-ast:0.3.0-dev-7' implementation 'space.kscience:kmath-ast:0.3.0-dev-11'
} }
``` ```
**Gradle Kotlin DSL:** **Gradle Kotlin DSL:**
```kotlin ```kotlin
repositories { repositories {
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap mavenCentral()
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
} }
dependencies { dependencies {
implementation("space.kscience:kmath-ast:0.3.0-dev-7") implementation("space.kscience:kmath-ast:0.3.0-dev-11")
} }
``` ```
@ -41,21 +39,26 @@ dependencies {
### On JVM ### On JVM
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds `kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a
a special implementation of `Expression<T>` with implemented `invoke` function. special implementation of `Expression<T>` with implemented `invoke` function.
For example, the following builder: For example, the following builder:
```kotlin ```kotlin
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.asm.*
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
``` ```
… leads to generation of bytecode, which can be decompiled to the following Java class: ... leads to generation of bytecode, which can be decompiled to the following Java class:
```java ```java
package space.kscience.kmath.asm.generated; package space.kscience.kmath.asm.generated;
import java.util.Map; import java.util.Map;
import kotlin.jvm.functions.Function2; import kotlin.jvm.functions.Function2;
import space.kscience.kmath.asm.internal.MapIntrinsics; import space.kscience.kmath.asm.internal.MapIntrinsics;
import space.kscience.kmath.expressions.Expression; import space.kscience.kmath.expressions.Expression;
@ -65,7 +68,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
private final Object[] constants; private final Object[] constants;
public final Double invoke(Map<Symbol, ? extends Double> arguments) { public final Double invoke(Map<Symbol, ? extends Double> arguments) {
return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2); return (Double) ((Function2) this.constants[0]).invoke((Double) MapIntrinsics.getOrFail(arguments, "x"), 2);
} }
public AsmCompiledExpression_45045_0(Object[] constants) { public AsmCompiledExpression_45045_0(Object[] constants) {
@ -77,8 +80,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
#### Known issues #### Known issues
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid - The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class
class loading overhead. loading overhead.
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders. - This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
### On JS ### On JS
@ -86,6 +89,10 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
A similar feature is also available on JS. A similar feature is also available on JS.
```kotlin ```kotlin
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.estree.*
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
``` ```
@ -97,14 +104,18 @@ var executable = function (constants, arguments) {
}; };
``` ```
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
```kotlin ```kotlin
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.wasm.* import space.kscience.kmath.wasm.*
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) 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 ```lisp
(func $executable (param $0 f64) (result f64) (func $executable (param $0 f64) (result f64)
@ -129,9 +140,11 @@ Example usage:
```kotlin ```kotlin
import space.kscience.kmath.ast.* import space.kscience.kmath.ast.*
import space.kscience.kmath.ast.rendering.* import space.kscience.kmath.ast.rendering.*
import space.kscience.kmath.misc.*
@OptIn(UnstableKMathAPI::class)
public fun main() { public fun main() {
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(12)+x^(2/3)".parseMath()
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax) val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax)
println("LaTeX:") println("LaTeX:")
@ -145,13 +158,78 @@ public fun main() {
Result LaTeX: Result LaTeX:
![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) ![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3})
Result MathML (embedding MathML is not allowed by GitHub Markdown): Result MathML (can be used with MathJax or other renderers):
<details>
```html ```html
<mrow><msup><mrow><mi>e</mi></mrow><mrow><msqrt><mi>x</mi></msqrt></mrow></msup><mo>-</mo><mfrac><mrow><mfrac><mrow><msup><mrow><mo>sin</mo></mrow><mrow><mo>-</mo><mn>1</mn></mrow></msup><mspace width="0.167em"></mspace><mfenced open="(" close=")" separators=""><mn>2</mn><mspace width="0.167em"></mspace><mi>x</mi></mfenced></mrow><mrow><mn>2</mn><mo>&times;</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>&times;</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 It is also possible to create custom algorithms of render, and even add support of other markup languages
(see API reference). (see API reference).

View File

@ -18,6 +18,10 @@ kotlin.js {
} }
kotlin.sourceSets { kotlin.sourceSets {
filter { it.name.contains("test", true) }
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
.forEach { it.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") }
commonMain { commonMain {
dependencies { dependencies {
api("com.github.h0tk3y.betterParse:better-parse:0.4.2") api("com.github.h0tk3y.betterParse:better-parse:0.4.2")
@ -54,7 +58,7 @@ tasks.dokkaHtml {
} }
readme { readme {
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
feature( feature(

View File

@ -1,6 +1,6 @@
# Module kmath-ast # Module kmath-ast
Abstract syntax tree expression representation and related optimizations. Performance and visualization extensions to MST API.
${features} ${features}
@ -10,21 +10,26 @@ ${artifact}
### On JVM ### On JVM
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds `kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a
a special implementation of `Expression<T>` with implemented `invoke` function. special implementation of `Expression<T>` with implemented `invoke` function.
For example, the following builder: For example, the following builder:
```kotlin ```kotlin
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.asm.*
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
``` ```
… leads to generation of bytecode, which can be decompiled to the following Java class: ... leads to generation of bytecode, which can be decompiled to the following Java class:
```java ```java
package space.kscience.kmath.asm.generated; package space.kscience.kmath.asm.generated;
import java.util.Map; import java.util.Map;
import kotlin.jvm.functions.Function2; import kotlin.jvm.functions.Function2;
import space.kscience.kmath.asm.internal.MapIntrinsics; import space.kscience.kmath.asm.internal.MapIntrinsics;
import space.kscience.kmath.expressions.Expression; import space.kscience.kmath.expressions.Expression;
@ -34,7 +39,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
private final Object[] constants; private final Object[] constants;
public final Double invoke(Map<Symbol, ? extends Double> arguments) { public final Double invoke(Map<Symbol, ? extends Double> arguments) {
return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2); return (Double) ((Function2) this.constants[0]).invoke((Double) MapIntrinsics.getOrFail(arguments, "x"), 2);
} }
public AsmCompiledExpression_45045_0(Object[] constants) { public AsmCompiledExpression_45045_0(Object[] constants) {
@ -46,8 +51,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
#### Known issues #### Known issues
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid - The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class
class loading overhead. loading overhead.
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders. - This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
### On JS ### On JS
@ -55,6 +60,10 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
A similar feature is also available on JS. A similar feature is also available on JS.
```kotlin ```kotlin
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.estree.*
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
``` ```
@ -66,14 +75,18 @@ var executable = function (constants, arguments) {
}; };
``` ```
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
```kotlin ```kotlin
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.wasm.* import space.kscience.kmath.wasm.*
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) 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 ```lisp
(func \$executable (param \$0 f64) (result f64) (func \$executable (param \$0 f64) (result f64)
@ -98,9 +111,11 @@ Example usage:
```kotlin ```kotlin
import space.kscience.kmath.ast.* import space.kscience.kmath.ast.*
import space.kscience.kmath.ast.rendering.* import space.kscience.kmath.ast.rendering.*
import space.kscience.kmath.misc.*
@OptIn(UnstableKMathAPI::class)
public fun main() { public fun main() {
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(12)+x^(2/3)".parseMath()
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax) val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax)
println("LaTeX:") println("LaTeX:")
@ -114,13 +129,78 @@ public fun main() {
Result LaTeX: Result LaTeX:
![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) ![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3})
Result MathML (embedding MathML is not allowed by GitHub Markdown): Result MathML (can be used with MathJax or other renderers):
<details>
```html ```html
<mrow><msup><mrow><mi>e</mi></mrow><mrow><msqrt><mi>x</mi></msqrt></mrow></msup><mo>-</mo><mfrac><mrow><mfrac><mrow><msup><mrow><mo>sin</mo></mrow><mrow><mo>-</mo><mn>1</mn></mrow></msup><mspace width="0.167em"></mspace><mfenced open="(" close=")" separators=""><mn>2</mn><mspace width="0.167em"></mspace><mi>x</mi></mfenced></mrow><mrow><mn>2</mn><mo>&times;</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>&times;</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 It is also possible to create custom algorithms of render, and even add support of other markup languages
(see API reference). (see API reference).

View File

@ -17,6 +17,7 @@ import com.github.h0tk3y.betterParse.lexer.regexToken
import com.github.h0tk3y.betterParse.parser.ParseResult import com.github.h0tk3y.betterParse.parser.ParseResult
import com.github.h0tk3y.betterParse.parser.Parser import com.github.h0tk3y.betterParse.parser.Parser
import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.StringSymbol
import space.kscience.kmath.operations.FieldOperations import space.kscience.kmath.operations.FieldOperations
import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.PowerOperations import space.kscience.kmath.operations.PowerOperations
@ -29,7 +30,6 @@ import space.kscience.kmath.operations.RingOperations
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
public object ArithmeticsEvaluator : Grammar<MST>() { public object ArithmeticsEvaluator : Grammar<MST>() {
// TODO replace with "...".toRegex() when better-parse 0.4.1 is released
private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?".toRegex()) private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?".toRegex())
private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*".toRegex()) private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*".toRegex())
private val lpar: Token by literalToken("(") private val lpar: Token by literalToken("(")
@ -43,7 +43,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
private val ws: Token by regexToken("\\s+".toRegex(), ignore = true) private val ws: Token by regexToken("\\s+".toRegex(), ignore = true)
private val number: Parser<MST> by num use { MST.Numeric(text.toDouble()) } 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) private val unaryFunction: Parser<MST> by (id and -lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
.map { (id, term) -> MST.Unary(id.text, term) } .map { (id, term) -> MST.Unary(id.text, term) }

View File

@ -5,6 +5,8 @@
package space.kscience.kmath.ast.rendering package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
/** /**
* [SyntaxRenderer] implementation for LaTeX. * [SyntaxRenderer] implementation for LaTeX.
* *
@ -23,6 +25,7 @@ package space.kscience.kmath.ast.rendering
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public object LatexSyntaxRenderer : SyntaxRenderer { public object LatexSyntaxRenderer : SyntaxRenderer {
public override fun render(node: MathSyntax, output: Appendable): Unit = output.run { public override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
fun render(syntax: MathSyntax) = render(syntax, output) fun render(syntax: MathSyntax) = render(syntax, output)
@ -115,7 +118,11 @@ public object LatexSyntaxRenderer : SyntaxRenderer {
render(node.right) render(node.right)
} }
is FractionSyntax -> { is FractionSyntax -> if (node.infix) {
render(node.left)
append('/')
render(node.right)
} else {
append("\\frac{") append("\\frac{")
render(node.left) render(node.left)
append("}{") append("}{")

View File

@ -5,6 +5,8 @@
package space.kscience.kmath.ast.rendering package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
/** /**
* [SyntaxRenderer] implementation for MathML. * [SyntaxRenderer] implementation for MathML.
* *
@ -12,14 +14,18 @@ package space.kscience.kmath.ast.rendering
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public object MathMLSyntaxRenderer : SyntaxRenderer { public object MathMLSyntaxRenderer : SyntaxRenderer {
public override fun render(node: MathSyntax, output: Appendable) { public override fun render(node: MathSyntax, output: Appendable) {
output.append("<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>") output.append("<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>")
render0(node, output) renderPart(node, output)
output.append("</mrow></math>") output.append("</mrow></math>")
} }
private fun render0(node: MathSyntax, output: Appendable): Unit = output.run { /**
* Renders a part of syntax returning a correct MathML tag not the whole MathML instance.
*/
public fun renderPart(node: MathSyntax, output: Appendable): Unit = output.run {
fun tag(tagName: String, vararg attr: Pair<String, String>, block: () -> Unit = {}) { fun tag(tagName: String, vararg attr: Pair<String, String>, block: () -> Unit = {}) {
append('<') append('<')
append(tagName) append(tagName)
@ -44,7 +50,7 @@ public object MathMLSyntaxRenderer : SyntaxRenderer {
append('>') append('>')
} }
fun render(syntax: MathSyntax) = render0(syntax, output) fun render(syntax: MathSyntax) = renderPart(syntax, output)
when (node) { when (node) {
is NumberSyntax -> tag("mn") { append(node.string) } is NumberSyntax -> tag("mn") { append(node.string) }
@ -127,14 +133,13 @@ public object MathMLSyntaxRenderer : SyntaxRenderer {
render(node.right) render(node.right)
} }
is FractionSyntax -> tag("mfrac") { is FractionSyntax -> if (node.infix) {
tag("mrow") {
render(node.left) render(node.left)
} tag("mo") { append('/') }
tag("mrow") {
render(node.right) render(node.right)
} } else tag("mfrac") {
tag("mrow") { render(node.left) }
tag("mrow") { render(node.right) }
} }
is RadicalWithIndexSyntax -> tag("mroot") { is RadicalWithIndexSyntax -> tag("mroot") {

View File

@ -6,12 +6,14 @@
package space.kscience.kmath.ast.rendering package space.kscience.kmath.ast.rendering
import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST
import space.kscience.kmath.misc.UnstableKMathAPI
/** /**
* Renders [MST] to [MathSyntax]. * Renders [MST] to [MathSyntax].
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun interface MathRenderer { public fun interface MathRenderer {
/** /**
* Renders [MST] to [MathSyntax]. * Renders [MST] to [MathSyntax].
@ -25,6 +27,7 @@ public fun interface MathRenderer {
* @property features The applied features. * @property features The applied features.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public open class FeaturedMathRenderer(public val features: List<RenderFeature>) : MathRenderer { public open class FeaturedMathRenderer(public val features: List<RenderFeature>) : MathRenderer {
public override fun render(mst: MST): MathSyntax { public override fun render(mst: MST): MathSyntax {
for (feature in features) feature.render(this, mst)?.let { return it } for (feature in features) feature.render(this, mst)?.let { return it }
@ -48,6 +51,7 @@ public open class FeaturedMathRenderer(public val features: List<RenderFeature>)
* @property stages The applied stages. * @property stages The applied stages.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public open class FeaturedMathRendererWithPostProcess( public open class FeaturedMathRendererWithPostProcess(
features: List<RenderFeature>, features: List<RenderFeature>,
public val stages: List<PostProcessStage>, public val stages: List<PostProcessStage>,
@ -85,6 +89,7 @@ public open class FeaturedMathRendererWithPostProcess(
SquareRoot.Default, SquareRoot.Default,
Exponent.Default, Exponent.Default,
InverseTrigonometricOperations.Default, InverseTrigonometricOperations.Default,
InverseHyperbolicOperations.Default,
// Fallback option for unknown operations - printing them as operator // Fallback option for unknown operations - printing them as operator
BinaryOperator.Default, BinaryOperator.Default,
@ -101,6 +106,7 @@ public open class FeaturedMathRendererWithPostProcess(
), ),
listOf( listOf(
BetterExponent, BetterExponent,
BetterFraction,
SimplifyParentheses.Default, SimplifyParentheses.Default,
BetterMultiplication, BetterMultiplication,
), ),

View File

@ -5,11 +5,14 @@
package space.kscience.kmath.ast.rendering package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
/** /**
* Mathematical typography syntax node. * Mathematical typography syntax node.
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public sealed class MathSyntax { public sealed class MathSyntax {
/** /**
* The parent node of this syntax node. * The parent node of this syntax node.
@ -22,6 +25,7 @@ public sealed class MathSyntax {
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public sealed class TerminalSyntax : MathSyntax() public sealed class TerminalSyntax : MathSyntax()
/** /**
@ -29,6 +33,7 @@ public sealed class TerminalSyntax : MathSyntax()
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public sealed class OperationSyntax : MathSyntax() { public sealed class OperationSyntax : MathSyntax() {
/** /**
* The operation token. * The operation token.
@ -41,6 +46,7 @@ public sealed class OperationSyntax : MathSyntax() {
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public sealed class UnarySyntax : OperationSyntax() { public sealed class UnarySyntax : OperationSyntax() {
/** /**
* The operand of this node. * The operand of this node.
@ -53,6 +59,7 @@ public sealed class UnarySyntax : OperationSyntax() {
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public sealed class BinarySyntax : OperationSyntax() { public sealed class BinarySyntax : OperationSyntax() {
/** /**
* The left-hand side operand. * The left-hand side operand.
@ -71,6 +78,7 @@ public sealed class BinarySyntax : OperationSyntax() {
* @property string The digits of number. * @property string The digits of number.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class NumberSyntax(public var string: String) : TerminalSyntax() public data class NumberSyntax(public var string: String) : TerminalSyntax()
/** /**
@ -79,6 +87,7 @@ public data class NumberSyntax(public var string: String) : TerminalSyntax()
* @property string The symbol. * @property string The symbol.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class SymbolSyntax(public var string: String) : TerminalSyntax() public data class SymbolSyntax(public var string: String) : TerminalSyntax()
/** /**
@ -89,14 +98,16 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax()
* @see UnaryOperatorSyntax * @see UnaryOperatorSyntax
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() public data class OperatorNameSyntax(public var name: String) : TerminalSyntax()
/** /**
* Represents a usage of special symbols. * Represents a usage of special symbols (e.g., *&infin;*).
* *
* @property kind The kind of symbol. * @property kind The kind of symbol.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() { public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() {
/** /**
* The kind of symbol. * The kind of symbol.
@ -121,6 +132,7 @@ public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax()
* @property parentheses Whether the operand should be wrapped with parentheses. * @property parentheses Whether the operand should be wrapped with parentheses.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class OperandSyntax( public data class OperandSyntax(
public val operand: MathSyntax, public val operand: MathSyntax,
public var parentheses: Boolean, public var parentheses: Boolean,
@ -131,11 +143,12 @@ public data class OperandSyntax(
} }
/** /**
* Represents unary, prefix operator syntax (like f x). * Represents unary, prefix operator syntax (like *f(x)*).
* *
* @property prefix The prefix. * @property prefix The prefix.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class UnaryOperatorSyntax( public data class UnaryOperatorSyntax(
public override val operation: String, public override val operation: String,
public var prefix: MathSyntax, public var prefix: MathSyntax,
@ -147,10 +160,11 @@ public data class UnaryOperatorSyntax(
} }
/** /**
* Represents prefix, unary plus operator. * Represents prefix, unary plus operator (*+x*).
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class UnaryPlusSyntax( public data class UnaryPlusSyntax(
public override val operation: String, public override val operation: String,
public override val operand: OperandSyntax, public override val operand: OperandSyntax,
@ -161,10 +175,11 @@ public data class UnaryPlusSyntax(
} }
/** /**
* Represents prefix, unary minus operator. * Represents prefix, unary minus operator (*-x*).
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class UnaryMinusSyntax( public data class UnaryMinusSyntax(
public override val operation: String, public override val operation: String,
public override val operand: OperandSyntax, public override val operand: OperandSyntax,
@ -175,11 +190,12 @@ public data class UnaryMinusSyntax(
} }
/** /**
* Represents radical with a node inside it. * Represents radical with a node inside it (*&radic;x*).
* *
* @property operand The radicand. * @property operand The radicand.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class RadicalSyntax( public data class RadicalSyntax(
public override val operation: String, public override val operation: String,
public override val operand: MathSyntax, public override val operand: MathSyntax,
@ -197,6 +213,7 @@ public data class RadicalSyntax(
* (*e<sup>x</sup>*). * (*e<sup>x</sup>*).
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class ExponentSyntax( public data class ExponentSyntax(
public override val operation: String, public override val operation: String,
public override val operand: OperandSyntax, 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 left The node.
* @property right The superscript. * @property right The superscript.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class SuperscriptSyntax( public data class SuperscriptSyntax(
public override val operation: String, public override val operation: String,
public override val left: MathSyntax, public override val left: MathSyntax,
@ -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 left The node.
* @property right The subscript. * @property right The subscript.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class SubscriptSyntax( public data class SubscriptSyntax(
public override val operation: String, public override val operation: String,
public override val left: MathSyntax, public override val left: MathSyntax,
@ -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. * @property prefix The prefix.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class BinaryOperatorSyntax( public data class BinaryOperatorSyntax(
public override val operation: String, public override val operation: String,
public var prefix: MathSyntax, public var prefix: MathSyntax,
@ -262,12 +282,13 @@ public data class BinaryOperatorSyntax(
} }
/** /**
* Represents binary, infix addition. * Represents binary, infix addition (*42 + 42*).
* *
* @param left The augend. * @param left The augend.
* @param right The addend. * @param right The addend.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class BinaryPlusSyntax( public data class BinaryPlusSyntax(
public override val operation: String, public override val operation: String,
public override val left: OperandSyntax, public override val left: OperandSyntax,
@ -280,12 +301,13 @@ public data class BinaryPlusSyntax(
} }
/** /**
* Represents binary, infix subtraction. * Represents binary, infix subtraction (*42 - 42*).
* *
* @param left The minuend. * @param left The minuend.
* @param right The subtrahend. * @param right The subtrahend.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class BinaryMinusSyntax( public data class BinaryMinusSyntax(
public override val operation: String, public override val operation: String,
public override val left: OperandSyntax, public override val left: OperandSyntax,
@ -302,12 +324,15 @@ public data class BinaryMinusSyntax(
* *
* @property left The numerator. * @property left The numerator.
* @property right The denominator. * @property right The denominator.
* @property infix Whether infix (*1 / 2*) or normal (*&frac12;*) fraction should be made.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class FractionSyntax( public data class FractionSyntax(
public override val operation: String, public override val operation: String,
public override val left: MathSyntax, public override val left: OperandSyntax,
public override val right: MathSyntax, public override val right: OperandSyntax,
public var infix: Boolean,
) : BinarySyntax() { ) : BinarySyntax() {
init { init {
left.parent = this left.parent = this
@ -316,12 +341,13 @@ public data class FractionSyntax(
} }
/** /**
* Represents radical syntax with index. * Represents radical syntax with index (*<sup>3</sup>&radic;x*).
* *
* @property left The index. * @property left The index.
* @property right The radicand. * @property right The radicand.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class RadicalWithIndexSyntax( public data class RadicalWithIndexSyntax(
public override val operation: String, public override val operation: String,
public override val left: MathSyntax, public override val left: MathSyntax,
@ -334,13 +360,14 @@ public data class RadicalWithIndexSyntax(
} }
/** /**
* Represents binary, infix multiplication in the form of coefficient (2 x) or with operator (x&times;2). * Represents binary, infix multiplication in the form of coefficient (*2 x*) or with operator (*x &times; 2*).
* *
* @property left The multiplicand. * @property left The multiplicand.
* @property right The multiplier. * @property right The multiplier.
* @property times whether the times (&times;) symbol should be used. * @property times Whether the times (&times;) symbol should be used.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public data class MultiplicationSyntax( public data class MultiplicationSyntax(
public override val operation: String, public override val operation: String,
public override val left: OperandSyntax, public override val left: OperandSyntax,

View File

@ -5,12 +5,15 @@
package space.kscience.kmath.ast.rendering package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
/** /**
* Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should * Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should
* involve traversal of MathSyntax with handling each its subtype. * involve traversal of MathSyntax with handling each its subtype.
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun interface SyntaxRenderer { public fun interface SyntaxRenderer {
/** /**
* Renders the [MathSyntax] to [output]. * Renders the [MathSyntax] to [output].
@ -23,6 +26,7 @@ public fun interface SyntaxRenderer {
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String { public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String {
val sb = StringBuilder() val sb = StringBuilder()
render(node, sb) render(node, sb)

View File

@ -7,6 +7,8 @@ package space.kscience.kmath.ast.rendering
import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature
import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -15,11 +17,11 @@ import kotlin.reflect.KClass
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public object PrintSymbolic : RenderFeature { public object PrintSymbolic : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? =
if (node !is MST.Symbolic) return null if (node !is Symbol) null
return SymbolSyntax(string = node.value) else SymbolSyntax(string = node.identity)
}
} }
/** /**
@ -27,35 +29,38 @@ public object PrintSymbolic : RenderFeature {
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public object PrintNumeric : RenderFeature { public object PrintNumeric : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { public override fun render(renderer: FeaturedMathRenderer, node: MST): NumberSyntax? = if (node !is MST.Numeric)
if (node !is MST.Numeric) return null null
return NumberSyntax(string = node.value.toString()) else
} NumberSyntax(string = node.value.toString())
} }
private fun printSignedNumberString(s: String): MathSyntax { @UnstableKMathAPI
if (s.startsWith('-')) private fun printSignedNumberString(s: String): MathSyntax = if (s.startsWith('-'))
return UnaryMinusSyntax( UnaryMinusSyntax(
operation = GroupOperations.MINUS_OPERATION, operation = GroupOperations.MINUS_OPERATION,
operand = OperandSyntax( operand = OperandSyntax(
operand = NumberSyntax(string = s.removePrefix("-")), operand = NumberSyntax(string = s.removePrefix("-")),
parentheses = true, parentheses = true,
), ),
) )
else
return NumberSyntax(string = s) NumberSyntax(string = s)
}
/** /**
* Special printing for numeric types which are printed in form of * Special printing for numeric types which are printed in form of
* *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*. * *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*.
* *
* @property types The suitable types. * @property types The suitable types.
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature { public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Numeric || node.value::class !in types) return null if (node !is MST.Numeric || node.value::class !in types) return null
val toString = when (val v = node.value) { val toString = when (val v = node.value) {
is Float -> v.multiplatformToString() is Float -> v.multiplatformToString()
is Double -> 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+*. * Special printing for numeric types which are printed in form of *'-'? DIGIT+*.
* *
* @property types The suitable types. * @property types The suitable types.
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature { public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
if (node !is MST.Numeric || node.value::class !in types) return null if (node !is MST.Numeric || node.value::class !in types)
return printSignedNumberString(node.value.toString()) null
} else
printSignedNumberString(node.value.toString())
public companion object { public companion object {
/** /**
@ -129,12 +137,15 @@ public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : Re
* Special printing for symbols meaning Pi. * Special printing for symbols meaning Pi.
* *
* @property symbols The allowed symbols. * @property symbols The allowed symbols.
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature { public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? =
if (node !is MST.Symbolic || node.value !in symbols) return null if (node !is Symbol || node.identity !in symbols)
return SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI) null
} else
SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI)
public companion object { public companion object {
/** /**
@ -149,17 +160,20 @@ public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
* not [MST.Unary]. * not [MST.Unary].
* *
* @param operations the allowed operations. If `null`, any operation is accepted. * @param operations the allowed operations. If `null`, any operation is accepted.
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public abstract class Unary(public val operations: Collection<String>?) : RenderFeature { public abstract class Unary(public val operations: Collection<String>?) : RenderFeature {
/** /**
* The actual render function. * The actual render function specialized for [MST.Unary].
*/ */
protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax? protected abstract fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax?
public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
if (node !is MST.Unary || operations != null && node.operation !in operations) return null if (node !is MST.Unary || operations != null && node.operation !in operations)
return render0(renderer, node) null
} else
renderUnary(renderer, node)
} }
/** /**
@ -167,79 +181,136 @@ public abstract class Unary(public val operations: Collection<String>?) : Render
* not [MST.Binary]. * not [MST.Binary].
* *
* @property operations the allowed operations. If `null`, any operation is accepted. * @property operations the allowed operations. If `null`, any operation is accepted.
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public abstract class Binary(public val operations: Collection<String>?) : RenderFeature { public abstract class Binary(public val operations: Collection<String>?) : RenderFeature {
/** /**
* The actual render function. * The actual render function specialized for [MST.Binary].
*/ */
protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax? protected abstract fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax?
public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Binary || operations != null && node.operation !in operations) return null if (node !is MST.Binary || operations != null && node.operation !in operations) return null
return render0(renderer, node) return renderBinary(renderer, node)
} }
} }
/**
* Handles binary nodes by producing [BinaryPlusSyntax].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class BinaryPlus(operations: Collection<String>?) : Binary(operations) { public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryPlusSyntax( public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryPlusSyntax =
BinaryPlusSyntax(
operation = node.operation, operation = node.operation,
left = OperandSyntax(parent.render(node.left), true), left = OperandSyntax(parent.render(node.left), true),
right = OperandSyntax(parent.render(node.right), true), right = OperandSyntax(parent.render(node.right), true),
) )
public companion object { public companion object {
/**
* The default instance configured with [GroupOperations.PLUS_OPERATION].
*/
public val Default: BinaryPlus = BinaryPlus(setOf(GroupOperations.PLUS_OPERATION)) public val Default: BinaryPlus = BinaryPlus(setOf(GroupOperations.PLUS_OPERATION))
} }
} }
/**
* Handles binary nodes by producing [BinaryMinusSyntax].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class BinaryMinus(operations: Collection<String>?) : Binary(operations) { public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryMinusSyntax( public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryMinusSyntax =
BinaryMinusSyntax(
operation = node.operation, operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true), left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
right = OperandSyntax(operand = parent.render(node.right), parentheses = true), right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
) )
public companion object { public companion object {
/**
* The default instance configured with [GroupOperations.MINUS_OPERATION].
*/
public val Default: BinaryMinus = BinaryMinus(setOf(GroupOperations.MINUS_OPERATION)) public val Default: BinaryMinus = BinaryMinus(setOf(GroupOperations.MINUS_OPERATION))
} }
} }
/**
* Handles unary nodes by producing [UnaryPlusSyntax].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class UnaryPlus(operations: Collection<String>?) : Unary(operations) { public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax( public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryPlusSyntax = UnaryPlusSyntax(
operation = node.operation, operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
) )
public companion object { public companion object {
/**
* The default instance configured with [GroupOperations.PLUS_OPERATION].
*/
public val Default: UnaryPlus = UnaryPlus(setOf(GroupOperations.PLUS_OPERATION)) public val Default: UnaryPlus = UnaryPlus(setOf(GroupOperations.PLUS_OPERATION))
} }
} }
/**
* Handles binary nodes by producing [UnaryMinusSyntax].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class UnaryMinus(operations: Collection<String>?) : Unary(operations) { public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax( public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryMinusSyntax = UnaryMinusSyntax(
operation = node.operation, operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
) )
public companion object { public companion object {
/**
* The default instance configured with [GroupOperations.MINUS_OPERATION].
*/
public val Default: UnaryMinus = UnaryMinus(setOf(GroupOperations.MINUS_OPERATION)) public val Default: UnaryMinus = UnaryMinus(setOf(GroupOperations.MINUS_OPERATION))
} }
} }
/**
* Handles binary nodes by producing [FractionSyntax].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class Fraction(operations: Collection<String>?) : Binary(operations) { public class Fraction(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax( public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax(
operation = node.operation, operation = node.operation,
left = parent.render(node.left), left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
right = parent.render(node.right), right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
infix = true,
) )
public companion object { public companion object {
/**
* The default instance configured with [FieldOperations.DIV_OPERATION].
*/
public val Default: Fraction = Fraction(setOf(FieldOperations.DIV_OPERATION)) public val Default: Fraction = Fraction(setOf(FieldOperations.DIV_OPERATION))
} }
} }
/**
* Handles binary nodes by producing [BinaryOperatorSyntax].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class BinaryOperator(operations: Collection<String>?) : Binary(operations) { public class BinaryOperator(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryOperatorSyntax( public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryOperatorSyntax =
BinaryOperatorSyntax(
operation = node.operation, operation = node.operation,
prefix = OperatorNameSyntax(name = node.operation), prefix = OperatorNameSyntax(name = node.operation),
left = parent.render(node.left), left = parent.render(node.left),
@ -247,57 +318,103 @@ public class BinaryOperator(operations: Collection<String>?) : Binary(operations
) )
public companion object { public companion object {
/**
* The default instance configured with `null`.
*/
public val Default: BinaryOperator = BinaryOperator(null) public val Default: BinaryOperator = BinaryOperator(null)
} }
} }
/**
* Handles unary nodes by producing [UnaryOperatorSyntax].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class UnaryOperator(operations: Collection<String>?) : Unary(operations) { public class UnaryOperator(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
UnaryOperatorSyntax(
operation = node.operation, operation = node.operation,
prefix = OperatorNameSyntax(node.operation), prefix = OperatorNameSyntax(node.operation),
operand = OperandSyntax(parent.render(node.value), true), operand = OperandSyntax(parent.render(node.value), true),
) )
public companion object { public companion object {
/**
* The default instance configured with `null`.
*/
public val Default: UnaryOperator = UnaryOperator(null) public val Default: UnaryOperator = UnaryOperator(null)
} }
} }
/**
* Handles binary nodes by producing [SuperscriptSyntax].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class Power(operations: Collection<String>?) : Binary(operations) { public class Power(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = SuperscriptSyntax( public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): SuperscriptSyntax =
SuperscriptSyntax(
operation = node.operation, operation = node.operation,
left = OperandSyntax(parent.render(node.left), true), left = OperandSyntax(parent.render(node.left), true),
right = OperandSyntax(parent.render(node.right), true), right = OperandSyntax(parent.render(node.right), true),
) )
public companion object { public companion object {
/**
* The default instance configured with [PowerOperations.POW_OPERATION].
*/
public val Default: Power = Power(setOf(PowerOperations.POW_OPERATION)) public val Default: Power = Power(setOf(PowerOperations.POW_OPERATION))
} }
} }
/**
* Handles binary nodes by producing [RadicalSyntax] with no index.
*/
@UnstableKMathAPI
public class SquareRoot(operations: Collection<String>?) : Unary(operations) { public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): RadicalSyntax =
RadicalSyntax(operation = node.operation, operand = parent.render(node.value)) RadicalSyntax(operation = node.operation, operand = parent.render(node.value))
public companion object { public companion object {
/**
* The default instance configured with [PowerOperations.SQRT_OPERATION].
*/
public val Default: SquareRoot = SquareRoot(setOf(PowerOperations.SQRT_OPERATION)) public val Default: SquareRoot = SquareRoot(setOf(PowerOperations.SQRT_OPERATION))
} }
} }
/**
* Handles unary nodes by producing [ExponentSyntax].
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class Exponent(operations: Collection<String>?) : Unary(operations) { 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, operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
useOperatorForm = true, useOperatorForm = true,
) )
public companion object { public companion object {
/**
* The default instance configured with [ExponentialOperations.EXP_OPERATION].
*/
public val Default: Exponent = Exponent(setOf(ExponentialOperations.EXP_OPERATION)) 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 class Multiplication(operations: Collection<String>?) : Binary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = MultiplicationSyntax( public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MultiplicationSyntax =
MultiplicationSyntax(
operation = node.operation, operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true), left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
right = OperandSyntax(operand = parent.render(node.right), parentheses = true), right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
@ -305,31 +422,60 @@ public class Multiplication(operations: Collection<String>?) : Binary(operations
) )
public companion object { 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 class InverseTrigonometricOperations(operations: Collection<String>?) : Unary(operations) {
public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
UnaryOperatorSyntax(
operation = node.operation, operation = node.operation,
prefix = SuperscriptSyntax( prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "arc")),
operation = PowerOperations.POW_OPERATION,
left = OperatorNameSyntax(name = node.operation.removePrefix("a")),
right = UnaryMinusSyntax(
operation = GroupOperations.MINUS_OPERATION,
operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true),
),
),
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
) )
public companion object { public companion object {
/**
* The default instance configured with [TrigonometricOperations.ACOS_OPERATION],
* [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION].
*/
public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf( public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf(
TrigonometricOperations.ACOS_OPERATION, TrigonometricOperations.ACOS_OPERATION,
TrigonometricOperations.ASIN_OPERATION, TrigonometricOperations.ASIN_OPERATION,
TrigonometricOperations.ATAN_OPERATION, TrigonometricOperations.ATAN_OPERATION,
))
}
}
/**
* Handles binary nodes by producing inverse [UnaryOperatorSyntax] with *ar* prefix instead of *a*.
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class InverseHyperbolicOperations(operations: Collection<String>?) : Unary(operations) {
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
UnaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "ar")),
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
)
public companion object {
/**
* The default instance configured with [ExponentialOperations.ACOSH_OPERATION],
* [ExponentialOperations.ASINH_OPERATION], and [ExponentialOperations.ATANH_OPERATION].
*/
public val Default: InverseHyperbolicOperations = InverseHyperbolicOperations(setOf(
ExponentialOperations.ACOSH_OPERATION, ExponentialOperations.ACOSH_OPERATION,
ExponentialOperations.ASINH_OPERATION, ExponentialOperations.ASINH_OPERATION,
ExponentialOperations.ATANH_OPERATION, ExponentialOperations.ATANH_OPERATION,

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.ast.rendering package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.FieldOperations import space.kscience.kmath.operations.FieldOperations
import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.PowerOperations import space.kscience.kmath.operations.PowerOperations
@ -15,6 +16,7 @@ import space.kscience.kmath.operations.RingOperations
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage { public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage {
public override fun perform(node: MathSyntax): Unit = when (node) { public override fun perform(node: MathSyntax): Unit = when (node) {
is NumberSyntax -> Unit 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 * Applies [ExponentSyntax.useOperatorForm] to [ExponentSyntax] when the operand contains a fraction, a
@ -88,6 +159,7 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage { public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage {
private fun perform0(node: MathSyntax): Boolean { private fun perform0(node: MathSyntax): Boolean {
return when (node) { return when (node) {
@ -99,7 +171,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt
is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand) is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand)
is UnaryPlusSyntax -> perform0(node.operand) is UnaryPlusSyntax -> perform0(node.operand)
is UnaryMinusSyntax -> perform0(node.operand) is UnaryMinusSyntax -> perform0(node.operand)
is RadicalSyntax -> perform0(node.operand) is RadicalSyntax -> true
is ExponentSyntax -> { is ExponentSyntax -> {
val r = perform0(node.operand) val r = perform0(node.operand)
@ -113,7 +185,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt
is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right) is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right)
is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right) is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right)
is FractionSyntax -> true is FractionSyntax -> true
is RadicalWithIndexSyntax -> perform0(node.left) || perform0(node.right) is RadicalWithIndexSyntax -> true
is MultiplicationSyntax -> perform0(node.left) || perform0(node.right) 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. * @property precedenceFunction Returns the precedence number for syntax node. Higher number is lower priority.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) : public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) :
FeaturedMathRendererWithPostProcess.PostProcessStage { FeaturedMathRendererWithPostProcess.PostProcessStage {
public override fun perform(node: MathSyntax): Unit = when (node) { public override fun perform(node: MathSyntax): Unit = when (node) {
@ -159,8 +232,11 @@ public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) ->
val isInsideExpOperator = val isInsideExpOperator =
node.parent is ExponentSyntax && (node.parent as ExponentSyntax).useOperatorForm node.parent is ExponentSyntax && (node.parent as ExponentSyntax).useOperatorForm
val isOnOrUnderNormalFraction = node.parent is FractionSyntax && !((node.parent as FractionSyntax).infix)
node.parentheses = !isRightOfSuperscript node.parentheses = !isRightOfSuperscript
&& (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax || isInsideExpOperator) && (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax || isInsideExpOperator)
&& !isOnOrUnderNormalFraction
perform(node.operand) perform(node.operand)
} }

View File

@ -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. * 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.MstField
import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.MstRing
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.interpret import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.bindSymbol
@ -16,45 +16,41 @@ import space.kscience.kmath.operations.invoke
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class TestWasmConsistencyWithInterpreter { internal class TestCompilerConsistencyWithInterpreter {
@Test @Test
fun intRing() { fun intRing() = runCompilerTest {
val mst = MstRing { val mst = MstRing {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
(bindSymbol(x) - (2.toByte() + (scale( (bindSymbol(x) - (2.toByte() + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2.0 2.0,
) + 1.toByte()))) * 3.0 - 1.toByte() ) + 1.toByte()))) * 3.0 - 1.toByte()
), ),
number(1) number(1),
) * number(2) ) * number(2)
} }
assertEquals( assertEquals(
mst.interpret(IntRing, x to 3), mst.interpret(IntRing, x to 3),
mst.compile(IntRing, x to 3) mst.compile(IntRing, x to 3),
) )
} }
@Test @Test
fun doubleField() { fun doubleField() = runCompilerTest {
val mst = MstField { val mst = MstField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
(3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
+ number(1), + number(1),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one,
) + zero ) + zero
} }
assertEquals( assertEquals(
mst.interpret(DoubleField, x to 2.0), 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
}
} }

View File

@ -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))
}
}

View File

@ -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. * 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.MstRing
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
@ -15,20 +15,16 @@ import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
internal class TestWasmVariables { internal class TestCompilerVariables {
@Test @Test
fun testVariable() { fun testVariable() = runCompilerTest {
val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
assertEquals(1, expr(x to 1)) assertEquals(1, expr(x to 1))
} }
@Test @Test
fun testUndefinedVariableFails() { fun testUndefinedVariableFails() = runCompilerTest {
val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
assertFailsWith<NoSuchElementException> { expr() } assertFailsWith<NoSuchElementException> { expr() }
} }
private companion object {
private val x by symbol
}
} }

View File

@ -13,7 +13,7 @@ import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class ParserTest { internal class TestParser {
@Test @Test
fun evaluateParsedMst() { fun evaluateParsedMst() {
val mst = "2+2*(2+2)".parseMath() val mst = "2+2*(2+2)".parseMath()

View File

@ -5,13 +5,12 @@
package space.kscience.kmath.ast package space.kscience.kmath.ast
import space.kscience.kmath.ast.parseMath
import space.kscience.kmath.expressions.evaluate import space.kscience.kmath.expressions.evaluate
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class ParserPrecedenceTest { internal class TestParserPrecedence {
@Test @Test
fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath())) fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath()))

View File

@ -99,13 +99,17 @@ internal class TestFeatures {
fun multiplication() = testLatex("x*1", "x\\times1") fun multiplication() = testLatex("x*1", "x\\times1")
@Test @Test
fun inverseTrigonometry() { fun inverseTrigonometric() {
testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)") testLatex("asin(x)", "\\operatorname{arcsin}\\,\\left(x\\right)")
testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)") testLatex("acos(x)", "\\operatorname{arccos}\\,\\left(x\\right)")
testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)") testLatex("atan(x)", "\\operatorname{arctan}\\,\\left(x\\right)")
testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)") }
testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)")
testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)") @Test
fun inverseHyperbolic() {
testLatex("asinh(x)", "\\operatorname{arsinh}\\,\\left(x\\right)")
testLatex("acosh(x)", "\\operatorname{arcosh}\\,\\left(x\\right)")
testLatex("atanh(x)", "\\operatorname{artanh}\\,\\left(x\\right)")
} }
// @Test // @Test

View File

@ -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(\\frac{x}{2}\\right)")
testLatex("exp(x^2)", "\\operatorname{exp}\\,\\left(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}")
}
} }

View File

@ -30,17 +30,17 @@ internal object TestUtils {
) )
internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals( internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals(
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>", expected = "<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
actual = mathML(mst), actual = mathML(mst),
) )
internal fun testMathML(expression: String, expectedMathML: String) = assertEquals( internal fun testMathML(expression: String, expectedMathML: String) = assertEquals(
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>", expected = "<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
actual = mathML(expression.parseMath()), actual = mathML(expression.parseMath()),
) )
internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals( internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals(
expected = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>", expected = "<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>$expectedMathML</mrow></math>",
actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression), actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression),
) )
} }

View File

@ -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)

View File

@ -9,22 +9,23 @@ import space.kscience.kmath.estree.internal.ESTreeBuilder
import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.MST.* import space.kscience.kmath.expressions.MST.*
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.internal.estree.BaseExpression import space.kscience.kmath.internal.estree.BaseExpression
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.NumericAlgebra import space.kscience.kmath.operations.NumericAlgebra
import space.kscience.kmath.operations.bindSymbolOrNull
@PublishedApi @PublishedApi
internal fun <T> MST.compileWith(algebra: Algebra<T>): Expression<T> { internal fun <T> MST.compileWith(algebra: Algebra<T>): Expression<T> {
fun ESTreeBuilder<T>.visit(node: MST): BaseExpression = when (node) { fun ESTreeBuilder<T>.visit(node: MST): BaseExpression = when (node) {
is Symbolic -> { is Symbol -> {
val symbol = algebra.bindSymbolOrNull(node.value) val symbol = algebra.bindSymbolOrNull(node)
if (symbol != null) if (symbol != null)
constant(symbol) constant(symbol)
else else
variable(node.value) variable(node.identity)
} }
is Numeric -> constant(node.value) is Numeric -> constant(node.value)

View File

@ -6,14 +6,9 @@
package space.kscience.kmath.estree.internal package space.kscience.kmath.estree.internal
import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.internal.astring.generate import space.kscience.kmath.internal.astring.generate
import space.kscience.kmath.internal.estree.* 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) { internal class ESTreeBuilder<T>(val bodyCallback: ESTreeBuilder<T>.() -> BaseExpression) {
private class GeneratedExpression<T>(val executable: dynamic, val constants: Array<dynamic>) : Expression<T> { private class GeneratedExpression<T>(val executable: dynamic, val constants: Array<dynamic>) : Expression<T> {

View File

@ -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. * 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", "OVERRIDING_FINAL_MEMBER",
"RETURN_TYPE_MISMATCH_ON_OVERRIDE", "RETURN_TYPE_MISMATCH_ON_OVERRIDE",
"CONFLICTING_OVERLOADS", "CONFLICTING_OVERLOADS",

View File

@ -8,9 +8,9 @@ package space.kscience.kmath.wasm.internal
import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.MST.* import space.kscience.kmath.expressions.MST.*
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.internal.binaryen.* import space.kscience.kmath.internal.binaryen.*
import space.kscience.kmath.internal.webassembly.Instance import space.kscience.kmath.internal.webassembly.Instance
import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import space.kscience.kmath.internal.binaryen.Module as BinaryenModule import space.kscience.kmath.internal.binaryen.Module as BinaryenModule
import space.kscience.kmath.internal.webassembly.Module as WasmModule import space.kscience.kmath.internal.webassembly.Module as WasmModule
@ -23,20 +23,20 @@ internal sealed class WasmBuilder<T>(
val algebra: Algebra<T>, val algebra: Algebra<T>,
val target: MST, val target: MST,
) where T : Number { ) where T : Number {
val keys: MutableList<String> = mutableListOf() val keys: MutableList<Symbol> = mutableListOf()
lateinit var ctx: BinaryenModule lateinit var ctx: BinaryenModule
open fun visitSymbolic(mst: MST.Symbolic): ExpressionRef { open fun visitSymbolic(mst: Symbol): ExpressionRef {
try { try {
algebra.bindSymbol(mst.value) algebra.bindSymbol(mst)
} catch (ignored: Throwable) { } catch (ignored: Throwable) {
null null
}?.let { return visitNumeric(Numeric(it)) } }?.let { return visitNumeric(Numeric(it)) }
var idx = keys.indexOf(mst.value) var idx = keys.indexOf(mst)
if (idx == -1) { if (idx == -1) {
keys += mst.value keys += mst
idx = keys.lastIndex idx = keys.lastIndex
} }
@ -54,7 +54,7 @@ internal sealed class WasmBuilder<T>(
open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()") open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()")
fun visit(mst: MST): ExpressionRef = when (mst) { fun visit(mst: MST): ExpressionRef = when (mst) {
is Symbolic -> visitSymbolic(mst) is Symbol -> visitSymbolic(mst)
is Numeric -> visitNumeric(mst) is Numeric -> visitNumeric(mst)
is Unary -> when { is Unary -> when {
@ -96,7 +96,7 @@ internal sealed class WasmBuilder<T>(
}) })
val i = Instance(c, js("{}") as Any) val i = Instance(c, js("{}") as Any)
val symbols = keys.map(::StringSymbol) val symbols = keys
keys.clear() keys.clear()
Expression<T> { args -> Expression<T> { args ->

View File

@ -8,8 +8,9 @@ package space.kscience.kmath.wasm
import space.kscience.kmath.estree.compileWith import space.kscience.kmath.estree.compileWith
import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.expressions.invoke 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.DoubleField
import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.wasm.internal.DoubleWasmBuilder import space.kscience.kmath.wasm.internal.DoubleWasmBuilder
@ -20,6 +21,7 @@ import space.kscience.kmath.wasm.internal.IntWasmBuilder
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun DoubleField.expression(mst: MST): Expression<Double> = public fun DoubleField.expression(mst: MST): Expression<Double> =
DoubleWasmBuilder(mst).instance DoubleWasmBuilder(mst).instance
@ -28,6 +30,7 @@ public fun DoubleField.expression(mst: MST): Expression<Double> =
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun IntRing.expression(mst: MST): Expression<Int> = public fun IntRing.expression(mst: MST): Expression<Int> =
IntWasmBuilder(mst).instance IntWasmBuilder(mst).instance
@ -36,6 +39,7 @@ public fun IntRing.expression(mst: MST): Expression<Int> =
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun MST.compileToExpression(algebra: IntRing): Expression<Int> = compileWith(algebra) 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 * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int = public fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int =
compileToExpression(algebra).invoke(arguments) compileToExpression(algebra).invoke(arguments)
@ -53,6 +58,7 @@ public fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int =
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun MST.compile(algebra: IntRing, vararg arguments: Pair<Symbol, Int>): Int = public fun MST.compile(algebra: IntRing, vararg arguments: Pair<Symbol, Int>): Int =
compileToExpression(algebra)(*arguments) compileToExpression(algebra)(*arguments)
@ -61,6 +67,7 @@ public fun MST.compile(algebra: IntRing, vararg arguments: Pair<Symbol, Int>): I
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = compileWith(algebra) 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 * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double = public fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double =
compileToExpression(algebra).invoke(arguments) compileToExpression(algebra).invoke(arguments)
@ -78,5 +86,6 @@ public fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Do
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI
public fun MST.compile(algebra: DoubleField, vararg arguments: Pair<Symbol, Double>): Double = public fun MST.compile(algebra: DoubleField, vararg arguments: Pair<Symbol, Double>): Double =
compileToExpression(algebra).invoke(*arguments) compileToExpression(algebra).invoke(*arguments)

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.ast package space.kscience.kmath.ast
import space.kscience.kmath.expressions.* import space.kscience.kmath.expressions.*
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.bindSymbol

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -8,7 +8,7 @@ package space.kscience.kmath.wasm
import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.MstExtendedField
import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.MstRing
import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.symbol import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.bindSymbol

View File

@ -10,10 +10,11 @@ import space.kscience.kmath.asm.internal.buildName
import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.MST.* import space.kscience.kmath.expressions.MST.*
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.NumericAlgebra import space.kscience.kmath.operations.NumericAlgebra
import space.kscience.kmath.operations.bindSymbolOrNull
/** /**
* Compiles given MST to an Expression using AST compiler. * Compiles given MST to an Expression using AST compiler.
@ -26,13 +27,13 @@ import space.kscience.kmath.operations.NumericAlgebra
@PublishedApi @PublishedApi
internal fun <T : Any> MST.compileWith(type: Class<T>, algebra: Algebra<T>): Expression<T> { internal fun <T : Any> MST.compileWith(type: Class<T>, algebra: Algebra<T>): Expression<T> {
fun AsmBuilder<T>.visit(node: MST): Unit = when (node) { fun AsmBuilder<T>.visit(node: MST): Unit = when (node) {
is Symbolic -> { is Symbol -> {
val symbol = algebra.bindSymbolOrNull(node.value) val symbol = algebra.bindSymbolOrNull(node)
if (symbol != null) if (symbol != null)
loadObjectConstant(symbol as Any) loadObjectConstant(symbol as Any)
else else
loadVariable(node.value) loadVariable(node.identity)
} }
is Numeric -> loadNumberConstant(node.value) is Numeric -> loadNumberConstant(node.value)

View File

@ -342,7 +342,7 @@ internal class AsmBuilder<T>(
val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") } val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") }
/** /**
* ASM Type for [kscience.kmath.expressions.Symbol]. * ASM Type for [space.kscience.kmath.expressions.Symbol].
*/ */
val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") } val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") }
} }

View File

@ -52,7 +52,7 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.(
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) } internal fun MethodVisitor.label(): Label = Label().also(::visitLabel)
/** /**
* Creates a class name for [Expression] subclassed to implement [mst] provided. * Creates a class name for [Expression] subclassed to implement [mst] provided.

View File

@ -7,8 +7,8 @@
package space.kscience.kmath.asm.internal package space.kscience.kmath.asm.internal
import space.kscience.kmath.misc.StringSymbol import space.kscience.kmath.expressions.StringSymbol
import space.kscience.kmath.misc.Symbol import space.kscience.kmath.expressions.Symbol
/** /**
* Gets value with given [key] or throws [NoSuchElementException] whenever it is not present. * Gets value with given [key] or throws [NoSuchElementException] whenever it is not present.

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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)

View File

@ -7,7 +7,6 @@ package space.kscience.kmath.commons.expressions
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
import space.kscience.kmath.expressions.* import space.kscience.kmath.expressions.*
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.NumbersAddOperations import space.kscience.kmath.operations.NumbersAddOperations

View File

@ -11,12 +11,12 @@ import space.kscience.kmath.integration.*
/** /**
* A simple one-pass integrator based on Gauss rule * A simple one-pass integrator based on Gauss rule
*/ */
public class GaussRuleIntegrator( public class CMGaussRuleIntegrator(
private val numpoints: Int, private val numpoints: Int,
private var type: GaussRule = GaussRule.LEGANDRE, private var type: GaussRule = GaussRule.LEGANDRE,
) : UnivariateIntegrator<Double> { ) : UnivariateIntegrator<Double> {
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> { override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
val range = integrand.getFeature<IntegrationRange>()?.range val range = integrand.getFeature<IntegrationRange>()?.range
?: error("Integration range is not provided") ?: error("Integration range is not provided")
val integrator: GaussIntegrator = getIntegrator(range) val integrator: GaussIntegrator = getIntegrator(range)
@ -76,8 +76,8 @@ public class GaussRuleIntegrator(
numPoints: Int = 100, numPoints: Int = 100,
type: GaussRule = GaussRule.LEGANDRE, type: GaussRule = GaussRule.LEGANDRE,
function: (Double) -> Double, function: (Double) -> Double,
): Double = GaussRuleIntegrator(numPoints, type).process( ): Double = CMGaussRuleIntegrator(numPoints, type).integrate(
UnivariateIntegrand(function, IntegrationRange(range)) UnivariateIntegrand(function, IntegrationRange(range))
).value!! ).valueOrNull!!
} }
} }

View File

@ -18,13 +18,7 @@ public class CMIntegrator(
public val integratorBuilder: (Integrand) -> org.apache.commons.math3.analysis.integration.UnivariateIntegrator, public val integratorBuilder: (Integrand) -> org.apache.commons.math3.analysis.integration.UnivariateIntegrator,
) : UnivariateIntegrator<Double> { ) : UnivariateIntegrator<Double> {
public class TargetRelativeAccuracy(public val value: Double) : IntegrandFeature override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
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> {
val integrator = integratorBuilder(integrand) val integrator = integratorBuilder(integrand)
val maxCalls = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: defaultMaxCalls val maxCalls = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: defaultMaxCalls
val remainingCalls = maxCalls - integrand.calls val remainingCalls = maxCalls - integrand.calls
@ -32,12 +26,11 @@ public class CMIntegrator(
?: error("Integration range is not provided") ?: error("Integration range is not provided")
val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive) val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive)
return integrand.with( return integrand +
IntegrandValue(res), IntegrandValue(res) +
IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy), IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy) +
IntegrandRelativeAccuracy(integrator.relativeAccuracy), IntegrandRelativeAccuracy(integrator.relativeAccuracy) +
IntegrandCallsPerformed(integrator.evaluations + integrand.calls) IntegrandCallsPerformed(integrator.evaluations + integrand.calls)
)
} }
@ -46,16 +39,15 @@ public class CMIntegrator(
* Create a Simpson integrator based on [SimpsonIntegrator] * Create a Simpson integrator based on [SimpsonIntegrator]
*/ */
public fun simpson(defaultMaxCalls: Int = 200): CMIntegrator = CMIntegrator(defaultMaxCalls) { integrand -> 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 ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val relativeAccuracy = integrand.getFeature<TargetRelativeAccuracy>()?.value val relativeAccuracy = integrand.getFeature<IntegrandRelativeAccuracy>()?.accuracy
?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val minIterations = integrand.getFeature<MinIterations>()?.value val iterations = integrand.getFeature<IntegrandIterationsRange>()?.range
?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT ?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT
val maxIterations = integrand.getFeature<MaxIterations>()?.value
?: 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 = public fun legandre(numPoints: Int, defaultMaxCalls: Int = numPoints * 5): CMIntegrator =
CMIntegrator(defaultMaxCalls) { integrand -> CMIntegrator(defaultMaxCalls) { integrand ->
val absoluteAccuracy = integrand.getFeature<TargetAbsoluteAccuracy>()?.value val absoluteAccuracy = integrand.getFeature<IntegrandAbsoluteAccuracy>()?.accuracy
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY ?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val relativeAccuracy = integrand.getFeature<TargetRelativeAccuracy>()?.value val relativeAccuracy = integrand.getFeature<IntegrandRelativeAccuracy>()?.accuracy
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY ?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val minIterations = integrand.getFeature<MinIterations>()?.value val iterations = integrand.getFeature<IntegrandIterationsRange>()?.range
?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT ?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT
val maxIterations = integrand.getFeature<MaxIterations>()?.value
?: IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT
IterativeLegendreGaussIntegrator( IterativeLegendreGaussIntegrator(
numPoints, numPoints,
relativeAccuracy, relativeAccuracy,
absoluteAccuracy, absoluteAccuracy,
minIterations, iterations.first,
maxIterations iterations.last
) )
} }
} }
@ -85,14 +75,14 @@ public class CMIntegrator(
@UnstableKMathAPI @UnstableKMathAPI
public var MutableList<IntegrandFeature>.targetAbsoluteAccuracy: Double? public var MutableList<IntegrandFeature>.targetAbsoluteAccuracy: Double?
get() = filterIsInstance<CMIntegrator.TargetAbsoluteAccuracy>().lastOrNull()?.value get() = filterIsInstance<IntegrandAbsoluteAccuracy>().lastOrNull()?.accuracy
set(value) { set(value) {
value?.let { add(CMIntegrator.TargetAbsoluteAccuracy(value)) } value?.let { add(IntegrandAbsoluteAccuracy(value)) }
} }
@UnstableKMathAPI @UnstableKMathAPI
public var MutableList<IntegrandFeature>.targetRelativeAccuracy: Double? public var MutableList<IntegrandFeature>.targetRelativeAccuracy: Double?
get() = filterIsInstance<CMIntegrator.TargetRelativeAccuracy>().lastOrNull()?.value get() = filterIsInstance<IntegrandRelativeAccuracy>().lastOrNull()?.accuracy
set(value) { set(value) {
value?.let { add(CMIntegrator.TargetRelativeAccuracy(value)) } value?.let { add(IntegrandRelativeAccuracy(value)) }
} }

View File

@ -5,11 +5,7 @@
package space.kscience.kmath.commons.expressions package space.kscience.kmath.commons.expressions
import space.kscience.kmath.expressions.binding import space.kscience.kmath.expressions.*
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 kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.test.Test import kotlin.test.Test

View File

@ -7,6 +7,7 @@ package space.kscience.kmath.commons.integration
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import space.kscience.kmath.integration.integrate import space.kscience.kmath.integration.integrate
import space.kscience.kmath.integration.value
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField.sin import space.kscience.kmath.operations.DoubleField.sin
import kotlin.math.PI import kotlin.math.PI
@ -19,16 +20,16 @@ internal class IntegrationTest {
@Test @Test
fun simpson() { fun simpson() {
val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function) val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function = function).value
assertTrue { abs(res) < 1e-3 } assertTrue { abs(res) < 1e-3 }
} }
@Test @Test
fun customSimpson() { fun customSimpson() {
val res = CMIntegrator.simpson().integrate(0.0..PI, function) { val res = CMIntegrator.simpson().integrate(0.0..PI, {
targetRelativeAccuracy = 1e-4 targetRelativeAccuracy = 1e-4
targetAbsoluteAccuracy = 1e-4 targetAbsoluteAccuracy = 1e-4
} }, function).value
assertTrue { abs(res - 2) < 1e-3 } assertTrue { abs(res - 2) < 1e-3 }
assertTrue { abs(res - 2) > 1e-12 } assertTrue { abs(res - 2) > 1e-12 }
} }

View File

@ -8,7 +8,7 @@ package space.kscience.kmath.commons.optimization
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import space.kscience.kmath.commons.expressions.DerivativeStructureExpression import space.kscience.kmath.commons.expressions.DerivativeStructureExpression
import space.kscience.kmath.distributions.NormalDistribution 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.FunctionOptimization
import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.stat.RandomGenerator
import kotlin.math.pow import kotlin.math.pow

View File

@ -8,29 +8,27 @@ Complex and hypercomplex number systems in KMath.
## Artifact: ## Artifact:
The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-7`. The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-11`.
**Gradle:** **Gradle:**
```gradle ```gradle
repositories { repositories {
maven { url 'https://repo.kotlin.link' } maven { url 'https://repo.kotlin.link' }
maven { url 'https://dl.bintray.com/hotkeytlt/maven' } mavenCentral()
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
} }
dependencies { dependencies {
implementation 'space.kscience:kmath-complex:0.3.0-dev-7' implementation 'space.kscience:kmath-complex:0.3.0-dev-11'
} }
``` ```
**Gradle Kotlin DSL:** **Gradle Kotlin DSL:**
```kotlin ```kotlin
repositories { repositories {
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap mavenCentral()
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
} }
dependencies { dependencies {
implementation("space.kscience:kmath-complex:0.3.0-dev-7") implementation("space.kscience:kmath-complex:0.3.0-dev-11")
} }
``` ```

View File

@ -9,7 +9,10 @@ import space.kscience.kmath.memory.MemoryReader
import space.kscience.kmath.memory.MemorySpec import space.kscience.kmath.memory.MemorySpec
import space.kscience.kmath.memory.MemoryWriter import space.kscience.kmath.memory.MemoryWriter
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.Norm
import space.kscience.kmath.operations.NumbersAddOperations
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.MemoryBuffer import space.kscience.kmath.structures.MemoryBuffer
import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableBuffer
@ -180,13 +183,11 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, Num
* @property im The imaginary part. * @property im The imaginary part.
*/ */
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public data class Complex(val re: Double, val im: Double) : FieldElement<Complex, ComplexField> { public data class Complex(val re: Double, val im: Double) {
public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble()) public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble())
public constructor(re: Number) : this(re.toDouble(), 0.0) public constructor(re: Number) : this(re.toDouble(), 0.0)
public override val context: ComplexField get() = ComplexField public override fun toString(): String = "($re + i * $im)"
public override fun toString(): String = "($re + i*$im)"
public companion object : MemorySpec<Complex> { public companion object : MemorySpec<Complex> {
public override val objectSize: Int public override val objectSize: Int

View File

@ -27,9 +27,11 @@ public val Quaternion.conjugate: Quaternion
*/ */
public val Quaternion.reciprocal: Quaternion public val Quaternion.reciprocal: Quaternion
get() { get() {
val n = QuaternionField { norm(this@reciprocal) } QuaternionField {
val n = norm(this@reciprocal)
return conjugate / (n * n) return conjugate / (n * n)
} }
}
/** /**
* Absolute value of the quaternion. * Absolute value of the quaternion.
@ -198,7 +200,7 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public data class Quaternion( public data class Quaternion(
val w: Double, val x: Double, val y: Double, val z: Double, val w: Double, val x: Double, val y: Double, val z: Double,
) : FieldElement<Quaternion, QuaternionField> { ) {
public constructor(w: Number, x: Number, y: Number, z: Number) : this( public constructor(w: Number, x: Number, y: Number, z: Number) : this(
w.toDouble(), w.toDouble(),
x.toDouble(), x.toDouble(),
@ -219,8 +221,6 @@ public data class Quaternion(
require(!z.isNaN()) { "x-component of quaternion is not-a-number" } require(!z.isNaN()) { "x-component of quaternion is not-a-number" }
} }
public override val context: QuaternionField get() = QuaternionField
/** /**
* Returns a string representation of this quaternion. * Returns a string representation of this quaternion.
*/ */

View File

@ -7,7 +7,7 @@ package space.kscience.kmath.complex
import space.kscience.kmath.expressions.FunctionalExpressionField import space.kscience.kmath.expressions.FunctionalExpressionField
import space.kscience.kmath.expressions.invoke 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 space.kscience.kmath.operations.bindSymbol
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -15,29 +15,27 @@ performance calculations to code generation.
## Artifact: ## Artifact:
The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-7`. The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-11`.
**Gradle:** **Gradle:**
```gradle ```gradle
repositories { repositories {
maven { url 'https://repo.kotlin.link' } maven { url 'https://repo.kotlin.link' }
maven { url 'https://dl.bintray.com/hotkeytlt/maven' } mavenCentral()
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
} }
dependencies { dependencies {
implementation 'space.kscience:kmath-core:0.3.0-dev-7' implementation 'space.kscience:kmath-core:0.3.0-dev-11'
} }
``` ```
**Gradle Kotlin DSL:** **Gradle Kotlin DSL:**
```kotlin ```kotlin
repositories { repositories {
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap mavenCentral()
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
} }
dependencies { dependencies {
implementation("space.kscience:kmath-core:0.3.0-dev-7") implementation("space.kscience:kmath-core:0.3.0-dev-11")
} }
``` ```

View File

@ -21,7 +21,7 @@ public class space/kscience/kmath/expressions/AutoDiffValue {
public final class space/kscience/kmath/expressions/DerivationResult { public final class space/kscience/kmath/expressions/DerivationResult {
public fun <init> (Ljava/lang/Object;Ljava/util/Map;Lspace/kscience/kmath/operations/Field;)V 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 div ()Ljava/lang/Object;
public final fun getContext ()Lspace/kscience/kmath/operations/Field; public final fun getContext ()Lspace/kscience/kmath/operations/Field;
public final fun getValue ()Ljava/lang/Object; 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 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/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;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 { 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 abstract class space/kscience/kmath/expressions/FirstDerivativeExpression : space/kscience/kmath/expressions/DifferentiableExpression {
public fun <init> ()V public fun <init> ()V
public final fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; 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 { 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 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 { 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 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 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 fun <init> (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)V
public final fun component1 ()Ljava/lang/String; 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 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 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 static final field INSTANCE Lspace/kscience/kmath/expressions/MstExtendedField;
public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; 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 atanh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; 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 synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object;
public fun cos (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public fun cos (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; 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 fun sin (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
public fun sinh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public fun sinh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
public fun sqrt (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST;
public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
public fun tan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public fun tan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
@ -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 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 fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; 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 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 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; 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 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 fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; 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 synthetic fun getZero ()Ljava/lang/Object;
public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric; public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric;
public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 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 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 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 static final field INSTANCE Lspace/kscience/kmath/expressions/MstRing;
public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 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 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 fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; 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 synthetic fun getOne ()Ljava/lang/Object;
public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric; public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric;
public synthetic fun getZero ()Ljava/lang/Object; 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 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 <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 getField ()Lspace/kscience/kmath/operations/Field;
public final fun getFunction ()Lkotlin/jvm/functions/Function1; public final fun getFunction ()Lkotlin/jvm/functions/Function1;
public fun invoke (Ljava/util/Map;)Ljava/lang/Object; 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 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 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 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 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;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; 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 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/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 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 <init> (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V
public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; 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 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 interface class space/kscience/kmath/linear/LinearSolver {
public abstract fun inverse (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; 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; 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 static final fun cumulativeSumOfLong (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
} }
public final class space/kscience/kmath/misc/StringSymbol : space/kscience/kmath/misc/Symbol { public abstract interface annotation class space/kscience/kmath/misc/PerformancePitfall : java/lang/annotation/Annotation {
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/UnstableKMathAPI : 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 static final fun ring (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedRingND;
} }
public final class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND { public class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND {
public fun <init> (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V public fun <init> (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V
public fun elements ()Lkotlin/sequences/Sequence; public fun elements ()Lkotlin/sequences/Sequence;
public fun get ([I)Ljava/lang/Object; public fun get ([I)Ljava/lang/Object;
@ -786,10 +785,9 @@ public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath
public fun equals (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z
public fun getLinearSize ()I public fun getLinearSize ()I
public fun getShape ()[I public fun getShape ()[I
public fun getStrides ()Ljava/util/List; public fun getStrides ()[I
public fun hashCode ()I public fun hashCode ()I
public fun index (I)[I public fun index (I)[I
public fun offset ([I)I
} }
public final class space/kscience/kmath/nd/DefaultStrides$Companion { public final class space/kscience/kmath/nd/DefaultStrides$Companion {
@ -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/GroupND$Companion {
} }
public final class space/kscience/kmath/nd/MutableBufferND : space/kscience/kmath/nd/BufferND, space/kscience/kmath/nd/MutableStructureND {
public fun <init> (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/MutableBuffer;)V
public final fun getMutableBuffer ()Lspace/kscience/kmath/structures/MutableBuffer;
public fun set ([ILjava/lang/Object;)V
}
public abstract interface class space/kscience/kmath/nd/MutableStructure1D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure1D, space/kscience/kmath/structures/MutableBuffer {
public fun set ([ILjava/lang/Object;)V
}
public abstract interface class space/kscience/kmath/nd/MutableStructure2D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure2D {
public fun getColumns ()Ljava/util/List;
public fun getRows ()Ljava/util/List;
public abstract fun set (IILjava/lang/Object;)V
}
public abstract interface class space/kscience/kmath/nd/MutableStructureND : space/kscience/kmath/nd/StructureND { public abstract interface class space/kscience/kmath/nd/MutableStructureND : space/kscience/kmath/nd/StructureND {
public abstract fun set ([ILjava/lang/Object;)V public abstract fun set ([ILjava/lang/Object;)V
} }
@ -912,10 +926,10 @@ public final class space/kscience/kmath/nd/ShortRingNDKt {
public abstract interface class space/kscience/kmath/nd/Strides { public abstract interface class space/kscience/kmath/nd/Strides {
public abstract fun getLinearSize ()I public abstract fun getLinearSize ()I
public abstract fun getShape ()[I public abstract fun getShape ()[I
public abstract fun getStrides ()Ljava/util/List; public abstract fun getStrides ()[I
public abstract fun index (I)[I public abstract fun index (I)[I
public fun indices ()Lkotlin/sequences/Sequence; public fun indices ()Lkotlin/sequences/Sequence;
public abstract fun offset ([I)I public fun offset ([I)I
} }
public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer { public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer {
@ -929,6 +943,7 @@ public final class space/kscience/kmath/nd/Structure1D$Companion {
} }
public final class space/kscience/kmath/nd/Structure1DKt { public final class space/kscience/kmath/nd/Structure1DKt {
public static final fun as1D (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructure1D;
public static final fun as1D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure1D; public static final fun as1D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure1D;
public static final fun asND (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/nd/Structure1D; public static final fun asND (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/nd/Structure1D;
} }
@ -949,6 +964,7 @@ public final class space/kscience/kmath/nd/Structure2D$Companion {
} }
public final class space/kscience/kmath/nd/Structure2DKt { public final class space/kscience/kmath/nd/Structure2DKt {
public static final fun as2D (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructure2D;
public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D; public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D;
} }
@ -988,14 +1004,7 @@ public abstract interface class space/kscience/kmath/operations/Algebra {
public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
} }
public abstract interface class space/kscience/kmath/operations/AlgebraElement {
public abstract fun getContext ()Lspace/kscience/kmath/operations/Algebra;
}
public final class space/kscience/kmath/operations/AlgebraElementsKt { public final class space/kscience/kmath/operations/AlgebraElementsKt {
public static final fun div (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
public static final fun plus (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
public static final fun times (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
} }
public final class space/kscience/kmath/operations/AlgebraExtensionsKt { public final class space/kscience/kmath/operations/AlgebraExtensionsKt {
@ -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 (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 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/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;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 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; 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 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 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/misc/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; 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 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 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 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 (I)I
public final fun rem (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public final fun rem (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt;
public final fun shl (I)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 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 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 static final field INSTANCE Lspace/kscience/kmath/operations/LongRing;
public fun add (JJ)Ljava/lang/Long; public fun add (JJ)Ljava/lang/Long;

View File

@ -5,7 +5,8 @@
package space.kscience.kmath.data 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.misc.UnstableKMathAPI
import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
@ -18,13 +19,17 @@ import space.kscience.kmath.structures.Buffer
public interface ColumnarData<out T> { public interface ColumnarData<out T> {
public val size: Int 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. * A zero-copy method to represent a [Structure2D] as a two-column x-y data.
* There could more than two columns in the structure. * There could more than two columns in the structure.
*/ */
@OptIn(PerformancePitfall::class)
@UnstableKMathAPI @UnstableKMathAPI
public fun <T> Structure2D<T>.asColumnarData(mapping: Map<Symbol, Int>): ColumnarData<T> { public fun <T> Structure2D<T>.asColumnarData(mapping: Map<Symbol, Int>): ColumnarData<T> {
require(shape[1] >= mapping.maxOf { it.value }) { "Column index out of bounds" } require(shape[1] >= mapping.maxOf { it.value }) { "Column index out of bounds" }

View File

@ -5,7 +5,8 @@
package space.kscience.kmath.data 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.misc.UnstableKMathAPI
import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.structures.Buffer 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> 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.x -> x
Symbol.y -> y 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. * A zero-copy method to represent a [Structure2D] as a two-column x-y data.
* There could more than two columns in the structure. * There could more than two columns in the structure.
*/ */
@OptIn(PerformancePitfall::class)
@UnstableKMathAPI @UnstableKMathAPI
public fun <T> Structure2D<T>.asXYData(xIndex: Int = 0, yIndex: Int = 1): XYColumnarData<T, T, T> { public fun <T> Structure2D<T>.asXYData(xIndex: Int = 0, yIndex: Int = 1): XYColumnarData<T, T, T> {
require(shape[1] >= max(xIndex, yIndex)) { "Column index out of bounds" } require(shape[1] >= max(xIndex, yIndex)) { "Column index out of bounds" }

View File

@ -5,7 +5,7 @@
package space.kscience.kmath.data 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.misc.UnstableKMathAPI
import space.kscience.kmath.structures.Buffer 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 interface XYZColumnarData<T, out X : T, out Y : T, out Z : T> : XYColumnarData<T, X, Y> {
public val z: Buffer<Z> 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.x -> x
Symbol.y -> y Symbol.y -> y
Symbol.z -> z Symbol.z -> z
else -> error("A column for symbol $symbol not found") else -> null
} }
} }

View File

@ -5,9 +5,6 @@
package space.kscience.kmath.expressions package space.kscience.kmath.expressions
import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.misc.Symbol
/** /**
* Represents expression which structure can be differentiated. * Represents expression which structure can be differentiated.
* *

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.expressions 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.Algebra
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty

View File

@ -5,7 +5,6 @@
package space.kscience.kmath.expressions package space.kscience.kmath.expressions
import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
/** /**

View File

@ -5,30 +5,23 @@
package space.kscience.kmath.expressions 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.Algebra
import space.kscience.kmath.operations.NumericAlgebra import space.kscience.kmath.operations.NumericAlgebra
import space.kscience.kmath.operations.bindSymbol
/** /**
* A Mathematical Syntax Tree (MST) node for mathematical expressions. * A Mathematical Syntax Tree (MST) node for mathematical expressions.
* *
* @author Alexander Nozik * @author Alexander Nozik
*/ */
public sealed class MST { public sealed interface MST {
/**
* A node containing raw string.
*
* @property value the value of this node.
*/
public data class Symbolic(val value: String) : MST()
/** /**
* A node containing a numeric value or scalar. * A node containing a numeric value or scalar.
* *
* @property value the value of this number. * @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. * A node containing an unary operation.
@ -36,7 +29,7 @@ public sealed class MST {
* @property operation the identifier of operation. * @property operation the identifier of operation.
* @property value the argument of this 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. * A node containing binary operation.
@ -45,7 +38,7 @@ public sealed class MST {
* @property left the left operand. * @property left the left operand.
* @property right the right 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 // 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) is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value)
?: error("Numeric nodes are not supported by $this") ?: error("Numeric nodes are not supported by $this")
is MST.Symbolic -> bindSymbol(node.value) is Symbol -> bindSymbol(node)
is MST.Unary -> when { is MST.Unary -> when {
this is NumericAlgebra && node.value is MST.Numeric -> unaryOperationFunction(node.operation)(number(node.value.value)) 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 bindSymbolOrNull(value: String): T? = algebra.bindSymbolOrNull(value) ?: arguments[StringSymbol(value)]
override fun unaryOperation(operation: String, arg: T): T = 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] * 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) 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. * @param algebra the algebra that provides operations.
* @return the value of expression. * @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)) interpret(algebra, mapOf(*arguments))
/** /**

View File

@ -11,10 +11,10 @@ import space.kscience.kmath.operations.*
/** /**
* [Algebra] over [MST] nodes. * [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 number(value: Number): MST.Numeric = MST.Numeric(value)
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MST.Symbolic(value) public override fun bindSymbolOrNull(value: String): Symbol = StringSymbol(value)
override fun bindSymbol(value: String): MST.Symbolic = bindSymbolOrNull(value) override fun bindSymbol(value: String): Symbol = bindSymbolOrNull(value)
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
{ arg -> MST.Unary(operation, arg) } { arg -> MST.Unary(operation, arg) }
@ -29,8 +29,8 @@ public object MstAlgebra : NumericAlgebra<MST> {
public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> { public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
public override val zero: MST.Numeric = number(0.0) public override val zero: MST.Numeric = number(0.0)
public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun number(value: Number): MST.Numeric = MstNumericAlgebra.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 = binaryOperationFunction(GroupOperations.PLUS_OPERATION)(a, b) public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(GroupOperations.PLUS_OPERATION)(a, b)
public override operator fun MST.unaryPlus(): MST.Unary = public override operator fun MST.unaryPlus(): MST.Unary =
unaryOperationFunction(GroupOperations.PLUS_OPERATION)(this) 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)) binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(value))
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = 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 = 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 val one: MST.Numeric = number(1.0)
public override fun number(value: Number): MST.Numeric = MstGroup.number(value) 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 add(a: MST, b: MST): MST.Binary = MstGroup.add(a, b)
public override fun scale(a: MST, value: Double): MST.Binary = 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) MstGroup.binaryOperationFunction(operation)
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = 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 zero: MST.Numeric get() = MstRing.zero
public override inline val one: MST.Numeric get() = MstRing.one 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 number(value: Number): MST.Numeric = MstRing.number(value)
public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) 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 zero: MST.Numeric get() = MstField.zero
public override inline val one: MST.Numeric get() = MstField.one 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 number(value: Number): MST.Numeric = MstRing.number(value)
public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg) 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) 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 acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg)
public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg) public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg)
public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b)
public override fun sqrt(arg: MST): MST = unaryOperationFunction(PowerOperations.SQRT_OPERATION)(arg)
public override fun scale(a: MST, value: Double): MST = public override fun scale(a: MST, value: Double): MST =
binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value)) binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value))
@ -157,3 +158,25 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
MstField.unaryOperationFunction(operation) 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)
}

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.expressions package space.kscience.kmath.expressions
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.asBuffer

View File

@ -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. * 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.jvm.JvmInline
import kotlin.properties.ReadOnlyProperty 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. * Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol.
*/ */
public val identity: String public val identity: String
public companion object{ public companion object {
public val x: StringSymbol = StringSymbol("x") public val x: StringSymbol = StringSymbol("x")
public val y: StringSymbol = StringSymbol("y") public val y: StringSymbol = StringSymbol("y")
public val z: StringSymbol = StringSymbol("z") 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] * 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) 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] * 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) set(StringSymbol(string), value)
} }

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.expressions package space.kscience.kmath.expressions
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.linear package space.kscience.kmath.linear
import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
@ -50,6 +51,7 @@ public class BufferedLinearSpace<T : Any, A : Ring<T>>(
this this
} }
@OptIn(PerformancePitfall::class)
override fun Matrix<T>.dot(other: Matrix<T>): Matrix<T> { 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})" } require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
return elementAlgebra { 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> { 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})" } require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
return elementAlgebra { return elementAlgebra {

View File

@ -19,6 +19,7 @@ import kotlin.reflect.KClass
* @param T the type of items. * @param T the type of items.
*/ */
public typealias Matrix<T> = Structure2D<T> 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. * Alias or using [Buffer] as a point/vector in a many-dimensional space.

View File

@ -8,7 +8,7 @@ package space.kscience.kmath.linear
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Ring 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 linearSpace: LinearSpace<T, A>,
public val rows: Int, public val rows: Int,
public val columns: Int, public val columns: Int,

View File

@ -75,6 +75,23 @@ public object LFeature : MatrixFeature
*/ */
public object UFeature : MatrixFeature public object UFeature : MatrixFeature
/**
* Matrices with this feature support LU factorization: *a = [l] &middot; [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] &middot; a = [l] &middot; [u]* where * Matrices with this feature support LU factorization with partial pivoting: *[p] &middot; a = [l] &middot; [u]* where
* *a* is the owning matrix. * *a* is the owning matrix.

View File

@ -16,7 +16,7 @@ import kotlin.reflect.KClass
* *
* @param T the type of items. * @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 origin: Matrix<T>,
public val features: Set<MatrixFeature>, public val features: Set<MatrixFeature>,
) : Matrix<T> by origin { ) : Matrix<T> by origin {
@ -26,12 +26,11 @@ public class MatrixWrapper<T : Any> internal constructor(
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <F : StructureFeature> getFeature(type: KClass<out F>): F? = features.singleOrNull { type.isInstance(it) } as? F public override fun <F : StructureFeature> getFeature(type: KClass<out F>): F? =
features.singleOrNull(type::isInstance) as? F
?: origin.getFeature(type) ?: origin.getFeature(type)
override fun toString(): String { public override fun toString(): String = "MatrixWrapper(matrix=$origin, features=$features)"
return "MatrixWrapper(matrix=$origin, features=$features)"
}
} }
/** /**
@ -82,7 +81,7 @@ public fun <T : Any> LinearSpace<T, Ring<T>>.zero(
elementAlgebra.zero elementAlgebra.zero
} + ZeroFeature } + 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` * 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