merge dev

This commit is contained in:
Roland Grinis 2021-05-06 07:45:53 +01:00
commit b7cc4e4b1b
61 changed files with 1010 additions and 990 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

@ -12,9 +12,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: Cache gradle - name: Cache gradle
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
@ -30,9 +32,7 @@ jobs:
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ 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,7 +10,8 @@
- 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)
### Changed ### Changed
- Exponential operations merged with hyperbolic functions - Exponential operations merged with hyperbolic functions
@ -24,6 +25,7 @@
- Redesign MST. Remove MSTExpression. - Redesign MST. Remove MSTExpression.
- Move MST to core - Move MST to core
- Separated benchmarks and examples - Separated benchmarks and examples
- Rewritten EJML module without ejml-simple
### Deprecated ### Deprecated

View File

@ -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,6 +200,12 @@ One can still use generic algebras though.
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
<hr/> <hr/>
* ### [kmath-jupyter](kmath-jupyter)
>
>
> **Maturity**: PROTOTYPE
<hr/>
* ### [kmath-kotlingrad](kmath-kotlingrad) * ### [kmath-kotlingrad](kmath-kotlingrad)
> >
> >

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,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,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,17 +1,16 @@
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://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
mavenCentral() mavenCentral()
} }
@ -23,22 +22,16 @@ 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

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

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

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
@ -16,8 +16,7 @@ The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-7`
```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 {
@ -28,8 +27,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 {
@ -41,12 +39,16 @@ 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)
``` ```
@ -56,6 +58,7 @@ MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
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)
``` ```
@ -93,13 +100,16 @@ The code above returns expression implemented with such a JS function:
```js ```js
var executable = function (constants, arguments) { var executable = function (constants, arguments) {
return constants[1](constants[0](arguments, "x"), 2); return constants[1](constants[0](arguments, "x"), 2);
}; };
``` ```
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. 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)
@ -130,7 +140,9 @@ 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)".parseMath()
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
@ -146,13 +158,68 @@ 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})
Result MathML (embedding MathML is not allowed by GitHub Markdown): Result MathML (embedding MathML is not allowed by GitHub Markdown):
<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>
<mo>-</mo>
<mn>12</mn>
</mrow>
</mfrac>
</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

@ -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,12 +10,16 @@ ${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)
``` ```
@ -25,6 +29,7 @@ MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
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)
``` ```
@ -62,13 +71,16 @@ The code above returns expression implemented with such a JS function:
```js ```js
var executable = function (constants, arguments) { var executable = function (constants, arguments) {
return constants[1](constants[0](arguments, "x"), 2); return constants[1](constants[0](arguments, "x"), 2);
}; };
``` ```
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. 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)
@ -99,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:")
@ -115,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

@ -118,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

