Merge branch 'dev' into beta/kotlin2.0.0

# Conflicts:
#	gradle.properties
#	kmath-histograms/build.gradle.kts
#	kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt
This commit is contained in:
Alexander Nozik 2024-03-19 09:15:55 +03:00
commit bd9430bab4
540 changed files with 5573 additions and 4172 deletions

1
.gitignore vendored
View File

@ -5,6 +5,7 @@ out/
.idea/ .idea/
.vscode/ .vscode/
.fleet/ .fleet/
.kotlin/
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)

View File

@ -3,28 +3,62 @@
## Unreleased ## Unreleased
### Added ### Added
- Integer division algebras
- Float32 geometries
### Changed ### Changed
- Default naming for algebra and buffers now uses IntXX/FloatXX notation instead of Java types.
- Remove unnecessary inlines in basic algebras.
- QuaternionField -> QuaternionAlgebra and does not implement `Field` anymore since it is non-commutative
- kmath-geometry is split into `euclidean2d` and `euclidean3d`
### Deprecated ### Deprecated
### Removed ### Removed
- `asPolynomial` function due to scope pollution
### Fixed ### Fixed
- Median statistics
### Security ### Security
## 0.4.0-dev-3 - 2024-02-18
### Added
- Reification. Explicit `SafeType` for algebras.
- Integer division algebras.
- Float32 geometries.
- New Attributes-kt module that could be used as stand-alone. It declares. type-safe attributes containers.
- Explicit `mutableStructureND` builders for mutable structures.
- `Buffer.asList()` zero-copy transformation.
- Wasm support.
- Parallel implementation of `LinearSpace` for Float64
- Parallel buffer factories
### Changed
- Buffer copy removed from API (added as an extension).
- Default naming for algebra and buffers now uses IntXX/FloatXX notation instead of Java types.
- Remove unnecessary inlines in basic algebras.
- QuaternionField -> QuaternionAlgebra and does not implement `Field` anymore since it is non-commutative
- kmath-geometry is split into `euclidean2d` and `euclidean3d`
- Features replaced with Attributes.
- Transposed refactored.
- Kmath-memory is moved on top of core.
### Deprecated
- ND4J engine
### Removed
- `asPolynomial` function due to scope pollution
- Codegend for ejml (450 lines of codegen for 1000 lines of code is too much)
### Fixed
- Median statistics
- Complex power of negative real numbers
- Add proper mutability for MutableBufferND rows and columns
- Generic Float32 and Float64 vectors are used in geometry algebras.
## 0.3.1 - 2023-04-09 ## 0.3.1 - 2023-04-09
### Added ### Added
- Wasm support for `memory`, `core`, `complex` and `functions` modules. - Wasm support for `memory`, `core`, `complex` and `functions` modules.
- Generic builders for `BufferND` and `MutableBufferND` - Generic builders for `BufferND` and `MutableBufferND`
- `NamedMatrix` - matrix with symbol-based indexing - `NamedMatrix` - matrix with symbol-based indexing
@ -34,6 +68,8 @@
- Algebra now has an obligatory `bufferFactory` (#477). - Algebra now has an obligatory `bufferFactory` (#477).
### Changed ### Changed
- Removed marker `Vector` type for geometry
- Geometry uses type-safe angles - Geometry uses type-safe angles
- Tensor operations switched to prefix notation - Tensor operations switched to prefix notation
- Row-wise and column-wise ND shapes in the core - Row-wise and column-wise ND shapes in the core
@ -45,12 +81,14 @@
- Multik went MPP - Multik went MPP
### Removed ### Removed
- Trajectory moved to https://github.com/SciProgCentre/maps-kt - Trajectory moved to https://github.com/SciProgCentre/maps-kt
- Polynomials moved to https://github.com/SciProgCentre/kmath-polynomial - Polynomials moved to https://github.com/SciProgCentre/kmath-polynomial
## 0.3.0 ## 0.3.0
### Added ### Added
- `ScaleOperations` interface - `ScaleOperations` interface
- `Field` extends `ScaleOperations` - `Field` extends `ScaleOperations`
- Basic integration API - Basic integration API
@ -75,6 +113,7 @@
- Compilation to TeX for MST: #254 - Compilation to TeX for MST: #254
### Changed ### Changed
- Annotations moved to `space.kscience.kmath` - Annotations moved to `space.kscience.kmath`
- Exponential operations merged with hyperbolic functions - Exponential operations merged with hyperbolic functions
- Space is replaced by Group. Space is reserved for vector spaces. - Space is replaced by Group. Space is reserved for vector spaces.
@ -108,9 +147,11 @@
- `UnivariateFunction` -> `Function1D`, `MultivariateFunction` -> `FunctionND` - `UnivariateFunction` -> `Function1D`, `MultivariateFunction` -> `FunctionND`
### Deprecated ### Deprecated
- Specialized `DoubleBufferAlgebra` - Specialized `DoubleBufferAlgebra`
### Removed ### Removed
- Nearest in Domain. To be implemented in geometry package. - Nearest in Domain. To be implemented in geometry package.
- Number multiplication and division in main Algebra chain - Number multiplication and division in main Algebra chain
- `contentEquals` from Buffer. It moved to the companion. - `contentEquals` from Buffer. It moved to the companion.
@ -121,12 +162,14 @@
- Algebra elements are completely removed. Use algebra contexts instead. - Algebra elements are completely removed. Use algebra contexts instead.
### Fixed ### Fixed
- Ring inherits RingOperations, not GroupOperations - Ring inherits RingOperations, not GroupOperations
- Univariate histogram filling - Univariate histogram filling
## 0.2.0 ## 0.2.0
### Added ### Added
- `fun` annotation for SAM interfaces in library - `fun` annotation for SAM interfaces in library
- Explicit `public` visibility for all public APIs - Explicit `public` visibility for all public APIs
- Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140) - Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140)
@ -146,6 +189,7 @@
- Basic Quaternion vector support in `kmath-complex`. - Basic Quaternion vector support in `kmath-complex`.
### Changed ### Changed
- Package changed from `scientifik` to `space.kscience` - Package changed from `scientifik` to `space.kscience`
- Gradle version: 6.6 -> 6.8.2 - Gradle version: 6.6 -> 6.8.2
- Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`) - Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`)
@ -170,6 +214,7 @@
- Add `out` projection to `Buffer` generic - Add `out` projection to `Buffer` generic
### Removed ### Removed
- `kmath-koma` module because it doesn't support Kotlin 1.4. - `kmath-koma` module because it doesn't support Kotlin 1.4.
- Support of `legacy` JS backend (we will support only IR) - Support of `legacy` JS backend (we will support only IR)
- `toGrid` method. - `toGrid` method.
@ -178,11 +223,13 @@
- StructureND identity and equals - StructureND identity and equals
### Fixed ### Fixed
- `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) - `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140)
## 0.1.4 ## 0.1.4
### Added ### Added
- Functional Expressions API - Functional Expressions API
- Mathematical Syntax Tree, its interpreter and API - Mathematical Syntax Tree, its interpreter and API
- String to MST parser (https://github.com/mipt-npm/kmath/pull/120) - String to MST parser (https://github.com/mipt-npm/kmath/pull/120)
@ -200,6 +247,7 @@
- Norm support for `Complex` - Norm support for `Complex`
### Changed ### Changed
- `readAsMemory` now has `throws IOException` in JVM signature. - `readAsMemory` now has `throws IOException` in JVM signature.
- Several functions taking functional types were made `inline`. - Several functions taking functional types were made `inline`.
- Several functions taking functional types now have `callsInPlace` contracts. - Several functions taking functional types now have `callsInPlace` contracts.
@ -211,6 +259,7 @@
- Moved probability distributions to commons-rng and to `kmath-prob` - Moved probability distributions to commons-rng and to `kmath-prob`
### Fixed ### Fixed
- Missing copy method in Memory implementation on JS (https://github.com/mipt-npm/kmath/pull/106) - Missing copy method in Memory implementation on JS (https://github.com/mipt-npm/kmath/pull/106)
- D3.dim value in `kmath-dimensions` - D3.dim value in `kmath-dimensions`
- Multiplication in integer rings in `kmath-core` (https://github.com/mipt-npm/kmath/pull/101) - Multiplication in integer rings in `kmath-core` (https://github.com/mipt-npm/kmath/pull/101)

View File

@ -2,7 +2,7 @@
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
![Gradle build](https://github.com/SciProgCentre/kmath/workflows/Gradle%20build/badge.svg) ![Gradle build](https://github.com/SciProgCentre/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) [![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/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/spc/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 # KMath
@ -11,18 +11,21 @@ analog to Python's NumPy library. Later we found that kotlin is much more flexib
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like 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. experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
[Documentation site (**WIP**)](https://SciProgCentre.github.io/kmath/) [Documentation site](https://SciProgCentre.github.io/kmath/)
## Publications and talks ## Publications and talks
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2) * [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
* [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814) * [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814)
* [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103) * [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103)
* [A talk at KotlinConf 2019 about using kotlin for science](https://youtu.be/LI_5TZ7tnOE?si=4LknX41gl_YeUbIe)
* [A talk on architecture at Joker-2021 (in Russian)](https://youtu.be/1bZ2doHiRRM?si=9w953ro9yu98X_KJ)
* [The same talk in English](https://youtu.be/yP5DIc2fVwQ?si=louZzQ1dcXV6gP10)
* [A seminar on tensor API](https://youtu.be/0H99wUs0xTM?si=6c__04jrByFQtVpo)
# Goal # 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, Native and Wasm).
.
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization). * Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries. * Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
@ -53,19 +56,21 @@ module definitions below. The module stability could have the following levels:
## Modules ## Modules
### [benchmarks](benchmarks) ### [attributes-kt](attributes-kt)
> An API and basic implementation for arranging objects in a continuous memory block.
> >
> **Maturity**: DEVELOPMENT
### [benchmarks](benchmarks)
> >
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
### [examples](examples) ### [examples](examples)
> >
>
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
### [kmath-ast](kmath-ast) ### [kmath-ast](kmath-ast)
> >
>
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
> >
> **Features:** > **Features:**
@ -76,7 +81,7 @@ module definitions below. The module stability could have the following levels:
### [kmath-commons](kmath-commons) ### [kmath-commons](kmath-commons)
> > Commons math binding for kmath
> >
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
@ -109,17 +114,15 @@ performance calculations to code generation.
### [kmath-coroutines](kmath-coroutines) ### [kmath-coroutines](kmath-coroutines)
> >
>
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
### [kmath-dimensions](kmath-dimensions) ### [kmath-dimensions](kmath-dimensions)
> > A proof of concept module for adding type-safe dimensions to structures
> >
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
### [kmath-ejml](kmath-ejml) ### [kmath-ejml](kmath-ejml)
> >
>
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
> >
> **Features:** > **Features:**
@ -142,7 +145,7 @@ One can still use generic algebras though.
### [kmath-functions](kmath-functions) ### [kmath-functions](kmath-functions)
> > Functions, integration and interpolation
> >
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
> >
@ -156,18 +159,16 @@ One can still use generic algebras though.
### [kmath-geometry](kmath-geometry) ### [kmath-geometry](kmath-geometry)
> >
>
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
### [kmath-histograms](kmath-histograms) ### [kmath-histograms](kmath-histograms)
> >
>
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
### [kmath-jafama](kmath-jafama) ### [kmath-jafama](kmath-jafama)
> Jafama integration module
> >
> > **Maturity**: DEPRECATED
> **Maturity**: PROTOTYPE
> >
> **Features:** > **Features:**
> - [jafama-double](kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama > - [jafama-double](kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama
@ -175,11 +176,10 @@ One can still use generic algebras though.
### [kmath-jupyter](kmath-jupyter) ### [kmath-jupyter](kmath-jupyter)
> >
>
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
### [kmath-kotlingrad](kmath-kotlingrad) ### [kmath-kotlingrad](kmath-kotlingrad)
> > Kotlin∇ integration module
> >
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
> >
@ -194,14 +194,14 @@ One can still use generic algebras though.
> **Maturity**: DEVELOPMENT > **Maturity**: DEVELOPMENT
### [kmath-multik](kmath-multik) ### [kmath-multik](kmath-multik)
> > JetBrains Multik connector
> >
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
### [kmath-nd4j](kmath-nd4j) ### [kmath-nd4j](kmath-nd4j)
> ND4J NDStructure implementation and according NDAlgebra classes
> >
> > **Maturity**: DEPRECATED
> **Maturity**: EXPERIMENTAL
> >
> **Features:** > **Features:**
> - [nd4jarraystructure](kmath-nd4j/#) : NDStructure wrapper for INDArray > - [nd4jarraystructure](kmath-nd4j/#) : NDStructure wrapper for INDArray
@ -211,27 +211,24 @@ One can still use generic algebras though.
### [kmath-optimization](kmath-optimization) ### [kmath-optimization](kmath-optimization)
> >
>
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
### [kmath-stat](kmath-stat) ### [kmath-stat](kmath-stat)
> >
>
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
### [kmath-symja](kmath-symja) ### [kmath-symja](kmath-symja)
> > Symja integration module
> >
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
### [kmath-tensorflow](kmath-tensorflow) ### [kmath-tensorflow](kmath-tensorflow)
> > Google tensorflow connector
> >
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
### [kmath-tensors](kmath-tensors) ### [kmath-tensors](kmath-tensors)
> >
>
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
> >
> **Features:** > **Features:**
@ -241,13 +238,12 @@ One can still use generic algebras though.
### [kmath-viktor](kmath-viktor) ### [kmath-viktor](kmath-viktor)
> > Binding for https://github.com/JetBrains-Research/viktor
> >
> **Maturity**: DEVELOPMENT > **Maturity**: DEVELOPMENT
### [test-utils](test-utils) ### [test-utils](test-utils)
> >
>
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
@ -256,22 +252,21 @@ One can still use generic algebras though.
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the 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 [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 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 reasons. Currently, Kotlin/JVM is the primary platform, however, Kotlin/Native and Kotlin/JS contributions and
feedback are also welcome. feedback are also welcome.
## Performance ## Performance
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both Calculation of performance is one of the major goals of KMath in the future, but in some cases it is impossible to achieve both
performance and flexibility. performance and flexibility.
We expect to focus on creating convenient universal API first and then work on increasing performance for specific We expect to focus on creating a 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 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. native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy.
## Requirements ## Requirements
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend using GraalVM-CE or Oracle GraalVM for execution to get better performance.
execution to get better performance.
### Repositories ### Repositories
@ -291,10 +286,7 @@ dependencies {
} }
``` ```
Gradle `6.0+` is required for multiplatform artifacts.
## Contributing ## Contributing
The project requires a lot of additional work. The most important thing we need is a feedback about what features are The project requires a lot of additional work. The most important thing we need is feedback about what features are
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with [good first issue](hhttps://github.com/SciProgCentre/kmath/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label.
marked with [waiting for a hero](https://github.com/SciProgCentre/kmath/labels/waiting%20for%20a%20hero) label.

4
attributes-kt/README.md Normal file
View File

@ -0,0 +1,4 @@
# Module attributes-kt

View File

@ -0,0 +1,104 @@
public abstract interface class space/kscience/attributes/Attribute {
}
public abstract interface class space/kscience/attributes/AttributeContainer {
public abstract fun getAttributes ()Lspace/kscience/attributes/Attributes;
}
public abstract interface class space/kscience/attributes/AttributeScope {
}
public abstract interface class space/kscience/attributes/AttributeWithDefault : space/kscience/attributes/Attribute {
public abstract fun getDefault ()Ljava/lang/Object;
}
public abstract interface class space/kscience/attributes/Attributes {
public static final field Companion Lspace/kscience/attributes/Attributes$Companion;
public abstract fun equals (Ljava/lang/Object;)Z
public fun get (Lspace/kscience/attributes/Attribute;)Ljava/lang/Object;
public abstract fun getContent ()Ljava/util/Map;
public fun getKeys ()Ljava/util/Set;
public abstract fun hashCode ()I
public abstract fun toString ()Ljava/lang/String;
}
public final class space/kscience/attributes/Attributes$Companion {
public final fun equals (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attributes;)Z
public final fun getEMPTY ()Lspace/kscience/attributes/Attributes;
}
public final class space/kscience/attributes/AttributesBuilder : space/kscience/attributes/Attributes {
public fun <init> ()V
public final fun add (Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)V
public final fun build ()Lspace/kscience/attributes/Attributes;
public fun equals (Ljava/lang/Object;)Z
public final fun from (Lspace/kscience/attributes/Attributes;)V
public fun getContent ()Ljava/util/Map;
public fun hashCode ()I
public final fun invoke (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)V
public final fun remove (Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)V
public final fun set (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)V
public fun toString ()Ljava/lang/String;
}
public final class space/kscience/attributes/AttributesBuilderKt {
public static final fun Attributes (Lkotlin/jvm/functions/Function1;)Lspace/kscience/attributes/Attributes;
}
public final class space/kscience/attributes/AttributesKt {
public static final fun Attributes (Lspace/kscience/attributes/Attribute;)Lspace/kscience/attributes/Attributes;
public static final fun Attributes (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
public static final fun getOrDefault (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/AttributeWithDefault;)Ljava/lang/Object;
public static final fun isEmpty (Lspace/kscience/attributes/Attributes;)Z
public static final fun modify (Lspace/kscience/attributes/Attributes;Lkotlin/jvm/functions/Function1;)Lspace/kscience/attributes/Attributes;
public static final fun plus (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attributes;)Lspace/kscience/attributes/Attributes;
public static final fun withAttribute (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attribute;)Lspace/kscience/attributes/Attributes;
public static final fun withAttribute (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
public static final fun withAttributeElement (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
public static final fun withoutAttribute (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attribute;)Lspace/kscience/attributes/Attributes;
public static final fun withoutAttributeElement (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
}
public abstract interface class space/kscience/attributes/FlagAttribute : space/kscience/attributes/Attribute {
}
public abstract class space/kscience/attributes/PolymorphicAttribute : space/kscience/attributes/Attribute {
public synthetic fun <init> (Lkotlin/reflect/KType;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun equals (Ljava/lang/Object;)Z
public final fun getType-V0oMfBY ()Lkotlin/reflect/KType;
public fun hashCode ()I
}
public final class space/kscience/attributes/PolymorphicAttributeKt {
public static final fun get (Lspace/kscience/attributes/Attributes;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;
public static final fun set (Lspace/kscience/attributes/AttributesBuilder;Lkotlin/jvm/functions/Function0;Ljava/lang/Object;)V
}
public final class space/kscience/attributes/SafeType {
public static final synthetic fun box-impl (Lkotlin/reflect/KType;)Lspace/kscience/attributes/SafeType;
public static fun constructor-impl (Lkotlin/reflect/KType;)Lkotlin/reflect/KType;
public fun equals (Ljava/lang/Object;)Z
public static fun equals-impl (Lkotlin/reflect/KType;Ljava/lang/Object;)Z
public static final fun equals-impl0 (Lkotlin/reflect/KType;Lkotlin/reflect/KType;)Z
public final fun getKType ()Lkotlin/reflect/KType;
public fun hashCode ()I
public static fun hashCode-impl (Lkotlin/reflect/KType;)I
public fun toString ()Ljava/lang/String;
public static fun toString-impl (Lkotlin/reflect/KType;)Ljava/lang/String;
public final synthetic fun unbox-impl ()Lkotlin/reflect/KType;
}
public final class space/kscience/attributes/SafeTypeKt {
public static final fun getKClass-X0YbwmU (Lkotlin/reflect/KType;)Lkotlin/reflect/KClass;
}
public abstract interface class space/kscience/attributes/SetAttribute : space/kscience/attributes/Attribute {
}
public abstract interface annotation class space/kscience/attributes/UnstableAttributesAPI : java/lang/annotation/Annotation {
}
public abstract interface class space/kscience/attributes/WithType {
public abstract fun getType-V0oMfBY ()Lkotlin/reflect/KType;
}

View File

@ -0,0 +1,20 @@
plugins {
id("space.kscience.gradle.mpp")
`maven-publish`
}
version = "0.1.0"
kscience {
jvm()
js()
native()
wasm()
}
readme {
maturity = space.kscience.gradle.Maturity.DEVELOPMENT
description = """
An API and basic implementation for arranging objects in a continuous memory block.
""".trimIndent()
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2018-2023 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.attributes
/**
* A marker interface for an attribute. Attributes are used as keys to access contents of type [T] in the container.
*/
public interface Attribute<T>
/**
* An attribute that could be either present or absent
*/
public interface FlagAttribute : Attribute<Unit>
/**
* An attribute with a default value
*/
public interface AttributeWithDefault<T> : Attribute<T> {
public val default: T
}
/**
* Attribute containing a set of values
*/
public interface SetAttribute<V> : Attribute<Set<V>>

View File

@ -0,0 +1,20 @@
/*
* Copyright 2018-2023 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.attributes
/**
* A container for [Attributes]
*/
public interface AttributeContainer {
public val attributes: Attributes
}
/**
* A scope, where attribute keys could be resolved.
* [O] is used only to resolve types in compile-time.
*/
public interface AttributeScope<O>

View File

@ -0,0 +1,135 @@
/*
* Copyright 2018-2023 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.attributes
/**
* A set of attributes. The implementation must guarantee that [content] keys correspond to their value types.
*/
public interface Attributes {
/**
* Raw content for this [Attributes]
*/
public val content: Map<out Attribute<*>, Any?>
/**
* Attribute keys contained in this [Attributes]
*/
public val keys: Set<Attribute<*>> get() = content.keys
/**
* Provide an attribute value. Return null if attribute is not present or if its value is null.
*/
@Suppress("UNCHECKED_CAST")
public operator fun <T> get(attribute: Attribute<T>): T? = content[attribute] as? T
override fun toString(): String
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
public companion object {
public val EMPTY: Attributes = AttributesImpl(emptyMap())
public fun equals(a1: Attributes, a2: Attributes): Boolean =
a1.keys == a2.keys && a1.keys.all { a1[it] == a2[it] }
}
}
internal class AttributesImpl(override val content: Map<out Attribute<*>, Any?>) : Attributes {
override fun toString(): String = "Attributes(value=${content.entries})"
override fun equals(other: Any?): Boolean = other is Attributes && Attributes.equals(this, other)
override fun hashCode(): Int = content.hashCode()
}
public fun Attributes.isEmpty(): Boolean = content.isEmpty()
/**
* Get attribute value or default
*/
public fun <T> Attributes.getOrDefault(attribute: AttributeWithDefault<T>): T = get(attribute) ?: attribute.default
/**
* Check if there is an attribute that matches given key by type and adheres to [predicate].
*/
@Suppress("UNCHECKED_CAST")
public inline fun <T, reified A : Attribute<T>> Attributes.hasAny(predicate: (value: T) -> Boolean): Boolean =
content.any { (mapKey, mapValue) -> mapKey is A && predicate(mapValue as T) }
/**
* Check if there is an attribute of given type (subtypes included)
*/
public inline fun <reified A : Attribute<*>> Attributes.hasAny(): Boolean =
content.any { (mapKey, _) -> mapKey is A }
/**
* Check if [Attributes] contains a flag. Multiple keys that are instances of a flag could be present
*/
public inline fun <reified A : FlagAttribute> Attributes.hasFlag(): Boolean =
content.keys.any { it is A }
/**
* Create [Attributes] with an added or replaced attribute key.
*/
public fun <T, A : Attribute<T>> Attributes.withAttribute(
attribute: A,
attrValue: T,
): Attributes = AttributesImpl(content + (attribute to attrValue))
public fun <A : Attribute<Unit>> Attributes.withAttribute(attribute: A): Attributes =
withAttribute(attribute, Unit)
/**
* Create a new [Attributes] by modifying the current one
*/
public fun <T> Attributes.modify(block: AttributesBuilder<T>.() -> Unit): Attributes = Attributes<T> {
from(this@modify)
block()
}
/**
* Create new [Attributes] by removing [attribute] key
*/
public fun Attributes.withoutAttribute(attribute: Attribute<*>): Attributes = AttributesImpl(content.minus(attribute))
/**
* Add an element to a [SetAttribute]
*/
public fun <T, A : SetAttribute<T>> Attributes.withAttributeElement(
attribute: A,
attrValue: T,
): Attributes {
val currentSet: Set<T> = get(attribute) ?: emptySet()
return AttributesImpl(
content + (attribute to (currentSet + attrValue))
)
}
/**
* Remove an element from [SetAttribute]
*/
public fun <T, A : SetAttribute<T>> Attributes.withoutAttributeElement(
attribute: A,
attrValue: T,
): Attributes {
val currentSet: Set<T> = get(attribute) ?: emptySet()
return AttributesImpl(content + (attribute to (currentSet - attrValue)))
}
/**
* Create [Attributes] with a single key
*/
public fun <T, A : Attribute<T>> Attributes(
attribute: A,
attrValue: T,
): Attributes = AttributesImpl(mapOf(attribute to attrValue))
/**
* Create Attributes with a single [Unit] valued attribute
*/
public fun <A : Attribute<Unit>> Attributes(
attribute: A,
): Attributes = AttributesImpl(mapOf(attribute to Unit))
public operator fun Attributes.plus(other: Attributes): Attributes = AttributesImpl(content + other.content)

View File

@ -0,0 +1,62 @@
/*
* Copyright 2018-2023 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.attributes
/**
* A safe builder for [Attributes]
*
* @param O type marker of an owner object, for which these attributes are made
*/
public class AttributesBuilder<out O> internal constructor(
private val map: MutableMap<Attribute<*>, Any?>,
) : Attributes {
public constructor() : this(mutableMapOf())
override fun toString(): String = "Attributes(value=${content.entries})"
override fun equals(other: Any?): Boolean = other is Attributes && Attributes.equals(this, other)
override fun hashCode(): Int = content.hashCode()
override val content: Map<out Attribute<*>, Any?> get() = map
public operator fun <T> set(attribute: Attribute<T>, value: T?) {
if (value == null) {
map.remove(attribute)
} else {
map[attribute] = value
}
}
public operator fun <V> Attribute<V>.invoke(value: V?) {
set(this, value)
}
public fun from(attributes: Attributes) {
map.putAll(attributes.content)
}
public fun <V> SetAttribute<V>.add(
attrValue: V,
) {
val currentSet: Set<V> = get(this) ?: emptySet()
map[this] = currentSet + attrValue
}
/**
* Remove an element from [SetAttribute]
*/
public fun <V> SetAttribute<V>.remove(
attrValue: V,
) {
val currentSet: Set<V> = get(this) ?: emptySet()
map[this] = currentSet - attrValue
}
public fun build(): Attributes = AttributesImpl(map)
}
public inline fun <O> Attributes(builder: AttributesBuilder<O>.() -> Unit): Attributes =
AttributesBuilder<O>().apply(builder).build()

View File

@ -0,0 +1,31 @@
/*
* Copyright 2018-2023 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.attributes
/**
* An attribute that has a type parameter for value
* @param type parameter-type
*/
public abstract class PolymorphicAttribute<T>(public val type: SafeType<T>) : Attribute<T> {
override fun equals(other: Any?): Boolean = other != null &&
(this::class == other::class) &&
(other as? PolymorphicAttribute<*>)?.type == this.type
override fun hashCode(): Int = this::class.hashCode() + type.hashCode()
}
/**
* Get a polymorphic attribute using attribute factory
*/
public operator fun <T> Attributes.get(attributeKeyBuilder: () -> PolymorphicAttribute<T>): T? = get(attributeKeyBuilder())
/**
* Set a polymorphic attribute using its factory
*/
public operator fun <O, T> AttributesBuilder<O>.set(attributeKeyBuilder: () -> PolymorphicAttribute<T>, value: T) {
set(attributeKeyBuilder(), value)
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2018-2023 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.attributes
import kotlin.jvm.JvmInline
import kotlin.reflect.KClass
import kotlin.reflect.KType
import kotlin.reflect.typeOf
/**
* Safe variant ok Kotlin [KType] that ensures that the type parameter is of the same type as [kType]
*
* @param kType raw [KType]
*/
@JvmInline
public value class SafeType<out T> @PublishedApi internal constructor(public val kType: KType)
public inline fun <reified T> safeTypeOf(): SafeType<T> = SafeType(typeOf<T>())
/**
* Derive Kotlin [KClass] from this type and fail if the type is not a class (should not happen)
*/
@Suppress("UNCHECKED_CAST")
@UnstableAttributesAPI
public val <T> SafeType<T>.kClass: KClass<T & Any> get() = kType.classifier as KClass<T & Any>
/**
* An interface containing [type] for dynamic type checking.
*/
public interface WithType<out T> {
public val type: SafeType<T>
}

View File

@ -0,0 +1,17 @@
/*
* Copyright 2018-2023 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.attributes
/**
* Marks declarations that are still experimental in the Attributes-kt APIs, which means that the design of the corresponding
* declarations has open issues that may (or may not) lead to their changes in the future. Roughly speaking, there is
* a chance of those declarations will be deprecated in the future or the semantics of their behavior may change
* in some way that may break some code.
*/
@MustBeDocumented
@Retention(value = AnnotationRetention.BINARY)
@RequiresOptIn("This API is unstable and could change in future", RequiresOptIn.Level.WARNING)
public annotation class UnstableAttributesAPI

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -99,7 +99,7 @@ class ExpressionsInterpretersBenchmark {
private val estree = node.estreeCompileToExpression(Float64Field) private val estree = node.estreeCompileToExpression(Float64Field)
private val raw = Expression<Double> { args -> private val raw = Expression<Double> { args ->
val x = args[x]!! val x = args.getValue(x)
x * 2.0 + 2.0 / x - 16.0 / sin(x) x * 2.0 + 2.0 / x - 16.0 / sin(x)
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -11,12 +11,11 @@ import kotlinx.benchmark.Scope
import kotlinx.benchmark.State import kotlinx.benchmark.State
import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.commons.linear.CMLinearSpace
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
import space.kscience.kmath.linear.Float64ParallelLinearSpace
import space.kscience.kmath.linear.invoke import space.kscience.kmath.linear.invoke
import space.kscience.kmath.linear.linearSpace import space.kscience.kmath.linear.linearSpace
import space.kscience.kmath.operations.Float64Field import space.kscience.kmath.operations.Float64Field
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.tensorflow.produceWithTF import space.kscience.kmath.tensorflow.produceWithTF
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.tensorAlgebra
import kotlin.random.Random import kotlin.random.Random
@ -72,12 +71,12 @@ internal class DotBenchmark {
} }
@Benchmark @Benchmark
fun tensorDot(blackhole: Blackhole) = with(Float64Field.tensorAlgebra) { fun multikDot(blackhole: Blackhole) = with(multikAlgebra) {
blackhole.consume(matrix1 dot matrix2) blackhole.consume(matrix1 dot matrix2)
} }
@Benchmark @Benchmark
fun multikDot(blackhole: Blackhole) = with(multikAlgebra) { fun tensorDot(blackhole: Blackhole) = with(Float64Field.tensorAlgebra) {
blackhole.consume(matrix1 dot matrix2) blackhole.consume(matrix1 dot matrix2)
} }
@ -87,12 +86,8 @@ internal class DotBenchmark {
} }
@Benchmark @Benchmark
fun doubleDot(blackhole: Blackhole) = with(Float64Field.linearSpace) { fun parallelDot(blackhole: Blackhole) = with(Float64ParallelLinearSpace) {
blackhole.consume(matrix1 dot matrix2) blackhole.consume(matrix1 dot matrix2)
} }
@Benchmark
fun doubleTensorDot(blackhole: Blackhole) = DoubleTensorAlgebra.invoke {
blackhole.consume(matrix1 dot matrix2)
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2023 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -15,6 +15,7 @@ import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
import space.kscience.kmath.linear.invoke import space.kscience.kmath.linear.invoke
import space.kscience.kmath.linear.linearSpace import space.kscience.kmath.linear.linearSpace
import space.kscience.kmath.linear.lupSolver import space.kscience.kmath.linear.lupSolver
import space.kscience.kmath.linear.parallel
import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.algebra
import kotlin.random.Random import kotlin.random.Random
@ -38,16 +39,19 @@ internal class MatrixInverseBenchmark {
} }
@Benchmark @Benchmark
fun cmLUPInversion(blackhole: Blackhole) { fun kmathParallelLupInversion(blackhole: Blackhole) {
CMLinearSpace { blackhole.consume(Double.algebra.linearSpace.parallel.lupSolver().inverse(matrix))
blackhole.consume(lupSolver().inverse(matrix))
}
} }
@Benchmark @Benchmark
fun ejmlInverse(blackhole: Blackhole) { fun cmLUPInversion(blackhole: Blackhole) = CMLinearSpace {
EjmlLinearSpaceDDRM { blackhole.consume(lupSolver().inverse(matrix))
blackhole.consume(matrix.toEjml().inverse())
} }
@Benchmark
fun ejmlInverse(blackhole: Blackhole) = EjmlLinearSpaceDDRM {
blackhole.consume(matrix.toEjml().inverted())
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -25,6 +25,16 @@ import space.kscience.kmath.viktor.viktorAlgebra
@State(Scope.Benchmark) @State(Scope.Benchmark)
internal class NDFieldBenchmark { internal class NDFieldBenchmark {
private companion object {
private const val dim = 1000
private const val n = 100
private val shape = ShapeND(dim, dim)
private val specializedField = Float64Field.ndAlgebra
private val genericField = BufferedFieldOpsND(Float64Field)
private val nd4jField = Float64Field.nd4j
private val viktorField = Float64Field.viktorAlgebra
}
@Benchmark @Benchmark
fun specializedFieldAdd(blackhole: Blackhole) = with(specializedField) { fun specializedFieldAdd(blackhole: Blackhole) = with(specializedField) {
var res: StructureND<Double> = one(shape) var res: StructureND<Double> = one(shape)
@ -82,13 +92,5 @@ internal class NDFieldBenchmark {
// blackhole.consume(res) // blackhole.consume(res)
// } // }
private companion object {
private const val dim = 1000
private const val n = 100
private val shape = ShapeND(dim, dim)
private val specializedField = Float64Field.ndAlgebra
private val genericField = BufferedFieldOpsND(Float64Field)
private val nd4jField = Float64Field.nd4j
private val viktorField = Float64Field.viktorAlgebra
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -3,7 +3,7 @@ import space.kscience.gradle.useSPCTeam
plugins { plugins {
id("space.kscience.gradle.project") id("space.kscience.gradle.project")
id("org.jetbrains.kotlinx.kover") version "0.6.0" id("org.jetbrains.kotlinx.kover") version "0.7.6"
} }
allprojects { allprojects {
@ -14,7 +14,7 @@ allprojects {
} }
group = "space.kscience" group = "space.kscience"
version = "0.4.0-dev-2" version = "0.4.0"
} }
subprojects { subprojects {
@ -34,7 +34,7 @@ subprojects {
localDirectory.set(kotlinDir) localDirectory.set(kotlinDir)
remoteUrl.set( remoteUrl.set(
java.net.URL("https://github.com/SciProgCentre/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath") uri("https://github.com/SciProgCentre/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath").toURL()
) )
} }
@ -69,4 +69,4 @@ ksciencePublish {
apiValidation.nonPublicMarkers.add("space.kscience.kmath.UnstableKMathAPI") apiValidation.nonPublicMarkers.add("space.kscience.kmath.UnstableKMathAPI")
val multikVersion by extra("0.2.2") val multikVersion by extra("0.2.3")

View File

@ -17,7 +17,7 @@ val benchmarksVersion = spclibs.versions.kotlinx.benchmark.get()
dependencies { dependencies {
api("space.kscience:gradle-tools:$toolsVersion") api("space.kscience:gradle-tools:$toolsVersion")
//plugins form benchmarks //plugins form benchmarks
api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.4.9") api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:$benchmarksVersion")
//api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion") //api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
//to be used inside build-script only //to be used inside build-script only
//implementation(spclibs.kotlinx.serialization.json) //implementation(spclibs.kotlinx.serialization.json)

View File

@ -6,7 +6,7 @@
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
plugins { plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0" id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
} }
dependencyResolutionManagement { dependencyResolutionManagement {
@ -22,6 +22,7 @@ dependencyResolutionManagement {
val toolsVersion: String = projectProperties["toolsVersion"].toString() val toolsVersion: String = projectProperties["toolsVersion"].toString()
@Suppress("UnstableApiUsage")
repositories { repositories {
mavenLocal() mavenLocal()
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,433 +0,0 @@
/*
* Copyright 2018-2022 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("KDocUnresolvedReference")
package space.kscience.kmath.ejml.codegen
import org.intellij.lang.annotations.Language
import java.io.File
private fun Appendable.appendEjmlVector(type: String, ejmlMatrixType: String) {
@Language("kotlin") val text = """/**
* [EjmlVector] specialization for [$type].
*/
public class Ejml${type}Vector<out M : $ejmlMatrixType>(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" }
}
override operator fun get(index: Int): $type = origin[0, index]
}"""
appendLine(text)
appendLine()
}
private fun Appendable.appendEjmlMatrix(type: String, ejmlMatrixType: String) {
val text = """/**
* [EjmlMatrix] specialization for [$type].
*/
public class Ejml${type}Matrix<out M : $ejmlMatrixType>(override val origin: M) : EjmlMatrix<$type, M>(origin) {
override operator fun get(i: Int, j: Int): $type = origin[i, j]
}"""
appendLine(text)
appendLine()
}
private fun Appendable.appendEjmlLinearSpace(
type: String,
kmathAlgebra: String,
ejmlMatrixParentTypeMatrix: String,
ejmlMatrixType: String,
ejmlMatrixDenseType: String,
ops: String,
denseOps: String,
isDense: Boolean,
) {
@Language("kotlin") val text = """/**
* [EjmlLinearSpace] implementation based on [CommonOps_$ops], [DecompositionFactory_${ops}] operations and
* [${ejmlMatrixType}] matrices.
*/
public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra}, $ejmlMatrixType>() {
/**
* The [${kmathAlgebra}] reference.
*/
override val elementAlgebra: $kmathAlgebra get() = $kmathAlgebra
@Suppress("UNCHECKED_CAST")
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")
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) }
})
}
override fun buildMatrix(
rows: Int,
columns: Int,
initializer: ${kmathAlgebra}.(i: Int, j: Int) -> ${type},
): Ejml${type}Matrix<${ejmlMatrixType}> = ${ejmlMatrixType}(rows, columns).also {
(0 until rows).forEach { row ->
(0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) }
}
}.wrapMatrix()
override fun buildVector(
size: Int,
initializer: ${kmathAlgebra}.(Int) -> ${type},
): Ejml${type}Vector<${ejmlMatrixType}> = Ejml${type}Vector(${ejmlMatrixType}(size, 1).also {
(0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) }
})
private fun <T : ${ejmlMatrixParentTypeMatrix}> T.wrapMatrix() = Ejml${type}Matrix(this)
private fun <T : ${ejmlMatrixParentTypeMatrix}> T.wrapVector() = Ejml${type}Vector(this)
override fun Matrix<${type}>.unaryMinus(): Matrix<${type}> = this * elementAlgebra { -one }
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()
}
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()
}
override operator fun Matrix<${type}>.minus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
elementAlgebra.one,
toEjml().origin,
elementAlgebra { -one },
other.toEjml().origin,
out,${
if (isDense) "" else
"""
null,
null,"""
}
)
return out.wrapMatrix()
}
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()
}
override fun Point<${type}>.unaryMinus(): Ejml${type}Vector<${ejmlMatrixType}> {
val res = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.changeSign(toEjml().origin, res)
return res.wrapVector()
}
override fun Matrix<${type}>.plus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
elementAlgebra.one,
toEjml().origin,
elementAlgebra.one,
other.toEjml().origin,
out,${
if (isDense) "" else
"""
null,
null,"""
}
)
return out.wrapMatrix()
}
override fun Point<${type}>.plus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
elementAlgebra.one,
toEjml().origin,
elementAlgebra.one,
other.toEjml().origin,
out,${
if (isDense) "" else
"""
null,
null,"""
}
)
return out.wrapVector()
}
override fun Point<${type}>.minus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
elementAlgebra.one,
toEjml().origin,
elementAlgebra { -one },
other.toEjml().origin,
out,${
if (isDense) "" else
"""
null,
null,"""
}
)
return out.wrapVector()
}
override fun ${type}.times(m: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> = m * this
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()
}
override fun ${type}.times(v: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> = v * this
@UnstableKMathAPI
override fun <F : StructureFeature> computeFeature(structure: Matrix<${type}>, type: KClass<out F>): F? {
structure.getFeature(type)?.let { return it }
val origin = structure.toEjml().origin
return when (type) {
${
if (isDense)
""" InverseMatrixFeature::class -> object : InverseMatrixFeature<${type}> {
override val inverse: Matrix<${type}> by lazy {
val res = origin.copy()
CommonOps_${ops}.invert(res)
res.wrapMatrix()
}
}
DeterminantFeature::class -> object : DeterminantFeature<${type}> {
override val determinant: $type by lazy { CommonOps_${ops}.det(origin) }
}
SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<${type}> {
private val svd by lazy {
DecompositionFactory_${ops}.svd(origin.numRows, origin.numCols, true, true, false)
.apply { decompose(origin.copy()) }
}
override val u: Matrix<${type}> by lazy { svd.getU(null, false).wrapMatrix() }
override val s: Matrix<${type}> by lazy { svd.getW(null).wrapMatrix() }
override val v: Matrix<${type}> by lazy { svd.getV(null, false).wrapMatrix() }
override val singularValues: Point<${type}> by lazy { ${type}Buffer(svd.singularValues) }
}
QRDecompositionFeature::class -> object : QRDecompositionFeature<${type}> {
private val qr by lazy {
DecompositionFactory_${ops}.qr().apply { decompose(origin.copy()) }
}
override val q: Matrix<${type}> by lazy {
qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature)
}
override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) }
}
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<${type}> {
override val l: Matrix<${type}> by lazy {
val cholesky =
DecompositionFactory_${ops}.chol(structure.rowNum, true).apply { decompose(origin.copy()) }
cholesky.getT(null).wrapMatrix().withFeature(LFeature)
}
}
LupDecompositionFeature::class -> object : LupDecompositionFeature<${type}> {
private val lup by lazy {
DecompositionFactory_${ops}.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) }
}
override val l: Matrix<${type}> by lazy {
lup.getLower(null).wrapMatrix().withFeature(LFeature)
}
override val u: Matrix<${type}> by lazy {
lup.getUpper(null).wrapMatrix().withFeature(UFeature)
}
override val p: Matrix<${type}> by lazy { lup.getRowPivot(null).wrapMatrix() }
}""" else """ QRDecompositionFeature::class -> object : QRDecompositionFeature<$type> {
private val qr by lazy {
DecompositionFactory_${ops}.qr(FillReducing.NONE).apply { decompose(origin.copy()) }
}
override val q: Matrix<${type}> by lazy {
qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature)
}
override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) }
}
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<${type}> {
override val l: Matrix<${type}> by lazy {
val cholesky =
DecompositionFactory_${ops}.cholesky().apply { decompose(origin.copy()) }
(cholesky.getT(null) as ${ejmlMatrixParentTypeMatrix}).wrapMatrix().withFeature(LFeature)
}
}
LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object :
LUDecompositionFeature<${type}>, DeterminantFeature<${type}>, InverseMatrixFeature<${type}> {
private val lu by lazy {
DecompositionFactory_${ops}.lu(FillReducing.NONE).apply { decompose(origin.copy()) }
}
override val l: Matrix<${type}> by lazy {
lu.getLower(null).wrapMatrix().withFeature(LFeature)
}
override val u: Matrix<${type}> by lazy {
lu.getUpper(null).wrapMatrix().withFeature(UFeature)
}
override val inverse: Matrix<${type}> by lazy {
var a = origin
val inverse = ${ejmlMatrixDenseType}(1, 1)
val solver = LinearSolverFactory_${ops}.lu(FillReducing.NONE)
if (solver.modifiesA()) a = a.copy()
val i = CommonOps_${denseOps}.identity(a.numRows)
solver.solve(i, inverse)
inverse.wrapMatrix()
}
override val determinant: $type by lazy { elementAlgebra.number(lu.computeDeterminant().real) }
}"""
}
else -> null
}?.let{
type.cast(it)
}
}
/**
* Solves for *x* in the following equation: *x = [a] <sup>-1</sup> &middot; [b]*.
*
* @param a the base matrix.
* @param b n by p matrix.
* @return the solution for *x* that is n by p.
*/
public fun solve(a: Matrix<${type}>, b: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
val res = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.solve(${ejmlMatrixType}(a.toEjml().origin), ${ejmlMatrixType}(b.toEjml().origin), res)
return res.wrapMatrix()
}
/**
* Solves for *x* in the following equation: *x = [a] <sup>-1</sup> &middot; [b]*.
*
* @param a the base matrix.
* @param b n by p vector.
* @return the solution for *x* that is n by p.
*/
public fun solve(a: Matrix<${type}>, b: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
val res = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.solve(${ejmlMatrixType}(a.toEjml().origin), ${ejmlMatrixType}(b.toEjml().origin), res)
return Ejml${type}Vector(res)
}
}"""
appendLine(text)
appendLine()
}
/**
* Generates routine EJML classes.
*/
fun ejmlCodegen(outputFile: String): Unit = File(outputFile).run {
parentFile.mkdirs()
writer().use {
it.appendLine("/*")
it.appendLine(" * Copyright 2018-2021 KMath contributors.")
it.appendLine(" * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.")
it.appendLine(" */")
it.appendLine()
it.appendLine("/* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */")
it.appendLine()
it.appendLine("package space.kscience.kmath.ejml")
it.appendLine()
it.appendLine("""import org.ejml.data.*
import org.ejml.dense.row.CommonOps_DDRM
import org.ejml.dense.row.CommonOps_FDRM
import org.ejml.dense.row.factory.DecompositionFactory_DDRM
import org.ejml.dense.row.factory.DecompositionFactory_FDRM
import org.ejml.sparse.FillReducing
import org.ejml.sparse.csc.CommonOps_DSCC
import org.ejml.sparse.csc.CommonOps_FSCC
import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC
import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC
import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC
import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC
import space.kscience.kmath.linear.*
import space.kscience.kmath.linear.Matrix
import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.nd.StructureFeature
import space.kscience.kmath.structures.Float64
import space.kscience.kmath.structures.Float32
import space.kscience.kmath.operations.Float64Field
import space.kscience.kmath.operations.Float32Field
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.FloatField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Float64Buffer
import space.kscience.kmath.structures.Float32Buffer
import space.kscience.kmath.structures.DoubleBuffer
import space.kscience.kmath.structures.FloatBuffer
import kotlin.reflect.KClass
import kotlin.reflect.cast""")
it.appendLine()
it.appendEjmlVector("Double", "DMatrix")
it.appendEjmlVector("Float", "FMatrix")
it.appendEjmlMatrix("Double", "DMatrix")
it.appendEjmlMatrix("Float", "FMatrix")
it.appendEjmlLinearSpace("Double", "Float64Field", "DMatrix", "DMatrixRMaj", "DMatrixRMaj", "DDRM", "DDRM", true)
it.appendEjmlLinearSpace("Float", "Float32Field", "FMatrix", "FMatrixRMaj", "FMatrixRMaj", "FDRM", "FDRM", true)
it.appendEjmlLinearSpace(
type = "Double",
kmathAlgebra = "Float64Field",
ejmlMatrixParentTypeMatrix = "DMatrix",
ejmlMatrixType = "DMatrixSparseCSC",
ejmlMatrixDenseType = "DMatrixRMaj",
ops = "DSCC",
denseOps = "DDRM",
isDense = false,
)
it.appendEjmlLinearSpace(
type = "Float",
kmathAlgebra = "Float32Field",
ejmlMatrixParentTypeMatrix = "FMatrix",
ejmlMatrixType = "FMatrixSparseCSC",
ejmlMatrixDenseType = "FMatrixRMaj",
ops = "FSCC",
denseOps = "FDRM",
isDense = false,
)
}
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- <!--
- Copyright 2018-2022 KMath contributors. - Copyright 2018-2024 KMath contributors.
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
--> -->

Before

Width:  |  Height:  |  Size: 249 KiB

After

Width:  |  Height:  |  Size: 249 KiB

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- <!--
- Copyright 2018-2022 KMath contributors. - Copyright 2018-2024 KMath contributors.
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
--> -->

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- <!--
- Copyright 2018-2022 KMath contributors. - Copyright 2018-2024 KMath contributors.
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
--> -->

Before

Width:  |  Height:  |  Size: 278 KiB

After

Width:  |  Height:  |  Size: 278 KiB

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- <!--
- Copyright 2018-2022 KMath contributors. - Copyright 2018-2024 KMath contributors.
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
--> -->

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

View File

@ -3,25 +3,10 @@
The Maven coordinates of this project are `${group}:${name}:${version}`. The Maven coordinates of this project are `${group}:${name}:${version}`.
**Gradle:** **Gradle:**
```groovy
repositories {
maven { url 'https://repo.kotlin.link' }
mavenCentral()
// development and snapshot versions
maven { url 'https://maven.pkg.jetbrains.space/spc/p/sci/dev' }
}
dependencies {
implementation '${group}:${name}:${version}'
}
```
**Gradle Kotlin DSL:**
```kotlin ```kotlin
repositories { repositories {
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
mavenCentral() mavenCentral()
// development and snapshot versions
maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev")
} }
dependencies { dependencies {

View File

@ -11,18 +11,21 @@ analog to Python's NumPy library. Later we found that kotlin is much more flexib
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like 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. experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
[Documentation site (**WIP**)](https://SciProgCentre.github.io/kmath/) [Documentation site](https://SciProgCentre.github.io/kmath/)
## Publications and talks ## Publications and talks
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2) * [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
* [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814) * [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814)
* [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103) * [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103)
* [A talk at KotlinConf 2019 about using kotlin for science](https://youtu.be/LI_5TZ7tnOE?si=4LknX41gl_YeUbIe)
* [A talk on architecture at Joker-2021 (in Russian)](https://youtu.be/1bZ2doHiRRM?si=9w953ro9yu98X_KJ)
* [The same talk in English](https://youtu.be/yP5DIc2fVwQ?si=louZzQ1dcXV6gP10)
* [A seminar on tensor API](https://youtu.be/0H99wUs0xTM?si=6c__04jrByFQtVpo)
# Goal # 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, Native and Wasm).
.
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization). * Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries. * Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
@ -59,22 +62,21 @@ ${modules}
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the 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 [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 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 reasons. Currently, Kotlin/JVM is the primary platform, however, Kotlin/Native and Kotlin/JS contributions and
feedback are also welcome. feedback are also welcome.
## Performance ## Performance
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both Calculation of performance is one of the major goals of KMath in the future, but in some cases it is impossible to achieve both
performance and flexibility. performance and flexibility.
We expect to focus on creating convenient universal API first and then work on increasing performance for specific We expect to focus on creating a 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 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. native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy.
## Requirements ## Requirements
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend using GraalVM-CE or Oracle GraalVM for execution to get better performance.
execution to get better performance.
### Repositories ### Repositories
@ -94,11 +96,7 @@ dependencies {
} }
``` ```
Gradle `6.0+` is required for multiplatform artifacts.
## Contributing ## Contributing
The project requires a lot of additional work. The most important thing we need is a feedback about what features are The project requires a lot of additional work. The most important thing we need is feedback about what features are
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with [good first issue](hhttps://github.com/SciProgCentre/kmath/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label.
marked with
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.

View File

@ -52,7 +52,7 @@ dependencies {
implementation("org.slf4j:slf4j-simple:1.7.32") implementation("org.slf4j:slf4j-simple:1.7.32")
// plotting // plotting
implementation("space.kscience:plotlykt-server:0.5.0") implementation("space.kscience:plotlykt-server:0.7.0")
} }
kotlin { kotlin {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2023 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -13,10 +13,7 @@ import space.kscience.kmath.expressions.autodiff
import space.kscience.kmath.expressions.symbol import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.asIterable import space.kscience.kmath.operations.asIterable
import space.kscience.kmath.operations.toList import space.kscience.kmath.operations.toList
import space.kscience.kmath.optimization.FunctionOptimizationTarget import space.kscience.kmath.optimization.*
import space.kscience.kmath.optimization.optimizeWith
import space.kscience.kmath.optimization.resultPoint
import space.kscience.kmath.optimization.resultValue
import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.DoubleVector
import space.kscience.kmath.real.map import space.kscience.kmath.real.map
@ -80,8 +77,9 @@ suspend fun main() {
val result = chi2.optimizeWith( val result = chi2.optimizeWith(
CMOptimizer, CMOptimizer,
mapOf(a to 1.5, b to 0.9, c to 1.0), mapOf(a to 1.5, b to 0.9, c to 1.0),
FunctionOptimizationTarget.MINIMIZE ){
) FunctionOptimizationTarget(OptimizationDirection.MINIMIZE)
}
//display a page with plot and numerical results //display a page with plot and numerical results
val page = Plotly.page { val page = Plotly.page {
@ -98,7 +96,7 @@ suspend fun main() {
scatter { scatter {
mode = ScatterMode.lines mode = ScatterMode.lines
x(x) x(x)
y(x.map { result.resultPoint[a]!! * it.pow(2) + result.resultPoint[b]!! * it + 1 }) y(x.map { result.result[a]!! * it.pow(2) + result.result[b]!! * it + 1 })
name = "fit" name = "fit"
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -7,6 +7,7 @@ package space.kscience.kmath.fit
import kotlinx.html.br import kotlinx.html.br
import kotlinx.html.h3 import kotlinx.html.h3
import space.kscience.attributes.Attributes
import space.kscience.kmath.data.XYErrorColumnarData import space.kscience.kmath.data.XYErrorColumnarData
import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.Symbol
@ -64,7 +65,7 @@ suspend fun main() {
QowOptimizer, QowOptimizer,
Double.autodiff, Double.autodiff,
mapOf(a to 0.9, b to 1.2, c to 2.0, e to 1.0, d to 1.0, e to 0.0), mapOf(a to 0.9, b to 1.2, c to 2.0, e to 1.0, d to 1.0, e to 0.0),
OptimizationParameters(a, b, c, d) attributes = Attributes(OptimizationParameters, listOf(a, b, c, d))
) { arg -> ) { arg ->
//bind variables to autodiff context //bind variables to autodiff context
val a by binding val a by binding
@ -94,13 +95,13 @@ suspend fun main() {
scatter { scatter {
mode = ScatterMode.lines mode = ScatterMode.lines
x(x) x(x)
y(x.map { result.model(result.startPoint + result.resultPoint + (Symbol.x to it)) }) y(x.map { result.model(result.startPoint + result.result + (Symbol.x to it)) })
name = "fit" name = "fit"
} }
} }
br() br()
h3 { h3 {
+"Fit result: ${result.resultPoint}" +"Fit result: ${result.result}"
} }
h3 { h3 {
+"Chi2/dof = ${result.chiSquaredOrNull!! / result.dof}" +"Chi2/dof = ${result.chiSquaredOrNull!! / result.dof}"

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -8,7 +8,6 @@ package space.kscience.kmath.functions
import space.kscience.kmath.interpolation.SplineInterpolator import space.kscience.kmath.interpolation.SplineInterpolator
import space.kscience.kmath.interpolation.interpolatePolynomials import space.kscience.kmath.interpolation.interpolatePolynomials
import space.kscience.kmath.operations.Float64Field import space.kscience.kmath.operations.Float64Field
import space.kscience.kmath.structures.Float64Buffer
import space.kscience.plotly.Plotly import space.kscience.plotly.Plotly
import space.kscience.plotly.UnstablePlotlyAPI import space.kscience.plotly.UnstablePlotlyAPI
import space.kscience.plotly.makeFile import space.kscience.plotly.makeFile
@ -24,9 +23,7 @@ fun main() {
x to sin(x) x to sin(x)
} }
val polynomial: PiecewisePolynomial<Double> = SplineInterpolator( val polynomial: PiecewisePolynomial<Double> = SplineInterpolator(Float64Field).interpolatePolynomials(data)
Float64Field, ::Float64Buffer
).interpolatePolynomials(data)
val function = polynomial.asFunction(Float64Field, 0.0) val function = polynomial.asFunction(Float64Field, 0.0)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,35 +1,30 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package space.kscience.kmath.linear package space.kscience.kmath.linear
import space.kscience.kmath.operations.algebra
import kotlin.random.Random import kotlin.random.Random
import kotlin.time.ExperimentalTime
import kotlin.time.measureTime import kotlin.time.measureTime
@OptIn(ExperimentalTime::class) fun main() = with(Float64ParallelLinearSpace) {
fun main() {
val random = Random(12224) val random = Random(12224)
val dim = 1000 val dim = 1000
//creating invertible matrix //creating invertible matrix
val matrix1 = Double.algebra.linearSpace.buildMatrix(dim, dim) { i, j -> val matrix1 = buildMatrix(dim, dim) { i, j ->
if (i <= j) random.nextDouble() else 0.0 if (i <= j) random.nextDouble() else 0.0
} }
val matrix2 = Double.algebra.linearSpace.buildMatrix(dim, dim) { i, j -> val matrix2 = buildMatrix(dim, dim) { i, j ->
if (i <= j) random.nextDouble() else 0.0 if (i <= j) random.nextDouble() else 0.0
} }
val time = measureTime { val time = measureTime {
with(Double.algebra.linearSpace) { repeat(30) {
repeat(10) {
matrix1 dot matrix2 matrix1 dot matrix2
} }
} }
}
println(time) println(time)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -0,0 +1,27 @@
/*
* Copyright 2018-2024 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.linear
import kotlin.random.Random
import kotlin.time.measureTime
fun main(): Unit = with(Float64LinearSpace) {
val random = Random(1224)
val dim = 500
//creating invertible matrix
val u = buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
val l = buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
val matrix = l dot u
val time = measureTime {
repeat(20) {
lupSolver().inverse(matrix)
}
}
println(time)
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -10,12 +10,14 @@ import space.kscience.kmath.linear.matrix
import space.kscience.kmath.nd.Float64BufferND import space.kscience.kmath.nd.Float64BufferND
import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.ShapeND
import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.nd.mutableStructureND
import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.nd.ndAlgebra
import space.kscience.kmath.viktor.ViktorStructureND
import space.kscience.kmath.viktor.viktorAlgebra import space.kscience.kmath.viktor.viktorAlgebra
import kotlin.collections.component1
import kotlin.collections.component2
fun main() { fun main() {
val viktorStructure: ViktorStructureND = Float64Field.viktorAlgebra.structureND(ShapeND(2, 2)) { (i, j) -> val viktorStructure = Float64Field.viktorAlgebra.mutableStructureND(2, 2) { (i, j) ->
if (i == j) 2.0 else 0.0 if (i == j) 2.0 else 0.0
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2023 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,3 +1,8 @@
/*
* Copyright 2018-2024 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.series package space.kscience.kmath.series
@ -13,7 +18,10 @@ import space.kscience.kmath.structures.slice
import space.kscience.plotly.* import space.kscience.plotly.*
import kotlin.math.PI import kotlin.math.PI
fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) { fun Double.Companion.seriesAlgebra() = Double.algebra.bufferAlgebra.seriesAlgebra()
fun main() = with(Double.seriesAlgebra()) {
fun Plot.plotSeries(name: String, buffer: Buffer<Double>) { fun Plot.plotSeries(name: String, buffer: Buffer<Double>) {

View File

@ -0,0 +1,50 @@
/*
* Copyright 2018-2023 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.series
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.Float64Buffer
import space.kscience.kmath.structures.asBuffer
import space.kscience.kmath.structures.toDoubleArray
import space.kscience.plotly.*
import space.kscience.plotly.models.Scatter
import space.kscience.plotly.models.ScatterMode
import kotlin.random.Random
fun main(): Unit = with(Double.seriesAlgebra()) {
val random = Random(1234)
val arrayOfRandoms = DoubleArray(20) { random.nextDouble() }
val series1: Float64Buffer = arrayOfRandoms.asBuffer()
val series2: Series<Double> = series1.moveBy(3)
val res = series2 - series1
println(res.size)
println(res)
fun Plot.series(name: String, buffer: Buffer<Double>, block: Scatter.() -> Unit = {}) {
scatter {
this.name = name
x.numbers = buffer.offsetIndices
y.doubles = buffer.toDoubleArray()
block()
}
}
Plotly.plot {
series("series1", series1)
series("series2", series2)
series("dif", res) {
mode = ScatterMode.lines
line.color("magenta")
}
}.makeFile(resourceLocation = ResourceLocation.REMOTE)
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -8,7 +8,7 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.kmath.complex.* import space.kscience.kmath.complex.*
import space.kscience.kmath.linear.transpose import space.kscience.kmath.linear.transposed
import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.nd.as2D import space.kscience.kmath.nd.as2D
import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.nd.ndAlgebra
@ -60,7 +60,7 @@ fun complexExample() {
val sum = matrix + x + 1.0 val sum = matrix + x + 1.0
//Represent the sum as 2d-structure and transpose //Represent the sum as 2d-structure and transpose
sum.as2D().transpose() sum.as2D().transposed()
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -7,6 +7,7 @@ package space.kscience.kmath.structures
import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.Float64Field import space.kscience.kmath.operations.Float64Field
import space.kscience.kmath.operations.NumbersAddOps import space.kscience.kmath.operations.NumbersAddOps
@ -52,6 +53,15 @@ class StreamDoubleFieldND(override val shape: ShapeND) : FieldND<Double, Float64
return BufferND(strides, array.asBuffer()) return BufferND(strides, array.asBuffer())
} }
override fun mutableStructureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): MutableBufferND<Double> {
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
val index = strides.index(offset)
DoubleField.initializer(index)
}.toArray()
return MutableBufferND(strides, array.asBuffer())
}
@OptIn(PerformancePitfall::class) @OptIn(PerformancePitfall::class)
override fun StructureND<Double>.map( override fun StructureND<Double>.map(
transform: Float64Field.(Double) -> Double, transform: Float64Field.(Double) -> Double,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,25 +1,23 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.kmath.nd.BufferND import space.kscience.kmath.nd.BufferND
import space.kscience.kmath.nd.ShapeND
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.operations.mapToBuffer import space.kscience.kmath.operations.mapToBuffer
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
private inline fun <T, reified R : Any> BufferND<T>.mapToBufferND( private inline fun <T, reified R : Any> BufferND<T>.mapToBufferND(
bufferFactory: BufferFactory<R> = BufferFactory.auto(), bufferFactory: BufferFactory<R> = BufferFactory(),
crossinline block: (T) -> R, crossinline block: (T) -> R,
): BufferND<R> = BufferND(indices, buffer.mapToBuffer(bufferFactory, block)) ): BufferND<R> = BufferND(indices, buffer.mapToBuffer(bufferFactory, block))
@Suppress("UNUSED_VARIABLE") @Suppress("UNUSED_VARIABLE")
fun main() { fun main() {
val n = 6000 val n = 6000
val structure = StructureND.buffered(ShapeND(n, n), Buffer.Companion::auto) { 1.0 } val structure = BufferND(n, n) { 1.0 }
structure.mapToBufferND { it + 1 } // warm-up structure.mapToBufferND { it + 1 } // warm-up
val time1 = measureTimeMillis { val res = structure.mapToBufferND { it + 1 } } val time1 = measureTimeMillis { val res = structure.mapToBufferND { it + 1 } }
println("Structure mapping finished in $time1 millis") println("Structure mapping finished in $time1 millis")

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -13,7 +13,7 @@ import space.kscience.kmath.operations.withSize
inline fun <reified R : Any> MutableBuffer.Companion.same( inline fun <reified R : Any> MutableBuffer.Companion.same(
n: Int, n: Int,
value: R value: R
): MutableBuffer<R> = auto(n) { value } ): MutableBuffer<R> = MutableBuffer(n) { value }
fun main() { fun main() {

View File

@ -0,0 +1,26 @@
/*
* Copyright 2018-2023 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.structures
import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.algebra
@OptIn(PerformancePitfall::class)
fun main(): Unit = with(Double.algebra.ndAlgebra) {
val structure: MutableStructure2D<Double> = mutableStructureND(ShapeND(2, 2)) { (i, j) ->
i.toDouble() + j.toDouble()
}.as2D()
structure[0, 1] = -2.0
val structure2 = mutableStructureND(2, 2) { (i, j) -> i.toDouble() + j.toDouble() }.as2D()
structure2[0, 1] = 2.0
println(structure + structure2)
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -15,7 +15,7 @@ private fun DMatrixContext<Double, *>.simple() {
val m2 = produce<D3, D2> { i, j -> (i + j).toDouble() } val m2 = produce<D3, D2> { i, j -> (i + j).toDouble() }
//Dimension-safe addition //Dimension-safe addition
m1.transpose() + m2 m1.transposed() + m2
} }
private object D5 : Dimension { private object D5 : Dimension {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2023 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2023 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2023 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2023 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2023 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2023 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -10,19 +10,8 @@ Extensions to MST API: transformations, dynamic compilation and visualization.
## Artifact: ## Artifact:
The Maven coordinates of this project are `space.kscience:kmath-ast:0.4.0-dev-1`. The Maven coordinates of this project are `space.kscience:kmath-ast:0.4.0-dev-3`.
**Gradle Groovy:**
```groovy
repositories {
maven { url 'https://repo.kotlin.link' }
mavenCentral()
}
dependencies {
implementation 'space.kscience:kmath-ast:0.4.0-dev-1'
}
```
**Gradle Kotlin DSL:** **Gradle Kotlin DSL:**
```kotlin ```kotlin
repositories { repositories {
@ -31,7 +20,7 @@ repositories {
} }
dependencies { dependencies {
implementation("space.kscience:kmath-ast:0.4.0-dev-1") implementation("space.kscience:kmath-ast:0.4.0-dev-3")
} }
``` ```

View File

@ -31,7 +31,7 @@ kscience{
kotlin { kotlin {
js { js {
nodejs { nodejs {
testTask { testTask{
useMocha().timeout = "0" useMocha().timeout = "0"
} }
} }

View File

@ -1,10 +1,12 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package space.kscience.kmath.ast package space.kscience.kmath.ast
import space.kscience.attributes.SafeType
import space.kscience.attributes.WithType
import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.Algebra
@ -15,7 +17,7 @@ import space.kscience.kmath.operations.NumericAlgebra
* *
* @param T the type. * @param T the type.
*/ */
public sealed interface TypedMst<T> { public sealed interface TypedMst<T> : WithType<T> {
/** /**
* A node containing a unary operation. * A node containing a unary operation.
* *
@ -24,8 +26,13 @@ public sealed interface TypedMst<T> {
* @property function The function implementing this operation. * @property function The function implementing this operation.
* @property value The argument of this operation. * @property value The argument of this operation.
*/ */
public class Unary<T>(public val operation: String, public val function: (T) -> T, public val value: TypedMst<T>) : public class Unary<T>(
TypedMst<T> { public val operation: String,
public val function: (T) -> T,
public val value: TypedMst<T>,
) : TypedMst<T> {
override val type: SafeType<T> get() = value.type
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other == null || this::class != other::class) return false if (other == null || this::class != other::class) return false
@ -59,6 +66,13 @@ public sealed interface TypedMst<T> {
public val left: TypedMst<T>, public val left: TypedMst<T>,
public val right: TypedMst<T>, public val right: TypedMst<T>,
) : TypedMst<T> { ) : TypedMst<T> {
init {
require(left.type==right.type){"Left and right expressions must be of the same type"}
}
override val type: SafeType<T> get() = left.type
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other == null || this::class != other::class) return false if (other == null || this::class != other::class) return false
@ -89,7 +103,12 @@ public sealed interface TypedMst<T> {
* @property value The held value. * @property value The held value.
* @property number The number this value corresponds. * @property number The number this value corresponds.
*/ */
public class Constant<T>(public val value: T, public val number: Number?) : TypedMst<T> { public class Constant<T>(
override val type: SafeType<T>,
public val value: T,
public val number: Number?,
) : TypedMst<T> {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other == null || this::class != other::class) return false if (other == null || this::class != other::class) return false
@ -114,7 +133,7 @@ public sealed interface TypedMst<T> {
* @param T the type. * @param T the type.
* @property symbol The symbol of the variable. * @property symbol The symbol of the variable.
*/ */
public class Variable<T>(public val symbol: Symbol) : TypedMst<T> { public class Variable<T>(override val type: SafeType<T>, public val symbol: Symbol) : TypedMst<T> {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other == null || this::class != other::class) return false if (other == null || this::class != other::class) return false
@ -167,6 +186,7 @@ public fun <T> TypedMst<T>.interpret(algebra: Algebra<T>, vararg arguments: Pair
/** /**
* Interpret this [TypedMst] node as expression. * Interpret this [TypedMst] node as expression.
*/ */
public fun <T : Any> TypedMst<T>.toExpression(algebra: Algebra<T>): Expression<T> = Expression { arguments -> public fun <T : Any> TypedMst<T>.toExpression(algebra: Algebra<T>): Expression<T> =
Expression(algebra.type) { arguments ->
interpret(algebra, arguments) interpret(algebra, arguments)
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@ -16,6 +16,7 @@ import space.kscience.kmath.operations.bindSymbolOrNull
*/ */
public fun <T> MST.evaluateConstants(algebra: Algebra<T>): TypedMst<T> = when (this) { public fun <T> MST.evaluateConstants(algebra: Algebra<T>): TypedMst<T> = when (this) {
is MST.Numeric -> TypedMst.Constant( is MST.Numeric -> TypedMst.Constant(
algebra.type,
(algebra as? NumericAlgebra<T>)?.number(value) ?: error("Numeric nodes are not supported by $algebra"), (algebra as? NumericAlgebra<T>)?.number(value) ?: error("Numeric nodes are not supported by $algebra"),
value, value,
) )
@ -27,7 +28,7 @@ public fun <T> MST.evaluateConstants(algebra: Algebra<T>): TypedMst<T> = when (t
arg.value, arg.value,
) )
TypedMst.Constant(value, if (value is Number) value else null) TypedMst.Constant(algebra.type, value, if (value is Number) value else null)
} }
else -> TypedMst.Unary(operation, algebra.unaryOperationFunction(operation), arg) else -> TypedMst.Unary(operation, algebra.unaryOperationFunction(operation), arg)
@ -59,7 +60,7 @@ public fun <T> MST.evaluateConstants(algebra: Algebra<T>): TypedMst<T> = when (t
) )
} }
TypedMst.Constant(value, if (value is Number) value else null) TypedMst.Constant(algebra.type, value, if (value is Number) value else null)
} }
algebra is NumericAlgebra && left is TypedMst.Constant && left.number != null -> TypedMst.Binary( algebra is NumericAlgebra && left is TypedMst.Constant && left.number != null -> TypedMst.Binary(
@ -84,8 +85,8 @@ public fun <T> MST.evaluateConstants(algebra: Algebra<T>): TypedMst<T> = when (t
val boundSymbol = algebra.bindSymbolOrNull(this) val boundSymbol = algebra.bindSymbolOrNull(this)
if (boundSymbol != null) if (boundSymbol != null)
TypedMst.Constant(boundSymbol, if (boundSymbol is Number) boundSymbol else null) TypedMst.Constant(algebra.type, boundSymbol, if (boundSymbol is Number) boundSymbol else null)
else else
TypedMst.Variable(this) TypedMst.Variable(algebra.type, this)
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022 KMath contributors. * Copyright 2018-2024 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */

Some files were not shown because too many files have changed in this diff Show More