diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9a9f04621..cde58b6d6 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,6 +1,9 @@
name: Gradle build
-on: [ push ]
+on:
+ push:
+ branches: [ dev, master ]
+ pull_request:
jobs:
build:
@@ -8,23 +11,22 @@ jobs:
matrix:
os: [ macOS-latest, windows-latest ]
runs-on: ${{matrix.os}}
- timeout-minutes: 30
+ timeout-minutes: 40
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Set up JDK 11
uses: DeLaGuardo/setup-graalvm@4.0
with:
- graalvm: 21.1.0
+ graalvm: 21.2.0
java: java11
arch: amd64
- - name: Add msys to path
- if: matrix.os == 'windows-latest'
- run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
- name: Cache gradle
uses: actions/cache@v2
with:
- path: ~/.gradle/caches
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
@@ -36,4 +38,4 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Build
- run: ./gradlew build --no-daemon --stacktrace
+ run: ./gradlew build --build-cache --no-daemon --stacktrace
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 86fdac6a6..23ed54357 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -2,23 +2,27 @@ name: Dokka publication
on:
push:
- branches:
- - master
+ branches: [ master ]
jobs:
build:
runs-on: ubuntu-20.04
+ timeout-minutes: 40
steps:
- - name: Checkout the repo
- uses: actions/checkout@v2
- - name: Set up JDK 11
- uses: actions/setup-java@v1
+ - uses: actions/checkout@v2
+ - uses: DeLaGuardo/setup-graalvm@4.0
with:
- java-version: 11
- - name: Build
- run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
- - name: Deploy to GitHub Pages
- uses: JamesIves/github-pages-deploy-action@4.1.0
+ graalvm: 21.2.0
+ java: java11
+ arch: amd64
+ - uses: actions/cache@v2
+ with:
+ path: ~/.gradle/caches
+ key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
+ restore-keys: |
+ ${{ runner.os }}-gradle-
+ - run: ./gradlew dokkaHtmlMultiModule --build-cache --no-daemon --no-parallel --stacktrace
+ - uses: JamesIves/github-pages-deploy-action@4.1.0
with:
branch: gh-pages
folder: build/dokka/htmlMultiModule
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index c5c110e89..c5075cb0f 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -3,8 +3,7 @@ name: Gradle publish
on:
workflow_dispatch:
release:
- types:
- - created
+ types: [ created ]
jobs:
publish:
@@ -20,16 +19,15 @@ jobs:
- name: Set up JDK 11
uses: DeLaGuardo/setup-graalvm@4.0
with:
- graalvm: 21.1.0
+ graalvm: 21.2.0
java: java11
arch: amd64
- - name: Add msys to path
- if: matrix.os == 'windows-latest'
- run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
- name: Cache gradle
uses: actions/cache@v2
with:
- path: ~/.gradle/caches
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
@@ -42,20 +40,14 @@ jobs:
${{ runner.os }}-gradle-
- name: Publish Windows Artifacts
if: matrix.os == 'windows-latest'
+ shell: cmd
run: >
- ./gradlew release --no-daemon
- -Ppublishing.enabled=true
- -Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }}
- -Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
- -Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
- -Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
+ ./gradlew release --no-daemon --build-cache -Ppublishing.enabled=true
+ -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
+ -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}
- name: Publish Mac Artifacts
if: matrix.os == 'macOS-latest'
run: >
- ./gradlew release --no-daemon
- -Ppublishing.enabled=true
- -Ppublishing.platform=macosX64
- -Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }}
- -Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
- -Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
- -Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
+ ./gradlew release --no-daemon --build-cache -Ppublishing.enabled=true -Ppublishing.platform=macosX64
+ -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
+ -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c4f5b547..eadf5877d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,11 +2,11 @@
## [Unreleased]
### Added
-- ScaleOperations interface
-- Field extends ScaleOperations
+- `ScaleOperations` interface
+- `Field` extends `ScaleOperations`
- Basic integration API
- Basic MPP distributions and samplers
-- bindSymbolOrNull
+- `bindSymbolOrNull`
- Blocking chains and Statistics
- Multiplatform integration
- Integration for any Field element
@@ -15,6 +15,8 @@
- `@PerformancePitfall` annotation to mark possibly slow API
- BigInt operation performance improvement and fixes by @zhelenskiy (#328)
- Unified architecture for Integration and Optimization using features.
+- `BigInt` operation performance improvement and fixes by @zhelenskiy (#328)
+- Integration between `MST` and Symja `IExpr`
### Changed
- Exponential operations merged with hyperbolic functions
@@ -53,6 +55,7 @@
### Fixed
- Ring inherits RingOperations, not GroupOperations
+- Univariate histogram filling
### Security
diff --git a/README.md b/README.md
index 9117582ac..db069d4e0 100644
--- a/README.md
+++ b/README.md
@@ -2,14 +2,14 @@
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
-[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
+[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
# KMath
-Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based analog to
-Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior architecture
-designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
-be achieved with [kmath-for-real](/kmath-for-real) extension module.
+Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based
+analog to Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior
+architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
+experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/)
@@ -21,26 +21,33 @@ be achieved with [kmath-for-real](/kmath-for-real) extension module.
# Goal
-* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native).
+* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
+ .
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
## Non-goals
-* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in terms of API.
+* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in API.
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
-* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
-for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
-experience for those, who want to work with specific types.
+* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
+ for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
+ experience for those, who want to work with specific types.
## Features and stability
-KMath is a modular library. Different modules provide different features with different API stability guarantees. All core modules are released with the same version, but with different API change policy. The features are described in module definitions below. The module stability could have following levels:
+KMath is a modular library. Different modules provide different features with different API stability guarantees. All
+core modules are released with the same version, but with different API change policy. The features are described in
+module definitions below. The module stability could have the following levels:
-* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
-* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations.
-* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
+* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could
+ break any moment. You can still use it, but be sure to fix the specific version.
+* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked
+ with `@UnstableKmathAPI` or other stability warning annotations.
+* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor
+ versions, but not in patch versions. API is protected
+ with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
@@ -132,7 +139,7 @@ KMath is a modular library. Different modules provide different features with di
objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high
performance calculations to code generation.
> - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
-> - [autodif](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
+> - [autodiff](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
@@ -161,7 +168,7 @@ performance calculations to code generation.
* ### [kmath-for-real](kmath-for-real)
-> Extension module that should be used to achieve numpy-like behavior.
+> Extension module that should be used to achieve numpy-like behavior.
All operations are specialized to work with `Double` numbers without declaring algebraic contexts.
One can still use generic algebras though.
>
@@ -175,7 +182,7 @@ One can still use generic algebras though.
* ### [kmath-functions](kmath-functions)
-> Functions, integration and interpolation
+>
>
> **Maturity**: EXPERIMENTAL
>
@@ -200,6 +207,16 @@ One can still use generic algebras though.
> **Maturity**: PROTOTYPE
+* ### [kmath-jafama](kmath-jafama)
+>
+>
+> **Maturity**: PROTOTYPE
+>
+> **Features:**
+> - [jafama-double](kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama
+
+
+
* ### [kmath-jupyter](kmath-jupyter)
>
>
@@ -207,24 +224,24 @@ One can still use generic algebras though.
* ### [kmath-kotlingrad](kmath-kotlingrad)
-> Functions, integration and interpolation
+>
>
> **Maturity**: EXPERIMENTAL
>
> **Features:**
-> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : MST based DifferentiableExpression.
-> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST
+> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt) : MST based DifferentiableExpression.
+> - [scalars-adapters](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt) : Conversions between Kotlin∇'s SFun and MST
* ### [kmath-memory](kmath-memory)
-> An API and basic implementation for arranging objects in a continous memory block.
+> An API and basic implementation for arranging objects in a continuous memory block.
>
> **Maturity**: DEVELOPMENT
* ### [kmath-nd4j](kmath-nd4j)
-> ND4J NDStructure implementation and according NDAlgebra classes
+>
>
> **Maturity**: EXPERIMENTAL
>
@@ -241,6 +258,12 @@ One can still use generic algebras though.
> **Maturity**: EXPERIMENTAL
+* ### [kmath-symja](kmath-symja)
+>
+>
+> **Maturity**: PROTOTYPE
+
+
* ### [kmath-tensors](kmath-tensors)
>
>
@@ -248,7 +271,7 @@ One can still use generic algebras though.
>
> **Features:**
> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.)
-> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting.
+> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting.
> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc.
@@ -262,30 +285,33 @@ One can still use generic algebras though.
## Multi-platform support
-KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
-[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
-are delegated to platform-specific implementations even if they could be provided in the common module for performance
-reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
+KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
+[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
+are delegated to platform-specific implementations even if they could be provided in the common module for performance
+reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
feedback are also welcome.
## Performance
-Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve
-both performance and flexibility.
+Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both
+performance and flexibility.
-We expect to focus on creating convenient universal API first and then work on increasing performance for specific
-cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
-native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
+We expect to focus on creating convenient universal API first and then work on increasing performance for specific
+cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
+native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
better than SciPy.
## Requirements
-KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for execution in order to get better performance.
+KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for
+execution to get better performance.
### Repositories
-Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
-[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
+Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/)
+repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
+[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could
+be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
```kotlin
repositories {
@@ -293,8 +319,8 @@ repositories {
}
dependencies {
- api("space.kscience:kmath-core:0.3.0-dev-11")
- // api("space.kscience:kmath-core-jvm:0.3.0-dev-11") for jvm-specific version
+ api("space.kscience:kmath-core:0.3.0-dev-14")
+ // api("space.kscience:kmath-core-jvm:0.3.0-dev-14") for jvm-specific version
}
```
@@ -302,7 +328,7 @@ Gradle `6.0+` is required for multiplatform artifacts.
## Contributing
-The project requires a lot of additional work. The most important thing we need is a feedback about what features are
-required the most. Feel free to create feature requests. We are also welcome to code contributions,
-especially in issues marked with
+The project requires a lot of additional work. The most important thing we need is a feedback about what features are
+required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
+marked with
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.
diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts
index 98ffc5a96..d96c5a8b6 100644
--- a/benchmarks/build.gradle.kts
+++ b/benchmarks/build.gradle.kts
@@ -1,3 +1,7 @@
+@file:Suppress("UNUSED_VARIABLE")
+
+import space.kscience.kmath.benchmarks.addBenchmarkProperties
+
plugins {
kotlin("multiplatform")
kotlin("plugin.allopen")
@@ -12,6 +16,7 @@ repositories {
maven("https://repo.kotlin.link")
maven("https://clojars.org/repo")
maven("https://jitpack.io")
+
maven("http://logicrunch.research.it.uu.se/maven") {
isAllowInsecureProtocol = true
}
@@ -30,7 +35,8 @@ kotlin {
implementation(project(":kmath-stat"))
implementation(project(":kmath-dimensions"))
implementation(project(":kmath-for-real"))
- implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.0")
+ implementation(project(":kmath-jafama"))
+ implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.1")
}
}
@@ -41,8 +47,7 @@ kotlin {
implementation(project(":kmath-nd4j"))
implementation(project(":kmath-kotlingrad"))
implementation(project(":kmath-viktor"))
- implementation("org.nd4j:nd4j-native:1.0.0-beta7")
-
+ implementation("org.nd4j:nd4j-native:1.0.0-M1")
// uncomment if your system supports AVX2
// val os = System.getProperty("os.name")
//
@@ -95,6 +100,11 @@ benchmark {
commonConfiguration()
include("BigIntBenchmark")
}
+
+ configurations.register("jafamaDouble") {
+ commonConfiguration()
+ include("JafamaBenchmark")
+ }
}
// Fix kotlinx-benchmarks bug
@@ -124,3 +134,5 @@ tasks.withType {
readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
}
+
+addBenchmarkProperties()
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
index 15cd14399..0294f924b 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt
@@ -14,22 +14,51 @@ import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
+import kotlin.math.sin
import kotlin.random.Random
@State(Scope.Benchmark)
internal class ExpressionsInterpretersBenchmark {
+ /**
+ * Benchmark case for [Expression] created with [expressionInExtendedField].
+ */
@Benchmark
fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
+ /**
+ * Benchmark case for [Expression] created with [toExpression].
+ */
@Benchmark
fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
+ /**
+ * Benchmark case for [Expression] created with [compileToExpression].
+ */
@Benchmark
fun asmExpression(blackhole: Blackhole) = invokeAndSum(asm, blackhole)
+ /**
+ * Benchmark case for [Expression] implemented manually with `kotlin.math` functions.
+ */
@Benchmark
fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole)
+ /**
+ * Benchmark case for direct computation w/o [Expression].
+ */
+ @Benchmark
+ fun justCalculate(blackhole: Blackhole) {
+ val random = Random(0)
+ var sum = 0.0
+
+ repeat(times) {
+ val x = random.nextDouble()
+ sum += x * 2.0 + 2.0 / x - 16.0 / sin(x)
+ }
+
+ blackhole.consume(sum)
+ }
+
private fun invokeAndSum(expr: Expression, blackhole: Blackhole) {
val random = Random(0)
var sum = 0.0
@@ -42,23 +71,24 @@ internal class ExpressionsInterpretersBenchmark {
}
private companion object {
- private val x: Symbol by symbol
- private val algebra: DoubleField = DoubleField
+ private val x by symbol
+ private val algebra = DoubleField
private const val times = 1_000_000
- private val functional: Expression = DoubleField.expressionInExtendedField {
+ private val functional = DoubleField.expressionInExtendedField {
bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x))
}
private val node = MstExtendedField {
- bindSymbol(x) * 2.0 + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x))
+ x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
}
- private val mst: Expression = node.toExpression(DoubleField)
- private val asm: Expression = node.compileToExpression(DoubleField)
+ private val mst = node.toExpression(DoubleField)
+ private val asm = node.compileToExpression(DoubleField)
- private val raw: Expression = Expression { args ->
- args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / kotlin.math.sin(args.getValue(x))
+ private val raw = Expression { args ->
+ val x = args[x]!!
+ x * 2.0 + 2.0 / x - 16.0 / sin(x)
}
}
}
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt
new file mode 100644
index 000000000..5d4eee7c0
--- /dev/null
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.benchmarks
+
+import kotlinx.benchmark.Blackhole
+import org.openjdk.jmh.annotations.Benchmark
+import org.openjdk.jmh.annotations.Scope
+import org.openjdk.jmh.annotations.State
+import space.kscience.kmath.jafama.JafamaDoubleField
+import space.kscience.kmath.jafama.StrictJafamaDoubleField
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.operations.invoke
+import kotlin.contracts.InvocationKind
+import kotlin.contracts.contract
+import kotlin.random.Random
+
+@State(Scope.Benchmark)
+internal class JafamaBenchmark {
+ @Benchmark
+ fun jafama(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
+ JafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
+ }
+
+ @Benchmark
+ fun core(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
+ DoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
+ }
+
+ @Benchmark
+ fun strictJafama(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
+ StrictJafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
+ }
+}
+
+private inline fun invokeBenchmarks(blackhole: Blackhole, expr: (Double) -> Double) {
+ contract { callsInPlace(expr, InvocationKind.AT_LEAST_ONCE) }
+ val rng = Random(0)
+ repeat(1000000) { blackhole.consume(expr(rng.nextDouble())) }
+}
diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt
index ff67ccc84..8da23bee1 100644
--- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt
+++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt
@@ -14,8 +14,8 @@ import space.kscience.kmath.commons.linear.inverse
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
import space.kscience.kmath.linear.InverseMatrixFeature
import space.kscience.kmath.linear.LinearSpace
-import space.kscience.kmath.linear.inverseWithLup
import space.kscience.kmath.linear.invoke
+import space.kscience.kmath.linear.lupSolver
import space.kscience.kmath.nd.getFeature
import kotlin.random.Random
@@ -35,19 +35,19 @@ internal class MatrixInverseBenchmark {
@Benchmark
fun kmathLupInversion(blackhole: Blackhole) {
- blackhole.consume(LinearSpace.double.inverseWithLup(matrix))
+ blackhole.consume(LinearSpace.double.lupSolver().inverse(matrix))
}
@Benchmark
fun cmLUPInversion(blackhole: Blackhole) {
- with(CMLinearSpace) {
+ CMLinearSpace {
blackhole.consume(inverse(matrix))
}
}
@Benchmark
fun ejmlInverse(blackhole: Blackhole) {
- with(EjmlLinearSpaceDDRM) {
+ EjmlLinearSpaceDDRM {
blackhole.consume(matrix.getFeature>()?.inverse)
}
}
diff --git a/build.gradle.kts b/build.gradle.kts
index 4de6d8bad..6bb19cd35 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,3 +1,5 @@
+import java.net.URL
+
plugins {
id("ru.mipt.npm.gradle.project")
kotlin("jupyter.api") apply false
@@ -7,15 +9,17 @@ allprojects {
repositories {
maven("https://clojars.org/repo")
maven("https://jitpack.io")
+
maven("http://logicrunch.research.it.uu.se/maven") {
isAllowInsecureProtocol = true
}
+
maven("https://oss.sonatype.org/content/repositories/snapshots")
mavenCentral()
}
group = "space.kscience"
- version = "0.3.0-dev-13"
+ version = "0.3.0-dev-14"
}
subprojects {
@@ -23,30 +27,46 @@ subprojects {
afterEvaluate {
tasks.withType {
- dependsOn(tasks.getByName("assemble"))
+ dependsOn(tasks["assemble"])
dokkaSourceSets.all {
- val readmeFile = File(this@subprojects.projectDir, "README.md")
- if (readmeFile.exists()) includes.setFrom(includes + readmeFile.absolutePath)
- externalDocumentationLink("http://ejml.org/javadoc/")
+ val readmeFile = this@subprojects.projectDir.resolve("README.md")
+ if (readmeFile.exists()) includes.from(readmeFile)
+ val kotlinDirPath = "src/$name/kotlin"
+ val kotlinDir = file(kotlinDirPath)
+
+ if (kotlinDir.exists()) sourceLink {
+ localDirectory.set(kotlinDir)
+
+ remoteUrl.set(
+ URL("https://github.com/mipt-npm/${rootProject.name}/tree/master/${this@subprojects.name}/$kotlinDirPath")
+ )
+ }
+
externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/")
externalDocumentationLink("https://deeplearning4j.org/api/latest/")
- externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/")
+ externalDocumentationLink("https://axelclk.bitbucket.io/symja/javadoc/")
+
+ externalDocumentationLink(
+ "https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/",
+ "https://kotlin.github.io/kotlinx.coroutines/package-list",
+ )
+
+ externalDocumentationLink(
+ "https://breandan.net/kotlingrad/kotlingrad/",
+ "https://breandan.net/kotlingrad/kotlingrad/kotlingrad/package-list",
+ )
}
}
}
}
-readme {
- readmeTemplate = file("docs/templates/README-TEMPLATE.md")
-}
+readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md")
ksciencePublish {
- github("kmath")
- space()
- sonatype()
+ vcs("https://github.com/mipt-npm/kmath")
+ space(publish = true)
+ sonatype(publish = true)
}
-apiValidation {
- nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI")
-}
+apiValidation.nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI")
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 7ca4df19d..36a1ffd9e 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -1,5 +1,20 @@
plugins {
`kotlin-dsl`
+ kotlin("plugin.serialization") version "1.4.31"
}
-repositories.mavenCentral()
+repositories {
+ maven("https://repo.kotlin.link")
+ mavenCentral()
+ gradlePluginPortal()
+}
+
+dependencies {
+ api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
+ api("ru.mipt.npm:gradle-tools:0.10.2")
+ api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.3.1")
+}
+
+kotlin.sourceSets.all {
+ languageSettings.useExperimentalAnnotation("kotlin.ExperimentalStdlibApi")
+}
diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt
new file mode 100644
index 000000000..eaa0f59d8
--- /dev/null
+++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.benchmarks
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class JmhReport(
+ val jmhVersion: String,
+ val benchmark: String,
+ val mode: String,
+ val threads: Int,
+ val forks: Int,
+ val jvm: String,
+ val jvmArgs: List,
+ val jdkVersion: String,
+ val vmName: String,
+ val vmVersion: String,
+ val warmupIterations: Int,
+ val warmupTime: String,
+ val warmupBatchSize: Int,
+ val measurementIterations: Int,
+ val measurementTime: String,
+ val measurementBatchSize: Int,
+ val params: Map = emptyMap(),
+ val primaryMetric: PrimaryMetric,
+ val secondaryMetrics: Map,
+) {
+ interface Metric {
+ val score: Double
+ val scoreError: Double
+ val scoreConfidence: List
+ val scorePercentiles: Map
+ val scoreUnit: String
+ }
+
+ @Serializable
+ data class PrimaryMetric(
+ override val score: Double,
+ override val scoreError: Double,
+ override val scoreConfidence: List,
+ override val scorePercentiles: Map,
+ override val scoreUnit: String,
+ val rawDataHistogram: List>>>? = null,
+ val rawData: List>? = null,
+ ) : Metric
+
+ @Serializable
+ data class SecondaryMetric(
+ override val score: Double,
+ override val scoreError: Double,
+ override val scoreConfidence: List,
+ override val scorePercentiles: Map,
+ override val scoreUnit: String,
+ val rawData: List>,
+ ) : Metric
+}
diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt
new file mode 100644
index 000000000..b55e1320e
--- /dev/null
+++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.benchmarks
+
+import kotlinx.benchmark.gradle.BenchmarksExtension
+import kotlinx.serialization.*
+import kotlinx.serialization.json.*
+import org.gradle.api.Project
+import ru.mipt.npm.gradle.KScienceReadmeExtension
+import java.time.*
+import java.time.format.*
+import java.time.temporal.ChronoField.*
+
+private val ISO_DATE_TIME: DateTimeFormatter = DateTimeFormatterBuilder().run {
+ parseCaseInsensitive()
+ appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
+ appendLiteral('-')
+ appendValue(MONTH_OF_YEAR, 2)
+ appendLiteral('-')
+ appendValue(DAY_OF_MONTH, 2)
+ appendLiteral('T')
+ appendValue(HOUR_OF_DAY, 2)
+ appendLiteral('.')
+ appendValue(MINUTE_OF_HOUR, 2)
+ optionalStart()
+ appendLiteral('.')
+ appendValue(SECOND_OF_MINUTE, 2)
+ optionalStart()
+ appendFraction(NANO_OF_SECOND, 0, 9, true)
+ optionalStart()
+ appendOffsetId()
+ optionalStart()
+ appendLiteral('[')
+ parseCaseSensitive()
+ appendZoneRegionId()
+ appendLiteral(']')
+ toFormatter()
+}
+
+private fun noun(number: Number, singular: String, plural: String) = if (number.toLong() == 1L) singular else plural
+
+fun Project.addBenchmarkProperties() {
+ val benchmarksProject = this
+ rootProject.subprojects.forEach { p ->
+ p.extensions.findByType(KScienceReadmeExtension::class.java)?.run {
+ benchmarksProject.extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg ->
+ property("benchmark${cfg.name.replaceFirstChar(Char::uppercase)}") {
+ val launches = benchmarksProject.buildDir.resolve("reports/benchmarks/${cfg.name}")
+
+ val resDirectory = launches.listFiles()?.maxByOrNull {
+ LocalDateTime.parse(it.name, ISO_DATE_TIME).atZone(ZoneId.systemDefault()).toInstant()
+ }
+
+ if (resDirectory == null) {
+ "> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**."
+ } else {
+ val reports =
+ Json.decodeFromString>(resDirectory.resolve("jvm.json").readText())
+
+ buildString {
+ appendLine("")
+ appendLine("")
+ appendLine("Report for benchmark configuration ${cfg.name}
")
+ appendLine("
")
+ appendLine()
+ val first = reports.first()
+
+ appendLine("* Run on ${first.vmName} (build ${first.vmVersion}) with Java process:")
+ appendLine()
+ appendLine("```")
+ appendLine("${first.jvm} ${
+ first.jvmArgs.joinToString(" ")
+ }")
+ appendLine("```")
+
+ appendLine("* JMH ${first.jmhVersion} was used in `${first.mode}` mode with ${first.warmupIterations} warmup ${
+ noun(first.warmupIterations, "iteration", "iterations")
+ } by ${first.warmupTime} and ${first.measurementIterations} measurement ${
+ noun(first.measurementIterations, "iteration", "iterations")
+ } by ${first.measurementTime}.")
+
+ appendLine()
+ appendLine("| Benchmark | Score |")
+ appendLine("|:---------:|:-----:|")
+
+ reports.forEach { report ->
+ appendLine("|`${report.benchmark}`|${report.primaryMetric.score} ± ${report.primaryMetric.scoreError} ${report.primaryMetric.scoreUnit}|")
+ }
+
+ appendLine(" ")
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt
index da1f45c1f..c68a7ae1c 100644
--- a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt
+++ b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt
@@ -14,12 +14,12 @@ private fun Appendable.appendEjmlVector(type: String, ejmlMatrixType: String) {
@Language("kotlin") val text = """/**
* [EjmlVector] specialization for [$type].
*/
-public class Ejml${type}Vector(public override val origin: M) : EjmlVector<$type, M>(origin) {
+public class Ejml${type}Vector(override val origin: M) : EjmlVector<$type, M>(origin) {
init {
require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" }
}
- public override operator fun get(index: Int): $type = origin[0, index]
+ override operator fun get(index: Int): $type = origin[0, index]
}"""
appendLine(text)
appendLine()
@@ -29,8 +29,8 @@ private fun Appendable.appendEjmlMatrix(type: String, ejmlMatrixType: String) {
val text = """/**
* [EjmlMatrix] specialization for [$type].
*/
-public class Ejml${type}Matrix(public override val origin: M) : EjmlMatrix<$type, M>(origin) {
- public override operator fun get(i: Int, j: Int): $type = origin[i, j]
+public class Ejml${type}Matrix(override val origin: M) : EjmlMatrix<$type, M>(origin) {
+ override operator fun get(i: Int, j: Int): $type = origin[i, j]
}"""
appendLine(text)
appendLine()
@@ -54,23 +54,23 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
/**
* The [${kmathAlgebra}] reference.
*/
- public override val elementAlgebra: $kmathAlgebra get() = $kmathAlgebra
+ override val elementAlgebra: $kmathAlgebra get() = $kmathAlgebra
@Suppress("UNCHECKED_CAST")
- public override fun Matrix<${type}>.toEjml(): Ejml${type}Matrix<${ejmlMatrixType}> = when {
+ override fun Matrix<${type}>.toEjml(): Ejml${type}Matrix<${ejmlMatrixType}> = when {
this is Ejml${type}Matrix<*> && origin is $ejmlMatrixType -> this as Ejml${type}Matrix<${ejmlMatrixType}>
else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) }
}
@Suppress("UNCHECKED_CAST")
- public override fun Point<${type}>.toEjml(): Ejml${type}Vector<${ejmlMatrixType}> = when {
+ override fun Point<${type}>.toEjml(): Ejml${type}Vector<${ejmlMatrixType}> = when {
this is Ejml${type}Vector<*> && origin is $ejmlMatrixType -> this as Ejml${type}Vector<${ejmlMatrixType}>
else -> Ejml${type}Vector(${ejmlMatrixType}(size, 1).also {
(0 until it.numRows).forEach { row -> it[row, 0] = get(row) }
})
}
- public override fun buildMatrix(
+ override fun buildMatrix(
rows: Int,
columns: Int,
initializer: ${kmathAlgebra}.(i: Int, j: Int) -> ${type},
@@ -80,7 +80,7 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
}
}.wrapMatrix()
- public override fun buildVector(
+ override fun buildVector(
size: Int,
initializer: ${kmathAlgebra}.(Int) -> ${type},
): Ejml${type}Vector<${ejmlMatrixType}> = Ejml${type}Vector(${ejmlMatrixType}(size, 1).also {
@@ -90,21 +90,21 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
private fun T.wrapMatrix() = Ejml${type}Matrix(this)
private fun T.wrapVector() = Ejml${type}Vector(this)
- public override fun Matrix<${type}>.unaryMinus(): Matrix<${type}> = this * elementAlgebra { -one }
+ override fun Matrix<${type}>.unaryMinus(): Matrix<${type}> = this * elementAlgebra { -one }
- public override fun Matrix<${type}>.dot(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
+ override fun Matrix<${type}>.dot(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.mult(toEjml().origin, other.toEjml().origin, out)
return out.wrapMatrix()
}
- public override fun Matrix<${type}>.dot(vector: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
+ override fun Matrix<${type}>.dot(vector: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.mult(toEjml().origin, vector.toEjml().origin, out)
return out.wrapVector()
}
- public override operator fun Matrix<${type}>.minus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
+ override operator fun Matrix<${type}>.minus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
@@ -123,19 +123,19 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
return out.wrapMatrix()
}
- public override operator fun Matrix<${type}>.times(value: ${type}): Ejml${type}Matrix<${ejmlMatrixType}> {
+ override operator fun Matrix<${type}>.times(value: ${type}): Ejml${type}Matrix<${ejmlMatrixType}> {
val res = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.scale(value, toEjml().origin, res)
return res.wrapMatrix()
}
- public override fun Point<${type}>.unaryMinus(): Ejml${type}Vector<${ejmlMatrixType}> {
+ override fun Point<${type}>.unaryMinus(): Ejml${type}Vector<${ejmlMatrixType}> {
val res = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.changeSign(toEjml().origin, res)
return res.wrapVector()
}
- public override fun Matrix<${type}>.plus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
+ override fun Matrix<${type}>.plus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
@@ -154,7 +154,7 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
return out.wrapMatrix()
}
- public override fun Point<${type}>.plus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
+ override fun Point<${type}>.plus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
@@ -173,7 +173,7 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
return out.wrapVector()
}
- public override fun Point<${type}>.minus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
+ override fun Point<${type}>.minus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
@@ -192,18 +192,18 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
return out.wrapVector()
}
- public override fun ${type}.times(m: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> = m * this
+ override fun ${type}.times(m: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> = m * this
- public override fun Point<${type}>.times(value: ${type}): Ejml${type}Vector<${ejmlMatrixType}> {
+ override fun Point<${type}>.times(value: ${type}): Ejml${type}Vector<${ejmlMatrixType}> {
val res = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.scale(value, toEjml().origin, res)
return res.wrapVector()
}
- public override fun ${type}.times(v: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> = v * this
+ override fun ${type}.times(v: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> = v * this
@UnstableKMathAPI
- public override fun computeFeature(structure: Matrix<${type}>, type: KClass): F? {
+ override fun computeFeature(structure: Matrix<${type}>, type: KClass): F? {
structure.getFeature(type)?.let { return it }
val origin = structure.toEjml().origin
diff --git a/docs/algebra.md b/docs/algebra.md
index 84693bb81..20158a125 100644
--- a/docs/algebra.md
+++ b/docs/algebra.md
@@ -1,85 +1,45 @@
# Algebraic Structures and Algebraic Elements
-The mathematical operations in KMath are generally separated from mathematical objects. This means that to perform an
-operation, say `+`, one needs two objects of a type `T` and an algebra context, which draws appropriate operation up,
-say `Space`. Next one needs to run the actual operation in the context:
+The mathematical operations in KMath are generally separated from mathematical objects. This means that to perform an
+operation, say `+`, one needs two objects of a type `T` and an algebra context, which draws appropriate operation up,
+say `Group`. Next one needs to run the actual operation in the context:
```kotlin
import space.kscience.kmath.operations.*
val a: T = ...
val b: T = ...
-val space: Space = ...
+val group: Group = ...
-val c = space { a + b }
+val c = group { a + b }
```
-At first glance, this distinction seems to be a needless complication, but in fact one needs to remember that in
-mathematics, one could draw up different operations on same objects. For example, one could use different types of
+At first glance, this distinction seems to be a needless complication, but in fact one needs to remember that in
+mathematics, one could draw up different operations on same objects. For example, one could use different types of
geometry for vectors.
## Algebraic Structures
-Mathematical contexts have the following hierarchy:
+Primary mathematical contexts have the following hierarchy:
-**Algebra** ← **Space** ← **Ring** ← **Field**
+`Field <: Ring <: Group <: Algebra`
These interfaces follow real algebraic structures:
-- [Space](https://mathworld.wolfram.com/VectorSpace.html) defines addition, its neutral element (i.e. 0) and scalar
-multiplication;
-- [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its neutral element (i.e. 1);
+- [Group](https://mathworld.wolfram.com/Group.html) defines addition, its identity element (i.e., 0) and additive
+ inverse (-x);
+- [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its identity element (i.e., 1);
- [Field](http://mathworld.wolfram.com/Field.html) adds division operation.
A typical implementation of `Field` is the `DoubleField` which works on doubles, and `VectorSpace` for `Space`.
In some cases algebra context can hold additional operations like `exp` or `sin`, and then it inherits appropriate
-interface. Also, contexts may have operations, which produce elements outside of the context. For example, `Matrix.dot`
-operation produces a matrix with new dimensions, which can be incompatible with initial matrix in terms of linear
-operations.
-
-## Algebraic Element
-
-To achieve more familiar behavior (where you apply operations directly to mathematical objects), without involving
-contexts KMath submits special type objects called `MathElement`. A `MathElement` is basically some object coupled to
-a mathematical context. For example `Complex` is the pair of real numbers representing real and imaginary parts,
-but it also holds reference to the `ComplexField` singleton, which allows performing direct operations on `Complex`
-numbers without explicit involving the context like:
-
-```kotlin
-import space.kscience.kmath.operations.*
-
-// Using elements
-val c1 = Complex(1.0, 1.0)
-val c2 = Complex(1.0, -1.0)
-val c3 = c1 + c2 + 3.0.toComplex()
-
-// Using context
-val c4 = ComplexField { c1 + i - 2.0 }
-```
-
-Both notations have their pros and cons.
-
-The hierarchy for algebraic elements follows the hierarchy for the corresponding algebraic structures.
-
-**MathElement** ← **SpaceElement** ← **RingElement** ← **FieldElement**
-
-`MathElement` is the generic common ancestor of the class with context.
-
-One major distinction between algebraic elements and algebraic contexts is that elements have three type
-parameters:
-
-1. The type of elements, the field operates on.
-2. The self-type of the element returned from operation (which has to be an algebraic element).
-3. The type of the algebra over first type-parameter.
-
-The middle type is needed for of algebra members do not store context. For example, it is impossible to add a context
-to regular `Double`. The element performs automatic conversions from context types and back. One should use context
-operations in all performance-critical places. The performance of element operations is not guaranteed.
+interface. Also, contexts may have operations, which produce elements outside the context. For example, `Matrix.dot`
+operation produces a matrix with new dimensions, which can be incompatible with initial matrix in linear operations.
## Spaces and Fields
-KMath submits both contexts and elements for builtin algebraic structures:
+KMath introduces contexts for builtin algebraic structures:
```kotlin
import space.kscience.kmath.operations.*
@@ -102,13 +62,13 @@ val c2 = ComplexField { c1 - 1.0 } // Returns: Complex(re=0.0, im=2.0)
val c3 = ComplexField { c1 - i * 2.0 }
```
-**Note**: In theory it is possible to add behaviors directly to the context, but as for now Kotlin does not support
-that. Watch [KT-10468](https://youtrack.jetbrains.com/issue/KT-10468) and
+**Note**: In theory it is possible to add behaviors directly to the context, but as for now Kotlin does not support
+that. Watch [KT-10468](https://youtrack.jetbrains.com/issue/KT-10468) and
[KEEP-176](https://github.com/Kotlin/KEEP/pull/176) for updates.
## Nested fields
-Contexts allow one to build more complex structures. For example, it is possible to create a `Matrix` from complex
+Contexts allow one to build more complex structures. For example, it is possible to create a `Matrix` from complex
elements like so:
```kotlin
@@ -118,8 +78,9 @@ val element = NDElement.complex(shape = intArrayOf(2, 2)) { index: IntArray ->
```
The `element` in this example is a member of the `Field` of 2D structures, each element of which is a member of its own
-`ComplexField`. It is important one does not need to create a special n-d class to hold complex
-numbers and implement operations on it, one just needs to provide a field for its elements.
+`ComplexField`. It is important one does not need to create a special n-d class to hold complex numbers and implement
+operations on it, one just needs to provide a field for its elements.
-**Note**: Fields themselves do not solve the problem of JVM boxing, but it is possible to solve with special contexts like
+**Note**: Fields themselves do not solve the problem of JVM boxing, but it is possible to solve with special contexts
+like
`MemorySpec`.
diff --git a/docs/buffers.md b/docs/buffers.md
index 679bd4e78..e7573497e 100644
--- a/docs/buffers.md
+++ b/docs/buffers.md
@@ -1,17 +1,20 @@
# Buffers
-Buffer is one of main building blocks of kmath. It is a basic interface allowing random-access read and write (with `MutableBuffer`).
-There are different types of buffers:
+Buffer is one of main building blocks of kmath. It is a basic interface allowing random-access read and write (
+with `MutableBuffer`). There are different types of buffers:
-* Primitive buffers wrapping like `RealBuffer` which are wrapping primitive arrays.
+* Primitive buffers wrapping like `DoubleBuffer` which are wrapping primitive arrays.
* Boxing `ListBuffer` wrapping a list
* Functionally defined `VirtualBuffer` which does not hold a state itself, but provides a function to calculate value
* `MemoryBuffer` allows direct allocation of objects in continuous memory block.
-Some kmath features require a `BufferFactory` class to operate properly. A general convention is to use functions defined in
-`Buffer` and `MutableBuffer` companion classes. For example factory `Buffer.Companion::auto` in most cases creates the most suitable
-buffer for given reified type (for types with custom memory buffer it still better to use their own `MemoryBuffer.create()` factory).
+Some kmath features require a `BufferFactory` class to operate properly. A general convention is to use functions
+defined in
+`Buffer` and `MutableBuffer` companion classes. For example factory `Buffer.Companion::auto` in most cases creates the
+most suitable buffer for given reified type (for types with custom memory buffer it still better to use their
+own `MemoryBuffer.create()` factory).
## Buffer performance
-One should avoid using default boxing buffer wherever it is possible. Try to use primitive buffers or memory buffers instead
+One should avoid using default boxing buffer wherever it is possible. Try to use primitive buffers or memory buffers
+instead .
diff --git a/docs/codestyle.md b/docs/codestyle.md
index 541dc4973..73ba5f754 100644
--- a/docs/codestyle.md
+++ b/docs/codestyle.md
@@ -1,26 +1,20 @@
# Coding Conventions
-KMath code follows general [Kotlin conventions](https://kotlinlang.org/docs/reference/coding-conventions.html), but
-with a number of small changes and clarifications.
+Generally, KMath code follows general [Kotlin coding conventions](https://kotlinlang.org/docs/reference/coding-conventions.html), but with a number of small changes and clarifications.
## Utility Class Naming
-Filename should coincide with a name of one of the classes contained in the file or start with small letter and
-describe its contents.
+Filename should coincide with a name of one of the classes contained in the file or start with small letter and describe its contents.
-The code convention [here](https://kotlinlang.org/docs/reference/coding-conventions.html#source-file-names) says that
-file names should start with a capital letter even if file does not contain classes. Yet starting utility classes and
-aggregators with a small letter seems to be a good way to visually separate those files.
+The code convention [here](https://kotlinlang.org/docs/reference/coding-conventions.html#source-file-names) says that file names should start with a capital letter even if file does not contain classes. Yet starting utility classes and aggregators with a small letter seems to be a good way to visually separate those files.
This convention could be changed in future in a non-breaking way.
## Private Variable Naming
-Private variables' names may start with underscore `_` for of the private mutable variable is shadowed by the public
-read-only value with the same meaning.
+Private variables' names may start with underscore `_` for of the private mutable variable is shadowed by the public read-only value with the same meaning.
-This rule does not permit underscores in names, but it is sometimes useful to "underscore" the fact that public and
-private versions draw up the same entity. It is allowed only for private variables.
+This rule does not permit underscores in names, but it is sometimes useful to "underscore" the fact that public and private versions draw up the same entity. It is allowed only for private variables.
This convention could be changed in future in a non-breaking way.
@@ -30,5 +24,4 @@ Use one-liners when they occupy single code window line both for functions and p
`val b: String get() = "fff"`. The same should be performed with multiline expressions when they could be
cleanly separated.
-There is no universal consensus whenever use `fun a() = ...` or `fun a() { return ... }`. Yet from reader outlook
-one-lines seem to better show that the property or function is easily calculated.
+There is no universal consensus whenever use `fun a() = ...` or `fun a() { return ... }`. Yet from reader outlook one-lines seem to better show that the property or function is easily calculated.
diff --git a/docs/contexts.md b/docs/contexts.md
index 58b198046..c26333860 100644
--- a/docs/contexts.md
+++ b/docs/contexts.md
@@ -2,18 +2,17 @@
## The problem
-A known problem for implementing mathematics in statically-typed languages (but not only in them) is that different
-sets of mathematical operators can be defined on the same mathematical objects. Sometimes there is no single way to
-treat some operations, including basic arithmetic operations, on a Java/Kotlin `Number`. Sometimes there are different ways to
-define the same structure, such as Euclidean and elliptic geometry vector spaces over real vectors. Another problem arises when
-one wants to add some kind of behavior to an existing entity. In dynamic languages those problems are usually solved
-by adding dynamic context-specific behaviors at runtime, but this solution has a lot of drawbacks.
+A known problem for implementing mathematics in statically-typed languages (but not only in them) is that different sets
+of mathematical operators can be defined on the same mathematical objects. Sometimes there is no single way to treat
+some operations, including basic arithmetic operations, on a Java/Kotlin `Number`. Sometimes there are different ways to
+define the same structure, such as Euclidean and elliptic geometry vector spaces over real vectors. Another problem
+arises when one wants to add some kind of behavior to an existing entity. In dynamic languages those problems are
+usually solved by adding dynamic context-specific behaviors at runtime, but this solution has a lot of drawbacks.
## Context-oriented approach
-One possible solution to these problems is to divorce numerical representations from behaviors.
-For example in Kotlin one can define a separate class which represents some entity without any operations,
-ex. a complex number:
+One possible solution to these problems is to divorce numerical representations from behaviors. For example in Kotlin
+one can define a separate class representing some entity without any operations, ex. a complex number:
```kotlin
data class Complex(val re: Double, val im: Double)
@@ -28,9 +27,10 @@ object ComplexOperations {
}
```
-In Java, applying such external operations could be very cumbersome, but Kotlin has a unique feature which allows us
-implement this naturally: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions).
-In Kotlin, an operation on complex number could be implemented as:
+In Java, applying such external operations could be cumbersome, but Kotlin has a unique feature that allows us
+implement this
+naturally: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions). In
+Kotlin, an operation on complex number could be implemented as:
```kotlin
with(ComplexOperations) { c1 + c2 - c3 }
@@ -52,20 +52,20 @@ In KMath, contexts are not only responsible for operations, but also for raw obj
### Type classes
-An obvious candidate to get more or less the same functionality is the type class, which allows one to bind a behavior to
-a specific type without modifying the type itself. On the plus side, type classes do not require explicit context
+An obvious candidate to get more or less the same functionality is the type class, which allows one to bind a behavior
+to a specific type without modifying the type itself. On the plus side, type classes do not require explicit context
declaration, so the code looks cleaner. On the minus side, if there are different sets of behaviors for the same types,
-it is impossible to combine them into one module. Also, unlike type classes, context can have parameters or even
-state. For example in KMath, sizes and strides for `NDElement` or `Matrix` could be moved to context to optimize
-performance in case of a large amount of structures.
+it is impossible to combine them into one module. Also, unlike type classes, context can have parameters or even state.
+For example in KMath, sizes and strides for `NDElement` or `Matrix` could be moved to context to optimize performance in
+case of a large amount of structures.
### Wildcard imports and importing-on-demand
-Sometimes, one may wish to use a single context throughout a file. In this case, is possible to import all members
-from a package or file, via `import context.complex.*`. Effectively, this is the same as enclosing an entire file
-with a single context. However when using multiple contexts, this technique can introduce operator ambiguity, due to
-namespace pollution. If there are multiple scoped contexts which define the same operation, it is still possible to
-to import specific operations as needed, without using an explicit context with extension functions, for example:
+Sometimes, one may wish to use a single context throughout a file. In this case, is possible to import all members from
+a package or file, via `import context.complex.*`. Effectively, this is the same as enclosing an entire file with a
+single context. However, when using multiple contexts, this technique can introduce operator ambiguity, due to namespace
+pollution. If there are multiple scoped contexts that define the same operation, it is still possible to import
+specific operations as needed, without using an explicit context with extension functions, for example:
```
import context.complex.op1
diff --git a/docs/expressions.md b/docs/expressions.md
index 1e05e5340..e6250110c 100644
--- a/docs/expressions.md
+++ b/docs/expressions.md
@@ -1,26 +1,21 @@
# Expressions
-**Experimental: this API is in early stage and could change any time**
-
-Expressions is an experimental feature which allows to construct lazily or immediately calculated parametric mathematical
-expressions.
+Expressions is a feature, which allows constructing lazily or immediately calculated parametric mathematical expressions.
The potential use-cases for it (so far) are following:
-* Lazy evaluation (in general simple lambda is better, but there are some border cases)
+* lazy evaluation (in general simple lambda is better, but there are some border cases);
+* automatic differentiation in single-dimension and in multiple dimensions;
+* generation of mathematical syntax trees with subsequent code generation for other languages;
+* symbolic computations, especially differentiation (and some other actions with `kmath-symja` integration with Symja's `IExpr`—integration, simplification, and more);
+* visualization with `kmath-jupyter`.
-* Automatic differentiation in single-dimension and in multiple dimensions
-
-* Generation of mathematical syntax trees with subsequent code generation for other languages
-
-* Maybe symbolic computations (needs additional research)
-
-The workhorse of this API is `Expression` interface which exposes single `operator fun invoke(arguments: Map): T`
-method. `ExpressionContext` is used to generate expressions and introduce variables.
+The workhorse of this API is `Expression` interface, which exposes single `operator fun invoke(arguments: Map): T`
+method. `ExpressionAlgebra` is used to generate expressions and introduce variables.
Currently there are two implementations:
* Generic `ExpressionField` in `kmath-core` which allows construction of custom lazy expressions
-* Auto-differentiation expression in `kmath-commons` module allows to use full power of `DerivativeStructure`
+* Auto-differentiation expression in `kmath-commons` module allows using full power of `DerivativeStructure`
from commons-math. **TODO: add example**
diff --git a/docs/features.md b/docs/features.md
deleted file mode 100644
index 1068a4417..000000000
--- a/docs/features.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Features
-
-* [Algebra](algebra.md) - [Context-based](contexts.md) operations on different primitives and structures.
-
-* [NDStructures](nd-structure.md)
-
-* [Linear algebra](linear.md) - Matrices, operations and linear equations solving. To be moved to separate module. Currently supports basic
-api and multiple library back-ends.
-
-* [Histograms](histograms.md) - Multidimensional histogram calculation and operations.
-
-* [Expressions](expressions.md)
-
-* Commons math integration
diff --git a/docs/linear.md b/docs/linear.md
index 6ccc6caac..2a05499ef 100644
--- a/docs/linear.md
+++ b/docs/linear.md
@@ -1,19 +1,31 @@
## Basic linear algebra layout
-KMath support for linear algebra organized in a context-oriented way. Meaning that operations are in most cases declared
-in context classes, and are not the members of classes that store data. This allows more flexible approach to maintain multiple
-back-ends. The new operations added as extensions to contexts instead of being member functions of data structures.
+KMath support for linear algebra organized in a context-oriented way, which means that operations are in most cases declared in context classes, and are not the members of classes that store data. This allows more flexible approach to maintain multiple back-ends. The new operations added as extensions to contexts instead of being member functions of data structures.
-Two major contexts used for linear algebra and hyper-geometry:
+The main context for linear algebra over matrices and vectors is `LinearSpace`, which defines addition and dot products of matrices and vectors:
-* `VectorSpace` forms a mathematical space on top of array-like structure (`Buffer` and its type alias `Point` used for geometry).
+```kotlin
+import space.kscience.kmath.linear.*
-* `MatrixContext` forms a space-like context for 2d-structures. It does not store matrix size and therefore does not implement
-`Space` interface (it is impossible to create zero element without knowing the matrix size).
+LinearSpace.Companion.real {
+ val vec = buildVector(10) { i -> i.toDouble() }
+ val mat = buildMatrix(10, 10) { i, j -> i.toDouble() + j }
-## Vector spaces
+ // Addition
+ vec + vec
+ mat + mat
+ // Multiplication by scalar
+ vec * 2.0
+ mat * 2.0
-## Matrix operations
+ // Dot product
+ mat dot vec
+ mat dot mat
+}
+```
-## Back-end overview
\ No newline at end of file
+## Backends overview
+
+### EJML
+### Commons Math
diff --git a/docs/nd-structure.md b/docs/nd-structure.md
index ec9b4d521..3e9203ec0 100644
--- a/docs/nd-structure.md
+++ b/docs/nd-structure.md
@@ -11,16 +11,16 @@ Let us consider following contexts:
```kotlin
// automatically build context most suited for given type.
val autoField = NDField.auto(DoubleField, dim, dim)
- // specialized nd-field for Double. It works as generic Double field as well
+ // specialized nd-field for Double. It works as generic Double field as well.
val specializedField = NDField.real(dim, dim)
//A generic boxing field. It should be used for objects, not primitives.
val genericField = NDField.buffered(DoubleField, dim, dim)
```
-Now let us perform several tests and see which implementation is best suited for each case:
+Now let us perform several tests and see, which implementation is best suited for each case:
## Test case
-In order to test performance we will take 2d-structures with `dim = 1000` and add a structure filled with `1.0`
+To test performance we will take 2d-structures with `dim = 1000` and add a structure filled with `1.0`
to it `n = 1000` times.
## Specialized
@@ -35,8 +35,8 @@ The code to run this looks like:
```
The performance of this code is the best of all tests since it inlines all operations and is specialized for operation
with doubles. We will measure everything else relative to this one, so time for this test will be `1x` (real time
-on my computer is about 4.5 seconds). The only problem with this approach is that it requires to specify type
-from the beginning. Everyone do so anyway, so it is the recommended approach.
+on my computer is about 4.5 seconds). The only problem with this approach is that it requires specifying type
+from the beginning. Everyone does so anyway, so it is the recommended approach.
## Automatic
Let's do the same with automatic field inference:
@@ -49,7 +49,7 @@ Let's do the same with automatic field inference:
}
```
Ths speed of this operation is approximately the same as for specialized case since `NDField.auto` just
-returns the same `RealNDField` in this case. Of course it is usually better to use specialized method to be sure.
+returns the same `RealNDField` in this case. Of course, it is usually better to use specialized method to be sure.
## Lazy
Lazy field does not produce a structure when asked, instead it generates an empty structure and fills it on-demand
@@ -63,7 +63,7 @@ When one calls
}
}
```
-The result will be calculated almost immediately but the result will be empty. In order to get the full result
+The result will be calculated almost immediately but the result will be empty. To get the full result
structure one needs to call all its elements. In this case computation overhead will be huge. So this field never
should be used if one expects to use the full result structure. Though if one wants only small fraction, it could
save a lot of time.
@@ -94,7 +94,7 @@ The boxing field produced by
}
}
```
-obviously is the slowest one, because it requires to box and unbox the `double` on each operation. It takes about
+is the slowest one, because it requires boxing and unboxing the `double` on each operation. It takes about
`15x` time (**TODO: there seems to be a problem here, it should be slow, but not that slow**). This field should
never be used for primitives.
@@ -115,12 +115,14 @@ via extension function.
Usually it is bad idea to compare the direct numerical operation performance in different languages, but it hard to
work completely without frame of reference. In this case, simple numpy code:
```python
+import numpy as np
+
res = np.ones((1000,1000))
for i in range(1000):
res = res + 1.0
```
gives the completion time of about `1.1x`, which means that specialized kotlin code in fact is working faster (I think it is
because better memory management). Of course if one writes `res += 1.0`, the performance will be different,
-but it would be differenc case, because numpy overrides `+=` with in-place operations. In-place operations are
+but it would be different case, because numpy overrides `+=` with in-place operations. In-place operations are
available in `kmath` with `MutableNDStructure` but there is no field for it (one can still work with mapping
functions).
\ No newline at end of file
diff --git a/docs/readme.md b/docs/readme.md
new file mode 100644
index 000000000..2953b7113
--- /dev/null
+++ b/docs/readme.md
@@ -0,0 +1,14 @@
+# Documentation
+
+* [Algebra](algebra.md): [context-based](contexts.md) operations on different primitives and structures.
+
+* [NDStructures](nd-structure.md)
+
+* [Linear algebra](linear.md): matrices, operations and linear equations solving. To be moved to separate module.
+ Currently, supports basic API and multiple library back-ends.
+
+* [Histograms](histograms.md): multidimensional histogram calculation and operations.
+
+* [Expressions](expressions.md)
+
+* Commons math integration
diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md
index 6bb1e9085..e75d4c5ed 100644
--- a/docs/templates/README-TEMPLATE.md
+++ b/docs/templates/README-TEMPLATE.md
@@ -2,14 +2,14 @@
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
-[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
+[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
# KMath
-Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based analog to
-Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior architecture
-designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
-be achieved with [kmath-for-real](/kmath-for-real) extension module.
+Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based
+analog to Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior
+architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
+experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/)
@@ -21,26 +21,33 @@ be achieved with [kmath-for-real](/kmath-for-real) extension module.
# Goal
-* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native).
+* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
+ .
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
## Non-goals
-* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in terms of API.
+* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in API.
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
-* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
-for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
-experience for those, who want to work with specific types.
+* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
+ for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
+ experience for those, who want to work with specific types.
## Features and stability
-KMath is a modular library. Different modules provide different features with different API stability guarantees. All core modules are released with the same version, but with different API change policy. The features are described in module definitions below. The module stability could have following levels:
+KMath is a modular library. Different modules provide different features with different API stability guarantees. All
+core modules are released with the same version, but with different API change policy. The features are described in
+module definitions below. The module stability could have the following levels:
-* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
-* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations.
-* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
+* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could
+ break any moment. You can still use it, but be sure to fix the specific version.
+* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked
+ with `@UnstableKmathAPI` or other stability warning annotations.
+* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor
+ versions, but not in patch versions. API is protected
+ with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
@@ -78,30 +85,33 @@ $modules
## Multi-platform support
-KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
-[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
-are delegated to platform-specific implementations even if they could be provided in the common module for performance
-reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
+KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
+[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
+are delegated to platform-specific implementations even if they could be provided in the common module for performance
+reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
feedback are also welcome.
## Performance
-Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve
-both performance and flexibility.
+Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both
+performance and flexibility.
-We expect to focus on creating convenient universal API first and then work on increasing performance for specific
-cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
-native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
+We expect to focus on creating convenient universal API first and then work on increasing performance for specific
+cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
+native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
better than SciPy.
## Requirements
-KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for execution in order to get better performance.
+KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for
+execution to get better performance.
### Repositories
-Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
-[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
+Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/)
+repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
+[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could
+be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
```kotlin
repositories {
@@ -118,7 +128,7 @@ Gradle `6.0+` is required for multiplatform artifacts.
## Contributing
-The project requires a lot of additional work. The most important thing we need is a feedback about what features are
-required the most. Feel free to create feature requests. We are also welcome to code contributions,
-especially in issues marked with
+The project requires a lot of additional work. The most important thing we need is a feedback about what features are
+required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
+marked with
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.
diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts
index d095db1ba..4cc6fecc0 100644
--- a/examples/build.gradle.kts
+++ b/examples/build.gradle.kts
@@ -26,7 +26,7 @@ dependencies {
implementation(project(":kmath-ejml"))
implementation(project(":kmath-nd4j"))
implementation(project(":kmath-tensors"))
-
+ implementation(project(":kmath-symja"))
implementation(project(":kmath-for-real"))
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
@@ -41,9 +41,11 @@ dependencies {
// } else
implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
- implementation("org.slf4j:slf4j-simple:1.7.30")
+ implementation("org.slf4j:slf4j-simple:1.7.31")
// plotting
- implementation("space.kscience:plotlykt-server:0.4.0")
+ implementation("space.kscience:plotlykt-server:0.4.2")
+ //jafama
+ implementation(project(":kmath-jafama"))
}
kotlin.sourceSets.all {
diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt
index e16769464..c4f263f97 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt
@@ -10,7 +10,7 @@ import space.kscience.kmath.ast.rendering.LatexSyntaxRenderer
import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer
import space.kscience.kmath.ast.rendering.renderWithStringBuilder
-public fun main() {
+fun main() {
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath()
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
println("MathSyntax:")
diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
index d5a82590f..96c9856cf 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt
@@ -9,12 +9,10 @@ import space.kscience.kmath.expressions.MstField
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.operations.DoubleField
-import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
fun main() {
val expr = MstField {
- val x = bindSymbol(x)
x * 2.0 + number(2.0) / x - 16.0
}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt
index 88fd312c7..dec3bfb81 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt
@@ -5,25 +5,23 @@
package space.kscience.kmath.ast
-import space.kscience.kmath.asm.compileToExpression
import space.kscience.kmath.expressions.derivative
import space.kscience.kmath.expressions.invoke
-import space.kscience.kmath.expressions.symbol
+import space.kscience.kmath.expressions.Symbol.Companion.x
+import space.kscience.kmath.expressions.toExpression
import space.kscience.kmath.kotlingrad.toKotlingradExpression
import space.kscience.kmath.operations.DoubleField
/**
- * In this example, x^2-4*x-44 function is differentiated with Kotlin∇, and the autodiff result is compared with
- * valid derivative.
+ * In this example, *x2 − 4 x − 44* function is differentiated with Kotlin∇, and the
+ * derivation result is compared with valid derivative in a certain point.
*/
fun main() {
- val x by symbol
-
- val actualDerivative = "x^2-4*x-44".parseMath()
+ val actualDerivative = "x^2-4*x-44"
+ .parseMath()
.toKotlingradExpression(DoubleField)
.derivative(x)
-
- val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField)
- assert(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
+ val expectedDerivative = "2*x-4".parseMath().toExpression(DoubleField)
+ check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt
new file mode 100644
index 000000000..7e09faeff
--- /dev/null
+++ b/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.ast
+
+import space.kscience.kmath.expressions.Symbol.Companion.x
+import space.kscience.kmath.expressions.derivative
+import space.kscience.kmath.expressions.invoke
+import space.kscience.kmath.expressions.toExpression
+import space.kscience.kmath.operations.DoubleField
+import space.kscience.kmath.symja.toSymjaExpression
+
+/**
+ * In this example, *x2 − 4 x − 44* function is differentiated with Symja, and the
+ * derivation result is compared with valid derivative in a certain point.
+ */
+fun main() {
+ val actualDerivative = "x^2-4*x-44"
+ .parseMath()
+ .toSymjaExpression(DoubleField)
+ .derivative(x)
+
+ val expectedDerivative = "2*x-4".parseMath().toExpression(DoubleField)
+ check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
+}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt
index 5660c76e8..8d95ebb4a 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt
@@ -7,11 +7,15 @@ package space.kscience.kmath.commons.fit
import kotlinx.html.br
import kotlinx.html.h3
-import space.kscience.kmath.commons.optimization.chiSquared
+import space.kscience.kmath.commons.expressions.DSProcessor
+import space.kscience.kmath.commons.optimization.CMOptimizer
import space.kscience.kmath.distributions.NormalDistribution
+import space.kscience.kmath.expressions.chiSquaredExpression
import space.kscience.kmath.expressions.symbol
-import space.kscience.kmath.optimization.FunctionOptimization
-import space.kscience.kmath.optimization.OptimizationResult
+import space.kscience.kmath.optimization.FunctionOptimizationTarget
+import space.kscience.kmath.optimization.optimizeWith
+import space.kscience.kmath.optimization.resultPoint
+import space.kscience.kmath.optimization.resultValue
import space.kscience.kmath.real.DoubleVector
import space.kscience.kmath.real.map
import space.kscience.kmath.real.step
@@ -24,8 +28,7 @@ import space.kscience.plotly.models.TraceValues
import kotlin.math.pow
import kotlin.math.sqrt
-//Forward declaration of symbols that will be used in expressions.
-// This declaration is required for
+// Forward declaration of symbols that will be used in expressions.
private val a by symbol
private val b by symbol
private val c by symbol
@@ -64,17 +67,21 @@ suspend fun main() {
val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma)
// compute differentiable chi^2 sum for given model ax^2 + bx + c
- val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 ->
+ val chi2 = DSProcessor.chiSquaredExpression(x, y, yErr) { arg ->
//bind variables to autodiff context
val a = bindSymbol(a)
val b = bindSymbol(b)
//Include default value for c if it is not provided as a parameter
val c = bindSymbolOrNull(c) ?: one
- a * x1.pow(2) + b * x1 + c
+ a * arg.pow(2) + b * arg + c
}
//minimize the chi^2 in given starting point. Derivatives are not required, they are already included.
- val result: OptimizationResult = chi2.minimize(a to 1.5, b to 0.9, c to 1.0)
+ val result = chi2.optimizeWith(
+ CMOptimizer,
+ mapOf(a to 1.5, b to 0.9, c to 1.0),
+ FunctionOptimizationTarget.MINIMIZE
+ )
//display a page with plot and numerical results
val page = Plotly.page {
@@ -91,7 +98,7 @@ suspend fun main() {
scatter {
mode = ScatterMode.lines
x(x)
- y(x.map { result.point[a]!! * it.pow(2) + result.point[b]!! * it + 1 })
+ y(x.map { result.resultPoint[a]!! * it.pow(2) + result.resultPoint[b]!! * it + 1 })
name = "fit"
}
}
@@ -100,7 +107,7 @@ suspend fun main() {
+"Fit result: $result"
}
h3 {
- +"Chi2/dof = ${result.value / (x.size - 3)}"
+ +"Chi2/dof = ${result.resultValue / (x.size - 3)}"
}
}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt
new file mode 100644
index 000000000..9c3d0fdbe
--- /dev/null
+++ b/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2018-2021 KMath contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package space.kscience.kmath.jafama
+
+import space.kscience.kmath.operations.invoke
+
+fun main() {
+ val a = 2.0
+ val b = StrictJafamaDoubleField { exp(a) }
+ println(JafamaDoubleField { b + a })
+ println(StrictJafamaDoubleField { ln(b) })
+}
diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt
index b319766e3..bde83cea9 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt
@@ -10,9 +10,6 @@ import space.kscience.kmath.chains.Chain
import space.kscience.kmath.chains.collectWithState
import space.kscience.kmath.distributions.NormalDistribution
-/**
- * The state of distribution averager.
- */
private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)
/**
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt
index 501bf98db..e1621d477 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt
@@ -32,7 +32,7 @@ fun main() {
// automatically build context most suited for given type.
val autoField = AlgebraND.auto(DoubleField, dim, dim)
- // specialized nd-field for Double. It works as generic Double field as well
+ // specialized nd-field for Double. It works as generic Double field as well.
val realField = AlgebraND.real(dim, dim)
//A generic boxing field. It should be used for objects, not primitives.
val boxingField = AlgebraND.field(DoubleField, Buffer.Companion::boxing, dim, dim)
diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt
index 955f86fa9..c28b566b9 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt
@@ -19,7 +19,7 @@ private fun DMatrixContext.simple() {
}
private object D5 : Dimension {
- override val dim: UInt = 5u
+ override val dim: Int = 5
}
private fun DMatrixContext.custom() {
diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt
index 74795cc68..ad6890b15 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt
@@ -17,7 +17,7 @@ fun main() = BroadcastDoubleTensorAlgebra { // work in context with broadcast m
dataset += fromArray(
intArrayOf(5),
- doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means
+ doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // row means
)
@@ -28,7 +28,7 @@ fun main() = BroadcastDoubleTensorAlgebra { // work in context with broadcast m
println("Mean:\n$mean")
println("Standard deviation:\n$std")
- // also we can calculate other statistic as minimum and maximum of rows
+ // also, we can calculate other statistic as minimum and maximum of rows
println("Minimum:\n${dataset.min(0, false)}")
println("Maximum:\n${dataset.max(0, false)}")
diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt
index 6453ca44e..3e6a60c31 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt
@@ -42,7 +42,7 @@ fun main() = BroadcastDoubleTensorAlgebra {// work in context with linear operat
// get P, L, U such that PA = LU
val (p, l, u) = a.lu()
- // check that P is permutation matrix
+ // check P is permutation matrix
println("P:\n$p")
// L is lower triangular matrix and U is upper triangular matrix
println("L:\n$l")
diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt
index b262bee02..55a9aa67a 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt
@@ -186,7 +186,7 @@ fun main() = BroadcastDoubleTensorAlgebra {
x += fromArray(
intArrayOf(5),
- doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means
+ doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // row means
)
diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt
index 411e048d7..b973abdef 100644
--- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt
+++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt
@@ -65,8 +65,8 @@ fun main(): Unit = BroadcastDoubleTensorAlgebra { // work in context with broad
val datasetReduced = v dot stack(listOf(xScaled, yScaled))
println("Reduced data:\n$datasetReduced")
- // we can restore original data from reduced data.
- // for example, find 7th element of dataset
+ // we can restore original data from reduced data;
+ // for example, find 7th element of dataset.
val n = 7
val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean
println("Original value:\n${dataset[n]}")
diff --git a/gradle.properties b/gradle.properties
index 7e9516660..b97db1c54 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -7,7 +7,6 @@ kotlin.code.style=official
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.mpp.stability.nowarn=true
kotlin.native.enableDependencyPropagation=false
-kotlin.parallel.tasks.in.project=true
org.gradle.configureondemand=true
-org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G
+org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G
org.gradle.parallel=true
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index e708b1c02..7454180f2 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index f371643ee..05679dc3c 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 4f906e0c8..744e882ed 100755
--- a/gradlew
+++ b/gradlew
@@ -72,7 +72,7 @@ case "`uname`" in
Darwin* )
darwin=true
;;
- MINGW* )
+ MSYS* | MINGW* )
msys=true
;;
NONSTOP* )
diff --git a/kmath-ast/README.md b/kmath-ast/README.md
index b0f2d59e5..686506f6f 100644
--- a/kmath-ast/README.md
+++ b/kmath-ast/README.md
@@ -10,7 +10,7 @@ Performance and visualization extensions to MST API.
## Artifact:
-The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-11`.
+The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-14`.
**Gradle:**
```gradle
@@ -20,7 +20,7 @@ repositories {
}
dependencies {
- implementation 'space.kscience:kmath-ast:0.3.0-dev-11'
+ implementation 'space.kscience:kmath-ast:0.3.0-dev-14'
}
```
**Gradle Kotlin DSL:**
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
- implementation("space.kscience:kmath-ast:0.3.0-dev-11")
+ implementation("space.kscience:kmath-ast:0.3.0-dev-14")
}
```
@@ -45,11 +45,12 @@ special implementation of `Expression` with implemented `invoke` function.
For example, the following builder:
```kotlin
+import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.asm.*
-MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
+MstField { x + 2 }.compileToExpression(DoubleField)
```
... leads to generation of bytecode, which can be decompiled to the following Java class:
@@ -89,11 +90,12 @@ public final class AsmCompiledExpression_45045_0 implements Expression {
A similar feature is also available on JS.
```kotlin
+import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.estree.*
-MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
+MstField { x + 2 }.compileToExpression(DoubleField)
```
The code above returns expression implemented with such a JS function:
@@ -104,15 +106,16 @@ var executable = function (constants, arguments) {
};
```
-JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
+JS also supports experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
```kotlin
+import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.wasm.*
-MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
+MstField { x + 2 }.compileToExpression(DoubleField)
```
An example of emitted Wasm IR in the form of WAT:
@@ -158,7 +161,10 @@ public fun main() {
Result LaTeX:
+
+
![](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 (can be used with MathJax or other renderers):
diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts
index 508374d82..9de7e9980 100644
--- a/kmath-ast/build.gradle.kts
+++ b/kmath-ast/build.gradle.kts
@@ -37,17 +37,15 @@ kotlin.sourceSets {
jsMain {
dependencies {
- implementation(npm("astring", "1.7.4"))
- implementation(npm("binaryen", "100.0"))
- implementation(npm("js-base64", "3.6.0"))
- implementation(npm("webassembly", "0.11.0"))
+ implementation(npm("astring", "1.7.5"))
+ implementation(npm("binaryen", "101.0.0"))
+ implementation(npm("js-base64", "3.6.1"))
}
}
jvmMain {
dependencies {
- implementation("org.ow2.asm:asm:9.1")
- implementation("org.ow2.asm:asm-commons:9.1")
+ implementation("org.ow2.asm:asm-commons:9.2")
}
}
}
@@ -63,25 +61,21 @@ readme {
feature(
id = "expression-language",
- description = "Expression language and its parser",
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt"
- )
+ ) { "Expression language and its parser" }
feature(
id = "mst-jvm-codegen",
- description = "Dynamic MST to JVM bytecode compiler",
ref = "src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt"
- )
+ ) { "Dynamic MST to JVM bytecode compiler" }
feature(
id = "mst-js-codegen",
- description = "Dynamic MST to JS compiler",
ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt"
- )
+ ) { "Dynamic MST to JS compiler" }
feature(
id = "rendering",
- description = "Extendable MST rendering",
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt"
- )
+ ) { "Extendable MST rendering" }
}
diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md
index 80ea31642..9494af63a 100644
--- a/kmath-ast/docs/README-TEMPLATE.md
+++ b/kmath-ast/docs/README-TEMPLATE.md
@@ -16,11 +16,12 @@ special implementation of `Expression` with implemented `invoke` function.
For example, the following builder:
```kotlin
+import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.asm.*
-MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
+MstField { x + 2 }.compileToExpression(DoubleField)
```
... leads to generation of bytecode, which can be decompiled to the following Java class:
@@ -60,11 +61,12 @@ public final class AsmCompiledExpression_45045_0 implements Expression {
A similar feature is also available on JS.
```kotlin
+import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.estree.*
-MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
+MstField { x + 2 }.compileToExpression(DoubleField)
```
The code above returns expression implemented with such a JS function:
@@ -75,15 +77,16 @@ var executable = function (constants, arguments) {
};
```
-JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
+JS also supports experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
```kotlin
+import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.*
import space.kscience.kmath.wasm.*
-MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
+MstField { x + 2 }.compileToExpression(DoubleField)
```
An example of emitted Wasm IR in the form of WAT:
@@ -129,7 +132,10 @@ public fun main() {
Result LaTeX:
+
+
![](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 (can be used with MathJax or other renderers):
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt
index 01717b0f9..2df3d3cc7 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt
@@ -27,7 +27,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
*/
@UnstableKMathAPI
public object LatexSyntaxRenderer : SyntaxRenderer {
- public override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
+ override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
fun render(syntax: MathSyntax) = render(syntax, output)
when (node) {
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt
index cda8e2322..8b5819b84 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt
@@ -16,7 +16,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
*/
@UnstableKMathAPI
public object MathMLSyntaxRenderer : SyntaxRenderer {
- public override fun render(node: MathSyntax, output: Appendable) {
+ override fun render(node: MathSyntax, output: Appendable) {
output.append("")
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt
index c33f95483..fdef35ebd 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt
@@ -29,7 +29,7 @@ public fun interface MathRenderer {
*/
@UnstableKMathAPI
public open class FeaturedMathRenderer(public val features: List) : MathRenderer {
- public override fun render(mst: MST): MathSyntax {
+ override fun render(mst: MST): MathSyntax {
for (feature in features) feature.render(this, mst)?.let { return it }
throw UnsupportedOperationException("Renderer $this has no appropriate feature to render node $mst.")
}
@@ -54,9 +54,9 @@ public open class FeaturedMathRenderer(public val features: List)
@UnstableKMathAPI
public open class FeaturedMathRendererWithPostProcess(
features: List,
- public val stages: List,
+ public val stages: List,
) : FeaturedMathRenderer(features) {
- public override fun render(mst: MST): MathSyntax {
+ override fun render(mst: MST): MathSyntax {
val res = super.render(mst)
for (stage in stages) stage.perform(res)
return res
@@ -65,7 +65,7 @@ public open class FeaturedMathRendererWithPostProcess(
/**
* Logical unit of [MathSyntax] post-processing.
*/
- public fun interface PostProcessStage {
+ public fun interface PostProcessPhase {
/**
* Performs the specified action over [MathSyntax].
*/
@@ -102,7 +102,7 @@ public open class FeaturedMathRendererWithPostProcess(
// Printing terminal nodes as string
PrintNumeric,
- PrintSymbolic,
+ PrintSymbol,
),
listOf(
BetterExponent,
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt
index a71985fbc..ee23ab408 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt
@@ -8,7 +8,7 @@ package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
/**
- * Mathematical typography syntax node.
+ * Syntax node for mathematical typography.
*
* @author Iaroslav Postovalov
*/
@@ -150,9 +150,9 @@ public data class OperandSyntax(
*/
@UnstableKMathAPI
public data class UnaryOperatorSyntax(
- public override val operation: String,
+ override val operation: String,
public var prefix: MathSyntax,
- public override val operand: OperandSyntax,
+ override val operand: OperandSyntax,
) : UnarySyntax() {
init {
operand.parent = this
@@ -166,8 +166,8 @@ public data class UnaryOperatorSyntax(
*/
@UnstableKMathAPI
public data class UnaryPlusSyntax(
- public override val operation: String,
- public override val operand: OperandSyntax,
+ override val operation: String,
+ override val operand: OperandSyntax,
) : UnarySyntax() {
init {
operand.parent = this
@@ -181,8 +181,8 @@ public data class UnaryPlusSyntax(
*/
@UnstableKMathAPI
public data class UnaryMinusSyntax(
- public override val operation: String,
- public override val operand: OperandSyntax,
+ override val operation: String,
+ override val operand: OperandSyntax,
) : UnarySyntax() {
init {
operand.parent = this
@@ -197,8 +197,8 @@ public data class UnaryMinusSyntax(
*/
@UnstableKMathAPI
public data class RadicalSyntax(
- public override val operation: String,
- public override val operand: MathSyntax,
+ override val operation: String,
+ override val operand: MathSyntax,
) : UnarySyntax() {
init {
operand.parent = this
@@ -215,8 +215,8 @@ public data class RadicalSyntax(
*/
@UnstableKMathAPI
public data class ExponentSyntax(
- public override val operation: String,
- public override val operand: OperandSyntax,
+ override val operation: String,
+ override val operand: OperandSyntax,
public var useOperatorForm: Boolean,
) : UnarySyntax() {
init {
@@ -233,9 +233,9 @@ public data class ExponentSyntax(
*/
@UnstableKMathAPI
public data class SuperscriptSyntax(
- public override val operation: String,
- public override val left: MathSyntax,
- public override val right: MathSyntax,
+ override val operation: String,
+ override val left: MathSyntax,
+ override val right: MathSyntax,
) : BinarySyntax() {
init {
left.parent = this
@@ -252,9 +252,9 @@ public data class SuperscriptSyntax(
*/
@UnstableKMathAPI
public data class SubscriptSyntax(
- public override val operation: String,
- public override val left: MathSyntax,
- public override val right: MathSyntax,
+ override val operation: String,
+ override val left: MathSyntax,
+ override val right: MathSyntax,
) : BinarySyntax() {
init {
left.parent = this
@@ -270,10 +270,10 @@ public data class SubscriptSyntax(
*/
@UnstableKMathAPI
public data class BinaryOperatorSyntax(
- public override val operation: String,
+ override val operation: String,
public var prefix: MathSyntax,
- public override val left: MathSyntax,
- public override val right: MathSyntax,
+ override val left: MathSyntax,
+ override val right: MathSyntax,
) : BinarySyntax() {
init {
left.parent = this
@@ -290,9 +290,9 @@ public data class BinaryOperatorSyntax(
*/
@UnstableKMathAPI
public data class BinaryPlusSyntax(
- public override val operation: String,
- public override val left: OperandSyntax,
- public override val right: OperandSyntax,
+ override val operation: String,
+ override val left: OperandSyntax,
+ override val right: OperandSyntax,
) : BinarySyntax() {
init {
left.parent = this
@@ -301,7 +301,7 @@ public data class BinaryPlusSyntax(
}
/**
- * Represents binary, infix subtraction (*42 - 42*).
+ * Represents binary, infix subtraction (*42 − 42*).
*
* @param left The minuend.
* @param right The subtrahend.
@@ -309,9 +309,9 @@ public data class BinaryPlusSyntax(
*/
@UnstableKMathAPI
public data class BinaryMinusSyntax(
- public override val operation: String,
- public override val left: OperandSyntax,
- public override val right: OperandSyntax,
+ override val operation: String,
+ override val left: OperandSyntax,
+ override val right: OperandSyntax,
) : BinarySyntax() {
init {
left.parent = this
@@ -329,9 +329,9 @@ public data class BinaryMinusSyntax(
*/
@UnstableKMathAPI
public data class FractionSyntax(
- public override val operation: String,
- public override val left: OperandSyntax,
- public override val right: OperandSyntax,
+ override val operation: String,
+ override val left: OperandSyntax,
+ override val right: OperandSyntax,
public var infix: Boolean,
) : BinarySyntax() {
init {
@@ -349,9 +349,9 @@ public data class FractionSyntax(
*/
@UnstableKMathAPI
public data class RadicalWithIndexSyntax(
- public override val operation: String,
- public override val left: MathSyntax,
- public override val right: MathSyntax,
+ override val operation: String,
+ override val left: MathSyntax,
+ override val right: MathSyntax,
) : BinarySyntax() {
init {
left.parent = this
@@ -369,9 +369,9 @@ public data class RadicalWithIndexSyntax(
*/
@UnstableKMathAPI
public data class MultiplicationSyntax(
- public override val operation: String,
- public override val left: OperandSyntax,
- public override val right: OperandSyntax,
+ override val operation: String,
+ override val left: OperandSyntax,
+ override val right: OperandSyntax,
public var times: Boolean,
) : BinarySyntax() {
init {
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt
index fb2b3b66f..362c07d72 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt
@@ -9,7 +9,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
/**
* Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should
- * involve traversal of MathSyntax with handling each its subtype.
+ * involve traversal of MathSyntax with handling each subtype.
*
* @author Iaroslav Postovalov
*/
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt
index 863825799..8a4804916 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt
@@ -13,15 +13,14 @@ import space.kscience.kmath.operations.*
import kotlin.reflect.KClass
/**
- * Prints any [MST.Symbolic] as a [SymbolSyntax] containing the [MST.Symbolic.value] of it.
+ * Prints any [Symbol] as a [SymbolSyntax] containing the [Symbol.identity] of it.
*
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
-public object PrintSymbolic : RenderFeature {
- public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? =
- if (node !is Symbol) null
- else SymbolSyntax(string = node.identity)
+public val PrintSymbol: RenderFeature = RenderFeature { _, node ->
+ if (node !is Symbol) null
+ else SymbolSyntax(string = node.identity)
}
/**
@@ -30,8 +29,8 @@ public object PrintSymbolic : RenderFeature {
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
-public object PrintNumeric : RenderFeature {
- public override fun render(renderer: FeaturedMathRenderer, node: MST): NumberSyntax? = if (node !is MST.Numeric)
+public val PrintNumeric: RenderFeature = RenderFeature { _, node ->
+ if (node !is MST.Numeric)
null
else
NumberSyntax(string = node.value.toString())
@@ -50,7 +49,7 @@ else
NumberSyntax(string = s)
/**
- * Special printing for numeric types which are printed in form of
+ * Special printing for numeric types that are printed in form of
* *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*.
*
* @property types The suitable types.
@@ -58,7 +57,7 @@ else
*/
@UnstableKMathAPI
public class PrettyPrintFloats(public val types: Set>) : RenderFeature {
- public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
+ override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Numeric || node.value::class !in types) return null
val toString = when (val v = node.value) {
@@ -111,14 +110,14 @@ public class PrettyPrintFloats(public val types: Set>) : Rend
}
/**
- * Special printing for numeric types which are printed in form of *'-'? DIGIT+*.
+ * Special printing for numeric types that are printed in form of *'-'? DIGIT+*.
*
* @property types The suitable types.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class PrettyPrintIntegers(public val types: Set>) : RenderFeature {
- public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
+ override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
if (node !is MST.Numeric || node.value::class !in types)
null
else
@@ -141,7 +140,7 @@ public class PrettyPrintIntegers(public val types: Set>) : Re
*/
@UnstableKMathAPI
public class PrettyPrintPi(public val symbols: Set) : RenderFeature {
- public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? =
+ override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
if (node !is Symbol || node.identity !in symbols)
null
else
@@ -156,7 +155,7 @@ public class PrettyPrintPi(public val symbols: Set) : RenderFeature {
}
/**
- * Abstract printing of unary operations which discards [MST] if their operation is not in [operations] or its type is
+ * Abstract printing of unary operations that discards [MST] if their operation is not in [operations] or its type is
* not [MST.Unary].
*
* @param operations the allowed operations. If `null`, any operation is accepted.
@@ -177,7 +176,7 @@ public abstract class Unary(public val operations: Collection?) : Render
}
/**
- * Abstract printing of unary operations which discards [MST] if their operation is not in [operations] or its type is
+ * Abstract printing of unary operations that discards [MST] if their operation is not in [operations] or its type is
* not [MST.Binary].
*
* @property operations the allowed operations. If `null`, any operation is accepted.
@@ -203,7 +202,7 @@ public abstract class Binary(public val operations: Collection?) : Rende
*/
@UnstableKMathAPI
public class BinaryPlus(operations: Collection?) : Binary(operations) {
- public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryPlusSyntax =
+ override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
BinaryPlusSyntax(
operation = node.operation,
left = OperandSyntax(parent.render(node.left), true),
@@ -225,7 +224,7 @@ public class BinaryPlus(operations: Collection?) : Binary(operations) {
*/
@UnstableKMathAPI
public class BinaryMinus(operations: Collection?) : Binary(operations) {
- public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryMinusSyntax =
+ override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
BinaryMinusSyntax(
operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
@@ -247,7 +246,7 @@ public class BinaryMinus(operations: Collection?) : Binary(operations) {
*/
@UnstableKMathAPI
public class UnaryPlus(operations: Collection?) : Unary(operations) {
- public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryPlusSyntax = UnaryPlusSyntax(
+ override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax(
operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
)
@@ -267,7 +266,7 @@ public class UnaryPlus(operations: Collection?) : Unary(operations) {
*/
@UnstableKMathAPI
public class UnaryMinus(operations: Collection?) : Unary(operations) {
- public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryMinusSyntax = UnaryMinusSyntax(
+ override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax(
operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
)
@@ -287,7 +286,7 @@ public class UnaryMinus(operations: Collection?) : Unary(operations) {
*/
@UnstableKMathAPI
public class Fraction(operations: Collection?) : Binary(operations) {
- public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax(
+ override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax(
operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
@@ -309,7 +308,7 @@ public class Fraction(operations: Collection?) : Binary(operations) {
*/
@UnstableKMathAPI
public class BinaryOperator(operations: Collection?) : Binary(operations) {
- public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryOperatorSyntax =
+ override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
BinaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(name = node.operation),
@@ -332,7 +331,7 @@ public class BinaryOperator(operations: Collection?) : Binary(operations
*/
@UnstableKMathAPI
public class UnaryOperator(operations: Collection?) : Unary(operations) {
- public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
+ override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
UnaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(node.operation),
@@ -354,7 +353,7 @@ public class UnaryOperator(operations: Collection?) : Unary(operations)
*/
@UnstableKMathAPI
public class Power(operations: Collection?) : Binary(operations) {
- public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): SuperscriptSyntax =
+ override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
SuperscriptSyntax(
operation = node.operation,
left = OperandSyntax(parent.render(node.left), true),
@@ -374,7 +373,7 @@ public class Power(operations: Collection?) : Binary(operations) {
*/
@UnstableKMathAPI
public class SquareRoot(operations: Collection?) : Unary(operations) {
- public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): RadicalSyntax =
+ override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
RadicalSyntax(operation = node.operation, operand = parent.render(node.value))
public companion object {
@@ -392,7 +391,7 @@ public class SquareRoot(operations: Collection?) : Unary(operations) {
*/
@UnstableKMathAPI
public class Exponent(operations: Collection?) : Unary(operations) {
- public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): ExponentSyntax = ExponentSyntax(
+ override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax(
operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
useOperatorForm = true,
@@ -413,7 +412,7 @@ public class Exponent(operations: Collection?) : Unary(operations) {
*/
@UnstableKMathAPI
public class Multiplication(operations: Collection?) : Binary(operations) {
- public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MultiplicationSyntax =
+ override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
MultiplicationSyntax(
operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
@@ -436,7 +435,7 @@ public class Multiplication(operations: Collection?) : Binary(operations
*/
@UnstableKMathAPI
public class InverseTrigonometricOperations(operations: Collection?) : Unary(operations) {
- public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
+ override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
UnaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "arc")),
@@ -463,7 +462,7 @@ public class InverseTrigonometricOperations(operations: Collection?) : U
*/
@UnstableKMathAPI
public class InverseHyperbolicOperations(operations: Collection?) : Unary(operations) {
- public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
+ override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
UnaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "ar")),
diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt
similarity index 75%
rename from kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt
rename to kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt
index 1f31af853..574bb54f4 100644
--- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt
+++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt
@@ -5,6 +5,7 @@
package space.kscience.kmath.ast.rendering
+import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess.PostProcessPhase
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.FieldOperations
import space.kscience.kmath.operations.GroupOperations
@@ -17,8 +18,8 @@ import space.kscience.kmath.operations.RingOperations
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
-public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage {
- public override fun perform(node: MathSyntax): Unit = when (node) {
+public val BetterMultiplication: PostProcessPhase = PostProcessPhase { node ->
+ fun perform(node: MathSyntax): Unit = when (node) {
is NumberSyntax -> Unit
is SymbolSyntax -> Unit
is OperatorNameSyntax -> Unit
@@ -81,6 +82,8 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro
perform(node.right)
}
}
+
+ perform(node)
}
/**
@@ -89,68 +92,68 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
-public object BetterFraction : FeaturedMathRendererWithPostProcess.PostProcessStage {
- private fun perform0(node: MathSyntax, infix: Boolean = false): Unit = when (node) {
+public val BetterFraction: PostProcessPhase = PostProcessPhase { node ->
+ fun perform(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 OperandSyntax -> perform(node.operand, infix)
is UnaryOperatorSyntax -> {
- perform0(node.prefix, infix)
- perform0(node.operand, infix)
+ perform(node.prefix, infix)
+ perform(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 UnaryPlusSyntax -> perform(node.operand, infix)
+ is UnaryMinusSyntax -> perform(node.operand, infix)
+ is RadicalSyntax -> perform(node.operand, infix)
+ is ExponentSyntax -> perform(node.operand, infix)
is SuperscriptSyntax -> {
- perform0(node.left, true)
- perform0(node.right, true)
+ perform(node.left, true)
+ perform(node.right, true)
}
is SubscriptSyntax -> {
- perform0(node.left, true)
- perform0(node.right, true)
+ perform(node.left, true)
+ perform(node.right, true)
}
is BinaryOperatorSyntax -> {
- perform0(node.prefix, infix)
- perform0(node.left, infix)
- perform0(node.right, infix)
+ perform(node.prefix, infix)
+ perform(node.left, infix)
+ perform(node.right, infix)
}
is BinaryPlusSyntax -> {
- perform0(node.left, infix)
- perform0(node.right, infix)
+ perform(node.left, infix)
+ perform(node.right, infix)
}
is BinaryMinusSyntax -> {
- perform0(node.left, infix)
- perform0(node.right, infix)
+ perform(node.left, infix)
+ perform(node.right, infix)
}
is FractionSyntax -> {
node.infix = infix
- perform0(node.left, infix)
- perform0(node.right, infix)
+ perform(node.left, infix)
+ perform(node.right, infix)
}
is RadicalWithIndexSyntax -> {
- perform0(node.left, true)
- perform0(node.right, true)
+ perform(node.left, true)
+ perform(node.right, true)
}
is MultiplicationSyntax -> {
- perform0(node.left, infix)
- perform0(node.right, infix)
+ perform(node.left, infix)
+ perform(node.right, infix)
}
}
- public override fun perform(node: MathSyntax): Unit = perform0(node)
+ perform(node)
}
/**
@@ -160,39 +163,37 @@ public object BetterFraction : FeaturedMathRendererWithPostProcess.PostProcessSt
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
-public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage {
- private fun perform0(node: MathSyntax): Boolean {
+public val BetterExponent: PostProcessPhase = PostProcessPhase { node ->
+ fun perform(node: MathSyntax): Boolean {
return when (node) {
is NumberSyntax -> false
is SymbolSyntax -> false
is OperatorNameSyntax -> false
is SpecialSymbolSyntax -> false
- is OperandSyntax -> perform0(node.operand)
- is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand)
- is UnaryPlusSyntax -> perform0(node.operand)
- is UnaryMinusSyntax -> perform0(node.operand)
+ is OperandSyntax -> perform(node.operand)
+ is UnaryOperatorSyntax -> perform(node.prefix) || perform(node.operand)
+ is UnaryPlusSyntax -> perform(node.operand)
+ is UnaryMinusSyntax -> perform(node.operand)
is RadicalSyntax -> true
is ExponentSyntax -> {
- val r = perform0(node.operand)
+ val r = perform(node.operand)
node.useOperatorForm = r
r
}
is SuperscriptSyntax -> true
is SubscriptSyntax -> true
- is BinaryOperatorSyntax -> perform0(node.prefix) || perform0(node.left) || perform0(node.right)
- is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right)
- is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right)
+ is BinaryOperatorSyntax -> perform(node.prefix) || perform(node.left) || perform(node.right)
+ is BinaryPlusSyntax -> perform(node.left) || perform(node.right)
+ is BinaryMinusSyntax -> perform(node.left) || perform(node.right)
is FractionSyntax -> true
is RadicalWithIndexSyntax -> true
- is MultiplicationSyntax -> perform0(node.left) || perform0(node.right)
+ is MultiplicationSyntax -> perform(node.left) || perform(node.right)
}
}
- public override fun perform(node: MathSyntax) {
- perform0(node)
- }
+ perform(node)
}
/**
@@ -203,8 +204,8 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt
*/
@UnstableKMathAPI
public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) :
- FeaturedMathRendererWithPostProcess.PostProcessStage {
- public override fun perform(node: MathSyntax): Unit = when (node) {
+ PostProcessPhase {
+ override fun perform(node: MathSyntax): Unit = when (node) {
is NumberSyntax -> Unit
is SymbolSyntax -> Unit
is OperatorNameSyntax -> Unit
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt
index 6209661b3..1edb5923e 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt
@@ -11,7 +11,6 @@ import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
-import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -22,7 +21,7 @@ internal class TestCompilerConsistencyWithInterpreter {
val mst = MstRing {
binaryOperationFunction("+")(
unaryOperationFunction("+")(
- (bindSymbol(x) - (2.toByte() + (scale(
+ (x - (2.toByte() + (scale(
add(number(1), number(1)),
2.0,
) + 1.toByte()))) * 3.0 - 1.toByte()
@@ -42,7 +41,7 @@ internal class TestCompilerConsistencyWithInterpreter {
fun doubleField() = runCompilerTest {
val mst = MstField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
- (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
+ (3.0 - (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
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt
index 073a03f14..929d17775 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt
@@ -9,7 +9,6 @@ import space.kscience.kmath.expressions.MstExtendedField
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.DoubleField
-import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -47,19 +46,19 @@ internal class TestCompilerOperations {
@Test
fun testSubtract() = runCompilerTest {
- val expr = MstExtendedField { bindSymbol(x) - bindSymbol(x) }.compileToExpression(DoubleField)
+ val expr = MstExtendedField { x - x }.compileToExpression(DoubleField)
assertEquals(0.0, expr(x to 2.0))
}
@Test
fun testDivide() = runCompilerTest {
- val expr = MstExtendedField { bindSymbol(x) / bindSymbol(x) }.compileToExpression(DoubleField)
+ val expr = MstExtendedField { x / x }.compileToExpression(DoubleField)
assertEquals(1.0, expr(x to 2.0))
}
@Test
fun testPower() = runCompilerTest {
- val expr = MstExtendedField { bindSymbol(x) pow 2 }.compileToExpression(DoubleField)
+ val expr = MstExtendedField { x pow 2 }.compileToExpression(DoubleField)
assertEquals(4.0, expr(x to 2.0))
}
}
diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt
index dcc15b311..af1a2e338 100644
--- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt
+++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt
@@ -9,7 +9,6 @@ import space.kscience.kmath.expressions.MstRing
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.IntRing
-import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -18,13 +17,13 @@ import kotlin.test.assertFailsWith
internal class TestCompilerVariables {
@Test
fun testVariable() = runCompilerTest {
- val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
+ val expr = MstRing { x }.compileToExpression(IntRing)
assertEquals(1, expr(x to 1))
}
@Test
fun testUndefinedVariableFails() = runCompilerTest {
- val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
+ val expr = MstRing { x }.compileToExpression(IntRing)
assertFailsWith { expr() }
}
}
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt
index e5254013e..b62b8c06c 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt
@@ -3,6 +3,8 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
+@file:Suppress("ClassName")
+
package space.kscience.kmath.internal.estree
import kotlin.js.RegExp
diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt
index 95ace1bad..c89ad83c4 100644
--- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt
+++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt
@@ -27,11 +27,7 @@ internal sealed class WasmBuilder(
lateinit var ctx: BinaryenModule
open fun visitSymbolic(mst: Symbol): ExpressionRef {
- try {
- algebra.bindSymbol(mst)
- } catch (ignored: Throwable) {
- null
- }?.let { return visitNumeric(Numeric(it)) }
+ algebra.bindSymbolOrNull(mst)?.let { return visitNumeric(Numeric(it)) }
var idx = keys.indexOf(mst)
diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt
index 6cb378182..d0e8128b4 100644
--- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt
+++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt
@@ -7,7 +7,6 @@ package space.kscience.kmath.ast
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.DoubleField
-import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import kotlin.math.sin
@@ -17,18 +16,19 @@ import kotlin.time.measureTime
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
+// TODO move to benchmarks when https://github.com/Kotlin/kotlinx-benchmark/pull/38 or similar feature is merged
internal class TestExecutionTime {
private companion object {
private const val times = 1_000_000
private val x by symbol
- private val algebra: ExtendedField = DoubleField
+ private val algebra = DoubleField
private val functional = DoubleField.expressionInExtendedField {
bindSymbol(x) * const(2.0) + const(2.0) / bindSymbol(x) - const(16.0) / sin(bindSymbol(x))
}
private val node = MstExtendedField {
- bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x))
+ x * number(2.0) + number(2.0) / x - number(16.0) / sin(x)
}
private val mst = node.toExpression(DoubleField)
@@ -43,7 +43,13 @@ internal class TestExecutionTime {
// };
private val raw = Expression { args ->
- args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / sin(args.getValue(x))
+ val x = args[x]!!
+ x * 2.0 + 2.0 / x - 16.0 / sin(x)
+ }
+
+ private val justCalculate = { args: dynamic ->
+ val x = args[x].unsafeCast()
+ x * 2.0 + 2.0 / x - 16.0 / sin(x)
}
}
@@ -51,21 +57,56 @@ internal class TestExecutionTime {
println(name)
val rng = Random(0)
var sum = 0.0
- measureTime { repeat(times) { sum += expr(x to rng.nextDouble()) } }.also(::println)
+ measureTime {
+ repeat(times) { sum += expr(x to rng.nextDouble()) }
+ }.also(::println)
}
+ /**
+ * [Expression] created with [expressionInExtendedField].
+ */
@Test
fun functionalExpression() = invokeAndSum("functional", functional)
+ /**
+ * [Expression] created with [mstExpression].
+ */
@Test
fun mstExpression() = invokeAndSum("mst", mst)
+ /**
+ * [Expression] created with [wasmCompileToExpression].
+ */
@Test
fun wasmExpression() = invokeAndSum("wasm", wasm)
+ /**
+ * [Expression] created with [estreeCompileToExpression].
+ */
@Test
fun estreeExpression() = invokeAndSum("estree", wasm)
+ /**
+ * [Expression] implemented manually with `kotlin.math`.
+ */
@Test
fun rawExpression() = invokeAndSum("raw", raw)
+
+ /**
+ * Direct computation w/o [Expression].
+ */
+ @Test
+ fun justCalculateExpression() {
+ println("justCalculate")
+ val rng = Random(0)
+ var sum = 0.0
+ measureTime {
+ repeat(times) {
+ val arg = rng.nextDouble()
+ val o = js("{}")
+ o["x"] = arg
+ sum += justCalculate(o)
+ }
+ }.also(::println)
+ }
}
diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt
index 93b7e9449..0d896c6f6 100644
--- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt
+++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt
@@ -10,6 +10,8 @@ import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
+import kotlin.contracts.InvocationKind
+import kotlin.contracts.contract
import space.kscience.kmath.estree.compile as estreeCompile
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
import space.kscience.kmath.wasm.compile as wasmCompile
@@ -34,6 +36,7 @@ private object ESTreeCompilerTestContext : CompilerTestContext {
}
internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) {
+ contract { callsInPlace(action, InvocationKind.AT_LEAST_ONCE) }
action(WasmCompilerTestContext)
action(ESTreeCompilerTestContext)
}
diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt
index abdf865c7..8ae5fcb36 100644
--- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt
+++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt
@@ -11,7 +11,6 @@ import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
-import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -31,7 +30,7 @@ internal class TestWasmSpecific {
@Test
fun argsPassing() {
- val res = MstExtendedField { bindSymbol(y) + bindSymbol(x).pow(10) }.compile(
+ val res = MstExtendedField { y + x.pow(10) }.compile(
DoubleField,
x to 2.0,
y to 100000000.0,
@@ -42,7 +41,7 @@ internal class TestWasmSpecific {
@Test
fun powFunction() {
- val expr = MstExtendedField { bindSymbol(x).pow(1.0 / 6.0) }.compileToExpression(DoubleField)
+ val expr = MstExtendedField { x.pow(1.0 / 6.0) }.compileToExpression(DoubleField)
assertEquals(0.9730585187140817, expr(x to 0.8488554755054833))
}
diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt
index cfac59847..06e040e93 100644
--- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt
+++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt
@@ -57,13 +57,13 @@ internal fun MethodVisitor.label(): Label = Label().also(::visitLabel)
/**
* Creates a class name for [Expression] subclassed to implement [mst] provided.
*
- * This methods helps to avoid collisions of class name to prevent loading several classes with the same name. If there
+ * These methods help to avoid collisions of class name to prevent loading several classes with the same name. If there
* is a colliding class, change [collision] parameter or leave it `0` to check existing classes recursively.
*
* @author Iaroslav Postovalov
*/
internal tailrec fun buildName(mst: MST, collision: Int = 0): String {
- val name = "kscience.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision"
+ val name = "space.kscience.kmath.asm.generated.CompiledExpression_${mst.hashCode()}_$collision"
try {
Class.forName(name)
diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt
index d3b554efd..a7f0bb3fb 100644
--- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt
+++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt
@@ -10,6 +10,8 @@ import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
+import kotlin.contracts.InvocationKind
+import kotlin.contracts.contract
import space.kscience.kmath.asm.compile as asmCompile
import space.kscience.kmath.asm.compileToExpression as asmCompileToExpression
@@ -22,4 +24,7 @@ private object AsmCompilerTestContext : CompilerTestContext {
asmCompile(algebra, arguments)
}
-internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) = action(AsmCompilerTestContext)
+internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) {
+ contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
+ action(AsmCompilerTestContext)
+}
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt
index a7ee9ff3f..5417b6156 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt
@@ -15,7 +15,7 @@ import space.kscience.kmath.operations.NumbersAddOperations
* A field over commons-math [DerivativeStructure].
*
* @property order The derivation order.
- * @property bindings The map of bindings values. All bindings are considered free parameters
+ * @param bindings The map of bindings values. All bindings are considered free parameters
*/
@OptIn(UnstableKMathAPI::class)
public class DerivativeStructureField(
@@ -25,13 +25,13 @@ public class DerivativeStructureField(
NumbersAddOperations {
public val numberOfVariables: Int = bindings.size
- public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) }
- public override val one: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order, 1.0) }
+ override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) }
+ override val one: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order, 1.0) }
- public override fun number(value: Number): DerivativeStructure = const(value.toDouble())
+ override fun number(value: Number): DerivativeStructure = const(value.toDouble())
/**
- * A class that implements both [DerivativeStructure] and a [Symbol]
+ * A class implementing both [DerivativeStructure] and [Symbol].
*/
public inner class DerivativeStructureSymbol(
size: Int,
@@ -39,10 +39,10 @@ public class DerivativeStructureField(
symbol: Symbol,
value: Double,
) : DerivativeStructure(size, order, index, value), Symbol {
- public override val identity: String = symbol.identity
- public override fun toString(): String = identity
- public override fun equals(other: Any?): Boolean = this.identity == (other as? Symbol)?.identity
- public override fun hashCode(): Int = identity.hashCode()
+ override val identity: String = symbol.identity
+ override fun toString(): String = identity
+ override fun equals(other: Any?): Boolean = this.identity == (other as? Symbol)?.identity
+ override fun hashCode(): Int = identity.hashCode()
}
/**
@@ -52,10 +52,10 @@ public class DerivativeStructureField(
key.identity to DerivativeStructureSymbol(numberOfVariables, index, key, value)
}.toMap()
- public override fun const(value: Double): DerivativeStructure = DerivativeStructure(numberOfVariables, order, value)
+ override fun const(value: Double): DerivativeStructure = DerivativeStructure(numberOfVariables, order, value)
- public override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol? = variables[value]
- public override fun bindSymbol(value: String): DerivativeStructureSymbol = variables.getValue(value)
+ override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol? = variables[value]
+ override fun bindSymbol(value: String): DerivativeStructureSymbol = variables.getValue(value)
public fun bindSymbolOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity]
public fun bindSymbol(symbol: Symbol): DerivativeStructureSymbol = variables.getValue(symbol.identity)
@@ -68,45 +68,48 @@ public class DerivativeStructureField(
public fun DerivativeStructure.derivative(vararg symbols: Symbol): Double = derivative(symbols.toList())
- public override fun DerivativeStructure.unaryMinus(): DerivativeStructure = negate()
+ override fun DerivativeStructure.unaryMinus(): DerivativeStructure = negate()
- public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b)
+ override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b)
- public override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure = a.multiply(value)
+ override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure = a.multiply(value)
- public override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b)
- public override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b)
- public override fun sin(arg: DerivativeStructure): DerivativeStructure = arg.sin()
- public override fun cos(arg: DerivativeStructure): DerivativeStructure = arg.cos()
- public override fun tan(arg: DerivativeStructure): DerivativeStructure = arg.tan()
- public override fun asin(arg: DerivativeStructure): DerivativeStructure = arg.asin()
- public override fun acos(arg: DerivativeStructure): DerivativeStructure = arg.acos()
- public override fun atan(arg: DerivativeStructure): DerivativeStructure = arg.atan()
- public override fun sinh(arg: DerivativeStructure): DerivativeStructure = arg.sinh()
- public override fun cosh(arg: DerivativeStructure): DerivativeStructure = arg.cosh()
- public override fun tanh(arg: DerivativeStructure): DerivativeStructure = arg.tanh()
- public override fun asinh(arg: DerivativeStructure): DerivativeStructure = arg.asinh()
- public override fun acosh(arg: DerivativeStructure): DerivativeStructure = arg.acosh()
- public override fun atanh(arg: DerivativeStructure): DerivativeStructure = arg.atanh()
+ override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b)
+ override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b)
+ override fun sin(arg: DerivativeStructure): DerivativeStructure = arg.sin()
+ override fun cos(arg: DerivativeStructure): DerivativeStructure = arg.cos()
+ override fun tan(arg: DerivativeStructure): DerivativeStructure = arg.tan()
+ override fun asin(arg: DerivativeStructure): DerivativeStructure = arg.asin()
+ override fun acos(arg: DerivativeStructure): DerivativeStructure = arg.acos()
+ override fun atan(arg: DerivativeStructure): DerivativeStructure = arg.atan()
+ override fun sinh(arg: DerivativeStructure): DerivativeStructure = arg.sinh()
+ override fun cosh(arg: DerivativeStructure): DerivativeStructure = arg.cosh()
+ override fun tanh(arg: DerivativeStructure): DerivativeStructure = arg.tanh()
+ override fun asinh(arg: DerivativeStructure): DerivativeStructure = arg.asinh()
+ override fun acosh(arg: DerivativeStructure): DerivativeStructure = arg.acosh()
+ override fun atanh(arg: DerivativeStructure): DerivativeStructure = arg.atanh()
- public override fun power(arg: DerivativeStructure, pow: Number): DerivativeStructure = when (pow) {
+ override fun power(arg: DerivativeStructure, pow: Number): DerivativeStructure = when (pow) {
is Double -> arg.pow(pow)
is Int -> arg.pow(pow)
else -> arg.pow(pow.toDouble())
}
public fun power(arg: DerivativeStructure, pow: DerivativeStructure): DerivativeStructure = arg.pow(pow)
- public override fun exp(arg: DerivativeStructure): DerivativeStructure = arg.exp()
- public override fun ln(arg: DerivativeStructure): DerivativeStructure = arg.log()
+ override fun exp(arg: DerivativeStructure): DerivativeStructure = arg.exp()
+ override fun ln(arg: DerivativeStructure): DerivativeStructure = arg.log()
- public override operator fun DerivativeStructure.plus(b: Number): DerivativeStructure = add(b.toDouble())
- public override operator fun DerivativeStructure.minus(b: Number): DerivativeStructure = subtract(b.toDouble())
- public override operator fun Number.plus(b: DerivativeStructure): DerivativeStructure = b + this
- public override operator fun Number.minus(b: DerivativeStructure): DerivativeStructure = b - this
+ override operator fun DerivativeStructure.plus(b: Number): DerivativeStructure = add(b.toDouble())
+ override operator fun DerivativeStructure.minus(b: Number): DerivativeStructure = subtract(b.toDouble())
+ override operator fun Number.plus(b: DerivativeStructure): DerivativeStructure = b + this
+ override operator fun Number.minus(b: DerivativeStructure): DerivativeStructure = b - this
}
+/**
+ * Auto-diff processor based on Commons-math [DerivativeStructure]
+ */
public object DSProcessor : AutoDiffProcessor {
- public override fun differentiate(
+ override fun differentiate(
function: DerivativeStructureField.() -> DerivativeStructure,
): DerivativeStructureExpression = DerivativeStructureExpression(function)
}
@@ -117,13 +120,13 @@ public object DSProcessor : AutoDiffProcessor DerivativeStructure,
) : DifferentiableExpression {
- public override operator fun invoke(arguments: Map): Double =
+ override operator fun invoke(arguments: Map): Double =
DerivativeStructureField(0, arguments).function().value
/**
* Get the derivative expression with given orders
*/
- public override fun derivativeOrNull(symbols: List): Expression = Expression { arguments ->
+ override fun derivativeOrNull(symbols: List): Expression = Expression { arguments ->
with(DerivativeStructureField(symbols.size, arguments)) { function().derivative(symbols) }
}
}
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt
index c6f1cd852..c7a253ff7 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt
@@ -15,18 +15,18 @@ import kotlin.reflect.KClass
import kotlin.reflect.cast
public class CMMatrix(public val origin: RealMatrix) : Matrix {
- public override val rowNum: Int get() = origin.rowDimension
- public override val colNum: Int get() = origin.columnDimension
+ override val rowNum: Int get() = origin.rowDimension
+ override val colNum: Int get() = origin.columnDimension
- public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j)
+ override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j)
}
public class CMVector(public val origin: RealVector) : Point {
- public override val size: Int get() = origin.dimension
+ override val size: Int get() = origin.dimension
- public override operator fun get(index: Int): Double = origin.getEntry(index)
+ override operator fun get(index: Int): Double = origin.getEntry(index)
- public override operator fun iterator(): Iterator = origin.toArray().iterator()
+ override operator fun iterator(): Iterator = origin.toArray().iterator()
}
public fun RealVector.toPoint(): CMVector = CMVector(this)
@@ -34,7 +34,7 @@ public fun RealVector.toPoint(): CMVector = CMVector(this)
public object CMLinearSpace : LinearSpace {
override val elementAlgebra: DoubleField get() = DoubleField
- public override fun buildMatrix(
+ override fun buildMatrix(
rows: Int,
columns: Int,
initializer: DoubleField.(i: Int, j: Int) -> Double,
@@ -73,16 +73,16 @@ public object CMLinearSpace : LinearSpace {
override fun Point.minus(other: Point): CMVector =
toCM().origin.subtract(other.toCM().origin).wrap()
- public override fun Matrix.dot(other: Matrix): CMMatrix =
+ override fun Matrix.dot(other: Matrix): CMMatrix =
toCM().origin.multiply(other.toCM().origin).wrap()
- public override fun Matrix.dot(vector: Point): CMVector =
+ override fun Matrix.dot(vector: Point): CMVector =
toCM().origin.preMultiply(vector.toCM().origin).wrap()
- public override operator fun Matrix.minus(other: Matrix): CMMatrix =
+ override operator fun Matrix.minus(other: Matrix): CMMatrix =
toCM().origin.subtract(other.toCM().origin).wrap()
- public override operator fun Matrix.times(value: Double): CMMatrix =
+ override operator fun Matrix.times(value: Double): CMMatrix =
toCM().origin.scalarMultiply(value).wrap()
override fun Double.times(m: Matrix): CMMatrix =
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt
index 16a6967e2..6aeebb68c 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt
@@ -5,35 +5,43 @@
package space.kscience.kmath.commons.random
+import kotlinx.coroutines.runBlocking
+import space.kscience.kmath.misc.PerformancePitfall
+import space.kscience.kmath.samplers.GaussianSampler
+import space.kscience.kmath.misc.toIntExact
import space.kscience.kmath.stat.RandomGenerator
+import space.kscience.kmath.stat.next
public class CMRandomGeneratorWrapper(
public val factory: (IntArray) -> RandomGenerator,
) : org.apache.commons.math3.random.RandomGenerator {
private var generator: RandomGenerator = factory(intArrayOf())
- public override fun nextBoolean(): Boolean = generator.nextBoolean()
- public override fun nextFloat(): Float = generator.nextDouble().toFloat()
+ override fun nextBoolean(): Boolean = generator.nextBoolean()
+ override fun nextFloat(): Float = generator.nextDouble().toFloat()
- public override fun setSeed(seed: Int) {
+ override fun setSeed(seed: Int) {
generator = factory(intArrayOf(seed))
}
- public override fun setSeed(seed: IntArray) {
+ override fun setSeed(seed: IntArray) {
generator = factory(seed)
}
- public override fun setSeed(seed: Long) {
- setSeed(seed.toInt())
+ override fun setSeed(seed: Long) {
+ setSeed(seed.toIntExact())
}
- public override fun nextBytes(bytes: ByteArray) {
+ override fun nextBytes(bytes: ByteArray) {
generator.fillBytes(bytes)
}
- public override fun nextInt(): Int = generator.nextInt()
- public override fun nextInt(n: Int): Int = generator.nextInt(n)
- public override fun nextGaussian(): Double = TODO()
- public override fun nextDouble(): Double = generator.nextDouble()
- public override fun nextLong(): Long = generator.nextLong()
+ override fun nextInt(): Int = generator.nextInt()
+ override fun nextInt(n: Int): Int = generator.nextInt(n)
+
+ @PerformancePitfall
+ override fun nextGaussian(): Double = runBlocking { GaussianSampler(0.0, 1.0).next(generator) }
+
+ override fun nextDouble(): Double = generator.nextDouble()
+ override fun nextLong(): Long = generator.nextLong()
}
diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt
index d29491d63..6fef12138 100644
--- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt
+++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt
@@ -32,7 +32,7 @@ public object Transformations {
/**
* Create a virtual buffer on top of array
*/
- private fun Array.asBuffer() = VirtualBuffer(size) {
+ private fun Array.asBuffer() = VirtualBuffer(size) {
val value = get(it)
Complex(value.real, value.imaginary)
}
diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt
index 966675062..3c57f5467 100644
--- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt
+++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt
@@ -16,7 +16,7 @@ internal inline fun diff(
order: Int,
vararg parameters: Pair,
block: DerivativeStructureField.() -> Unit,
-): Unit {
+) {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
DerivativeStructureField(order, mapOf(*parameters)).run(block)
}
@@ -34,7 +34,7 @@ internal class AutoDiffTest {
println(z.derivative(x))
println(z.derivative(y, x))
assertEquals(z.derivative(x, y), z.derivative(y, x))
- //check that improper order cause failure
+ // check improper order cause failure
assertFails { z.derivative(x, x, y) }
}
}
diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt
index 97761cfa2..170fceceb 100644
--- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt
+++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt
@@ -11,9 +11,12 @@ import space.kscience.kmath.commons.expressions.DerivativeStructureExpression
import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.Symbol.Companion.y
+import space.kscience.kmath.expressions.chiSquaredExpression
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.optimization.*
import space.kscience.kmath.stat.RandomGenerator
+import space.kscience.kmath.structures.asBuffer
+import space.kscience.kmath.structures.map
import kotlin.math.pow
import kotlin.test.Test
@@ -49,26 +52,27 @@ internal class OptimizeTest {
val sigma = 1.0
val generator = NormalDistribution(0.0, sigma)
val chain = generator.sample(RandomGenerator.default(112667))
- val x = (1..100).map(Int::toDouble)
+ val x = (1..100).map(Int::toDouble).asBuffer()
val y = x.map {
it.pow(2) + it + 1 + chain.next()
}
- val yErr = List(x.size) { sigma }
+ val yErr = List(x.size) { sigma }.asBuffer()
- val model = DSProcessor.differentiate { x1 ->
+ val chi2 = DSProcessor.chiSquaredExpression(
+ x, y, yErr
+ ) { arg ->
val cWithDefault = bindSymbolOrNull(c) ?: one
- bindSymbol(a) * x1.pow(2) + bindSymbol(b) * x1 + cWithDefault
+ bindSymbol(a) * arg.pow(2) + bindSymbol(b) * arg + cWithDefault
}
- val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 ->
- val cWithDefault = bindSymbolOrNull(c) ?: one
- bindSymbol(a) * x1.pow(2) + bindSymbol(b) * x1 + cWithDefault
- }
-
- val result = chi2.minimize(a to 1.5, b to 0.9, c to 1.0)
+ val result: FunctionOptimization = chi2.optimizeWith(
+ CMOptimizer,
+ mapOf(a to 1.5, b to 0.9, c to 1.0),
+ FunctionOptimizationTarget.MINIMIZE
+ )
println(result)
- println("Chi2/dof = ${result.value / (x.size - 3)}")
+ println("Chi2/dof = ${result.resultValue / (x.size - 3)}")
}
}
diff --git a/kmath-complex/README.md b/kmath-complex/README.md
index 04431cf6c..110529b72 100644
--- a/kmath-complex/README.md
+++ b/kmath-complex/README.md
@@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath.
## Artifact:
-The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-11`.
+The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-14`.
**Gradle:**
```gradle
@@ -18,7 +18,7 @@ repositories {
}
dependencies {
- implementation 'space.kscience:kmath-complex:0.3.0-dev-11'
+ implementation 'space.kscience:kmath-complex:0.3.0-dev-14'
}
```
**Gradle Kotlin DSL:**
@@ -29,6 +29,6 @@ repositories {
}
dependencies {
- implementation("space.kscience:kmath-complex:0.3.0-dev-11")
+ implementation("space.kscience:kmath-complex:0.3.0-dev-14")
}
```
diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt
index a96d046c9..8b064a05f 100644
--- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt
+++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt
@@ -54,8 +54,8 @@ private val PI_DIV_2 = Complex(PI / 2, 0)
@OptIn(UnstableKMathAPI::class)
public object ComplexField : ExtendedField, Norm, NumbersAddOperations,
ScaleOperations {
- public override val zero: Complex = 0.0.toComplex()
- public override val one: Complex = 1.0.toComplex()
+ override val zero: Complex = 0.0.toComplex()
+ override val one: Complex = 1.0.toComplex()
/**
* The imaginary unit.
@@ -68,13 +68,13 @@ public object ComplexField : ExtendedField, Norm, Num
override fun scale(a: Complex, value: Double): Complex = Complex(a.re * value, a.im * value)
- public override fun add(a: Complex, b: Complex): Complex = Complex(a.re + b.re, a.im + b.im)
-// public override fun multiply(a: Complex, k: Number): Complex = Complex(a.re * k.toDouble(), a.im * k.toDouble())
+ override fun add(a: Complex, b: Complex): Complex = Complex(a.re + b.re, a.im + b.im)
+// override fun multiply(a: Complex, k: Number): Complex = Complex(a.re * k.toDouble(), a.im * k.toDouble())
- public override fun multiply(a: Complex, b: Complex): Complex =
+ override fun multiply(a: Complex, b: Complex): Complex =
Complex(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re)
- public override fun divide(a: Complex, b: Complex): Complex = when {
+ override fun divide(a: Complex, b: Complex): Complex = when {
abs(b.im) < abs(b.re) -> {
val wr = b.im / b.re
val wd = b.re + wr * b.im
@@ -100,31 +100,31 @@ public object ComplexField : ExtendedField, Norm, Num
override operator fun Complex.div(k: Number): Complex = Complex(re / k.toDouble(), im / k.toDouble())
- public override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2.0
- public override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2.0
+ override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2.0
+ override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2.0
- public override fun tan(arg: Complex): Complex {
+ override fun tan(arg: Complex): Complex {
val e1 = exp(-i * arg)
val e2 = exp(i * arg)
return i * (e1 - e2) / (e1 + e2)
}
- public override fun asin(arg: Complex): Complex = -i * ln(sqrt(1 - (arg * arg)) + i * arg)
- public override fun acos(arg: Complex): Complex = PI_DIV_2 + i * ln(sqrt(1 - (arg * arg)) + i * arg)
+ override fun asin(arg: Complex): Complex = -i * ln(sqrt(1 - (arg * arg)) + i * arg)
+ override fun acos(arg: Complex): Complex = PI_DIV_2 + i * ln(sqrt(1 - (arg * arg)) + i * arg)
- public override fun atan(arg: Complex): Complex {
+ override fun atan(arg: Complex): Complex {
val iArg = i * arg
return i * (ln(1 - iArg) - ln(1 + iArg)) / 2
}
- public override fun power(arg: Complex, pow: Number): Complex = if (arg.im == 0.0)
+ override fun power(arg: Complex, pow: Number): Complex = if (arg.im == 0.0)
arg.re.pow(pow.toDouble()).toComplex()
else
exp(pow * ln(arg))
- public override fun exp(arg: Complex): Complex = exp(arg.re) * (cos(arg.im) + i * sin(arg.im))
+ override fun exp(arg: Complex): Complex = exp(arg.re) * (cos(arg.im) + i * sin(arg.im))
- public override fun ln(arg: Complex): Complex = ln(arg.r) + i * atan2(arg.im, arg.re)
+ override fun ln(arg: Complex): Complex = ln(arg.r) + i * atan2(arg.im, arg.re)
/**
* Adds complex number to real one.
@@ -171,9 +171,9 @@ public object ComplexField : ExtendedField, Norm, Num
*/
public operator fun Double.times(c: Complex): Complex = Complex(c.re * this, c.im * this)
- public override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg)
+ override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg)
- public override fun bindSymbolOrNull(value: String): Complex? = if (value == "i") i else null
+ override fun bindSymbolOrNull(value: String): Complex? = if (value == "i") i else null
}
/**
@@ -187,16 +187,16 @@ public data class Complex(val re: Double, val im: Double) {
public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble())
public constructor(re: Number) : this(re.toDouble(), 0.0)
- public override fun toString(): String = "($re + i * $im)"
+ override fun toString(): String = "($re + i * $im)"
public companion object : MemorySpec {
- public override val objectSize: Int
+ override val objectSize: Int
get() = 16
- public override fun MemoryReader.read(offset: Int): Complex =
+ override fun MemoryReader.read(offset: Int): Complex =
Complex(readDouble(offset), readDouble(offset + 8))
- public override fun MemoryWriter.write(offset: Int, value: Complex) {
+ override fun MemoryWriter.write(offset: Int, value: Complex) {
writeDouble(offset, value.re)
writeDouble(offset + 8, value.im)
}
diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt
index 2c783eda0..1b54fc227 100644
--- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt
+++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt
@@ -27,10 +27,10 @@ public class ComplexFieldND(
NumbersAddOperations>,
ExtendedField> {
- public override val zero: BufferND by lazy { produce { zero } }
- public override val one: BufferND by lazy { produce { one } }
+ override val zero: BufferND by lazy { produce { zero } }
+ override val one: BufferND by lazy { produce { one } }
- public override fun number(value: Number): BufferND {
+ override fun number(value: Number): BufferND {
val d = value.toComplex() // minimize conversions
return produce { d }
}
@@ -81,25 +81,25 @@ public class ComplexFieldND(
// return BufferedNDFieldElement(this, buffer)
// }
- public override fun power(arg: StructureND, pow: Number): BufferND = arg.map { power(it, pow) }
+ override fun power(arg: StructureND, pow: Number): BufferND = arg.map { power(it, pow) }
- public override fun exp(arg: StructureND): BufferND = arg.map { exp(it) }
+ override fun exp(arg: StructureND): BufferND = arg.map { exp(it) }
- public override fun ln(arg: StructureND): BufferND = arg.map { ln(it) }
+ override fun ln(arg: StructureND): BufferND = arg.map { ln(it) }
- public override fun sin(arg: StructureND): BufferND = arg.map { sin(it) }
- public override fun cos(arg: StructureND): BufferND = arg.map { cos(it) }
- public override fun tan(arg: StructureND): BufferND = arg.map { tan(it) }
- public override fun asin(arg: StructureND): BufferND = arg.map { asin(it) }
- public override fun acos(arg: StructureND): BufferND = arg.map { acos(it) }
- public override fun atan(arg: StructureND): BufferND = arg.map { atan(it) }
+ override fun sin(arg: StructureND): BufferND = arg.map { sin(it) }
+ override fun cos(arg: StructureND): BufferND = arg.map { cos(it) }
+ override fun tan(arg: StructureND): BufferND = arg.map { tan(it) }
+ override fun asin(arg: StructureND): BufferND = arg.map { asin(it) }
+ override fun acos(arg: StructureND): BufferND = arg.map { acos(it) }
+ override fun atan(arg: StructureND): BufferND = arg.map { atan(it) }
- public override fun sinh(arg: StructureND): BufferND = arg.map { sinh(it) }
- public override fun cosh(arg: StructureND): BufferND = arg.map { cosh(it) }
- public override fun tanh(arg: StructureND): BufferND = arg.map { tanh(it) }
- public override fun asinh(arg: StructureND): BufferND = arg.map { asinh(it) }
- public override fun acosh(arg: StructureND): BufferND = arg.map { acosh(it) }
- public override fun atanh(arg: StructureND): BufferND = arg.map { atanh(it) }
+ override fun sinh(arg: StructureND): BufferND = arg.map { sinh(it) }
+ override fun cosh(arg: StructureND): BufferND = arg.map { cosh(it) }
+ override fun tanh(arg: StructureND): BufferND = arg.map { tanh(it) }
+ override fun asinh(arg: StructureND): BufferND = arg.map { asinh(it) }
+ override fun acosh(arg: StructureND): BufferND = arg.map { acosh(it) }
+ override fun atanh(arg: StructureND): BufferND = arg.map { atanh(it) }
}
diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt
index c59aabdcb..423cef1d1 100644
--- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt
+++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt
@@ -63,20 +63,20 @@ public object QuaternionField : Field, Norm,
*/
public val k: Quaternion = Quaternion(0, 0, 0, 1)
- public override fun add(a: Quaternion, b: Quaternion): Quaternion =
+ override fun add(a: Quaternion, b: Quaternion): Quaternion =
Quaternion(a.w + b.w, a.x + b.x, a.y + b.y, a.z + b.z)
- public override fun scale(a: Quaternion, value: Double): Quaternion =
+ override fun scale(a: Quaternion, value: Double): Quaternion =
Quaternion(a.w * value, a.x * value, a.y * value, a.z * value)
- public override fun multiply(a: Quaternion, b: Quaternion): Quaternion = Quaternion(
+ override fun multiply(a: Quaternion, b: Quaternion): Quaternion = Quaternion(
a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,
)
- public override fun divide(a: Quaternion, b: Quaternion): Quaternion {
+ override fun divide(a: Quaternion, b: Quaternion): Quaternion {
val s = b.w * b.w + b.x * b.x + b.y * b.y + b.z * b.z
return Quaternion(
@@ -87,7 +87,7 @@ public object QuaternionField : Field, Norm,
)
}
- public override fun power(arg: Quaternion, pow: Number): Quaternion {
+ override fun power(arg: Quaternion, pow: Number): Quaternion {
if (pow is Int) return pwr(arg, pow)
if (floor(pow.toDouble()) == pow.toDouble()) return pwr(arg, pow.toInt())
return exp(pow * ln(arg))
@@ -131,7 +131,7 @@ public object QuaternionField : Field, Norm,
return Quaternion(a2 * a2 - 6 * a2 * n1 + n1 * n1, x.x * n2, x.y * n2, x.z * n2)
}
- public override fun exp(arg: Quaternion): Quaternion {
+ override fun exp(arg: Quaternion): Quaternion {
val un = arg.x * arg.x + arg.y * arg.y + arg.z * arg.z
if (un == 0.0) return exp(arg.w).toQuaternion()
val n1 = sqrt(un)
@@ -140,14 +140,14 @@ public object QuaternionField : Field, Norm,
return Quaternion(ea * cos(n1), n2 * arg.x, n2 * arg.y, n2 * arg.z)
}
- public override fun ln(arg: Quaternion): Quaternion {
+ override fun ln(arg: Quaternion): Quaternion {
val nu2 = arg.x * arg.x + arg.y * arg.y + arg.z * arg.z
if (nu2 == 0.0)
return if (arg.w > 0)
Quaternion(ln(arg.w), 0, 0, 0)
else {
- val l = ComplexField { ComplexField.ln(arg.w.toComplex()) }
+ val l = ComplexField { ln(arg.w.toComplex()) }
Quaternion(l.re, l.im, 0, 0)
}
@@ -158,21 +158,21 @@ public object QuaternionField : Field, Norm,
return Quaternion(ln(n), th * arg.x, th * arg.y, th * arg.z)
}
- public override operator fun Number.plus(b: Quaternion): Quaternion = Quaternion(toDouble() + b.w, b.x, b.y, b.z)
+ override operator fun Number.plus(b: Quaternion): Quaternion = Quaternion(toDouble() + b.w, b.x, b.y, b.z)
- public override operator fun Number.minus(b: Quaternion): Quaternion =
+ override operator fun Number.minus(b: Quaternion): Quaternion =
Quaternion(toDouble() - b.w, -b.x, -b.y, -b.z)
- public override operator fun Quaternion.plus(b: Number): Quaternion = Quaternion(w + b.toDouble(), x, y, z)
- public override operator fun Quaternion.minus(b: Number): Quaternion = Quaternion(w - b.toDouble(), x, y, z)
+ override operator fun Quaternion.plus(b: Number): Quaternion = Quaternion(w + b.toDouble(), x, y, z)
+ override operator fun Quaternion.minus(b: Number): Quaternion = Quaternion(w - b.toDouble(), x, y, z)
- public override operator fun Number.times(b: Quaternion): Quaternion =
+ override operator fun Number.times(b: Quaternion): Quaternion =
Quaternion(toDouble() * b.w, toDouble() * b.x, toDouble() * b.y, toDouble() * b.z)
- public override fun Quaternion.unaryMinus(): Quaternion = Quaternion(-w, -x, -y, -z)
- public override fun norm(arg: Quaternion): Quaternion = sqrt(arg.conjugate * arg)
+ override fun Quaternion.unaryMinus(): Quaternion = Quaternion(-w, -x, -y, -z)
+ override fun norm(arg: Quaternion): Quaternion = sqrt(arg.conjugate * arg)
- public override fun bindSymbolOrNull(value: String): Quaternion? = when (value) {
+ override fun bindSymbolOrNull(value: String): Quaternion? = when (value) {
"i" -> i
"j" -> j
"k" -> k
@@ -181,12 +181,12 @@ public object QuaternionField : Field, Norm,
override fun number(value: Number): Quaternion = value.toQuaternion()
- public override fun sinh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / 2.0
- public override fun cosh(arg: Quaternion): Quaternion = (exp(arg) + exp(-arg)) / 2.0
- public override fun tanh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
- public override fun asinh(arg: Quaternion): Quaternion = ln(sqrt(arg * arg + one) + arg)
- public override fun acosh(arg: Quaternion): Quaternion = ln(arg + sqrt((arg - one) * (arg + one)))
- public override fun atanh(arg: Quaternion): Quaternion = (ln(arg + one) - ln(one - arg)) / 2.0
+ override fun sinh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / 2.0
+ override fun cosh(arg: Quaternion): Quaternion = (exp(arg) + exp(-arg)) / 2.0
+ override fun tanh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
+ override fun asinh(arg: Quaternion): Quaternion = ln(sqrt(arg * arg + one) + arg)
+ override fun acosh(arg: Quaternion): Quaternion = ln(arg + sqrt((arg - one) * (arg + one)))
+ override fun atanh(arg: Quaternion): Quaternion = (ln(arg + one) - ln(one - arg)) / 2.0
}
/**
@@ -224,16 +224,16 @@ public data class Quaternion(
/**
* Returns a string representation of this quaternion.
*/
- public override fun toString(): String = "($w + $x * i + $y * j + $z * k)"
+ override fun toString(): String = "($w + $x * i + $y * j + $z * k)"
public companion object : MemorySpec {
- public override val objectSize: Int
+ override val objectSize: Int
get() = 32
- public override fun MemoryReader.read(offset: Int): Quaternion =
+ override fun MemoryReader.read(offset: Int): Quaternion =
Quaternion(readDouble(offset), readDouble(offset + 8), readDouble(offset + 16), readDouble(offset + 24))
- public override fun MemoryWriter.write(offset: Int, value: Quaternion) {
+ override fun MemoryWriter.write(offset: Int, value: Quaternion) {
writeDouble(offset, value.w)
writeDouble(offset + 8, value.x)
writeDouble(offset + 16, value.y)
diff --git a/kmath-core/README.md b/kmath-core/README.md
index 700eaef38..4ea493f44 100644
--- a/kmath-core/README.md
+++ b/kmath-core/README.md
@@ -10,12 +10,12 @@ The core interfaces of KMath.
objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high
performance calculations to code generation.
- [domains](src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
- - [autodif](src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
+ - [autodiff](src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
## Artifact:
-The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-11`.
+The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-14`.
**Gradle:**
```gradle
@@ -25,7 +25,7 @@ repositories {
}
dependencies {
- implementation 'space.kscience:kmath-core:0.3.0-dev-11'
+ implementation 'space.kscience:kmath-core:0.3.0-dev-14'
}
```
**Gradle Kotlin DSL:**
@@ -36,6 +36,6 @@ repositories {
}
dependencies {
- implementation("space.kscience:kmath-core:0.3.0-dev-11")
+ implementation("space.kscience:kmath-core:0.3.0-dev-14")
}
```
diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts
index 92a5f419d..564d06f49 100644
--- a/kmath-core/build.gradle.kts
+++ b/kmath-core/build.gradle.kts
@@ -19,51 +19,42 @@ readme {
feature(
id = "algebras",
- description = """
- Algebraic structures like rings, spaces and fields.
- """.trimIndent(),
- ref = "src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt"
- )
+ ref = "src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt",
+ ) { "Algebraic structures like rings, spaces and fields." }
feature(
id = "nd",
- description = "Many-dimensional structures and operations on them.",
- ref = "src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt"
- )
+ ref = "src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt",
+ ) { "Many-dimensional structures and operations on them." }
feature(
id = "linear",
- description = """
- Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition.
- """.trimIndent(),
- ref = "src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt"
- )
+ ref = "src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt",
+ ) { "Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition." }
feature(
id = "buffers",
- description = "One-dimensional structure",
- ref = "src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt"
- )
+ ref = "src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt",
+ ) { "One-dimensional structure" }
feature(
id = "expressions",
- description = """
+ ref = "src/commonMain/kotlin/space/kscience/kmath/expressions"
+ ) {
+ """
By writing a single mathematical expression once, users will be able to apply different types of
objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high
performance calculations to code generation.
- """.trimIndent(),
- ref = "src/commonMain/kotlin/space/kscience/kmath/expressions"
- )
+ """.trimIndent()
+ }
feature(
id = "domains",
- description = "Domains",
- ref = "src/commonMain/kotlin/space/kscience/kmath/domains"
- )
+ ref = "src/commonMain/kotlin/space/kscience/kmath/domains",
+ ) { "Domains" }
feature(
- id = "autodif",
- description = "Automatic differentiation",
+ id = "autodiff",
ref = "src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt"
- )
+ ) { "Automatic differentiation" }
}
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt
index 2dc82c02e..bd0e13b9d 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt
@@ -16,7 +16,7 @@ import kotlin.math.max
* The buffer of X values.
*/
@UnstableKMathAPI
-public interface XYColumnarData : ColumnarData {
+public interface XYColumnarData : ColumnarData {
/**
* The buffer of X values
*/
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt
index bc21b7f45..e99ae0698 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt
@@ -14,7 +14,7 @@ import space.kscience.kmath.structures.Buffer
* Inherits [XYColumnarData].
*/
@UnstableKMathAPI
-public interface XYZColumnarData : XYColumnarData {
+public interface XYZColumnarData : XYColumnarData {
public val z: Buffer
override fun get(symbol: Symbol): Buffer? = when (symbol) {
@@ -23,4 +23,4 @@ public interface XYZColumnarData : XYColumna
Symbol.z -> z
else -> null
}
-}
\ No newline at end of file
+}
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt
index e6e703cbf..b5a84cf6c 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt
@@ -12,7 +12,7 @@ import space.kscience.kmath.linear.Point
*
* @param T the type of element of this domain.
*/
-public interface Domain {
+public interface Domain {
/**
* Checks if the specified point is contained in this domain.
*/
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt
index f5560d935..bd5514623 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt
@@ -17,17 +17,17 @@ import space.kscience.kmath.structures.indices
*/
@UnstableKMathAPI
public class HyperSquareDomain(private val lower: Buffer, private val upper: Buffer) : DoubleDomain {
- public override val dimension: Int get() = lower.size
+ override val dimension: Int get() = lower.size
- public override operator fun contains(point: Point): Boolean = point.indices.all { i ->
+ override operator fun contains(point: Point): Boolean = point.indices.all { i ->
point[i] in lower[i]..upper[i]
}
- public override fun getLowerBound(num: Int): Double = lower[num]
+ override fun getLowerBound(num: Int): Double = lower[num]
- public override fun getUpperBound(num: Int): Double = upper[num]
+ override fun getUpperBound(num: Int): Double = upper[num]
- public override fun volume(): Double {
+ override fun volume(): Double {
var res = 1.0
for (i in 0 until dimension) {
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt
index 7ffc0659d..32a5fc56c 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt
@@ -8,12 +8,12 @@ import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI
@UnstableKMathAPI
-public class UnconstrainedDomain(public override val dimension: Int) : DoubleDomain {
- public override operator fun contains(point: Point): Boolean = true
+public class UnconstrainedDomain(override val dimension: Int) : DoubleDomain {
+ override operator fun contains(point: Point): Boolean = true
- public override fun getLowerBound(num: Int): Double = Double.NEGATIVE_INFINITY
+ override fun getLowerBound(num: Int): Double = Double.NEGATIVE_INFINITY
- public override fun getUpperBound(num: Int): Double = Double.POSITIVE_INFINITY
+ override fun getUpperBound(num: Int): Double = Double.POSITIVE_INFINITY
- public override fun volume(): Double = Double.POSITIVE_INFINITY
+ override fun volume(): Double = Double.POSITIVE_INFINITY
}
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt
index e7acada85..9020ef8cb 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt
@@ -10,24 +10,24 @@ import space.kscience.kmath.misc.UnstableKMathAPI
@UnstableKMathAPI
public class UnivariateDomain(public val range: ClosedFloatingPointRange) : DoubleDomain {
- public override val dimension: Int get() = 1
+ override val dimension: Int get() = 1
public operator fun contains(d: Double): Boolean = range.contains(d)
- public override operator fun contains(point: Point): Boolean {
+ override operator fun contains(point: Point): Boolean {
require(point.size == 0)
return contains(point[0])
}
- public override fun getLowerBound(num: Int): Double {
+ override fun getLowerBound(num: Int): Double {
require(num == 0)
return range.start
}
- public override fun getUpperBound(num: Int): Double {
+ override fun getUpperBound(num: Int): Double {
require(num == 0)
return range.endInclusive
}
- public override fun volume(): Double = range.endInclusive - range.start
+ override fun volume(): Double = range.endInclusive - range.start
}
diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt
index 1782ff406..12b7df0ea 100644
--- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt
+++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt
@@ -8,10 +8,9 @@ package space.kscience.kmath.expressions
import space.kscience.kmath.operations.Algebra
/**
- * Represents expression which structure can be differentiated.
+ * Represents expression, which structure can be differentiated.
*
* @param T the type this expression takes as argument and returns.
- * @param R the type of expression this expression can be differentiated to.
*/
public interface DifferentiableExpression : Expression {
/**
@@ -26,16 +25,18 @@ public interface DifferentiableExpression : Expression {
public fun DifferentiableExpression.derivative(symbols: List): Expression =
derivativeOrNull(symbols) ?: error("Derivative by symbols $symbols not provided")
-public fun DifferentiableExpression.derivative(vararg symbols: Symbol): Expression