@ -18,11 +18,14 @@ import space.kscience.kmath.misc.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=\"https://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)
@ -47,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) }
@ -130,14 +133,13 @@ public object MathMLSyntaxRenderer : SyntaxRenderer {
render(node.right) render(node.right)
} }
is FractionSyntax -> tag("mfrac") { is FractionSyntax -> if (node.infix) {
tag("mrow") { render(node.left)
render(node.left) tag("mo") { append('/') }
} render(node.right)
} else tag("mfrac") {
tag("mrow") { tag("mrow") { render(node.left) }
render(node.right) tag("mrow") { render(node.right) }
}
} }
is RadicalWithIndexSyntax -> tag("mroot") { is RadicalWithIndexSyntax -> tag("mroot") {

View File

@ -89,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,
@ -105,6 +106,7 @@ public open class FeaturedMathRendererWithPostProcess(
), ),
listOf( listOf(
BetterExponent, BetterExponent,
BetterFraction,
SimplifyParentheses.Default, SimplifyParentheses.Default,
BetterMultiplication, BetterMultiplication,
), ),

View File

@ -102,7 +102,7 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax()
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
@ -143,7 +143,7 @@ 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
@ -160,7 +160,7 @@ public data class UnaryOperatorSyntax(
} }
/** /**
* Represents prefix, unary plus operator. * Represents prefix, unary plus operator (*+x*).
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@ -175,7 +175,7 @@ public data class UnaryPlusSyntax(
} }
/** /**
* Represents prefix, unary minus operator. * Represents prefix, unary minus operator (*-x*).
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
@ -190,7 +190,7 @@ 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
@ -225,7 +225,7 @@ 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.
@ -244,7 +244,7 @@ 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.
@ -263,7 +263,7 @@ 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
@ -282,7 +282,7 @@ 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.
@ -301,7 +301,7 @@ 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.
@ -324,13 +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 @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
@ -339,7 +341,7 @@ 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.
@ -358,11 +360,11 @@ 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 @UnstableKMathAPI

View File

@ -54,6 +54,7 @@ else
* *('-'? (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 @UnstableKMathAPI
public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature { public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature {
@ -113,6 +114,7 @@ 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 @UnstableKMathAPI
public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature { public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature {
@ -135,6 +137,7 @@ 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 @UnstableKMathAPI
public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature { public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
@ -157,6 +160,7 @@ 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 @UnstableKMathAPI
public abstract class Unary(public val operations: Collection<String>?) : RenderFeature { public abstract class Unary(public val operations: Collection<String>?) : RenderFeature {
@ -177,6 +181,7 @@ 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 @UnstableKMathAPI
public abstract class Binary(public val operations: Collection<String>?) : RenderFeature { public abstract class Binary(public val operations: Collection<String>?) : RenderFeature {
@ -193,6 +198,8 @@ public abstract class Binary(public val operations: Collection<String>?) : Rende
/** /**
* Handles binary nodes by producing [BinaryPlusSyntax]. * Handles binary nodes by producing [BinaryPlusSyntax].
*
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class BinaryPlus(operations: Collection<String>?) : Binary(operations) { public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
@ -213,6 +220,8 @@ public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
/** /**
* Handles binary nodes by producing [BinaryMinusSyntax]. * Handles binary nodes by producing [BinaryMinusSyntax].
*
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class BinaryMinus(operations: Collection<String>?) : Binary(operations) { public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
@ -233,6 +242,8 @@ public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
/** /**
* Handles unary nodes by producing [UnaryPlusSyntax]. * Handles unary nodes by producing [UnaryPlusSyntax].
*
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class UnaryPlus(operations: Collection<String>?) : Unary(operations) { public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
@ -251,6 +262,8 @@ public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
/** /**
* Handles binary nodes by producing [UnaryMinusSyntax]. * Handles binary nodes by producing [UnaryMinusSyntax].
*
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class UnaryMinus(operations: Collection<String>?) : Unary(operations) { public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
@ -269,13 +282,16 @@ public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
/** /**
* Handles binary nodes by producing [FractionSyntax]. * Handles binary nodes by producing [FractionSyntax].
*
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class Fraction(operations: Collection<String>?) : Binary(operations) { public class Fraction(operations: Collection<String>?) : Binary(operations) {
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = 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 {
@ -288,6 +304,8 @@ public class Fraction(operations: Collection<String>?) : Binary(operations) {
/** /**
* Handles binary nodes by producing [BinaryOperatorSyntax]. * Handles binary nodes by producing [BinaryOperatorSyntax].
*
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class BinaryOperator(operations: Collection<String>?) : Binary(operations) { public class BinaryOperator(operations: Collection<String>?) : Binary(operations) {
@ -309,6 +327,8 @@ public class BinaryOperator(operations: Collection<String>?) : Binary(operations
/** /**
* Handles unary nodes by producing [UnaryOperatorSyntax]. * Handles unary nodes by producing [UnaryOperatorSyntax].
*
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class UnaryOperator(operations: Collection<String>?) : Unary(operations) { public class UnaryOperator(operations: Collection<String>?) : Unary(operations) {
@ -329,6 +349,8 @@ public class UnaryOperator(operations: Collection<String>?) : Unary(operations)
/** /**
* Handles binary nodes by producing [SuperscriptSyntax]. * Handles binary nodes by producing [SuperscriptSyntax].
*
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class Power(operations: Collection<String>?) : Binary(operations) { public class Power(operations: Collection<String>?) : Binary(operations) {
@ -365,6 +387,8 @@ public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
/** /**
* Handles unary nodes by producing [ExponentSyntax]. * Handles unary nodes by producing [ExponentSyntax].
*
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class Exponent(operations: Collection<String>?) : Unary(operations) { public class Exponent(operations: Collection<String>?) : Unary(operations) {
@ -384,6 +408,8 @@ public class Exponent(operations: Collection<String>?) : Unary(operations) {
/** /**
* Handles binary nodes by producing [MultiplicationSyntax]. * Handles binary nodes by producing [MultiplicationSyntax].
*
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class Multiplication(operations: Collection<String>?) : Binary(operations) { public class Multiplication(operations: Collection<String>?) : Binary(operations) {
@ -404,36 +430,52 @@ public class Multiplication(operations: Collection<String>?) : Binary(operations
} }
/** /**
* Handles binary nodes by producing inverse [UnaryOperatorSyntax] (like *sin<sup>-1</sup>*) with removing the `a` * Handles binary nodes by producing inverse [UnaryOperatorSyntax] with *arc* prefix instead of *a*.
* prefix of operation ID. *
* @author Iaroslav Postovalov
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public class InverseTrigonometricOperations(operations: Collection<String>?) : Unary(operations) { public class InverseTrigonometricOperations(operations: Collection<String>?) : Unary(operations) {
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
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], * The default instance configured with [TrigonometricOperations.ACOS_OPERATION],
* [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION], * [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION].
* [ExponentialOperations.ACOSH_OPERATION], [ExponentialOperations.ASINH_OPERATION], and
* [ExponentialOperations.ATANH_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

@ -83,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
@ -102,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)
@ -116,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)
} }
} }
@ -163,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.interpret import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.misc.symbol 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.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.invoke
import space.kscience.kmath.misc.Symbol.Companion.x
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestCompilerOperations {
@Test
fun testUnaryPlus() = runCompilerTest {
val expr = MstExtendedField { +bindSymbol(x) }.compileToExpression(DoubleField)
assertEquals(2.0, expr(x to 2.0))
}
@Test
fun testUnaryMinus() = runCompilerTest {
val expr = MstExtendedField { -bindSymbol(x) }.compileToExpression(DoubleField)
assertEquals(-2.0, expr(x to 2.0))
}
@Test
fun testAdd() = runCompilerTest {
val expr = MstExtendedField { bindSymbol(x) + bindSymbol(x) }.compileToExpression(DoubleField)
assertEquals(4.0, expr(x to 2.0))
}
@Test
fun testSine() = runCompilerTest {
val expr = MstExtendedField { sin(bindSymbol(x)) }.compileToExpression(DoubleField)
assertEquals(0.0, expr(x to 0.0))
}
@Test
fun testCosine() = runCompilerTest {
val expr = MstExtendedField { cos(bindSymbol(x)) }.compileToExpression(DoubleField)
assertEquals(1.0, expr(x to 0.0))
}
@Test
fun testSubtract() = runCompilerTest {
val expr = MstExtendedField { bindSymbol(x) - bindSymbol(x) }.compileToExpression(DoubleField)
assertEquals(0.0, expr(x to 2.0))
}
@Test
fun testDivide() = runCompilerTest {
val expr = MstExtendedField { bindSymbol(x) / bindSymbol(x) }.compileToExpression(DoubleField)
assertEquals(1.0, expr(x to 2.0))
}
@Test
fun testPower() = runCompilerTest {
val expr = MstExtendedField { bindSymbol(x) pow 2 }.compileToExpression(DoubleField)
assertEquals(4.0, expr(x to 2.0))
}
}

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.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.symbol import space.kscience.kmath.misc.Symbol.Companion.x
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

@ -10,7 +10,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 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

@ -0,0 +1,25 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.ast
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
internal interface CompilerTestContext {
fun MST.compileToExpression(algebra: IntRing): Expression<Int>
fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int
fun MST.compile(algebra: IntRing, vararg arguments: Pair<Symbol, Int>): Int = compile(algebra, mapOf(*arguments))
fun MST.compileToExpression(algebra: DoubleField): Expression<Double>
fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double
fun MST.compile(algebra: DoubleField, vararg arguments: Pair<Symbol, Double>): Double =
compile(algebra, mapOf(*arguments))
}
internal expect inline fun runCompilerTest(action: CompilerTestContext.() -> Unit)

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.misc.Symbol
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.estree.compile as estreeCompile
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
import space.kscience.kmath.wasm.compile as wasmCompile
import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
private object WasmCompilerTestContext : CompilerTestContext {
override fun MST.compileToExpression(algebra: IntRing): Expression<Int> = wasmCompileToExpression(algebra)
override fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int = wasmCompile(algebra, arguments)
override fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = wasmCompileToExpression(algebra)
override fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double =
wasmCompile(algebra, arguments)
}
private object ESTreeCompilerTestContext : CompilerTestContext {
override fun MST.compileToExpression(algebra: IntRing): Expression<Int> = estreeCompileToExpression(algebra)
override fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int = estreeCompile(algebra, arguments)
override fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = estreeCompileToExpression(algebra)
override fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double =
estreeCompile(algebra, arguments)
}
internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) {
action(WasmCompilerTestContext)
action(ESTreeCompilerTestContext)
}

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

@ -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.misc.Symbol
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.asm.compile as asmCompile
import space.kscience.kmath.asm.compileToExpression as asmCompileToExpression
private object AsmCompilerTestContext : CompilerTestContext {
override fun MST.compileToExpression(algebra: IntRing): Expression<Int> = asmCompileToExpression(algebra)
override fun MST.compile(algebra: IntRing, arguments: Map<Symbol, Int>): Int = asmCompile(algebra, arguments)
override fun MST.compileToExpression(algebra: DoubleField): Expression<Double> = asmCompileToExpression(algebra)
override fun MST.compile(algebra: DoubleField, arguments: Map<Symbol, Double>): Double =
asmCompile(algebra, arguments)
}
internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) = action(AsmCompilerTestContext)

View File

@ -14,8 +14,7 @@ The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-de
```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 {
@ -26,8 +25,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

@ -21,8 +21,7 @@ The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-7
```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 {
@ -33,8 +32,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

@ -272,6 +272,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;
@ -1008,14 +1010,7 @@ public abstract interface class space/kscience/kmath/operations/Algebra {
public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
} }
public abstract interface class space/kscience/kmath/operations/AlgebraElement {
public abstract fun getContext ()Lspace/kscience/kmath/operations/Algebra;
}
public final class space/kscience/kmath/operations/AlgebraElementsKt { public final class space/kscience/kmath/operations/AlgebraElementsKt {
public static final fun div (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
public static final fun plus (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
public static final fun times (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement;
} }
public final class space/kscience/kmath/operations/AlgebraExtensionsKt { public final class space/kscience/kmath/operations/AlgebraExtensionsKt {

View File

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

View File

@ -13,6 +13,8 @@ import space.kscience.kmath.misc.UnstableKMathAPI
* @param C the type of mathematical context for this element. * @param C the type of mathematical context for this element.
* @param T the type wrapped by this wrapper. * @param T the type wrapped by this wrapper.
*/ */
@UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public interface AlgebraElement<T, C : Algebra<T>> { public interface AlgebraElement<T, C : Algebra<T>> {
/** /**
* The context this element belongs to. * The context this element belongs to.
@ -45,6 +47,7 @@ public interface AlgebraElement<T, C : Algebra<T>> {
* @return the difference. * @return the difference.
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public operator fun <T : AlgebraElement<T, S>, S : NumbersAddOperations<T>> T.minus(b: T): T = public operator fun <T : AlgebraElement<T, S>, S : NumbersAddOperations<T>> T.minus(b: T): T =
context.add(this, context.run { -b }) context.add(this, context.run { -b })
@ -55,6 +58,8 @@ public operator fun <T : AlgebraElement<T, S>, S : NumbersAddOperations<T>> T.mi
* @param b the addend. * @param b the addend.
* @return the sum. * @return the sum.
*/ */
@UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public operator fun <T : AlgebraElement<T, S>, S : Ring<T>> T.plus(b: T): T = public operator fun <T : AlgebraElement<T, S>, S : Ring<T>> T.plus(b: T): T =
context.add(this, b) context.add(this, b)
@ -71,6 +76,8 @@ public operator fun <T : AlgebraElement<T, S>, S : Ring<T>> T.plus(b: T): T =
* @param b the multiplier. * @param b the multiplier.
* @return the product. * @return the product.
*/ */
@UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public operator fun <T : AlgebraElement<T, R>, R : Ring<T>> T.times(b: T): T = public operator fun <T : AlgebraElement<T, R>, R : Ring<T>> T.times(b: T): T =
context.multiply(this, b) context.multiply(this, b)
@ -81,6 +88,8 @@ public operator fun <T : AlgebraElement<T, R>, R : Ring<T>> T.times(b: T): T =
* @param b the divisor. * @param b the divisor.
* @return the quotient. * @return the quotient.
*/ */
@UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public operator fun <T : AlgebraElement<T, F>, F : Field<T>> T.div(b: T): T = public operator fun <T : AlgebraElement<T, F>, F : Field<T>> T.div(b: T): T =
context.divide(this, b) context.divide(this, b)
@ -93,6 +102,7 @@ public operator fun <T : AlgebraElement<T, F>, F : Field<T>> T.div(b: T): T =
* @param S the type of space. * @param S the type of space.
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public interface GroupElement<T : GroupElement<T, S>, S : Group<T>> : AlgebraElement<T, S> public interface GroupElement<T : GroupElement<T, S>, S : Group<T>> : AlgebraElement<T, S>
/** /**
@ -103,6 +113,7 @@ public interface GroupElement<T : GroupElement<T, S>, S : Group<T>> : AlgebraEle
* @param R the type of ring. * @param R the type of ring.
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public interface RingElement<T : RingElement<T, R>, R : Ring<T>> : GroupElement<T, R> public interface RingElement<T : RingElement<T, R>, R : Ring<T>> : GroupElement<T, R>
/** /**
@ -113,4 +124,5 @@ public interface RingElement<T : RingElement<T, R>, R : Ring<T>> : GroupElement<
* @param F the type of field. * @param F the type of field.
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public interface FieldElement<T : FieldElement<T, F>, F : Field<T>> : RingElement<T, F> @Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public interface FieldElement<T : FieldElement<T, F>, F : Field<T>> : RingElement<T, F>

View File

@ -80,36 +80,42 @@ public interface TrigonometricOperations<T> : Algebra<T> {
* Computes the sine of [arg]. * Computes the sine of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> sin(arg: T): T = arg.context.sin(arg) public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> sin(arg: T): T = arg.context.sin(arg)
/** /**
* Computes the cosine of [arg]. * Computes the cosine of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> cos(arg: T): T = arg.context.cos(arg) public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> cos(arg: T): T = arg.context.cos(arg)
/** /**
* Computes the tangent of [arg]. * Computes the tangent of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> tan(arg: T): T = arg.context.tan(arg) public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> tan(arg: T): T = arg.context.tan(arg)
/** /**
* Computes the inverse sine of [arg]. * Computes the inverse sine of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> asin(arg: T): T = arg.context.asin(arg) public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> asin(arg: T): T = arg.context.asin(arg)
/** /**
* Computes the inverse cosine of [arg]. * Computes the inverse cosine of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> acos(arg: T): T = arg.context.acos(arg) public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> acos(arg: T): T = arg.context.acos(arg)
/** /**
* Computes the inverse tangent of [arg]. * Computes the inverse tangent of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> atan(arg: T): T = arg.context.atan(arg) public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> atan(arg: T): T = arg.context.atan(arg)
/** /**
@ -154,18 +160,21 @@ public interface PowerOperations<T> : Algebra<T> {
* @return the base raised to the power. * @return the base raised to the power.
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public infix fun <T : AlgebraElement<T, out PowerOperations<T>>> T.pow(power: Double): T = context.power(this, power) public infix fun <T : AlgebraElement<T, out PowerOperations<T>>> T.pow(power: Double): T = context.power(this, power)
/** /**
* Computes the square root of the value [arg]. * Computes the square root of the value [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out PowerOperations<T>>> sqrt(arg: T): T = arg pow 0.5 public fun <T : AlgebraElement<T, out PowerOperations<T>>> sqrt(arg: T): T = arg pow 0.5
/** /**
* Computes the square of the value [arg]. * Computes the square of the value [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out PowerOperations<T>>> sqr(arg: T): T = arg pow 2.0 public fun <T : AlgebraElement<T, out PowerOperations<T>>> sqr(arg: T): T = arg pow 2.0
/** /**
@ -261,12 +270,14 @@ public interface ExponentialOperations<T> : Algebra<T> {
* The identifier of exponential function. * The identifier of exponential function.
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> exp(arg: T): T = arg.context.exp(arg) public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> exp(arg: T): T = arg.context.exp(arg)
/** /**
* The identifier of natural logarithm. * The identifier of natural logarithm.
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> ln(arg: T): T = arg.context.ln(arg) public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> ln(arg: T): T = arg.context.ln(arg)
@ -280,30 +291,35 @@ public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> sinh(arg: T): T
* Computes the hyperbolic cosine of [arg]. * Computes the hyperbolic cosine of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> cosh(arg: T): T = arg.context.cosh(arg) public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> cosh(arg: T): T = arg.context.cosh(arg)
/** /**
* Computes the hyperbolic tangent of [arg]. * Computes the hyperbolic tangent of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> tanh(arg: T): T = arg.context.tanh(arg) public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> tanh(arg: T): T = arg.context.tanh(arg)
/** /**
* Computes the inverse hyperbolic sine of [arg]. * Computes the inverse hyperbolic sine of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> asinh(arg: T): T = arg.context.asinh(arg) public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> asinh(arg: T): T = arg.context.asinh(arg)
/** /**
* Computes the inverse hyperbolic cosine of [arg]. * Computes the inverse hyperbolic cosine of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> acosh(arg: T): T = arg.context.acosh(arg) public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> acosh(arg: T): T = arg.context.acosh(arg)
/** /**
* Computes the inverse hyperbolic tangent of [arg]. * Computes the inverse hyperbolic tangent of [arg].
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Deprecated("AlgebraElements are considered odd and will be removed in future releases.")
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> atanh(arg: T): T = arg.context.atanh(arg) public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> atanh(arg: T): T = arg.context.atanh(arg)
/** /**

View File

@ -2,9 +2,9 @@
EJML based linear algebra implementation. EJML based linear algebra implementation.
- [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix. - [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : Point implementations.
- [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix. - [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : Matrix implementation.
- [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix. - [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : LinearSpace implementations.
## Artifact: ## Artifact:
@ -15,8 +15,7 @@ The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-7
```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 {
@ -27,8 +26,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

@ -4,7 +4,7 @@ plugins {
} }
dependencies { dependencies {
api("org.ejml:ejml-simple:0.40") api("org.ejml:ejml-ddense:0.40")
api(project(":kmath-core")) api(project(":kmath-core"))
} }
@ -14,19 +14,19 @@ readme {
feature( feature(
id = "ejml-vector", id = "ejml-vector",
description = "The Point implementation using SimpleMatrix.", description = "Point implementations.",
ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt" ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt"
) )
feature( feature(
id = "ejml-matrix", id = "ejml-matrix",
description = "The Matrix implementation using SimpleMatrix.", description = "Matrix implementation.",
ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt" ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt"
) )
feature( feature(
id = "ejml-linear-space", id = "ejml-linear-space",
description = "The LinearSpace implementation using SimpleMatrix.", description = "LinearSpace implementations.",
ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt" ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt"
) )
} }

View File

@ -5,45 +5,71 @@
package space.kscience.kmath.ejml package space.kscience.kmath.ejml
import org.ejml.data.DMatrix
import org.ejml.data.DMatrixD1
import org.ejml.data.DMatrixRMaj
import org.ejml.dense.row.CommonOps_DDRM
import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.dense.row.factory.DecompositionFactory_DDRM
import org.ejml.simple.SimpleMatrix
import space.kscience.kmath.linear.* import space.kscience.kmath.linear.*
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.nd.StructureFeature
import space.kscience.kmath.nd.getFeature
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.DoubleBuffer
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.cast import kotlin.reflect.cast
/** /**
* Represents context of basic operations operating with [EjmlMatrix]. * [LinearSpace] implementation specialized for a certain EJML type.
*
* @param T the type of items in the matrices.
* @param A the element context type.
* @param M the EJML matrix type.
* @author Iaroslav Postovalov
*/
public abstract class EjmlLinearSpace<T : Any, out A : Ring<T>, M : org.ejml.data.Matrix> : LinearSpace<T, A> {
/**
* Converts this matrix to EJML one.
*/
public abstract fun Matrix<T>.toEjml(): EjmlMatrix<T, M>
/**
* Converts this vector to EJML one.
*/
public abstract fun Point<T>.toEjml(): EjmlVector<T, M>
public abstract override fun buildMatrix(
rows: Int,
columns: Int,
initializer: A.(i: Int, j: Int) -> T,
): EjmlMatrix<T, M>
public abstract override fun buildVector(size: Int, initializer: A.(Int) -> T): EjmlVector<T, M>
}
/**
* [EjmlLinearSpace] implementation based on [CommonOps_DDRM], [DecompositionFactory_DDRM] operations and
* [DMatrixRMaj] matrices.
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
* @author Alexander Nozik
*/ */
public object EjmlLinearSpace : LinearSpace<Double, DoubleField> { public object EjmlLinearSpaceDDRM : EjmlLinearSpace<Double, DoubleField, DMatrixRMaj>() {
/** /**
* The [DoubleField] reference. * The [DoubleField] reference.
*/ */
public override val elementAlgebra: DoubleField get() = DoubleField public override val elementAlgebra: DoubleField get() = DoubleField
/** @Suppress("UNCHECKED_CAST")
* Converts this matrix to EJML one. public override fun Matrix<Double>.toEjml(): EjmlDoubleMatrix<DMatrixRMaj> = when {
*/ this is EjmlDoubleMatrix<*> && origin is DMatrixRMaj -> this as EjmlDoubleMatrix<DMatrixRMaj>
@OptIn(UnstableKMathAPI::class)
public fun Matrix<Double>.toEjml(): EjmlMatrix = when (val matrix = origin) {
is EjmlMatrix -> matrix
else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) }
} }
/** @Suppress("UNCHECKED_CAST")
* Converts this vector to EJML one. public override fun Point<Double>.toEjml(): EjmlDoubleVector<DMatrixRMaj> = when {
*/ this is EjmlDoubleVector<*> && origin is DMatrixRMaj -> this as EjmlDoubleVector<DMatrixRMaj>
public fun Point<Double>.toEjml(): EjmlVector = when (this) { else -> EjmlDoubleVector(DMatrixRMaj(size, 1).also {
is EjmlVector -> this (0 until it.numRows).forEach { row -> it[row, 0] = get(row) }
else -> EjmlVector(SimpleMatrix(size, 1).also {
(0 until it.numRows()).forEach { row -> it[row, 0] = get(row) }
}) })
} }
@ -51,159 +77,178 @@ public object EjmlLinearSpace : LinearSpace<Double, DoubleField> {
rows: Int, rows: Int,
columns: Int, columns: Int,
initializer: DoubleField.(i: Int, j: Int) -> Double, initializer: DoubleField.(i: Int, j: Int) -> Double,
): EjmlMatrix = EjmlMatrix(SimpleMatrix(rows, columns).also { ): EjmlDoubleMatrix<DMatrixRMaj> = EjmlDoubleMatrix(DMatrixRMaj(rows, columns).also {
(0 until rows).forEach { row -> (0 until rows).forEach { row ->
(0 until columns).forEach { col -> it[row, col] = DoubleField.initializer(row, col) } (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) }
} }
}) })
public override fun buildVector(size: Int, initializer: DoubleField.(Int) -> Double): Point<Double> = public override fun buildVector(
EjmlVector(SimpleMatrix(size, 1).also { size: Int,
(0 until it.numRows()).forEach { row -> it[row, 0] = DoubleField.initializer(row) } initializer: DoubleField.(Int) -> Double,
}) ): EjmlDoubleVector<DMatrixRMaj> = EjmlDoubleVector(DMatrixRMaj(size, 1).also {
(0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) }
})
private fun SimpleMatrix.wrapMatrix() = EjmlMatrix(this) private fun <T : DMatrix> T.wrapMatrix() = EjmlDoubleMatrix(this)
private fun SimpleMatrix.wrapVector() = EjmlVector(this) private fun <T : DMatrixD1> T.wrapVector() = EjmlDoubleVector(this)
public override fun Matrix<Double>.unaryMinus(): Matrix<Double> = this * (-1.0) public override fun Matrix<Double>.unaryMinus(): Matrix<Double> = this * (-1.0)
public override fun Matrix<Double>.dot(other: Matrix<Double>): EjmlMatrix = public override fun Matrix<Double>.dot(other: Matrix<Double>): EjmlDoubleMatrix<DMatrixRMaj> {
EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) val out = DMatrixRMaj(1, 1)
CommonOps_DDRM.mult(toEjml().origin, other.toEjml().origin, out)
return out.wrapMatrix()
}
public override fun Matrix<Double>.dot(vector: Point<Double>): EjmlVector = public override fun Matrix<Double>.dot(vector: Point<Double>): EjmlDoubleVector<DMatrixRMaj> {
EjmlVector(toEjml().origin.mult(vector.toEjml().origin)) val out = DMatrixRMaj(1, 1)
CommonOps_DDRM.mult(toEjml().origin, vector.toEjml().origin, out)
return out.wrapVector()
}
public override operator fun Matrix<Double>.minus(other: Matrix<Double>): EjmlMatrix = public override operator fun Matrix<Double>.minus(other: Matrix<Double>): EjmlDoubleMatrix<DMatrixRMaj> {
(toEjml().origin - other.toEjml().origin).wrapMatrix() val out = DMatrixRMaj(1, 1)
CommonOps_DDRM.subtract(toEjml().origin, other.toEjml().origin, out)
return out.wrapMatrix()
}
public override operator fun Matrix<Double>.times(value: Double): EjmlMatrix = public override operator fun Matrix<Double>.times(value: Double): EjmlDoubleMatrix<DMatrixRMaj> {
toEjml().origin.scale(value).wrapMatrix() val res = this.toEjml().origin.copy()
CommonOps_DDRM.scale(value, res)
return res.wrapMatrix()
}
public override fun Point<Double>.unaryMinus(): EjmlVector = public override fun Point<Double>.unaryMinus(): EjmlDoubleVector<DMatrixRMaj> {
toEjml().origin.negative().wrapVector() val out = toEjml().origin.copy()
CommonOps_DDRM.changeSign(out)
return out.wrapVector()
}
public override fun Matrix<Double>.plus(other: Matrix<Double>): EjmlMatrix = public override fun Matrix<Double>.plus(other: Matrix<Double>): EjmlDoubleMatrix<DMatrixRMaj> {
(toEjml().origin + other.toEjml().origin).wrapMatrix() val out = DMatrixRMaj(1, 1)
CommonOps_DDRM.add(toEjml().origin, other.toEjml().origin, out)
return out.wrapMatrix()
}
public override fun Point<Double>.plus(other: Point<Double>): EjmlVector = public override fun Point<Double>.plus(other: Point<Double>): EjmlDoubleVector<DMatrixRMaj> {
(toEjml().origin + other.toEjml().origin).wrapVector() val out = DMatrixRMaj(1, 1)
CommonOps_DDRM.add(toEjml().origin, other.toEjml().origin, out)
return out.wrapVector()
}
public override fun Point<Double>.minus(other: Point<Double>): EjmlVector = public override fun Point<Double>.minus(other: Point<Double>): EjmlDoubleVector<DMatrixRMaj> {
(toEjml().origin - other.toEjml().origin).wrapVector() val out = DMatrixRMaj(1, 1)
CommonOps_DDRM.subtract(toEjml().origin, other.toEjml().origin, out)
return out.wrapVector()
}
public override fun Double.times(m: Matrix<Double>): EjmlMatrix = public override fun Double.times(m: Matrix<Double>): EjmlDoubleMatrix<DMatrixRMaj> = m * this
m.toEjml().origin.scale(this).wrapMatrix()
public override fun Point<Double>.times(value: Double): EjmlVector = public override fun Point<Double>.times(value: Double): EjmlDoubleVector<DMatrixRMaj> {
toEjml().origin.scale(value).wrapVector() val res = this.toEjml().origin.copy()
CommonOps_DDRM.scale(value, res)
return res.wrapVector()
}
public override fun Double.times(v: Point<Double>): EjmlVector = public override fun Double.times(v: Point<Double>): EjmlDoubleVector<DMatrixRMaj> = v * this
v.toEjml().origin.scale(this).wrapVector()
@UnstableKMathAPI @UnstableKMathAPI
public override fun <F : StructureFeature> getFeature(structure: Matrix<Double>, type: KClass<out F>): F? { public override fun <F : StructureFeature> getFeature(structure: Matrix<Double>, type: KClass<out F>): F? {
//Return the feature if it is intrinsic to the structure // Return the feature if it is intrinsic to the structure
structure.getFeature(type)?.let { return it } structure.getFeature(type)?.let { return it }
val origin = structure.toEjml().origin val origin = structure.toEjml().origin
return when (type) { return when (type) {
InverseMatrixFeature::class -> object : InverseMatrixFeature<Double> { InverseMatrixFeature::class -> object : InverseMatrixFeature<Double> {
override val inverse: Matrix<Double> by lazy { EjmlMatrix(origin.invert()) } override val inverse: Matrix<Double> by lazy {
val res = origin.copy()
CommonOps_DDRM.invert(res)
EjmlDoubleMatrix(res)
}
} }
DeterminantFeature::class -> object : DeterminantFeature<Double> { DeterminantFeature::class -> object : DeterminantFeature<Double> {
override val determinant: Double by lazy(origin::determinant) override val determinant: Double by lazy { CommonOps_DDRM.det(DMatrixRMaj(origin)) }
} }
SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<Double> { SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<Double> {
private val svd by lazy { private val svd by lazy {
DecompositionFactory_DDRM.svd(origin.numRows(), origin.numCols(), true, true, false) DecompositionFactory_DDRM.svd(origin.numRows, origin.numCols, true, true, false)
.apply { decompose(origin.ddrm.copy()) } .apply { decompose(origin.copy()) }
} }
override val u: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(svd.getU(null, false))) } override val u: Matrix<Double> by lazy { EjmlDoubleMatrix(svd.getU(null, false)) }
override val s: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(svd.getW(null))) } override val s: Matrix<Double> by lazy { EjmlDoubleMatrix(svd.getW(null)) }
override val v: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(svd.getV(null, false))) } override val v: Matrix<Double> by lazy { EjmlDoubleMatrix(svd.getV(null, false)) }
override val singularValues: Point<Double> by lazy { DoubleBuffer(svd.singularValues) } override val singularValues: Point<Double> by lazy { DoubleBuffer(svd.singularValues) }
} }
QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> { QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> {
private val qr by lazy { private val qr by lazy {
DecompositionFactory_DDRM.qr().apply { decompose(origin.ddrm.copy()) } DecompositionFactory_DDRM.qr().apply { decompose(origin.copy()) }
} }
override val q: Matrix<Double> by lazy { override val q: Matrix<Double> by lazy {
EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) + OrthogonalFeature EjmlDoubleMatrix(qr.getQ(null, false)) + OrthogonalFeature
} }
override val r: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) + UFeature } override val r: Matrix<Double> by lazy { EjmlDoubleMatrix(qr.getR(null, false)) + UFeature }
} }
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Double> { CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Double> {
override val l: Matrix<Double> by lazy { override val l: Matrix<Double> by lazy {
val cholesky = val cholesky =
DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.ddrm.copy()) } DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) }
EjmlMatrix(SimpleMatrix(cholesky.getT(null))) + LFeature EjmlDoubleMatrix(cholesky.getT(null)) + LFeature
} }
} }
LupDecompositionFeature::class -> object : LupDecompositionFeature<Double> { LupDecompositionFeature::class -> object : LupDecompositionFeature<Double> {
private val lup by lazy { private val lup by lazy {
DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()) DecompositionFactory_DDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) }
.apply { decompose(origin.ddrm.copy()) }
} }
override val l: Matrix<Double> by lazy { override val l: Matrix<Double> by lazy {
EjmlMatrix(SimpleMatrix(lup.getLower(null))) + LFeature EjmlDoubleMatrix(lup.getLower(null)) + LFeature
} }
override val u: Matrix<Double> by lazy { override val u: Matrix<Double> by lazy {
EjmlMatrix(SimpleMatrix(lup.getUpper(null))) + UFeature EjmlDoubleMatrix(lup.getUpper(null)) + UFeature
} }
override val p: Matrix<Double> by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) } override val p: Matrix<Double> by lazy { EjmlDoubleMatrix(lup.getRowPivot(null)) }
} }
else -> null else -> null
}?.let(type::cast) }?.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<Double>, b: Matrix<Double>): EjmlDoubleMatrix<DMatrixRMaj> {
val res = DMatrixRMaj(1, 1)
CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res)
return EjmlDoubleMatrix(res)
}
/**
* 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<Double>, b: Point<Double>): EjmlDoubleVector<DMatrixRMaj> {
val res = DMatrixRMaj(1, 1)
CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res)
return EjmlDoubleVector(res)
}
} }
/**
* 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.
* @author Iaroslav Postovalov
*/
public fun EjmlLinearSpace.solve(a: Matrix<Double>, b: Matrix<Double>): EjmlMatrix =
EjmlMatrix(a.toEjml().origin.solve(b.toEjml().origin))
/**
* 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.
* @author Iaroslav Postovalov
*/
public fun EjmlLinearSpace.solve(a: Matrix<Double>, b: Point<Double>): EjmlVector =
EjmlVector(a.toEjml().origin.solve(b.toEjml().origin))
/**
* Inverts this matrix.
*
* @author Alexander Nozik
*/
@OptIn(UnstableKMathAPI::class)
public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature<InverseMatrixFeature<Double>>()!!.inverse as EjmlMatrix
/**
* Inverts the given matrix.
*
* @author Alexander Nozik
*/
public fun EjmlLinearSpace.inverse(matrix: Matrix<Double>): Matrix<Double> = matrix.toEjml().inverted()

View File

@ -5,18 +5,28 @@
package space.kscience.kmath.ejml package space.kscience.kmath.ejml
import org.ejml.simple.SimpleMatrix import org.ejml.data.DMatrix
import space.kscience.kmath.linear.Matrix import org.ejml.data.Matrix
import space.kscience.kmath.nd.Structure2D
/** /**
* The matrix implementation over EJML [SimpleMatrix]. * [space.kscience.kmath.linear.Matrix] implementation based on EJML [Matrix].
* *
* @property origin the underlying [SimpleMatrix]. * @param T the type of elements contained in the buffer.
* @param M the type of EJML matrix.
* @property origin The underlying EJML matrix.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
public class EjmlMatrix(public val origin: SimpleMatrix) : Matrix<Double> { public abstract class EjmlMatrix<T, out M : Matrix>(public open val origin: M) : Structure2D<T> {
public override val rowNum: Int get() = origin.numRows() public override val rowNum: Int get() = origin.numRows
public override val colNum: Int get() = origin.numCols() public override val colNum: Int get() = origin.numCols
}
/**
* [EjmlMatrix] specialization for [Double].
*
* @author Iaroslav Postovalov
*/
public class EjmlDoubleMatrix<out M : DMatrix>(public override val origin: M) : EjmlMatrix<Double, M>(origin) {
public override operator fun get(i: Int, j: Int): Double = origin[i, j] public override operator fun get(i: Int, j: Int): Double = origin[i, j]
} }

View File

@ -5,35 +5,41 @@
package space.kscience.kmath.ejml package space.kscience.kmath.ejml
import org.ejml.simple.SimpleMatrix import org.ejml.data.DMatrixD1
import org.ejml.data.Matrix
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
/** /**
* Represents point over EJML [SimpleMatrix]. * [Point] implementation based on EJML [Matrix].
* *
* @property origin the underlying [SimpleMatrix]. * @param T the type of elements contained in the buffer.
* @param M the type of EJML matrix.
* @property origin The underlying matrix.
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
public class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point<Double> { public abstract class EjmlVector<out T, out M : Matrix>(public open val origin: M) : Point<T> {
public override val size: Int public override val size: Int
get() = origin.numRows() get() = origin.numRows
init { public override operator fun iterator(): Iterator<T> = object : Iterator<T> {
require(origin.numCols() == 1) { "Only single column matrices are allowed" }
}
public override operator fun get(index: Int): Double = origin[index]
public override operator fun iterator(): Iterator<Double> = object : Iterator<Double> {
private var cursor: Int = 0 private var cursor: Int = 0
override fun next(): Double { override fun next(): T {
cursor += 1 cursor += 1
return origin[cursor - 1] return this@EjmlVector[cursor - 1]
} }
override fun hasNext(): Boolean = cursor < origin.numCols() * origin.numRows() override fun hasNext(): Boolean = cursor < origin.numCols * origin.numRows
} }
public override fun toString(): String = "EjmlVector(origin=$origin)" public override fun toString(): String = "EjmlVector(origin=$origin)"
} }
/**
* [EjmlVector] specialization for [Double].
*
* @author Iaroslav Postovalov
*/
public class EjmlDoubleVector<out M : DMatrixD1>(public override val origin: M) : EjmlVector<Double, M>(origin) {
public override operator fun get(index: Int): Double = origin[index]
}

View File

@ -5,12 +5,15 @@
package space.kscience.kmath.ejml package space.kscience.kmath.ejml
import org.ejml.data.DMatrixRMaj
import org.ejml.dense.row.CommonOps_DDRM
import org.ejml.dense.row.RandomMatrices_DDRM
import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.dense.row.factory.DecompositionFactory_DDRM
import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.DeterminantFeature
import space.kscience.kmath.linear.* import space.kscience.kmath.linear.LupDecompositionFeature
import space.kscience.kmath.linear.getFeature
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.nd.getFeature
import kotlin.random.Random import kotlin.random.Random
import kotlin.random.asJavaRandom import kotlin.random.asJavaRandom
import kotlin.test.* import kotlin.test.*
@ -22,65 +25,59 @@ fun <T : Any> assertMatrixEquals(expected: StructureND<T>, actual: StructureND<T
internal class EjmlMatrixTest { internal class EjmlMatrixTest {
private val random = Random(0) private val random = Random(0)
private val randomMatrix: SimpleMatrix private val randomMatrix: DMatrixRMaj
get() { get() {
val s = random.nextInt(2, 100) val s = random.nextInt(2, 100)
return SimpleMatrix.random_DDRM(s, s, 0.0, 10.0, random.asJavaRandom()) val d = DMatrixRMaj(s, s)
RandomMatrices_DDRM.fillUniform(d, random.asJavaRandom())
return d
} }
@Test @Test
fun rowNum() { fun rowNum() {
val m = randomMatrix val m = randomMatrix
assertEquals(m.numRows(), EjmlMatrix(m).rowNum) assertEquals(m.numRows, EjmlDoubleMatrix(m).rowNum)
} }
@Test @Test
fun colNum() { fun colNum() {
val m = randomMatrix val m = randomMatrix
assertEquals(m.numCols(), EjmlMatrix(m).rowNum) assertEquals(m.numCols, EjmlDoubleMatrix(m).rowNum)
} }
@Test @Test
fun shape() { fun shape() {
val m = randomMatrix val m = randomMatrix
val w = EjmlMatrix(m) val w = EjmlDoubleMatrix(m)
assertEquals(listOf(m.numRows(), m.numCols()), w.shape.toList()) assertContentEquals(intArrayOf(m.numRows, m.numCols), w.shape)
} }
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
@Test @Test
fun features() { fun features() {
val m = randomMatrix val m = randomMatrix
val w = EjmlMatrix(m) val w = EjmlDoubleMatrix(m)
val det: DeterminantFeature<Double> = EjmlLinearSpace.getFeature(w) ?: fail() val det: DeterminantFeature<Double> = EjmlLinearSpaceDDRM.getFeature(w) ?: fail()
assertEquals(m.determinant(), det.determinant) assertEquals(CommonOps_DDRM.det(m), det.determinant)
val lup: LupDecompositionFeature<Double> = EjmlLinearSpace.getFeature(w) ?: fail() val lup: LupDecompositionFeature<Double> = EjmlLinearSpaceDDRM.getFeature(w) ?: fail()
val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows(), m.numCols()) val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows, m.numCols)
.also { it.decompose(m.ddrm.copy()) } .also { it.decompose(m.copy()) }
assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getLower(null))), lup.l) assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getLower(null)), lup.l)
assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getUpper(null))), lup.u) assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getUpper(null)), lup.u)
assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getRowPivot(null))), lup.p) assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getRowPivot(null)), lup.p)
}
private object SomeFeature : MatrixFeature {}
@OptIn(UnstableKMathAPI::class)
@Test
fun suggestFeature() {
assertNotNull((EjmlMatrix(randomMatrix) + SomeFeature).getFeature<SomeFeature>())
} }
@Test @Test
fun get() { fun get() {
val m = randomMatrix val m = randomMatrix
assertEquals(m[0, 0], EjmlMatrix(m)[0, 0]) assertEquals(m[0, 0], EjmlDoubleMatrix(m)[0, 0])
} }
@Test @Test
fun origin() { fun origin() {
val m = randomMatrix val m = randomMatrix
assertSame(m, EjmlMatrix(m).origin) assertSame(m, EjmlDoubleMatrix(m).origin)
} }
} }

View File

@ -5,7 +5,8 @@
package space.kscience.kmath.ejml package space.kscience.kmath.ejml
import org.ejml.simple.SimpleMatrix import org.ejml.data.DMatrixRMaj
import org.ejml.dense.row.RandomMatrices_DDRM
import kotlin.random.Random import kotlin.random.Random
import kotlin.random.asJavaRandom import kotlin.random.asJavaRandom
import kotlin.test.Test import kotlin.test.Test
@ -15,30 +16,34 @@ import kotlin.test.assertSame
internal class EjmlVectorTest { internal class EjmlVectorTest {
private val random = Random(0) private val random = Random(0)
private val randomMatrix: SimpleMatrix private val randomMatrix: DMatrixRMaj
get() = SimpleMatrix.random_DDRM(random.nextInt(2, 100), 1, 0.0, 10.0, random.asJavaRandom()) get() {
val d = DMatrixRMaj(random.nextInt(2, 100), 1)
RandomMatrices_DDRM.fillUniform(d, random.asJavaRandom())
return d
}
@Test @Test
fun size() { fun size() {
val m = randomMatrix val m = randomMatrix
val w = EjmlVector(m) val w = EjmlDoubleVector(m)
assertEquals(m.numRows(), w.size) assertEquals(m.numRows, w.size)
} }
@Test @Test
fun get() { fun get() {
val m = randomMatrix val m = randomMatrix
val w = EjmlVector(m) val w = EjmlDoubleVector(m)
assertEquals(m[0, 0], w[0]) assertEquals(m[0, 0], w[0])
} }
@Test @Test
fun iterator() { fun iterator() {
val m = randomMatrix val m = randomMatrix
val w = EjmlVector(m) val w = EjmlDoubleVector(m)
assertEquals( assertEquals(
m.iterator(true, 0, 0, m.numRows() - 1, 0).asSequence().toList(), m.iterator(true, 0, 0, m.numRows - 1, 0).asSequence().toList(),
w.iterator().asSequence().toList() w.iterator().asSequence().toList()
) )
} }
@ -46,7 +51,7 @@ internal class EjmlVectorTest {
@Test @Test
fun origin() { fun origin() {
val m = randomMatrix val m = randomMatrix
val w = EjmlVector(m) val w = EjmlDoubleVector(m)
assertSame(m, w.origin) assertSame(m, w.origin)
} }
} }

View File

@ -15,8 +15,7 @@ The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-d
```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 {
@ -27,8 +26,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

@ -17,8 +17,7 @@ The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-
```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 {
@ -29,8 +28,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

@ -0,0 +1,19 @@
plugins {
id("ru.mipt.npm.gradle.jvm")
kotlin("jupyter.api")
}
dependencies {
api(project(":kmath-ast"))
api(project(":kmath-complex"))
api(project(":kmath-for-real"))
implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.3")
}
readme {
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
}
kotlin.sourceSets.all {
languageSettings.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI")
}

View File

@ -0,0 +1,120 @@
package space.kscience.kmath.jupyter
import kotlinx.html.Unsafe
import kotlinx.html.div
import kotlinx.html.stream.createHTML
import kotlinx.html.unsafe
import org.jetbrains.kotlinx.jupyter.api.DisplayResult
import org.jetbrains.kotlinx.jupyter.api.HTML
import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary
import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess
import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer
import space.kscience.kmath.ast.rendering.renderWithStringBuilder
import space.kscience.kmath.complex.Complex
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.RingOperations
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.asSequence
@JupyterLibrary
internal class KMathJupyter : JupyterIntegration() {
private val mathRender = FeaturedMathRendererWithPostProcess.Default
private val syntaxRender = MathMLSyntaxRenderer
override fun Builder.onLoaded() {
import(
"space.kscience.kmath.ast.*",
"space.kscience.kmath.ast.rendering.*",
"space.kscience.kmath.operations.*",
"space.kscience.kmath.expressions.*",
"space.kscience.kmath.misc.*",
"space.kscience.kmath.real.*",
)
fun MST.toDisplayResult(): DisplayResult = HTML(createHTML().div {
unsafe {
+syntaxRender.renderWithStringBuilder(mathRender.render(this@toDisplayResult))
}
})
render<MST> { it.toDisplayResult() }
render<Number> { MST.Numeric(it).toDisplayResult() }
fun Unsafe.appendCellValue(it: Any?) {
when (it) {
is Number -> {
val s = StringBuilder()
syntaxRender.renderPart(mathRender.render(MST.Numeric(it)), s)
+s.toString()
}
is MST -> {
val s = StringBuilder()
syntaxRender.renderPart(mathRender.render(it), s)
+s.toString()
}
else -> {
+"<ms>"
+it.toString()
+"</ms>"
}
}
}
render<Structure2D<*>> { structure ->
HTML(createHTML().div {
unsafe {
+"<math xmlns=\"https://www.w3.org/1998/Math/MathML\">"
+"<mrow>"
+"<mfenced open=\"[\" close=\"]\" separators=\"\">"
+"<mtable>"
structure.rows.forEach { row ->
+"<mtr>"
row.asSequence().forEach {
+"<mtd>"
appendCellValue(it)
+"</mtd>"
}
+"</mtr>"
}
+"</mtable>"
+"</mfenced>"
+"</mrow>"
+"</math>"
}
})
}
render<Buffer<*>> { buffer ->
HTML(createHTML().div {
unsafe {
+"<math xmlns=\"https://www.w3.org/1998/Math/MathML\">"
+"<mrow>"
+"<mfenced open=\"[\" close=\"]\" separators=\"\">"
+"<mtable>"
buffer.asSequence().forEach {
+"<mtr>"
+"<mtd>"
appendCellValue(it)
+"</mtd>"
+"</mtr>"
}
+"</mtable>"
+"</mfenced>"
+"</mrow>"
+"</math>"
}
})
}
render<Complex> {
MST.Binary(
operation = GroupOperations.PLUS_OPERATION,
left = MST.Numeric(it.re),
right = MST.Binary(RingOperations.TIMES_OPERATION, MST.Numeric(it.im), MST.Symbolic("i")),
).toDisplayResult()
}
}
}

View File

@ -4,8 +4,8 @@ plugins {
} }
dependencies { dependencies {
implementation("com.github.breandan:kaliningraph:0.1.4") api("com.github.breandan:kaliningraph:0.1.4")
implementation("com.github.breandan:kotlingrad:0.4.0") api("com.github.breandan:kotlingrad:0.4.5")
api(project(":kmath-ast")) api(project(":kmath-ast"))
} }

View File

@ -15,8 +15,7 @@ The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-7
```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 {
@ -27,8 +26,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

@ -26,11 +26,6 @@ public open class BufferedTensor<T>(
override fun elements(): Sequence<Pair<IntArray, T>> = linearStructure.indices().map { override fun elements(): Sequence<Pair<IntArray, T>> = linearStructure.indices().map {
it to this[it] it to this[it]
} }
override fun equals(other: Any?): Boolean = false
override fun hashCode(): Int = 0
} }
public class IntTensor internal constructor( public class IntTensor internal constructor(

View File

@ -7,9 +7,9 @@ description = "Binding for https://github.com/JetBrains-Research/viktor"
dependencies { dependencies {
api(project(":kmath-core")) api(project(":kmath-core"))
api("org.jetbrains.bio:viktor:1.0.1") api("org.jetbrains.bio:viktor:1.1.0")
} }
readme { readme {
maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT
} }

View File

@ -17,6 +17,9 @@ pluginManagement {
id("ru.mipt.npm.gradle.project") version toolsVersion id("ru.mipt.npm.gradle.project") version toolsVersion
id("ru.mipt.npm.gradle.mpp") version toolsVersion id("ru.mipt.npm.gradle.mpp") version toolsVersion
id("ru.mipt.npm.gradle.jvm") version toolsVersion id("ru.mipt.npm.gradle.jvm") version toolsVersion
kotlin("jupyter.api") version "0.9.0.12"
kotlin("jvm") version kotlinVersion
kotlin("plugin.allopen") version kotlinVersion
} }
} }
@ -40,6 +43,7 @@ include(
":kmath-ejml", ":kmath-ejml",
":kmath-kotlingrad", ":kmath-kotlingrad",
":kmath-tensors", ":kmath-tensors",
":kmath-jupyter",
":examples", ":examples",
":benchmarks" ":benchmarks"
) )