Compare commits
No commits in common. "fd9da63ef98f9cd75f4b21f19733fc5c9ebcbcd8" and "9e3fd240b82e9874517781a523620d5a862b19bb" have entirely different histories.
fd9da63ef9
...
9e3fd240b8
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,7 +5,6 @@ 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)
|
||||||
|
44
CHANGELOG.md
44
CHANGELOG.md
@ -3,33 +3,14 @@
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
## 0.4.0-dev-3 - 2024-02-18
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Reification. Explicit `SafeType` for algebras and buffers.
|
- Reification. Explicit `SafeType` for algebras and buffers.
|
||||||
- Integer division algebras.
|
- Integer division algebras.
|
||||||
- Float32 geometries.
|
- Float32 geometries.
|
||||||
- New Attributes-kt module that could be used as stand-alone. It declares. type-safe attributes containers.
|
- New Attributes-kt module that could be used as stand-alone. It declares. type-safe attributes containers.
|
||||||
- Explicit `mutableStructureND` builders for mutable structures.
|
- Explicit `mutableStructureND` builders for mutable structures.
|
||||||
- `Buffer.asList()` zero-copy transformation.
|
- `Buffer.asList()` zero-copy transformation.
|
||||||
- Wasm support.
|
|
||||||
- Parallel implementation of `LinearSpace` for Float64
|
|
||||||
- Parallel buffer factories
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Default naming for algebra and buffers now uses IntXX/FloatXX notation instead of Java types.
|
- Default naming for algebra and buffers now uses IntXX/FloatXX notation instead of Java types.
|
||||||
- Remove unnecessary inlines in basic algebras.
|
- Remove unnecessary inlines in basic algebras.
|
||||||
- QuaternionField -> QuaternionAlgebra and does not implement `Field` anymore since it is non-commutative
|
- QuaternionField -> QuaternionAlgebra and does not implement `Field` anymore since it is non-commutative
|
||||||
@ -40,23 +21,18 @@
|
|||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
- ND4J engine
|
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- `asPolynomial` function due to scope pollution
|
- `asPolynomial` function due to scope pollution
|
||||||
- Codegend for ejml (450 lines of codegen for 1000 lines of code is too much)
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Median statistics
|
- Median statistics
|
||||||
- Complex power of negative real numbers
|
- Complex power of negative real numbers
|
||||||
- Add proper mutability for MutableBufferND rows and columns
|
|
||||||
|
### Security
|
||||||
|
|
||||||
## 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
|
||||||
@ -66,7 +42,6 @@
|
|||||||
- Algebra now has an obligatory `bufferFactory` (#477).
|
- Algebra now has an obligatory `bufferFactory` (#477).
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Removed marker `Vector` type for geometry
|
- 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
|
||||||
@ -79,14 +54,12 @@
|
|||||||
- 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
|
||||||
@ -111,7 +84,6 @@
|
|||||||
- 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.
|
||||||
@ -145,11 +117,9 @@
|
|||||||
- `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.
|
||||||
@ -160,14 +130,12 @@
|
|||||||
- 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)
|
||||||
@ -187,7 +155,6 @@
|
|||||||
- 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`)
|
||||||
@ -212,7 +179,6 @@
|
|||||||
- 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.
|
||||||
@ -221,13 +187,11 @@
|
|||||||
- 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)
|
||||||
@ -245,7 +209,6 @@
|
|||||||
- 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.
|
||||||
@ -257,7 +220,6 @@
|
|||||||
- 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)
|
||||||
|
68
README.md
68
README.md
@ -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/mipt-npm/p/sci/maven/space/kscience/)
|
[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/spc/p/sci/maven/space/kscience/)
|
||||||
|
|
||||||
# KMath
|
# KMath
|
||||||
|
|
||||||
@ -11,21 +11,18 @@ 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](https://SciProgCentre.github.io/kmath/)
|
[Documentation site (**WIP**)](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, Native and Wasm).
|
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
|
||||||
|
.
|
||||||
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
|
* Provide 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.
|
||||||
|
|
||||||
@ -56,20 +53,18 @@ module definitions below. The module stability could have the following levels:
|
|||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
|
|
||||||
### [attributes-kt](attributes-kt)
|
|
||||||
> An API and basic implementation for arranging objects in a continuous memory block.
|
|
||||||
>
|
|
||||||
> **Maturity**: DEVELOPMENT
|
|
||||||
|
|
||||||
### [benchmarks](benchmarks)
|
### [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
|
||||||
>
|
>
|
||||||
@ -81,7 +76,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
|
||||||
|
|
||||||
@ -113,15 +108,17 @@ 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
|
||||||
>
|
>
|
||||||
@ -145,7 +142,7 @@ One can still use generic algebras though.
|
|||||||
|
|
||||||
|
|
||||||
### [kmath-functions](kmath-functions)
|
### [kmath-functions](kmath-functions)
|
||||||
> Functions, integration and interpolation
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
>
|
>
|
||||||
@ -158,28 +155,31 @@ 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
|
||||||
|
|
||||||
|
|
||||||
### [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
|
||||||
@ -210,24 +210,27 @@ 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
|
||||||
>
|
>
|
||||||
@ -238,11 +241,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
|
||||||
|
|
||||||
@ -252,21 +256,22 @@ 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, Kotlin/JVM is the primary platform, however, Kotlin/Native and Kotlin/JS contributions and
|
reasons. Currently, the 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 of performance is one of the major goals of KMath in the future, but in some cases it is impossible to achieve both
|
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both
|
||||||
performance and flexibility.
|
performance and flexibility.
|
||||||
|
|
||||||
We expect to focus on creating a convenient universal API first and then work on increasing performance for specific
|
We expect to focus on creating convenient universal API first and then work on increasing performance for specific
|
||||||
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
|
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 using GraalVM-CE or Oracle GraalVM for execution to get better performance.
|
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for
|
||||||
|
execution to get better performance.
|
||||||
|
|
||||||
### Repositories
|
### Repositories
|
||||||
|
|
||||||
@ -286,7 +291,10 @@ 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 feedback about what features are
|
The project requires a lot of additional work. The most important thing we need is a feedback about what features are
|
||||||
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with [good first issue](hhttps://github.com/SciProgCentre/kmath/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label.
|
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
|
||||||
|
marked with [waiting for a hero](https://github.com/SciProgCentre/kmath/labels/waiting%20for%20a%20hero) label.
|
@ -1,4 +0,0 @@
|
|||||||
# Module attributes-kt
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
|||||||
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 fun get (Lspace/kscience/attributes/Attribute;)Ljava/lang/Object;
|
|
||||||
public abstract fun getContent ()Ljava/util/Map;
|
|
||||||
public fun getKeys ()Ljava/util/Set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/attributes/Attributes$Companion {
|
|
||||||
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 final fun from (Lspace/kscience/attributes/Attributes;)V
|
|
||||||
public fun getContent ()Ljava/util/Map;
|
|
||||||
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 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;
|
|
||||||
}
|
|
||||||
|
|
@ -2,8 +2,6 @@ plugins {
|
|||||||
id("space.kscience.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
kscience {
|
kscience {
|
||||||
jvm()
|
jvm()
|
||||||
js()
|
js()
|
||||||
|
@ -5,9 +5,6 @@
|
|||||||
|
|
||||||
package space.kscience.attributes
|
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>
|
public interface Attribute<T>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,8 +13,7 @@ public interface AttributeContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A scope, where attribute keys could be resolved.
|
* A scope, where attribute keys could be resolved
|
||||||
* [O] is used only to resolve types in compile-time.
|
|
||||||
*/
|
*/
|
||||||
public interface AttributeScope<O>
|
public interface AttributeScope<O>
|
||||||
|
|
||||||
|
@ -11,19 +11,10 @@ import kotlin.jvm.JvmInline
|
|||||||
* A set of attributes. The implementation must guarantee that [content] keys correspond to its value types.
|
* A set of attributes. The implementation must guarantee that [content] keys correspond to its value types.
|
||||||
*/
|
*/
|
||||||
public interface Attributes {
|
public interface Attributes {
|
||||||
/**
|
|
||||||
* Raw content for this [Attributes]
|
|
||||||
*/
|
|
||||||
public val content: Map<out Attribute<*>, Any?>
|
public val content: Map<out Attribute<*>, Any?>
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute keys contained in this [Attributes]
|
|
||||||
*/
|
|
||||||
public val keys: Set<Attribute<*>> get() = content.keys
|
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")
|
@Suppress("UNCHECKED_CAST")
|
||||||
public operator fun <T> get(attribute: Attribute<T>): T? = content[attribute] as? T
|
public operator fun <T> get(attribute: Attribute<T>): T? = content[attribute] as? T
|
||||||
|
|
||||||
|
@ -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.getValue(x)
|
val x = args[x]!!
|
||||||
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,12 @@ 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
|
||||||
|
|
||||||
@ -71,12 +72,12 @@ internal class DotBenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,8 +87,12 @@ internal class DotBenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun parallelDot(blackhole: Blackhole) = with(Float64ParallelLinearSpace) {
|
fun doubleDot(blackhole: Blackhole) = with(Float64Field.linearSpace) {
|
||||||
blackhole.consume(matrix1 dot matrix2)
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun doubleTensorDot(blackhole: Blackhole) = DoubleTensorAlgebra.invoke {
|
||||||
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ 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
|
||||||
|
|
||||||
@ -39,19 +38,16 @@ internal class MatrixInverseBenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun kmathParallelLupInversion(blackhole: Blackhole) {
|
fun cmLUPInversion(blackhole: Blackhole) {
|
||||||
blackhole.consume(Double.algebra.linearSpace.parallel.lupSolver().inverse(matrix))
|
CMLinearSpace {
|
||||||
|
blackhole.consume(lupSolver().inverse(matrix))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun cmLUPInversion(blackhole: Blackhole) = CMLinearSpace {
|
fun ejmlInverse(blackhole: Blackhole) {
|
||||||
blackhole.consume(lupSolver().inverse(matrix))
|
EjmlLinearSpaceDDRM {
|
||||||
|
blackhole.consume(matrix.toEjml().inverted())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Benchmark
|
|
||||||
fun ejmlInverse(blackhole: Blackhole) = EjmlLinearSpaceDDRM {
|
|
||||||
blackhole.consume(matrix.toEjml().inverted())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.7.6"
|
id("org.jetbrains.kotlinx.kover") version "0.6.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
@ -14,7 +14,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.4.0"
|
version = "0.4.0-dev-3"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
@ -34,7 +34,7 @@ subprojects {
|
|||||||
localDirectory.set(kotlinDir)
|
localDirectory.set(kotlinDir)
|
||||||
|
|
||||||
remoteUrl.set(
|
remoteUrl.set(
|
||||||
uri("https://github.com/SciProgCentre/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath").toURL()
|
java.net.URL("https://github.com/SciProgCentre/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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:$benchmarksVersion")
|
api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.4.9")
|
||||||
//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)
|
||||||
|
@ -0,0 +1,443 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@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 val type: SafeType<${type}> get() = safeTypeOf()
|
||||||
|
|
||||||
|
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 val type: SafeType<${type}> get() = safeTypeOf()
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
override val type: SafeType<${type}> get() = safeTypeOf()
|
||||||
|
|
||||||
|
@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> · [b]*.
|
||||||
|
*
|
||||||
|
* @param a the base matrix.
|
||||||
|
* @param b n by p matrix.
|
||||||
|
* @return the solution for *x* that is n by p.
|
||||||
|
*/
|
||||||
|
public fun solve(a: Matrix<${type}>, b: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||||
|
val res = ${ejmlMatrixType}(1, 1)
|
||||||
|
CommonOps_${ops}.solve(${ejmlMatrixType}(a.toEjml().origin), ${ejmlMatrixType}(b.toEjml().origin), res)
|
||||||
|
return res.wrapMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solves for *x* in the following equation: *x = [a] <sup>-1</sup> · [b]*.
|
||||||
|
*
|
||||||
|
* @param a the base matrix.
|
||||||
|
* @param b n by p vector.
|
||||||
|
* @return the solution for *x* that is n by p.
|
||||||
|
*/
|
||||||
|
public fun solve(a: Matrix<${type}>, b: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||||
|
val res = ${ejmlMatrixType}(1, 1)
|
||||||
|
CommonOps_${ops}.solve(${ejmlMatrixType}(a.toEjml().origin), ${ejmlMatrixType}(b.toEjml().origin), res)
|
||||||
|
return Ejml${type}Vector(res)
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
appendLine(text)
|
||||||
|
appendLine()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates routine EJML classes.
|
||||||
|
*/
|
||||||
|
fun ejmlCodegen(outputFile: String): Unit = File(outputFile).run {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
|
||||||
|
writer().use {
|
||||||
|
it.appendLine("/*")
|
||||||
|
it.appendLine(" * Copyright 2018-2024 KMath contributors.")
|
||||||
|
it.appendLine(" * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.")
|
||||||
|
it.appendLine(" */")
|
||||||
|
it.appendLine()
|
||||||
|
it.appendLine("/* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */")
|
||||||
|
it.appendLine()
|
||||||
|
it.appendLine("package space.kscience.kmath.ejml")
|
||||||
|
it.appendLine()
|
||||||
|
it.appendLine("""import org.ejml.data.*
|
||||||
|
import org.ejml.dense.row.CommonOps_DDRM
|
||||||
|
import org.ejml.dense.row.CommonOps_FDRM
|
||||||
|
import org.ejml.dense.row.factory.DecompositionFactory_DDRM
|
||||||
|
import org.ejml.dense.row.factory.DecompositionFactory_FDRM
|
||||||
|
import org.ejml.sparse.FillReducing
|
||||||
|
import org.ejml.sparse.csc.CommonOps_DSCC
|
||||||
|
import org.ejml.sparse.csc.CommonOps_FSCC
|
||||||
|
import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC
|
||||||
|
import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC
|
||||||
|
import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC
|
||||||
|
import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC
|
||||||
|
import space.kscience.attributes.SafeType
|
||||||
|
import space.kscience.attributes.safeTypeOf
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
15
docs/templates/ARTIFACT-TEMPLATE.md
vendored
15
docs/templates/ARTIFACT-TEMPLATE.md
vendored
@ -3,10 +3,25 @@
|
|||||||
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 {
|
||||||
|
17
docs/templates/README-TEMPLATE.md
vendored
17
docs/templates/README-TEMPLATE.md
vendored
@ -11,21 +11,18 @@ 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](https://SciProgCentre.github.io/kmath/)
|
[Documentation site (**WIP**)](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, Native and Wasm).
|
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
|
||||||
|
.
|
||||||
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
|
* Provide 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.
|
||||||
|
|
||||||
@ -76,7 +73,7 @@ native/SciPy (mostly due to boxing operations on primitive numbers). The best pe
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
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.
|
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend using GraalVM-CE 11/17 for execution to get better performance.
|
||||||
|
|
||||||
### Repositories
|
### Repositories
|
||||||
|
|
||||||
@ -98,5 +95,7 @@ dependencies {
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
The project requires a lot of additional work. The most important thing we need is feedback about what features are
|
The project requires a lot of additional work. The most important thing we need is a feedback about what features are
|
||||||
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with [good first issue](hhttps://github.com/SciProgCentre/kmath/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label.
|
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.
|
@ -13,7 +13,10 @@ 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.*
|
import space.kscience.kmath.optimization.FunctionOptimizationTarget
|
||||||
|
import space.kscience.kmath.optimization.optimizeWith
|
||||||
|
import space.kscience.kmath.optimization.result
|
||||||
|
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
|
||||||
@ -77,9 +80,8 @@ 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 {
|
||||||
|
@ -7,7 +7,6 @@ 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
|
||||||
@ -65,7 +64,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),
|
||||||
attributes = Attributes(OptimizationParameters, listOf(a, b, c, d))
|
OptimizationParameters(a, b, c, d)
|
||||||
) { arg ->
|
) { arg ->
|
||||||
//bind variables to autodiff context
|
//bind variables to autodiff context
|
||||||
val a by binding
|
val a by binding
|
||||||
|
@ -8,6 +8,7 @@ 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
|
||||||
@ -23,7 +24,9 @@ fun main() {
|
|||||||
x to sin(x)
|
x to sin(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
val polynomial: PiecewisePolynomial<Double> = SplineInterpolator(Float64Field).interpolatePolynomials(data)
|
val polynomial: PiecewisePolynomial<Double> = SplineInterpolator(
|
||||||
|
Float64Field, ::Float64Buffer
|
||||||
|
).interpolatePolynomials(data)
|
||||||
|
|
||||||
val function = polynomial.asFunction(Float64Field, 0.0)
|
val function = polynomial.asFunction(Float64Field, 0.0)
|
||||||
|
|
||||||
|
@ -5,24 +5,29 @@
|
|||||||
|
|
||||||
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
|
||||||
|
|
||||||
fun main() = with(Float64ParallelLinearSpace) {
|
@OptIn(ExperimentalTime::class)
|
||||||
|
fun main() {
|
||||||
val random = Random(12224)
|
val random = Random(12224)
|
||||||
val dim = 1000
|
val dim = 1000
|
||||||
|
|
||||||
//creating invertible matrix
|
//creating invertible matrix
|
||||||
val matrix1 = buildMatrix(dim, dim) { i, j ->
|
val matrix1 = Double.algebra.linearSpace.buildMatrix(dim, dim) { i, j ->
|
||||||
if (i <= j) random.nextDouble() else 0.0
|
if (i <= j) random.nextDouble() else 0.0
|
||||||
}
|
}
|
||||||
val matrix2 = buildMatrix(dim, dim) { i, j ->
|
val matrix2 = Double.algebra.linearSpace.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 {
|
||||||
repeat(30) {
|
with(Double.algebra.linearSpace) {
|
||||||
matrix1 dot matrix2
|
repeat(10) {
|
||||||
|
matrix1 dot matrix2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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)
|
|
||||||
}
|
|
@ -7,7 +7,7 @@ package space.kscience.kmath.series
|
|||||||
|
|
||||||
|
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.Float64Buffer
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
import space.kscience.kmath.structures.asBuffer
|
import space.kscience.kmath.structures.asBuffer
|
||||||
import space.kscience.kmath.structures.toDoubleArray
|
import space.kscience.kmath.structures.toDoubleArray
|
||||||
import space.kscience.plotly.*
|
import space.kscience.plotly.*
|
||||||
@ -21,7 +21,7 @@ fun main(): Unit = with(Double.seriesAlgebra()) {
|
|||||||
|
|
||||||
val arrayOfRandoms = DoubleArray(20) { random.nextDouble() }
|
val arrayOfRandoms = DoubleArray(20) { random.nextDouble() }
|
||||||
|
|
||||||
val series1: Float64Buffer = arrayOfRandoms.asBuffer()
|
val series1: DoubleBuffer = arrayOfRandoms.asBuffer()
|
||||||
val series2: Series<Double> = series1.moveBy(3)
|
val series2: Series<Double> = series1.moveBy(3)
|
||||||
|
|
||||||
val res = series2 - series1
|
val res = series2 - series1
|
||||||
@ -42,7 +42,7 @@ fun main(): Unit = with(Double.seriesAlgebra()) {
|
|||||||
Plotly.plot {
|
Plotly.plot {
|
||||||
series("series1", series1)
|
series("series1", series1)
|
||||||
series("series2", series2)
|
series("series2", series2)
|
||||||
series("dif", res) {
|
series("dif", res){
|
||||||
mode = ScatterMode.lines
|
mode = ScatterMode.lines
|
||||||
line.color("magenta")
|
line.color("magenta")
|
||||||
}
|
}
|
||||||
|
@ -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.transposed
|
import space.kscience.kmath.linear.transpose
|
||||||
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().transposed()
|
sum.as2D().transpose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ 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
|
||||||
|
@ -6,18 +6,20 @@
|
|||||||
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(),
|
bufferFactory: BufferFactory<R> = BufferFactory.auto(),
|
||||||
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 = BufferND(n, n) { 1.0 }
|
val structure = StructureND.buffered(ShapeND(n, n), Buffer.Companion::auto) { 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")
|
||||||
|
@ -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> = MutableBuffer(n) { value }
|
): MutableBuffer<R> = auto(n) { value }
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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.6-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -10,8 +10,19 @@ 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-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-ast:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**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 {
|
||||||
@ -20,7 +31,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-ast:0.4.0-dev-3")
|
implementation("space.kscience:kmath-ast:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -6,8 +6,19 @@ Commons math binding for kmath
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-commons:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-commons:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-commons:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -16,6 +27,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-commons:0.4.0-dev-3")
|
implementation("space.kscience:kmath-commons:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -7,20 +7,16 @@ package space.kscience.kmath.commons.linear
|
|||||||
|
|
||||||
import org.apache.commons.math3.linear.*
|
import org.apache.commons.math3.linear.*
|
||||||
import org.apache.commons.math3.linear.LUDecomposition
|
import org.apache.commons.math3.linear.LUDecomposition
|
||||||
import org.apache.commons.math3.linear.SingularValueDecomposition
|
|
||||||
import space.kscience.attributes.SafeType
|
import space.kscience.attributes.SafeType
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.linear.*
|
import space.kscience.kmath.linear.*
|
||||||
import space.kscience.kmath.linear.CholeskyDecomposition
|
|
||||||
import space.kscience.kmath.linear.QRDecomposition
|
|
||||||
import space.kscience.kmath.nd.Structure2D
|
import space.kscience.kmath.nd.Structure2D
|
||||||
import space.kscience.kmath.nd.StructureAttribute
|
import space.kscience.kmath.nd.StructureAttribute
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.Float64Field
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.Float64
|
import space.kscience.kmath.structures.Float64Buffer
|
||||||
import space.kscience.kmath.structures.IntBuffer
|
import kotlin.reflect.cast
|
||||||
import space.kscience.kmath.structures.asBuffer
|
|
||||||
|
|
||||||
public class CMMatrix(public val origin: RealMatrix) : Matrix<Double> {
|
public class CMMatrix(public val origin: RealMatrix) : Matrix<Double> {
|
||||||
override val type: SafeType<Double> get() = DoubleField.type
|
override val type: SafeType<Double> get() = DoubleField.type
|
||||||
@ -113,44 +109,45 @@ public object CMLinearSpace : LinearSpace<Double, Float64Field> {
|
|||||||
|
|
||||||
val origin = structure.toCM().origin
|
val origin = structure.toCM().origin
|
||||||
|
|
||||||
val raw: Any? = when (attribute) {
|
return when (attribute) {
|
||||||
IsDiagonal -> if (origin is DiagonalMatrix) Unit else null
|
IsDiagonal -> if (origin is DiagonalMatrix) IsDiagonal else null
|
||||||
Determinant -> LUDecomposition(origin).determinant
|
Determinant -> LUDecomposition(origin).determinant
|
||||||
|
LUP -> GenericLupDecomposition {
|
||||||
LUP -> object : LupDecomposition<Float64> {
|
private val lup by lazy { LUDecomposition(origin) }
|
||||||
val lup by lazy { LUDecomposition(origin) }
|
override val determinant: Double by lazy { lup.determinant }
|
||||||
override val pivot: IntBuffer get() = lup.pivot.asBuffer()
|
override val l: Matrix<Double> by lazy<Matrix<Double>> { CMMatrix(lup.l).withAttribute(LowerTriangular) }
|
||||||
override val l: Matrix<Float64> get() = lup.l.wrap()
|
override val u: Matrix<Double> by lazy<Matrix<Double>> { CMMatrix(lup.u).withAttribute(UpperTriangular) }
|
||||||
override val u: Matrix<Float64> get() = lup.u.wrap()
|
override val p: Matrix<Double> by lazy { CMMatrix(lup.p) }
|
||||||
}
|
}
|
||||||
|
|
||||||
Cholesky -> object : CholeskyDecomposition<Float64> {
|
CholeskyDecompositionAttribute -> object : CholeskyDecompositionAttribute<Double> {
|
||||||
val cmCholesky by lazy { org.apache.commons.math3.linear.CholeskyDecomposition(origin) }
|
override val l: Matrix<Double> by lazy<Matrix<Double>> {
|
||||||
override val l: Matrix<Double> get() = cmCholesky.l.wrap()
|
val cholesky = CholeskyDecomposition(origin)
|
||||||
|
CMMatrix(cholesky.l).withAttribute(LowerTriangular)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QR -> object : QRDecomposition<Float64> {
|
QRDecompositionAttribute -> object : QRDecompositionAttribute<Double> {
|
||||||
val cmQr by lazy { org.apache.commons.math3.linear.QRDecomposition(origin) }
|
private val qr by lazy { QRDecomposition(origin) }
|
||||||
override val q: Matrix<Float64> get() = cmQr.q.wrap().withAttribute(OrthogonalAttribute)
|
override val q: Matrix<Double> by lazy<Matrix<Double>> {
|
||||||
override val r: Matrix<Float64> get() = cmQr.r.wrap().withAttribute(UpperTriangular)
|
CMMatrix(qr.q).withAttribute(
|
||||||
|
OrthogonalAttribute
|
||||||
|
)
|
||||||
|
}
|
||||||
|
override val r: Matrix<Double> by lazy<Matrix<Double>> { CMMatrix(qr.r).withAttribute(UpperTriangular) }
|
||||||
}
|
}
|
||||||
|
|
||||||
SVD -> object : space.kscience.kmath.linear.SingularValueDecomposition<Float64> {
|
SVDAttribute -> object : SVDAttribute<Double> {
|
||||||
val cmSvd by lazy { SingularValueDecomposition(origin) }
|
private val sv by lazy { SingularValueDecomposition(origin) }
|
||||||
|
override val u: Matrix<Double> by lazy { CMMatrix(sv.u) }
|
||||||
override val u: Matrix<Float64> get() = cmSvd.u.wrap()
|
override val s: Matrix<Double> by lazy { CMMatrix(sv.s) }
|
||||||
override val s: Matrix<Float64> get() = cmSvd.s.wrap()
|
override val v: Matrix<Double> by lazy { CMMatrix(sv.v) }
|
||||||
override val v: Matrix<Float64> get() = cmSvd.v.wrap()
|
override val singularValues: Point<Double> by lazy { Float64Buffer(sv.singularValues) }
|
||||||
override val singularValues: Point<Float64> get() = cmSvd.singularValues.asBuffer()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}?.let(type::cast)
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return raw as V?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = CMMatrix(origin.add(other.origin))
|
public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = CMMatrix(origin.add(other.origin))
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
@file:OptIn(UnstableKMathAPI::class)
|
@file:OptIn(UnstableKMathAPI::class)
|
||||||
|
|
||||||
package space.kscience.kmath.commons.optimization
|
package space.kscience.kmath.commons.optimization
|
||||||
|
|
||||||
import org.apache.commons.math3.optim.*
|
import org.apache.commons.math3.optim.*
|
||||||
@ -21,6 +20,7 @@ import space.kscience.kmath.expressions.Symbol
|
|||||||
import space.kscience.kmath.expressions.SymbolIndexer
|
import space.kscience.kmath.expressions.SymbolIndexer
|
||||||
import space.kscience.kmath.expressions.derivative
|
import space.kscience.kmath.expressions.derivative
|
||||||
import space.kscience.kmath.expressions.withSymbols
|
import space.kscience.kmath.expressions.withSymbols
|
||||||
|
import space.kscience.kmath.misc.log
|
||||||
import space.kscience.kmath.optimization.*
|
import space.kscience.kmath.optimization.*
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@ -28,7 +28,7 @@ import kotlin.reflect.KClass
|
|||||||
public operator fun PointValuePair.component1(): DoubleArray = point
|
public operator fun PointValuePair.component1(): DoubleArray = point
|
||||||
public operator fun PointValuePair.component2(): Double = value
|
public operator fun PointValuePair.component2(): Double = value
|
||||||
|
|
||||||
public object CMOptimizerEngine : OptimizationAttribute<() -> MultivariateOptimizer>
|
public object CMOptimizerEngine: OptimizationAttribute<() -> MultivariateOptimizer>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a Commons-maths optimization engine
|
* Specify a Commons-maths optimization engine
|
||||||
@ -37,7 +37,7 @@ public fun AttributesBuilder<FunctionOptimization<Double>>.cmEngine(optimizerBui
|
|||||||
set(CMOptimizerEngine, optimizerBuilder)
|
set(CMOptimizerEngine, optimizerBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
public object CMOptimizerData : SetAttribute<SymbolIndexer.() -> OptimizationData>
|
public object CMOptimizerData: SetAttribute<SymbolIndexer.() -> OptimizationData>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify Commons-maths optimization data.
|
* Specify Commons-maths optimization data.
|
||||||
@ -118,24 +118,21 @@ public object CMOptimizer : Optimizer<Double, FunctionOptimization<Double>> {
|
|||||||
|
|
||||||
val logger = problem.attributes[OptimizationLog]
|
val logger = problem.attributes[OptimizationLog]
|
||||||
|
|
||||||
problem.attributes[CMOptimizerData]?.let { builders: Set<SymbolIndexer.() -> OptimizationData> ->
|
for (feature in problem.attributes) {
|
||||||
builders.forEach { dataBuilder ->
|
when (feature) {
|
||||||
addOptimizationData(dataBuilder())
|
is CMOptimizerData -> feature.data.forEach { dataBuilder ->
|
||||||
}
|
addOptimizationData(dataBuilder())
|
||||||
}
|
}
|
||||||
|
is FunctionOptimizationTarget -> when (feature) {
|
||||||
problem.attributes[FunctionOptimizationTarget]?.let { direction: OptimizationDirection ->
|
FunctionOptimizationTarget.MAXIMIZE -> addOptimizationData(GoalType.MAXIMIZE)
|
||||||
when (direction) {
|
FunctionOptimizationTarget.MINIMIZE -> addOptimizationData(GoalType.MINIMIZE)
|
||||||
OptimizationDirection.MAXIMIZE -> addOptimizationData(GoalType.MAXIMIZE)
|
}
|
||||||
OptimizationDirection.MINIMIZE -> addOptimizationData(GoalType.MINIMIZE)
|
else -> logger?.log { "The feature $feature is unused in optimization" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val (point, value) = cmOptimizer.optimize(*optimizationData.values.toTypedArray())
|
val (point, value) = cmOptimizer.optimize(*optimizationData.values.toTypedArray())
|
||||||
return problem.withAttributes {
|
return problem.withAttributes(OptimizationResult(point.toMap()), OptimizationValue(value))
|
||||||
result(point.toMap())
|
|
||||||
value(value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,6 @@ package space.kscience.kmath.commons.integration
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.integration.IntegrandAbsoluteAccuracy
|
|
||||||
import space.kscience.kmath.integration.IntegrandRelativeAccuracy
|
|
||||||
import space.kscience.kmath.integration.integrate
|
import space.kscience.kmath.integration.integrate
|
||||||
import space.kscience.kmath.integration.value
|
import space.kscience.kmath.integration.value
|
||||||
import space.kscience.kmath.operations.Float64Field.sin
|
import space.kscience.kmath.operations.Float64Field.sin
|
||||||
@ -29,8 +27,8 @@ internal class IntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
fun customSimpson() {
|
fun customSimpson() {
|
||||||
val res = CMIntegrator.simpson().integrate(0.0..PI, {
|
val res = CMIntegrator.simpson().integrate(0.0..PI, {
|
||||||
IntegrandRelativeAccuracy(1e-4)
|
targetRelativeAccuracy = 1e-4
|
||||||
IntegrandAbsoluteAccuracy(1e-4)
|
targetAbsoluteAccuracy = 1e-4
|
||||||
}, function).value
|
}, function).value
|
||||||
assertTrue { abs(res - 2) < 1e-3 }
|
assertTrue { abs(res - 2) < 1e-3 }
|
||||||
assertTrue { abs(res - 2) > 1e-12 }
|
assertTrue { abs(res - 2) > 1e-12 }
|
||||||
|
@ -73,9 +73,8 @@ internal class OptimizeTest {
|
|||||||
val result: FunctionOptimization<Double> = chi2.optimizeWith(
|
val result: FunctionOptimization<Double> = 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)
|
)
|
||||||
}
|
|
||||||
println(result)
|
println(result)
|
||||||
println("Chi2/dof = ${result.resultValue / (x.size - 3)}")
|
println("Chi2/dof = ${result.resultValue / (x.size - 3)}")
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,19 @@ Complex and hypercomplex number systems in KMath.
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-complex:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-complex:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-complex:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -18,6 +29,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-complex:0.4.0-dev-3")
|
implementation("space.kscience:kmath-complex:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -144,19 +144,12 @@ public object ComplexField :
|
|||||||
zero
|
zero
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
exp(pow * ln(arg))
|
exp(pow * ln(arg))
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun power(arg: Complex, pow: Complex): Complex = if(arg == zero || arg == (-0.0).toComplex()){
|
public fun power(arg: Complex, pow: Complex): Complex = exp(pow * ln(arg))
|
||||||
if(pow == zero){
|
|
||||||
one
|
|
||||||
} else {
|
|
||||||
zero
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
exp(pow * ln(arg))
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun Complex.pow(power: Complex): Complex = power(this, power)
|
public fun Complex.pow(power: Complex): Complex = power(this, power)
|
||||||
|
|
||||||
|
@ -71,11 +71,6 @@ internal class ComplexFieldTest {
|
|||||||
(i * 8).let { it.im.toInt() to it.re.toInt() },
|
(i * 8).let { it.im.toInt() to it.re.toInt() },
|
||||||
(Complex(2, 2) pow 2).let { it.im.toInt() to it.re.toInt() })
|
(Complex(2, 2) pow 2).let { it.im.toInt() to it.re.toInt() })
|
||||||
|
|
||||||
assertEquals(1.0, Complex(0.0).pow(Complex(0.0)).re, 0.01)
|
|
||||||
assertEquals(1.0, Complex(-0.0).pow(Complex(0.0)).re, 0.01)
|
|
||||||
assertEquals(0.0, Complex(0.0).pow(Complex(2.0)).re, 0.01)
|
|
||||||
assertEquals(0.0, Complex(-0.0).pow(Complex(2.0)).re, 0.01)
|
|
||||||
assertEquals(1.0, Complex(-1.0).pow(Complex(2.0)).re, 0.01)
|
|
||||||
assertEquals(2.0, power(Complex(-4.0, 0.0), 0.5 + 0 * i).im, 0.01)
|
assertEquals(2.0, power(Complex(-4.0, 0.0), 0.5 + 0 * i).im, 0.01)
|
||||||
assertEquals(2.0, power(Complex(-4.0, 0.0), 0.5).im, 0.01)
|
assertEquals(2.0, power(Complex(-4.0, 0.0), 0.5).im, 0.01)
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,23 @@ objects to the expression by providing a context. Expressions can be used for a
|
|||||||
performance calculations to code generation.
|
performance calculations to code generation.
|
||||||
- [domains](src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
|
- [domains](src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
|
||||||
- [autodiff](src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
- [autodiff](src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
||||||
- [linear.parallel](#) : Parallel implementation for `LinearAlgebra`
|
|
||||||
|
|
||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-core:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-core:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-core:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -26,6 +36,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-core:0.4.0-dev-3")
|
implementation("space.kscience:kmath-core:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -71,12 +71,4 @@ readme {
|
|||||||
id = "autodiff",
|
id = "autodiff",
|
||||||
ref = "src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt"
|
ref = "src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt"
|
||||||
) { "Automatic differentiation" }
|
) { "Automatic differentiation" }
|
||||||
|
|
||||||
feature(
|
|
||||||
id="Parallel linear algebra"
|
|
||||||
){
|
|
||||||
"""
|
|
||||||
Parallel implementation for `LinearAlgebra`
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ package space.kscience.kmath.expressions
|
|||||||
|
|
||||||
import space.kscience.attributes.SafeType
|
import space.kscience.attributes.SafeType
|
||||||
import space.kscience.attributes.WithType
|
import space.kscience.attributes.WithType
|
||||||
import space.kscience.attributes.safeTypeOf
|
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.Algebra
|
import space.kscience.kmath.operations.Algebra
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
@ -31,18 +30,12 @@ public interface Expression<T> : WithType<T> {
|
|||||||
public operator fun invoke(arguments: Map<Symbol, T>): T
|
public operator fun invoke(arguments: Map<Symbol, T>): T
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an expression from a functional block.
|
|
||||||
*/
|
|
||||||
public fun <T> Expression(type: SafeType<T>, block: (Map<Symbol, T>) -> T): Expression<T> = object : Expression<T> {
|
public fun <T> Expression(type: SafeType<T>, block: (Map<Symbol, T>) -> T): Expression<T> = object : Expression<T> {
|
||||||
override fun invoke(arguments: Map<Symbol, T>): T = block(arguments)
|
override fun invoke(arguments: Map<Symbol, T>): T = block(arguments)
|
||||||
|
|
||||||
override val type: SafeType<T> = type
|
override val type: SafeType<T> = type
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline fun <reified T> Expression(noinline block: (Map<Symbol, T>) -> T): Expression<T> =
|
|
||||||
Expression(safeTypeOf<T>(), block)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialization of [Expression] for [Double] allowing better performance because of using array.
|
* Specialization of [Expression] for [Double] allowing better performance because of using array.
|
||||||
*/
|
*/
|
||||||
|
@ -54,12 +54,11 @@ public object Float64LinearSpace : LinearSpace<Double, Float64Field> {
|
|||||||
require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
|
require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
|
||||||
val rows = this@dot.rows.map { it.linearize() }
|
val rows = this@dot.rows.map { it.linearize() }
|
||||||
val columns = other.columns.map { it.linearize() }
|
val columns = other.columns.map { it.linearize() }
|
||||||
val indices = 0 until this.colNum
|
|
||||||
return buildMatrix(rowNum, other.colNum) { i, j ->
|
return buildMatrix(rowNum, other.colNum) { i, j ->
|
||||||
val r = rows[i]
|
val r = rows[i]
|
||||||
val c = columns[j]
|
val c = columns[j]
|
||||||
var res = 0.0
|
var res = 0.0
|
||||||
for (l in indices) {
|
for (l in r.indices) {
|
||||||
res += r[l] * c[l]
|
res += r[l] * c[l]
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
@ -70,11 +69,10 @@ public object Float64LinearSpace : LinearSpace<Double, Float64Field> {
|
|||||||
override fun Matrix<Double>.dot(vector: Point<Double>): Float64Buffer {
|
override fun Matrix<Double>.dot(vector: Point<Double>): Float64Buffer {
|
||||||
require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
|
require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
|
||||||
val rows = this@dot.rows.map { it.linearize() }
|
val rows = this@dot.rows.map { it.linearize() }
|
||||||
val indices = 0 until this.colNum
|
|
||||||
return Float64Buffer(rowNum) { i ->
|
return Float64Buffer(rowNum) { i ->
|
||||||
val r = rows[i]
|
val r = rows[i]
|
||||||
var res = 0.0
|
var res = 0.0
|
||||||
for (j in indices) {
|
for (j in r.indices) {
|
||||||
res += r[j] * vector[j]
|
res += r[j] * vector[j]
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
|
@ -4,33 +4,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("UnusedReceiverParameter")
|
@file:Suppress("UnusedReceiverParameter")
|
||||||
@file:OptIn(PerformancePitfall::class)
|
|
||||||
|
|
||||||
package space.kscience.kmath.linear
|
package space.kscience.kmath.linear
|
||||||
|
|
||||||
import space.kscience.attributes.Attributes
|
import space.kscience.attributes.Attributes
|
||||||
import space.kscience.attributes.PolymorphicAttribute
|
import space.kscience.attributes.PolymorphicAttribute
|
||||||
import space.kscience.attributes.safeTypeOf
|
import space.kscience.attributes.safeTypeOf
|
||||||
import space.kscience.kmath.PerformancePitfall
|
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.nd.*
|
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.structures.*
|
import space.kscience.kmath.structures.*
|
||||||
|
|
||||||
public interface LupDecomposition<T> {
|
public interface LupDecomposition<T> {
|
||||||
|
public val linearSpace: LinearSpace<T, Field<T>>
|
||||||
|
public val elementAlgebra: Field<T> get() = linearSpace.elementAlgebra
|
||||||
|
|
||||||
public val pivot: IntBuffer
|
public val pivot: IntBuffer
|
||||||
public val l: Matrix<T>
|
public val l: Matrix<T>
|
||||||
public val u: Matrix<T>
|
public val u: Matrix<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a pivot matrix from pivot vector using provided [LinearSpace]
|
|
||||||
*/
|
|
||||||
public fun <T> LupDecomposition<T>.pivotMatrix(linearSpace: LinearSpace<T, Ring<T>>): Matrix<T> =
|
|
||||||
VirtualMatrix(linearSpace.type, l.rowNum, l.colNum) { row, column ->
|
|
||||||
if (column == pivot[row]) linearSpace.elementAlgebra.one else linearSpace.elementAlgebra.zero
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matrices with this feature support LU factorization with partial pivoting: *[p] · a = [l] · [u]* where
|
* Matrices with this feature support LU factorization with partial pivoting: *[p] · a = [l] · [u]* where
|
||||||
* *a* is the owning matrix.
|
* *a* is the owning matrix.
|
||||||
@ -39,13 +31,12 @@ public fun <T> LupDecomposition<T>.pivotMatrix(linearSpace: LinearSpace<T, Ring<
|
|||||||
* @param lu combined L and U matrix
|
* @param lu combined L and U matrix
|
||||||
*/
|
*/
|
||||||
public class GenericLupDecomposition<T>(
|
public class GenericLupDecomposition<T>(
|
||||||
public val elementAlgebra: Field<T>,
|
override val linearSpace: LinearSpace<T, Field<T>>,
|
||||||
private val lu: Matrix<T>,
|
private val lu: Matrix<T>,
|
||||||
override val pivot: IntBuffer,
|
override val pivot: IntBuffer,
|
||||||
private val even: Boolean,
|
private val even: Boolean,
|
||||||
) : LupDecomposition<T> {
|
) : LupDecomposition<T> {
|
||||||
|
|
||||||
|
|
||||||
override val l: Matrix<T>
|
override val l: Matrix<T>
|
||||||
get() = VirtualMatrix(lu.type, lu.rowNum, lu.colNum, attributes = Attributes(LowerTriangular)) { i, j ->
|
get() = VirtualMatrix(lu.type, lu.rowNum, lu.colNum, attributes = Attributes(LowerTriangular)) { i, j ->
|
||||||
when {
|
when {
|
||||||
@ -60,6 +51,11 @@ public class GenericLupDecomposition<T>(
|
|||||||
if (j >= i) lu[i, j] else elementAlgebra.zero
|
if (j >= i) lu[i, j] else elementAlgebra.zero
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public val pivotMatrix: Matrix<T>
|
||||||
|
get() = VirtualMatrix(linearSpace.type, l.rowNum, l.colNum) { row, column ->
|
||||||
|
if (column == pivot[row]) elementAlgebra.one else elementAlgebra.zero
|
||||||
|
}
|
||||||
|
|
||||||
public val determinant: T by lazy {
|
public val determinant: T by lazy {
|
||||||
elementAlgebra { (0 until l.shape[0]).fold(if (even) one else -one) { value, i -> value * lu[i, i] } }
|
elementAlgebra { (0 until l.shape[0]).fold(if (even) one else -one) { value, i -> value * lu[i, i] } }
|
||||||
}
|
}
|
||||||
@ -80,145 +76,136 @@ internal fun <T : Comparable<T>> LinearSpace<T, Ring<T>>.abs(value: T): T =
|
|||||||
/**
|
/**
|
||||||
* Create a lup decomposition of generic matrix.
|
* Create a lup decomposition of generic matrix.
|
||||||
*/
|
*/
|
||||||
public fun <T : Comparable<T>> Field<T>.lup(
|
public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
|
||||||
matrix: Matrix<T>,
|
matrix: Matrix<T>,
|
||||||
checkSingular: (T) -> Boolean,
|
checkSingular: (T) -> Boolean,
|
||||||
): GenericLupDecomposition<T> {
|
): LupDecomposition<T> = elementAlgebra {
|
||||||
require(matrix.rowNum == matrix.colNum) { "LU decomposition supports only square matrices" }
|
require(matrix.rowNum == matrix.colNum) { "LU decomposition supports only square matrices" }
|
||||||
val m = matrix.colNum
|
val m = matrix.colNum
|
||||||
val pivot = IntArray(matrix.rowNum)
|
val pivot = IntArray(matrix.rowNum)
|
||||||
|
|
||||||
val strides = RowStrides(ShapeND(matrix.rowNum, matrix.colNum))
|
//TODO just waits for multi-receivers
|
||||||
|
with(BufferAccessor2D(matrix.rowNum, matrix.colNum, elementAlgebra.bufferFactory)) {
|
||||||
|
|
||||||
val lu = MutableBufferND(
|
val lu = create(matrix)
|
||||||
strides,
|
|
||||||
bufferAlgebra.buffer(strides.linearSize) { offset ->
|
|
||||||
matrix[strides.index(offset)]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
// Initialize the permutation array and parity
|
||||||
|
for (row in 0 until m) pivot[row] = row
|
||||||
|
var even = true
|
||||||
|
|
||||||
// Initialize the permutation array and parity
|
// Initialize the permutation array and parity
|
||||||
for (row in 0 until m) pivot[row] = row
|
for (row in 0 until m) pivot[row] = row
|
||||||
var even = true
|
|
||||||
|
|
||||||
// Initialize the permutation array and parity
|
// Loop over columns
|
||||||
for (row in 0 until m) pivot[row] = row
|
for (col in 0 until m) {
|
||||||
|
// upper
|
||||||
// Loop over columns
|
for (row in 0 until col) {
|
||||||
for (col in 0 until m) {
|
val luRow = lu.row(row)
|
||||||
// upper
|
var sum = luRow[col]
|
||||||
for (row in 0 until col) {
|
for (i in 0 until row) sum -= luRow[i] * lu[i, col]
|
||||||
var sum = lu[row, col]
|
luRow[col] = sum
|
||||||
for (i in 0 until row){
|
|
||||||
sum -= lu[row, i] * lu[i, col]
|
|
||||||
}
|
|
||||||
lu[row, col] = sum
|
|
||||||
}
|
|
||||||
|
|
||||||
// lower
|
|
||||||
var max = col // permutation row
|
|
||||||
var largest = -one
|
|
||||||
|
|
||||||
for (row in col until m) {
|
|
||||||
var sum = lu[row, col]
|
|
||||||
for (i in 0 until col){
|
|
||||||
sum -= lu[row, i] * lu[i, col]
|
|
||||||
}
|
|
||||||
lu[row, col] = sum
|
|
||||||
|
|
||||||
// maintain the best permutation choice
|
|
||||||
if (abs(sum) > largest) {
|
|
||||||
largest = abs(sum)
|
|
||||||
max = row
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Singularity check
|
|
||||||
check(!checkSingular(abs(lu[max, col]))) { "The matrix is singular" }
|
|
||||||
|
|
||||||
// Pivot if necessary
|
|
||||||
if (max != col) {
|
|
||||||
for (i in 0 until m) {
|
|
||||||
val tmp = lu[max, i]
|
|
||||||
lu[max, i] = lu[col, i]
|
|
||||||
lu[col, i] = tmp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val temp = pivot[max]
|
// lower
|
||||||
pivot[max] = pivot[col]
|
var max = col // permutation row
|
||||||
pivot[col] = temp
|
var largest = -one
|
||||||
even = !even
|
|
||||||
|
for (row in col until m) {
|
||||||
|
val luRow = lu.row(row)
|
||||||
|
var sum = luRow[col]
|
||||||
|
for (i in 0 until col) sum -= luRow[i] * lu[i, col]
|
||||||
|
luRow[col] = sum
|
||||||
|
|
||||||
|
// maintain the best permutation choice
|
||||||
|
if (abs(sum) > largest) {
|
||||||
|
largest = abs(sum)
|
||||||
|
max = row
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Singularity check
|
||||||
|
check(!checkSingular(abs(lu[max, col]))) { "The matrix is singular" }
|
||||||
|
|
||||||
|
// Pivot if necessary
|
||||||
|
if (max != col) {
|
||||||
|
val luMax = lu.row(max)
|
||||||
|
val luCol = lu.row(col)
|
||||||
|
|
||||||
|
for (i in 0 until m) {
|
||||||
|
val tmp = luMax[i]
|
||||||
|
luMax[i] = luCol[i]
|
||||||
|
luCol[i] = tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
val temp = pivot[max]
|
||||||
|
pivot[max] = pivot[col]
|
||||||
|
pivot[col] = temp
|
||||||
|
even = !even
|
||||||
|
}
|
||||||
|
|
||||||
|
// Divide the lower elements by the "winning" diagonal elt.
|
||||||
|
val luDiag = lu[col, col]
|
||||||
|
for (row in col + 1 until m) lu[row, col] /= luDiag
|
||||||
}
|
}
|
||||||
|
|
||||||
// Divide the lower elements by the "winning" diagonal elt.
|
return GenericLupDecomposition(this@lup, lu.toStructure2D(), pivot.asBuffer(), even)
|
||||||
val luDiag = lu[col, col]
|
|
||||||
for (row in col + 1 until m) lu[row, col] /= luDiag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return GenericLupDecomposition(this, lu.as2D(), pivot.asBuffer(), even)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun Field<Float64>.lup(
|
public fun LinearSpace<Double, Float64Field>.lup(
|
||||||
matrix: Matrix<Double>,
|
matrix: Matrix<Double>,
|
||||||
singularityThreshold: Double = 1e-11,
|
singularityThreshold: Double = 1e-11,
|
||||||
): GenericLupDecomposition<Double> = lup(matrix) { it < singularityThreshold }
|
): LupDecomposition<Double> = lup(matrix) { it < singularityThreshold }
|
||||||
|
|
||||||
private fun <T> Field<T>.solve(
|
internal fun <T> LinearSpace<T, Field<T>>.solve(
|
||||||
lup: LupDecomposition<T>,
|
lup: LupDecomposition<T>,
|
||||||
matrix: Matrix<T>,
|
matrix: Matrix<T>,
|
||||||
): Matrix<T> {
|
): Matrix<T> {
|
||||||
require(matrix.rowNum == lup.l.rowNum) { "Matrix dimension mismatch. Expected ${lup.l.rowNum}, but got ${matrix.colNum}" }
|
require(matrix.rowNum == lup.l.rowNum) { "Matrix dimension mismatch. Expected ${lup.l.rowNum}, but got ${matrix.colNum}" }
|
||||||
|
|
||||||
val strides = RowStrides(ShapeND(matrix.rowNum, matrix.colNum))
|
BufferAccessor2D(matrix.rowNum, matrix.colNum, elementAlgebra.bufferFactory).run {
|
||||||
|
elementAlgebra {
|
||||||
|
// Apply permutations to b
|
||||||
|
val bp = create { _, _ -> zero }
|
||||||
|
|
||||||
// Apply permutations to b
|
for (row in 0 until rowNum) {
|
||||||
val bp = MutableBufferND(
|
val bpRow = bp.row(row)
|
||||||
strides,
|
val pRow = lup.pivot[row]
|
||||||
bufferAlgebra.buffer(strides.linearSize) { _ -> zero }
|
for (col in 0 until matrix.colNum) bpRow[col] = matrix[pRow, col]
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
for (row in 0 until matrix.rowNum) {
|
|
||||||
val pRow = lup.pivot[row]
|
|
||||||
for (col in 0 until matrix.colNum) {
|
|
||||||
bp[row, col] = matrix[pRow, col]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Solve LY = b
|
|
||||||
for (col in 0 until matrix.colNum) {
|
|
||||||
|
|
||||||
for (i in col + 1 until matrix.colNum) {
|
|
||||||
val luICol = lup.l[i, col]
|
|
||||||
for (j in 0 until matrix.colNum) {
|
|
||||||
bp[i, j] -= bp[col, j] * luICol
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Solve UX = Y
|
// Solve LY = b
|
||||||
for (col in matrix.colNum - 1 downTo 0) {
|
for (col in 0 until colNum) {
|
||||||
val luDiag = lup.u[col, col]
|
val bpCol = bp.row(col)
|
||||||
for (j in 0 until matrix.colNum) {
|
|
||||||
bp[col, j] /= luDiag
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in 0 until col) {
|
for (i in col + 1 until colNum) {
|
||||||
val luICol = lup.u[i, col]
|
val bpI = bp.row(i)
|
||||||
for (j in 0 until matrix.colNum) {
|
val luICol = lup.l[i, col]
|
||||||
bp[i, j] -= bp[col, j] * luICol
|
for (j in 0 until matrix.colNum) {
|
||||||
|
bpI[j] -= bpCol[j] * luICol
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Solve UX = Y
|
||||||
|
for (col in colNum - 1 downTo 0) {
|
||||||
|
val bpCol = bp.row(col)
|
||||||
|
val luDiag = lup.u[col, col]
|
||||||
|
for (j in 0 until matrix.colNum) bpCol[j] /= luDiag
|
||||||
|
|
||||||
|
for (i in 0 until col) {
|
||||||
|
val bpI = bp.row(i)
|
||||||
|
val luICol = lup.u[i, col]
|
||||||
|
for (j in 0 until matrix.colNum) bpI[j] -= bpCol[j] * luICol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildMatrix(matrix.rowNum, matrix.colNum) { i, j -> bp[i, j] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bp.as2D()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a generic solver based on LUP decomposition
|
* Produce a generic solver based on LUP decomposition
|
||||||
*/
|
*/
|
||||||
@ -226,7 +213,7 @@ private fun <T> Field<T>.solve(
|
|||||||
public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lupSolver(
|
public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lupSolver(
|
||||||
singularityCheck: (T) -> Boolean,
|
singularityCheck: (T) -> Boolean,
|
||||||
): LinearSolver<T> = object : LinearSolver<T> {
|
): LinearSolver<T> = object : LinearSolver<T> {
|
||||||
override fun solve(a: Matrix<T>, b: Matrix<T>): Matrix<T> = elementAlgebra{
|
override fun solve(a: Matrix<T>, b: Matrix<T>): Matrix<T> {
|
||||||
// Use existing decomposition if it is provided by matrix or linear space itself
|
// Use existing decomposition if it is provided by matrix or linear space itself
|
||||||
val decomposition = a.getOrComputeAttribute(LUP) ?: lup(a, singularityCheck)
|
val decomposition = a.getOrComputeAttribute(LUP) ?: lup(a, singularityCheck)
|
||||||
return solve(decomposition, b)
|
return solve(decomposition, b)
|
||||||
|
@ -25,4 +25,5 @@ public class TransposedMatrix<T>(public val origin: Matrix<T>) : Matrix<T> {
|
|||||||
/**
|
/**
|
||||||
* Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A`
|
* Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A`
|
||||||
*/
|
*/
|
||||||
public fun <T> Matrix<T>.transposed(): Matrix<T> = (this as? TransposedMatrix<T>)?.origin ?: TransposedMatrix(this)
|
public val <T> Matrix<T>.transposed: Matrix<T>
|
||||||
|
get() = (this as? TransposedMatrix<T>)?.origin ?: TransposedMatrix(this)
|
@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.nd
|
package space.kscience.kmath.nd
|
||||||
|
|
||||||
import space.kscience.attributes.SafeType
|
|
||||||
import space.kscience.kmath.PerformancePitfall
|
import space.kscience.kmath.PerformancePitfall
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import space.kscience.kmath.structures.Float64Buffer
|
import space.kscience.kmath.structures.Float64Buffer
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
@ -22,10 +20,7 @@ import kotlin.math.pow as kpow
|
|||||||
public class Float64BufferND(
|
public class Float64BufferND(
|
||||||
indexes: ShapeIndexer,
|
indexes: ShapeIndexer,
|
||||||
override val buffer: Float64Buffer,
|
override val buffer: Float64Buffer,
|
||||||
) : MutableBufferND<Double>(indexes, buffer), MutableStructureNDOfDouble {
|
) : MutableBufferND<Double>(indexes, buffer), MutableStructureNDOfDouble{
|
||||||
|
|
||||||
override val type: SafeType<Float64> get() = Float64Field.type
|
|
||||||
|
|
||||||
override fun getDouble(index: IntArray): Double = buffer[indices.offset(index)]
|
override fun getDouble(index: IntArray): Double = buffer[indices.offset(index)]
|
||||||
|
|
||||||
override fun setDouble(index: IntArray, value: Double) {
|
override fun setDouble(index: IntArray, value: Double) {
|
||||||
|
@ -69,29 +69,6 @@ public interface Structure2D<out T> : StructureND<T> {
|
|||||||
public companion object
|
public companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A linear accessor for a [MutableStructureND]
|
|
||||||
*/
|
|
||||||
@OptIn(PerformancePitfall::class)
|
|
||||||
public class MutableStructureNDAccessorBuffer<T>(
|
|
||||||
public val structure: MutableStructureND<T>,
|
|
||||||
override val size: Int,
|
|
||||||
private val indexer: (Int) -> IntArray,
|
|
||||||
) : MutableBuffer<T> {
|
|
||||||
|
|
||||||
override val type: SafeType<T> get() = structure.type
|
|
||||||
|
|
||||||
override fun set(index: Int, value: T) {
|
|
||||||
structure[indexer(index)] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun get(index: Int): T = structure[indexer(index)]
|
|
||||||
|
|
||||||
override fun toString(): String = "AccessorBuffer(structure=$structure, size=$size)"
|
|
||||||
|
|
||||||
override fun copy(): MutableBuffer<T> = MutableBuffer(type, size, ::get)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents mutable [Structure2D].
|
* Represents mutable [Structure2D].
|
||||||
*/
|
*/
|
||||||
@ -110,18 +87,14 @@ public interface MutableStructure2D<T> : Structure2D<T>, MutableStructureND<T> {
|
|||||||
*/
|
*/
|
||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
override val rows: List<MutableBuffer<T>>
|
override val rows: List<MutableBuffer<T>>
|
||||||
get() = List(rowNum) { i ->
|
get() = List(rowNum) { i -> MutableBuffer(type, colNum) { j -> get(i, j) } }
|
||||||
MutableStructureNDAccessorBuffer(this, colNum) { j -> intArrayOf(i, j) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The buffer of columns for this structure. It gets elements from the structure dynamically.
|
* The buffer of columns for this structure. It gets elements from the structure dynamically.
|
||||||
*/
|
*/
|
||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
override val columns: List<MutableBuffer<T>>
|
override val columns: List<MutableBuffer<T>>
|
||||||
get() = List(colNum) { j ->
|
get() = List(colNum) { j -> MutableBuffer(type, rowNum) { i -> get(i, j) } }
|
||||||
MutableStructureNDAccessorBuffer(this, rowNum) { i -> intArrayOf(i, j) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,15 +5,9 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.nd
|
package space.kscience.kmath.nd
|
||||||
|
|
||||||
import space.kscience.attributes.SafeType
|
|
||||||
import space.kscience.kmath.PerformancePitfall
|
import space.kscience.kmath.PerformancePitfall
|
||||||
import space.kscience.kmath.operations.Float64Field
|
|
||||||
import space.kscience.kmath.operations.Int32Field
|
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
|
|
||||||
public interface StructureNDOfDouble : StructureND<Double> {
|
public interface StructureNDOfDouble : StructureND<Double> {
|
||||||
override val type: SafeType<Float64> get() = Float64Field.type
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guaranteed non-blocking access to content
|
* Guaranteed non-blocking access to content
|
||||||
*/
|
*/
|
||||||
@ -28,7 +22,6 @@ public fun StructureND<Double>.getDouble(index: IntArray): Double =
|
|||||||
if (this is StructureNDOfDouble) getDouble(index) else get(index)
|
if (this is StructureNDOfDouble) getDouble(index) else get(index)
|
||||||
|
|
||||||
public interface MutableStructureNDOfDouble : StructureNDOfDouble, MutableStructureND<Double> {
|
public interface MutableStructureNDOfDouble : StructureNDOfDouble, MutableStructureND<Double> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guaranteed non-blocking access to content
|
* Guaranteed non-blocking access to content
|
||||||
*/
|
*/
|
||||||
@ -41,9 +34,6 @@ public fun MutableStructureND<Double>.getDouble(index: IntArray): Double =
|
|||||||
|
|
||||||
|
|
||||||
public interface StructureNDOfInt : StructureND<Int> {
|
public interface StructureNDOfInt : StructureND<Int> {
|
||||||
|
|
||||||
override val type: SafeType<Int> get() = Int32Field.type
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guaranteed non-blocking access to content
|
* Guaranteed non-blocking access to content
|
||||||
*/
|
*/
|
||||||
|
@ -77,11 +77,13 @@ private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.zipInline(
|
|||||||
return elementBufferFactory(l.size) { elementAlgebra.block(l[it], r[it]) }
|
return elementBufferFactory(l.size) { elementAlgebra.block(l[it], r[it]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T> BufferAlgebra<T, *>.buffer(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
|
public fun <T> BufferAlgebra<T, *>.buffer(size: Int, initializer: (Int) -> T): MutableBuffer<T> {
|
||||||
elementBufferFactory(size, initializer)
|
return elementBufferFactory(size, initializer)
|
||||||
|
}
|
||||||
|
|
||||||
public fun <T, A> A.buffer(initializer: (Int) -> T): MutableBuffer<T> where A : BufferAlgebra<T, *>, A : WithSize =
|
public fun <T, A> A.buffer(initializer: (Int) -> T): MutableBuffer<T> where A : BufferAlgebra<T, *>, A : WithSize {
|
||||||
elementBufferFactory(size, initializer)
|
return elementBufferFactory(size, initializer)
|
||||||
|
}
|
||||||
|
|
||||||
public fun <T, A : TrigonometricOperations<T>> BufferAlgebra<T, A>.sin(arg: Buffer<T>): Buffer<T> =
|
public fun <T, A : TrigonometricOperations<T>> BufferAlgebra<T, A>.sin(arg: Buffer<T>): Buffer<T> =
|
||||||
mapInline(arg) { sin(it) }
|
mapInline(arg) { sin(it) }
|
||||||
|
@ -42,8 +42,6 @@ public inline fun <reified T> BufferFactory(): BufferFactory<T> = BufferFactory(
|
|||||||
*/
|
*/
|
||||||
public interface MutableBufferFactory<T> : BufferFactory<T> {
|
public interface MutableBufferFactory<T> : BufferFactory<T> {
|
||||||
override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer<T>
|
override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer<T>
|
||||||
|
|
||||||
public companion object
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,7 +6,12 @@
|
|||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
import space.kscience.attributes.SafeType
|
import space.kscience.attributes.SafeType
|
||||||
|
import space.kscience.kmath.nd.BufferND
|
||||||
|
import space.kscience.kmath.nd.ShapeND
|
||||||
import space.kscience.kmath.nd.Structure2D
|
import space.kscience.kmath.nd.Structure2D
|
||||||
|
import space.kscience.kmath.nd.as2D
|
||||||
|
import kotlin.collections.component1
|
||||||
|
import kotlin.collections.component2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A context that allows to operate on a [MutableBuffer] as on 2d array
|
* A context that allows to operate on a [MutableBuffer] as on 2d array
|
||||||
@ -27,10 +32,10 @@ internal class BufferAccessor2D<T>(
|
|||||||
|
|
||||||
fun create(mat: Structure2D<T>): MutableBuffer<T> = create { i, j -> mat[i, j] }
|
fun create(mat: Structure2D<T>): MutableBuffer<T> = create { i, j -> mat[i, j] }
|
||||||
|
|
||||||
// //TODO optimize wrapper
|
//TODO optimize wrapper
|
||||||
// fun MutableBuffer<T>.toStructure2D(): Structure2D<T> = BufferND(
|
fun MutableBuffer<T>.toStructure2D(): Structure2D<T> = BufferND(
|
||||||
// type, ShapeND(rowNum, colNum)
|
type, ShapeND(rowNum, colNum)
|
||||||
// ) { (i, j) -> get(i, j) }.as2D()
|
) { (i, j) -> get(i, j) }.as2D()
|
||||||
|
|
||||||
inner class Row(val buffer: MutableBuffer<T>, val rowIndex: Int) : MutableBuffer<T> {
|
inner class Row(val buffer: MutableBuffer<T>, val rowIndex: Int) : MutableBuffer<T> {
|
||||||
override val type: SafeType<T> get() = buffer.type
|
override val type: SafeType<T> get() = buffer.type
|
||||||
|
@ -39,7 +39,6 @@ public value class Float64Buffer(public val array: DoubleArray) : PrimitiveBuffe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Use Float64Buffer instead", ReplaceWith("Float64Buffer"))
|
|
||||||
public typealias DoubleBuffer = Float64Buffer
|
public typealias DoubleBuffer = Float64Buffer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,6 +77,7 @@ public inline fun <T> MutableBuffer(
|
|||||||
size: Int,
|
size: Int,
|
||||||
initializer: (Int) -> T,
|
initializer: (Int) -> T,
|
||||||
): MutableBuffer<T> = when (type.kType) {
|
): MutableBuffer<T> = when (type.kType) {
|
||||||
|
typeOf<Boolean>() -> TODO()
|
||||||
typeOf<Int8>() -> Int8Buffer(size) { initializer(it) as Int8 } as MutableBuffer<T>
|
typeOf<Int8>() -> Int8Buffer(size) { initializer(it) as Int8 } as MutableBuffer<T>
|
||||||
typeOf<Int16>() -> MutableBuffer.short(size) { initializer(it) as Int16 } as MutableBuffer<T>
|
typeOf<Int16>() -> MutableBuffer.short(size) { initializer(it) as Int16 } as MutableBuffer<T>
|
||||||
typeOf<Int32>() -> MutableBuffer.int(size) { initializer(it) as Int32 } as MutableBuffer<T>
|
typeOf<Int32>() -> MutableBuffer.int(size) { initializer(it) as Int32 } as MutableBuffer<T>
|
||||||
|
@ -10,6 +10,7 @@ import space.kscience.kmath.UnstableKMathAPI
|
|||||||
import space.kscience.kmath.nd.StructureND
|
import space.kscience.kmath.nd.StructureND
|
||||||
import space.kscience.kmath.operations.algebra
|
import space.kscience.kmath.operations.algebra
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
@ -28,18 +29,18 @@ class DoubleLUSolverTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDecomposition() = with(Double.algebra.linearSpace){
|
fun testDecomposition() = Double.algebra.linearSpace.run {
|
||||||
val matrix = matrix(2, 2)(
|
val matrix = matrix(2, 2)(
|
||||||
3.0, 1.0,
|
3.0, 1.0,
|
||||||
2.0, 3.0
|
2.0, 3.0
|
||||||
)
|
)
|
||||||
|
|
||||||
val lup = elementAlgebra.lup(matrix)
|
val lup = lup(matrix)
|
||||||
|
|
||||||
//Check determinant
|
//Check determinant
|
||||||
// assertEquals(7.0, lup.determinant)
|
assertEquals(7.0, lup.determinant)
|
||||||
|
|
||||||
assertMatrixEquals(lup.pivotMatrix(this) dot matrix, lup.l dot lup.u)
|
assertMatrixEquals(lup.pivotMatrix dot matrix, lup.l dot lup.u)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -8,7 +8,6 @@ package space.kscience.kmath.linear
|
|||||||
import space.kscience.kmath.PerformancePitfall
|
import space.kscience.kmath.PerformancePitfall
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.nd.StructureND
|
import space.kscience.kmath.nd.StructureND
|
||||||
import space.kscience.kmath.operations.Float64Field
|
|
||||||
import space.kscience.kmath.operations.algebra
|
import space.kscience.kmath.operations.algebra
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -22,7 +21,7 @@ class MatrixTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testTranspose() = Double.algebra.linearSpace.run {
|
fun testTranspose() = Double.algebra.linearSpace.run {
|
||||||
val matrix = one(3, 3)
|
val matrix = one(3, 3)
|
||||||
val transposed = matrix.transposed()
|
val transposed = matrix.transposed
|
||||||
assertTrue { StructureND.contentEquals(matrix, transposed) }
|
assertTrue { StructureND.contentEquals(matrix, transposed) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +58,7 @@ class MatrixTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test2DDot() = Float64Field.linearSpace {
|
fun test2DDot() = Double.algebra.linearSpace.run {
|
||||||
val firstMatrix = buildMatrix(2, 3) { i, j -> (i + j).toDouble() }
|
val firstMatrix = buildMatrix(2, 3) { i, j -> (i + j).toDouble() }
|
||||||
val secondMatrix = buildMatrix(3, 2) { i, j -> (i + j).toDouble() }
|
val secondMatrix = buildMatrix(3, 2) { i, j -> (i + j).toDouble() }
|
||||||
|
|
||||||
@ -71,5 +70,6 @@ class MatrixTest {
|
|||||||
assertEquals(8.0, result[0, 1])
|
assertEquals(8.0, result[0, 1])
|
||||||
assertEquals(8.0, result[1, 0])
|
assertEquals(8.0, result[1, 0])
|
||||||
assertEquals(14.0, result[1, 1])
|
assertEquals(14.0, result[1, 1])
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 space.kscience.kmath.PerformancePitfall
|
|
||||||
import space.kscience.kmath.nd.*
|
|
||||||
import space.kscience.kmath.operations.Float64BufferOps
|
|
||||||
import space.kscience.kmath.operations.Float64Field
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import space.kscience.kmath.structures.Buffer
|
|
||||||
import space.kscience.kmath.structures.Float64Buffer
|
|
||||||
import space.kscience.kmath.structures.asBuffer
|
|
||||||
import java.util.stream.IntStream
|
|
||||||
|
|
||||||
|
|
||||||
public object Float64ParallelLinearSpace : LinearSpace<Double, Float64Field> {
|
|
||||||
|
|
||||||
override val elementAlgebra: Float64Field = Float64Field
|
|
||||||
|
|
||||||
|
|
||||||
override fun buildMatrix(
|
|
||||||
rows: Int,
|
|
||||||
columns: Int,
|
|
||||||
initializer: Float64Field.(i: Int, j: Int) -> Double,
|
|
||||||
): Matrix<Double> {
|
|
||||||
val shape = ShapeND(rows, columns)
|
|
||||||
val indexer = BufferAlgebraND.defaultIndexerBuilder(shape)
|
|
||||||
|
|
||||||
val buffer = IntStream.range(0, indexer.linearSize).parallel().mapToDouble { offset ->
|
|
||||||
val (i, j) = indexer.index(offset)
|
|
||||||
elementAlgebra.initializer(i, j)
|
|
||||||
}.toArray().asBuffer()
|
|
||||||
|
|
||||||
return MutableBufferND(
|
|
||||||
indexer,
|
|
||||||
buffer
|
|
||||||
).as2D()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun buildVector(size: Int, initializer: Float64Field.(Int) -> Double): Float64Buffer =
|
|
||||||
IntStream.range(0, size).parallel().mapToDouble{ Float64Field.initializer(it) }.toArray().asBuffer()
|
|
||||||
|
|
||||||
override fun Matrix<Double>.unaryMinus(): Matrix<Double> = Floa64FieldOpsND {
|
|
||||||
asND().map { -it }.as2D()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun Matrix<Double>.plus(other: Matrix<Double>): Matrix<Double> = Floa64FieldOpsND {
|
|
||||||
require(shape.contentEquals(other.shape)) { "Shape mismatch on Matrix::plus. Expected $shape but found ${other.shape}" }
|
|
||||||
asND().plus(other.asND()).as2D()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun Matrix<Double>.minus(other: Matrix<Double>): Matrix<Double> = Floa64FieldOpsND {
|
|
||||||
require(shape.contentEquals(other.shape)) { "Shape mismatch on Matrix::minus. Expected $shape but found ${other.shape}" }
|
|
||||||
asND().minus(other.asND()).as2D()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a continuous in-memory representation of this vector for better memory layout handling
|
|
||||||
private fun Buffer<Double>.linearize() = if (this is Float64Buffer) {
|
|
||||||
this.array
|
|
||||||
} else {
|
|
||||||
DoubleArray(size) { get(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
|
||||||
override fun Matrix<Double>.dot(other: Matrix<Double>): Matrix<Double> {
|
|
||||||
require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
|
|
||||||
val rows = this@dot.rows.map { it.linearize() }
|
|
||||||
val columns = other.columns.map { it.linearize() }
|
|
||||||
val indices = 0 until this.colNum
|
|
||||||
return buildMatrix(rowNum, other.colNum) { i, j ->
|
|
||||||
val r = rows[i]
|
|
||||||
val c = columns[j]
|
|
||||||
var res = 0.0
|
|
||||||
for (l in indices) {
|
|
||||||
res += r[l] * c[l]
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
|
||||||
override fun Matrix<Double>.dot(vector: Point<Double>): Float64Buffer {
|
|
||||||
require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
|
|
||||||
val rows = this@dot.rows.map { it.linearize() }
|
|
||||||
val indices = 0 until this.colNum
|
|
||||||
return Float64Buffer(rowNum) { i ->
|
|
||||||
val r = rows[i]
|
|
||||||
var res = 0.0
|
|
||||||
for (j in indices) {
|
|
||||||
res += r[j] * vector[j]
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun Matrix<Double>.times(value: Double): Matrix<Double> = Floa64FieldOpsND {
|
|
||||||
asND().map { it * value }.as2D()
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun Point<Double>.plus(other: Point<Double>): Float64Buffer = Float64BufferOps.run {
|
|
||||||
this@plus + other
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun Point<Double>.minus(other: Point<Double>): Float64Buffer = Float64BufferOps.run {
|
|
||||||
this@minus - other
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun Point<Double>.times(value: Double): Float64Buffer = Float64BufferOps.run {
|
|
||||||
scale(this@times, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public operator fun Point<Double>.div(value: Double): Float64Buffer = Float64BufferOps.run {
|
|
||||||
scale(this@div, 1.0 / value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun Double.times(v: Point<Double>): Float64Buffer = v * this
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public val Float64LinearSpace.parallel: Float64ParallelLinearSpace get() = Float64ParallelLinearSpace
|
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.structures
|
|
||||||
|
|
||||||
import space.kscience.attributes.SafeType
|
|
||||||
import java.util.stream.Collectors
|
|
||||||
import java.util.stream.IntStream
|
|
||||||
import kotlin.reflect.typeOf
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Java stream-based parallel version of [MutableBuffer].
|
|
||||||
* There is no parallelization for [Int8], [Int16] and [Float32] types.
|
|
||||||
* They are processed sequentially.
|
|
||||||
*/
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
public fun <T> MutableBuffer.Companion.parallel(
|
|
||||||
type: SafeType<T>,
|
|
||||||
size: Int,
|
|
||||||
initializer: (Int) -> T,
|
|
||||||
): MutableBuffer<T> = when (type.kType) {
|
|
||||||
typeOf<Int8>() -> Int8Buffer(size) { initializer(it) as Int8 } as MutableBuffer<T>
|
|
||||||
typeOf<Int16>() -> Int16Buffer(size) { initializer(it) as Int16 } as MutableBuffer<T>
|
|
||||||
typeOf<Int32>() -> IntStream.range(0, size).parallel().map { initializer(it) as Int32 }.toArray()
|
|
||||||
.asBuffer() as MutableBuffer<T>
|
|
||||||
|
|
||||||
typeOf<Int64>() -> IntStream.range(0, size).parallel().mapToLong { initializer(it) as Int64 }.toArray()
|
|
||||||
.asBuffer() as MutableBuffer<T>
|
|
||||||
|
|
||||||
typeOf<Float>() -> Float32Buffer(size) { initializer(it) as Float } as MutableBuffer<T>
|
|
||||||
typeOf<Double>() -> IntStream.range(0, size).parallel().mapToDouble { initializer(it) as Float64 }.toArray()
|
|
||||||
.asBuffer() as MutableBuffer<T>
|
|
||||||
//TODO add unsigned types
|
|
||||||
else -> IntStream.range(0, size).parallel().mapToObj { initializer(it) }.collect(Collectors.toList<T>()).asMutableBuffer(type)
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ParallelBufferFactory<T>(override val type: SafeType<T>) : MutableBufferFactory<T> {
|
|
||||||
override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer<T> {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Java stream-based parallel alternative to [MutableBufferFactory].
|
|
||||||
* See [MutableBuffer.Companion.parallel] for details.
|
|
||||||
*/
|
|
||||||
public fun <T> MutableBufferFactory.Companion.parallel(
|
|
||||||
type: SafeType<T>,
|
|
||||||
): MutableBufferFactory<T> = object : MutableBufferFactory<T> {
|
|
||||||
|
|
||||||
override val type: SafeType<T> = type
|
|
||||||
|
|
||||||
override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer<T> = MutableBuffer.parallel(type, size, builder)
|
|
||||||
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 space.kscience.kmath.PerformancePitfall
|
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
|
||||||
import space.kscience.kmath.nd.StructureND
|
|
||||||
import space.kscience.kmath.operations.Float64Field
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
@UnstableKMathAPI
|
|
||||||
@OptIn(PerformancePitfall::class)
|
|
||||||
@Suppress("UNUSED_VARIABLE")
|
|
||||||
class ParallelMatrixTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testTranspose() = Float64Field.linearSpace.parallel{
|
|
||||||
val matrix = one(3, 3)
|
|
||||||
val transposed = matrix.transposed()
|
|
||||||
assertTrue { StructureND.contentEquals(matrix, transposed) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testBuilder() = Float64Field.linearSpace.parallel{
|
|
||||||
val matrix = matrix(2, 3)(
|
|
||||||
1.0, 0.0, 0.0,
|
|
||||||
0.0, 1.0, 2.0
|
|
||||||
)
|
|
||||||
|
|
||||||
assertEquals(2.0, matrix[1, 2])
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testMatrixExtension() = Float64Field.linearSpace.parallel{
|
|
||||||
val transitionMatrix: Matrix<Double> = VirtualMatrix(type,6, 6) { row, col ->
|
|
||||||
when {
|
|
||||||
col == 0 -> .50
|
|
||||||
row + 1 == col -> .50
|
|
||||||
row == 5 && col == 5 -> 1.0
|
|
||||||
else -> 0.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
infix fun Matrix<Double>.pow(power: Int): Matrix<Double> {
|
|
||||||
var res = this
|
|
||||||
repeat(power - 1) {
|
|
||||||
res = res dot this@pow
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
val toTenthPower = transitionMatrix pow 10
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun test2DDot() = Float64Field.linearSpace.parallel {
|
|
||||||
val firstMatrix = buildMatrix(2, 3) { i, j -> (i + j).toDouble() }
|
|
||||||
val secondMatrix = buildMatrix(3, 2) { i, j -> (i + j).toDouble() }
|
|
||||||
|
|
||||||
// val firstMatrix = produce(2, 3) { i, j -> (i + j).toDouble() }
|
|
||||||
// val secondMatrix = produce(3, 2) { i, j -> (i + j).toDouble() }
|
|
||||||
val result = firstMatrix dot secondMatrix
|
|
||||||
assertEquals(2, result.rowNum)
|
|
||||||
assertEquals(2, result.colNum)
|
|
||||||
assertEquals(8.0, result[0, 1])
|
|
||||||
assertEquals(8.0, result[1, 0])
|
|
||||||
assertEquals(14.0, result[1, 1])
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,8 +6,19 @@
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-coroutines:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-coroutines:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-coroutines:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -16,6 +27,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-coroutines:0.4.0-dev-3")
|
implementation("space.kscience:kmath-coroutines:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -6,7 +6,6 @@ kscience {
|
|||||||
jvm()
|
jvm()
|
||||||
js()
|
js()
|
||||||
native()
|
native()
|
||||||
wasm()
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":kmath-core"))
|
api(project(":kmath-core"))
|
||||||
|
@ -7,7 +7,6 @@ package space.kscience.kmath.streaming
|
|||||||
|
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import space.kscience.kmath.operations.Int32Ring
|
|
||||||
import space.kscience.kmath.operations.asSequence
|
import space.kscience.kmath.operations.asSequence
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -15,7 +14,7 @@ import kotlin.test.assertEquals
|
|||||||
internal class RingBufferTest {
|
internal class RingBufferTest {
|
||||||
@Test
|
@Test
|
||||||
fun push() {
|
fun push() {
|
||||||
val buffer = RingBuffer(20, Double.NaN)
|
val buffer = RingBuffer.build(20, Double.NaN)
|
||||||
runBlocking {
|
runBlocking {
|
||||||
for (i in 1..30) {
|
for (i in 1..30) {
|
||||||
buffer.push(i.toDouble())
|
buffer.push(i.toDouble())
|
||||||
@ -31,7 +30,7 @@ internal class RingBufferTest {
|
|||||||
while (true) emit(i++)
|
while (true) emit(i++)
|
||||||
}
|
}
|
||||||
|
|
||||||
val windowed = flow.windowed(10, Int32Ring)
|
val windowed = flow.windowed(10)
|
||||||
|
|
||||||
runBlocking {
|
runBlocking {
|
||||||
@Suppress("UNUSED_VARIABLE") val first = windowed.take(1).single()
|
@Suppress("UNUSED_VARIABLE") val first = windowed.take(1).single()
|
||||||
|
@ -6,8 +6,19 @@ A proof of concept module for adding type-safe dimensions to structures
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-dimensions:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-dimensions:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-dimensions:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -16,6 +27,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-dimensions:0.4.0-dev-3")
|
implementation("space.kscience:kmath-dimensions:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -6,7 +6,6 @@ kscience{
|
|||||||
jvm()
|
jvm()
|
||||||
js()
|
js()
|
||||||
native()
|
native()
|
||||||
wasm()
|
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
api(projects.kmathCore)
|
api(projects.kmathCore)
|
||||||
|
@ -153,7 +153,7 @@ public value class DMatrixContext<T : Any, out A : Ring<T>>(public val context:
|
|||||||
context.run { this@unaryMinus.unaryMinus() }.coerce()
|
context.run { this@unaryMinus.unaryMinus() }.coerce()
|
||||||
|
|
||||||
public inline fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.transposed(): DMatrix<T, R, C> =
|
public inline fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.transposed(): DMatrix<T, R, C> =
|
||||||
context.run { (this@transposed as Matrix<T>).transposed() }.coerce()
|
context.run { (this@transposed as Matrix<T>).transposed }.coerce()
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public val real: DMatrixContext<Double, Float64Field> = DMatrixContext(Double.algebra.linearSpace)
|
public val real: DMatrixContext<Double, Float64Field> = DMatrixContext(Double.algebra.linearSpace)
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.dimensions
|
|
||||||
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
private val dimensionMap: MutableMap<Int, Dimension> = hashMapOf(1 to D1, 2 to D2, 3 to D3)
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
public actual fun <D : Dimension> Dimension.Companion.resolve(type: KClass<D>): D = dimensionMap
|
|
||||||
.entries
|
|
||||||
.map(MutableMap.MutableEntry<Int, Dimension>::value)
|
|
||||||
.find { it::class == type } as? D
|
|
||||||
?: error("Can't resolve dimension $type")
|
|
||||||
|
|
||||||
public actual fun Dimension.Companion.of(dim: Int): Dimension = dimensionMap.getOrPut(dim) {
|
|
||||||
object : Dimension {
|
|
||||||
override val dim: Int get() = dim
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,8 +9,19 @@ EJML based linear algebra implementation.
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-ejml:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-ejml:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-ejml:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -19,6 +30,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-ejml:0.4.0-dev-3")
|
implementation("space.kscience:kmath-ejml:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
|
import space.kscience.kmath.ejml.codegen.ejmlCodegen
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("space.kscience.gradle.jvm")
|
id("space.kscience.gradle.jvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
val ejmlVerision = "0.43.1"
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api("org.ejml:ejml-ddense:$ejmlVerision")
|
api("org.ejml:ejml-ddense:0.41")
|
||||||
api("org.ejml:ejml-fdense:$ejmlVerision")
|
api("org.ejml:ejml-fdense:0.41")
|
||||||
api("org.ejml:ejml-dsparse:$ejmlVerision")
|
api("org.ejml:ejml-dsparse:0.41")
|
||||||
api("org.ejml:ejml-fsparse:$ejmlVerision")
|
api("org.ejml:ejml-fsparse:0.41")
|
||||||
api(projects.kmathCore)
|
api(project(":kmath-core"))
|
||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
@ -32,10 +32,10 @@ readme {
|
|||||||
) { "LinearSpace implementations." }
|
) { "LinearSpace implementations." }
|
||||||
}
|
}
|
||||||
|
|
||||||
//kotlin.sourceSets.main {
|
kotlin.sourceSets.main {
|
||||||
// val codegen by tasks.creating {
|
val codegen by tasks.creating {
|
||||||
// ejmlCodegen(kotlin.srcDirs.first().absolutePath + "/space/kscience/kmath/ejml/_generated.kt")
|
ejmlCodegen(kotlin.srcDirs.first().absolutePath + "/space/kscience/kmath/ejml/_generated.kt")
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// kotlin.srcDirs(files().builtBy(codegen))
|
kotlin.srcDirs(files().builtBy(codegen))
|
||||||
//}
|
}
|
||||||
|
@ -17,18 +17,21 @@ import org.ejml.sparse.csc.CommonOps_DSCC
|
|||||||
import org.ejml.sparse.csc.CommonOps_FSCC
|
import org.ejml.sparse.csc.CommonOps_FSCC
|
||||||
import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC
|
import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC
|
||||||
import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC
|
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.attributes.SafeType
|
import space.kscience.attributes.SafeType
|
||||||
import space.kscience.attributes.safeTypeOf
|
import space.kscience.attributes.safeTypeOf
|
||||||
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.linear.*
|
import space.kscience.kmath.linear.*
|
||||||
import space.kscience.kmath.linear.Matrix
|
import space.kscience.kmath.linear.Matrix
|
||||||
import space.kscience.kmath.nd.Structure2D
|
import space.kscience.kmath.nd.StructureFeature
|
||||||
import space.kscience.kmath.nd.StructureAttribute
|
|
||||||
import space.kscience.kmath.operations.Float32Field
|
import space.kscience.kmath.operations.Float32Field
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.Float64Field
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.structures.Float32
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
import space.kscience.kmath.structures.IntBuffer
|
import space.kscience.kmath.structures.FloatBuffer
|
||||||
import space.kscience.kmath.structures.asBuffer
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.cast
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [EjmlVector] specialization for [Double].
|
* [EjmlVector] specialization for [Double].
|
||||||
@ -75,6 +78,7 @@ public class EjmlFloatMatrix<out M : FMatrix>(override val origin: M) : EjmlMatr
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [EjmlLinearSpace] implementation based on [CommonOps_DDRM], [DecompositionFactory_DDRM] operations and
|
* [EjmlLinearSpace] implementation based on [CommonOps_DDRM], [DecompositionFactory_DDRM] operations and
|
||||||
* [DMatrixRMaj] matrices.
|
* [DMatrixRMaj] matrices.
|
||||||
@ -139,10 +143,10 @@ public object EjmlLinearSpaceDDRM : EjmlLinearSpace<Double, Float64Field, DMatri
|
|||||||
val out = DMatrixRMaj(1, 1)
|
val out = DMatrixRMaj(1, 1)
|
||||||
|
|
||||||
CommonOps_DDRM.add(
|
CommonOps_DDRM.add(
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
toEjml().origin,
|
toEjml().origin,
|
||||||
elementAlgebra { -one },
|
elementAlgebra { -one },
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -163,12 +167,12 @@ public object EjmlLinearSpaceDDRM : EjmlLinearSpace<Double, Float64Field, DMatri
|
|||||||
|
|
||||||
override fun Matrix<Double>.plus(other: Matrix<Double>): EjmlDoubleMatrix<DMatrixRMaj> {
|
override fun Matrix<Double>.plus(other: Matrix<Double>): EjmlDoubleMatrix<DMatrixRMaj> {
|
||||||
val out = DMatrixRMaj(1, 1)
|
val out = DMatrixRMaj(1, 1)
|
||||||
|
|
||||||
CommonOps_DDRM.add(
|
CommonOps_DDRM.add(
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
toEjml().origin,
|
toEjml().origin,
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -213,65 +217,77 @@ public object EjmlLinearSpaceDDRM : EjmlLinearSpace<Double, Float64Field, DMatri
|
|||||||
|
|
||||||
override fun Double.times(v: Point<Double>): EjmlDoubleVector<DMatrixRMaj> = v * this
|
override fun Double.times(v: Point<Double>): EjmlDoubleVector<DMatrixRMaj> = v * this
|
||||||
|
|
||||||
override fun <V, A : StructureAttribute<V>> computeAttribute(structure: Structure2D<Double>, attribute: A): V? {
|
@UnstableKMathAPI
|
||||||
|
override fun <F : StructureFeature> computeFeature(structure: Matrix<Double>, type: KClass<out F>): F? {
|
||||||
|
structure.getFeature(type)?.let { return it }
|
||||||
val origin = structure.toEjml().origin
|
val origin = structure.toEjml().origin
|
||||||
|
|
||||||
val raw: Any? = when (attribute) {
|
return when (type) {
|
||||||
Inverted -> {
|
InverseMatrixFeature::class -> object : InverseMatrixFeature<Double> {
|
||||||
val res = origin.copy()
|
override val inverse: Matrix<Double> by lazy {
|
||||||
CommonOps_DDRM.invert(res)
|
val res = origin.copy()
|
||||||
res.wrapMatrix()
|
CommonOps_DDRM.invert(res)
|
||||||
|
res.wrapMatrix()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Determinant -> CommonOps_DDRM.det(origin)
|
DeterminantFeature::class -> object : DeterminantFeature<Double> {
|
||||||
SVD -> object : SingularValueDecomposition<Double> {
|
override val determinant: Double by lazy { CommonOps_DDRM.det(origin) }
|
||||||
val ejmlSvd by lazy {
|
}
|
||||||
DecompositionFactory_DDRM
|
|
||||||
.svd(origin.numRows, origin.numCols, true, true, false)
|
SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<Double> {
|
||||||
|
private val svd by lazy {
|
||||||
|
DecompositionFactory_DDRM.svd(origin.numRows, origin.numCols, true, true, false)
|
||||||
.apply { decompose(origin.copy()) }
|
.apply { decompose(origin.copy()) }
|
||||||
}
|
}
|
||||||
override val u: Matrix<Double> get() = ejmlSvd.getU(null, false).wrapMatrix()
|
|
||||||
|
|
||||||
override val s: Matrix<Double> get() = ejmlSvd.getW(null).wrapMatrix()
|
|
||||||
override val v: Matrix<Double> get() = ejmlSvd.getV(null, false).wrapMatrix()
|
|
||||||
override val singularValues: Point<Double> get() = ejmlSvd.singularValues.asBuffer()
|
|
||||||
|
|
||||||
|
override val u: Matrix<Double> by lazy { svd.getU(null, false).wrapMatrix() }
|
||||||
|
override val s: Matrix<Double> by lazy { svd.getW(null).wrapMatrix() }
|
||||||
|
override val v: Matrix<Double> by lazy { svd.getV(null, false).wrapMatrix() }
|
||||||
|
override val singularValues: Point<Double> by lazy { DoubleBuffer(svd.singularValues) }
|
||||||
}
|
}
|
||||||
|
|
||||||
QR -> object : QRDecomposition<Double> {
|
QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> {
|
||||||
val ejmlQr by lazy { DecompositionFactory_DDRM.qr().apply { decompose(origin.copy()) } }
|
private val qr by lazy {
|
||||||
override val q: Matrix<Double> get() = ejmlQr.getQ(null, false).wrapMatrix()
|
DecompositionFactory_DDRM.qr().apply { decompose(origin.copy()) }
|
||||||
override val r: Matrix<Double> get() = ejmlQr.getR(null, false).wrapMatrix()
|
}
|
||||||
|
|
||||||
|
override val q: Matrix<Double> by lazy {
|
||||||
|
qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val r: Matrix<Double> by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) }
|
||||||
}
|
}
|
||||||
|
|
||||||
Cholesky -> object : CholeskyDecomposition<Double> {
|
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Double> {
|
||||||
override val l: Matrix<Double> by lazy {
|
override val l: Matrix<Double> by lazy {
|
||||||
val cholesky =
|
val cholesky =
|
||||||
DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) }
|
DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) }
|
||||||
|
|
||||||
cholesky.getT(null).wrapMatrix().withAttribute(LowerTriangular)
|
cholesky.getT(null).wrapMatrix().withFeature(LFeature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LUP -> object : LupDecomposition<Double> {
|
LupDecompositionFeature::class -> object : LupDecompositionFeature<Double> {
|
||||||
private val lup by lazy {
|
private val lup by lazy {
|
||||||
DecompositionFactory_DDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) }
|
DecompositionFactory_DDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val l: Matrix<Double>
|
override val l: Matrix<Double> by lazy {
|
||||||
get() = lup.getLower(null).wrapMatrix().withAttribute(LowerTriangular)
|
lup.getLower(null).wrapMatrix().withFeature(LFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val u: Matrix<Double> by lazy {
|
||||||
|
lup.getUpper(null).wrapMatrix().withFeature(UFeature)
|
||||||
|
}
|
||||||
|
|
||||||
override val u: Matrix<Double>
|
override val p: Matrix<Double> by lazy { lup.getRowPivot(null).wrapMatrix() }
|
||||||
get() = lup.getUpper(null).wrapMatrix().withAttribute(UpperTriangular)
|
|
||||||
override val pivot: IntBuffer get() = lup.getRowPivotV(null).asBuffer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
|
}?.let{
|
||||||
|
type.cast(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return raw as V?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -302,6 +318,7 @@ public object EjmlLinearSpaceDDRM : EjmlLinearSpace<Double, Float64Field, DMatri
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [EjmlLinearSpace] implementation based on [CommonOps_FDRM], [DecompositionFactory_FDRM] operations and
|
* [EjmlLinearSpace] implementation based on [CommonOps_FDRM], [DecompositionFactory_FDRM] operations and
|
||||||
* [FMatrixRMaj] matrices.
|
* [FMatrixRMaj] matrices.
|
||||||
@ -366,10 +383,10 @@ public object EjmlLinearSpaceFDRM : EjmlLinearSpace<Float, Float32Field, FMatrix
|
|||||||
val out = FMatrixRMaj(1, 1)
|
val out = FMatrixRMaj(1, 1)
|
||||||
|
|
||||||
CommonOps_FDRM.add(
|
CommonOps_FDRM.add(
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
toEjml().origin,
|
toEjml().origin,
|
||||||
elementAlgebra { -one },
|
elementAlgebra { -one },
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -390,12 +407,12 @@ public object EjmlLinearSpaceFDRM : EjmlLinearSpace<Float, Float32Field, FMatrix
|
|||||||
|
|
||||||
override fun Matrix<Float>.plus(other: Matrix<Float>): EjmlFloatMatrix<FMatrixRMaj> {
|
override fun Matrix<Float>.plus(other: Matrix<Float>): EjmlFloatMatrix<FMatrixRMaj> {
|
||||||
val out = FMatrixRMaj(1, 1)
|
val out = FMatrixRMaj(1, 1)
|
||||||
|
|
||||||
CommonOps_FDRM.add(
|
CommonOps_FDRM.add(
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
toEjml().origin,
|
toEjml().origin,
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -440,65 +457,77 @@ public object EjmlLinearSpaceFDRM : EjmlLinearSpace<Float, Float32Field, FMatrix
|
|||||||
|
|
||||||
override fun Float.times(v: Point<Float>): EjmlFloatVector<FMatrixRMaj> = v * this
|
override fun Float.times(v: Point<Float>): EjmlFloatVector<FMatrixRMaj> = v * this
|
||||||
|
|
||||||
override fun <V, A : StructureAttribute<V>> computeAttribute(structure: Structure2D<Float32>, attribute: A): V? {
|
@UnstableKMathAPI
|
||||||
|
override fun <F : StructureFeature> computeFeature(structure: Matrix<Float>, type: KClass<out F>): F? {
|
||||||
|
structure.getFeature(type)?.let { return it }
|
||||||
val origin = structure.toEjml().origin
|
val origin = structure.toEjml().origin
|
||||||
|
|
||||||
val raw: Any? = when (attribute) {
|
return when (type) {
|
||||||
Inverted -> {
|
InverseMatrixFeature::class -> object : InverseMatrixFeature<Float> {
|
||||||
val res = origin.copy()
|
override val inverse: Matrix<Float> by lazy {
|
||||||
CommonOps_FDRM.invert(res)
|
val res = origin.copy()
|
||||||
res.wrapMatrix()
|
CommonOps_FDRM.invert(res)
|
||||||
|
res.wrapMatrix()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Determinant -> CommonOps_FDRM.det(origin)
|
DeterminantFeature::class -> object : DeterminantFeature<Float> {
|
||||||
SVD -> object : SingularValueDecomposition<Float32> {
|
override val determinant: Float by lazy { CommonOps_FDRM.det(origin) }
|
||||||
val ejmlSvd by lazy {
|
}
|
||||||
DecompositionFactory_FDRM
|
|
||||||
.svd(origin.numRows, origin.numCols, true, true, false)
|
SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<Float> {
|
||||||
|
private val svd by lazy {
|
||||||
|
DecompositionFactory_FDRM.svd(origin.numRows, origin.numCols, true, true, false)
|
||||||
.apply { decompose(origin.copy()) }
|
.apply { decompose(origin.copy()) }
|
||||||
}
|
}
|
||||||
override val u: Matrix<Float32> get() = ejmlSvd.getU(null, false).wrapMatrix()
|
|
||||||
|
|
||||||
override val s: Matrix<Float32> get() = ejmlSvd.getW(null).wrapMatrix()
|
|
||||||
override val v: Matrix<Float32> get() = ejmlSvd.getV(null, false).wrapMatrix()
|
|
||||||
override val singularValues: Point<Float32> get() = ejmlSvd.singularValues.asBuffer()
|
|
||||||
|
|
||||||
|
override val u: Matrix<Float> by lazy { svd.getU(null, false).wrapMatrix() }
|
||||||
|
override val s: Matrix<Float> by lazy { svd.getW(null).wrapMatrix() }
|
||||||
|
override val v: Matrix<Float> by lazy { svd.getV(null, false).wrapMatrix() }
|
||||||
|
override val singularValues: Point<Float> by lazy { FloatBuffer(svd.singularValues) }
|
||||||
}
|
}
|
||||||
|
|
||||||
QR -> object : QRDecomposition<Float32> {
|
QRDecompositionFeature::class -> object : QRDecompositionFeature<Float> {
|
||||||
val ejmlQr by lazy { DecompositionFactory_FDRM.qr().apply { decompose(origin.copy()) } }
|
private val qr by lazy {
|
||||||
override val q: Matrix<Float32> get() = ejmlQr.getQ(null, false).wrapMatrix()
|
DecompositionFactory_FDRM.qr().apply { decompose(origin.copy()) }
|
||||||
override val r: Matrix<Float32> get() = ejmlQr.getR(null, false).wrapMatrix()
|
}
|
||||||
|
|
||||||
|
override val q: Matrix<Float> by lazy {
|
||||||
|
qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val r: Matrix<Float> by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) }
|
||||||
}
|
}
|
||||||
|
|
||||||
Cholesky -> object : CholeskyDecomposition<Float32> {
|
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Float> {
|
||||||
override val l: Matrix<Float32> by lazy {
|
override val l: Matrix<Float> by lazy {
|
||||||
val cholesky =
|
val cholesky =
|
||||||
DecompositionFactory_FDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) }
|
DecompositionFactory_FDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) }
|
||||||
|
|
||||||
cholesky.getT(null).wrapMatrix().withAttribute(LowerTriangular)
|
cholesky.getT(null).wrapMatrix().withFeature(LFeature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LUP -> object : LupDecomposition<Float32> {
|
LupDecompositionFeature::class -> object : LupDecompositionFeature<Float> {
|
||||||
private val lup by lazy {
|
private val lup by lazy {
|
||||||
DecompositionFactory_FDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) }
|
DecompositionFactory_FDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val l: Matrix<Float32>
|
override val l: Matrix<Float> by lazy {
|
||||||
get() = lup.getLower(null).wrapMatrix().withAttribute(LowerTriangular)
|
lup.getLower(null).wrapMatrix().withFeature(LFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val u: Matrix<Float> by lazy {
|
||||||
|
lup.getUpper(null).wrapMatrix().withFeature(UFeature)
|
||||||
|
}
|
||||||
|
|
||||||
override val u: Matrix<Float32>
|
override val p: Matrix<Float> by lazy { lup.getRowPivot(null).wrapMatrix() }
|
||||||
get() = lup.getUpper(null).wrapMatrix().withAttribute(UpperTriangular)
|
|
||||||
override val pivot: IntBuffer get() = lup.getRowPivotV(null).asBuffer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
|
}?.let{
|
||||||
|
type.cast(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return raw as V?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -529,6 +558,7 @@ public object EjmlLinearSpaceFDRM : EjmlLinearSpace<Float, Float32Field, FMatrix
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [EjmlLinearSpace] implementation based on [CommonOps_DSCC], [DecompositionFactory_DSCC] operations and
|
* [EjmlLinearSpace] implementation based on [CommonOps_DSCC], [DecompositionFactory_DSCC] operations and
|
||||||
* [DMatrixSparseCSC] matrices.
|
* [DMatrixSparseCSC] matrices.
|
||||||
@ -593,12 +623,12 @@ public object EjmlLinearSpaceDSCC : EjmlLinearSpace<Double, Float64Field, DMatri
|
|||||||
val out = DMatrixSparseCSC(1, 1)
|
val out = DMatrixSparseCSC(1, 1)
|
||||||
|
|
||||||
CommonOps_DSCC.add(
|
CommonOps_DSCC.add(
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
toEjml().origin,
|
toEjml().origin,
|
||||||
elementAlgebra { -one },
|
elementAlgebra { -one },
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -619,14 +649,14 @@ public object EjmlLinearSpaceDSCC : EjmlLinearSpace<Double, Float64Field, DMatri
|
|||||||
|
|
||||||
override fun Matrix<Double>.plus(other: Matrix<Double>): EjmlDoubleMatrix<DMatrixSparseCSC> {
|
override fun Matrix<Double>.plus(other: Matrix<Double>): EjmlDoubleMatrix<DMatrixSparseCSC> {
|
||||||
val out = DMatrixSparseCSC(1, 1)
|
val out = DMatrixSparseCSC(1, 1)
|
||||||
|
|
||||||
CommonOps_DSCC.add(
|
CommonOps_DSCC.add(
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
toEjml().origin,
|
toEjml().origin,
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -642,7 +672,7 @@ public object EjmlLinearSpaceDSCC : EjmlLinearSpace<Double, Float64Field, DMatri
|
|||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -658,7 +688,7 @@ public object EjmlLinearSpaceDSCC : EjmlLinearSpace<Double, Float64Field, DMatri
|
|||||||
elementAlgebra { -one },
|
elementAlgebra { -one },
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -675,52 +705,64 @@ public object EjmlLinearSpaceDSCC : EjmlLinearSpace<Double, Float64Field, DMatri
|
|||||||
|
|
||||||
override fun Double.times(v: Point<Double>): EjmlDoubleVector<DMatrixSparseCSC> = v * this
|
override fun Double.times(v: Point<Double>): EjmlDoubleVector<DMatrixSparseCSC> = v * this
|
||||||
|
|
||||||
override fun <V, A : StructureAttribute<V>> computeAttribute(structure: Structure2D<Double>, attribute: A): V? {
|
@UnstableKMathAPI
|
||||||
|
override fun <F : StructureFeature> computeFeature(structure: Matrix<Double>, type: KClass<out F>): F? {
|
||||||
|
structure.getFeature(type)?.let { return it }
|
||||||
val origin = structure.toEjml().origin
|
val origin = structure.toEjml().origin
|
||||||
|
|
||||||
val raw: Any? = when (attribute) {
|
return when (type) {
|
||||||
Inverted -> {
|
QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> {
|
||||||
val res = DMatrixRMaj(origin.numRows,origin.numCols)
|
private val qr by lazy {
|
||||||
CommonOps_DSCC.invert(origin,res)
|
DecompositionFactory_DSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) }
|
||||||
res.wrapMatrix()
|
}
|
||||||
|
|
||||||
|
override val q: Matrix<Double> by lazy {
|
||||||
|
qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val r: Matrix<Double> by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) }
|
||||||
}
|
}
|
||||||
|
|
||||||
Determinant -> CommonOps_DSCC.det(origin)
|
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Double> {
|
||||||
|
|
||||||
QR -> object : QRDecomposition<Double> {
|
|
||||||
val ejmlQr by lazy { DecompositionFactory_DSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) } }
|
|
||||||
override val q: Matrix<Double> get() = ejmlQr.getQ(null, false).wrapMatrix()
|
|
||||||
override val r: Matrix<Double> get() = ejmlQr.getR(null, false).wrapMatrix()
|
|
||||||
}
|
|
||||||
|
|
||||||
Cholesky -> object : CholeskyDecomposition<Double> {
|
|
||||||
override val l: Matrix<Double> by lazy {
|
override val l: Matrix<Double> by lazy {
|
||||||
val cholesky =
|
val cholesky =
|
||||||
DecompositionFactory_DSCC.cholesky().apply { decompose(origin.copy()) }
|
DecompositionFactory_DSCC.cholesky().apply { decompose(origin.copy()) }
|
||||||
|
|
||||||
(cholesky.getT(null) as DMatrix).wrapMatrix().withAttribute(LowerTriangular)
|
(cholesky.getT(null) as DMatrix).wrapMatrix().withFeature(LFeature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LUP -> object : LupDecomposition<Double> {
|
LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object :
|
||||||
private val lup by lazy {
|
LUDecompositionFeature<Double>, DeterminantFeature<Double>, InverseMatrixFeature<Double> {
|
||||||
|
private val lu by lazy {
|
||||||
DecompositionFactory_DSCC.lu(FillReducing.NONE).apply { decompose(origin.copy()) }
|
DecompositionFactory_DSCC.lu(FillReducing.NONE).apply { decompose(origin.copy()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val l: Matrix<Double>
|
override val l: Matrix<Double> by lazy {
|
||||||
get() = lup.getLower(null).wrapMatrix().withAttribute(LowerTriangular)
|
lu.getLower(null).wrapMatrix().withFeature(LFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val u: Matrix<Double> by lazy {
|
||||||
|
lu.getUpper(null).wrapMatrix().withFeature(UFeature)
|
||||||
|
}
|
||||||
|
|
||||||
override val u: Matrix<Double>
|
override val inverse: Matrix<Double> by lazy {
|
||||||
get() = lup.getUpper(null).wrapMatrix().withAttribute(UpperTriangular)
|
var a = origin
|
||||||
override val pivot: IntBuffer get() = lup.getRowPivotV(null).asBuffer()
|
val inverse = DMatrixRMaj(1, 1)
|
||||||
|
val solver = LinearSolverFactory_DSCC.lu(FillReducing.NONE)
|
||||||
|
if (solver.modifiesA()) a = a.copy()
|
||||||
|
val i = CommonOps_DDRM.identity(a.numRows)
|
||||||
|
solver.solve(i, inverse)
|
||||||
|
inverse.wrapMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val determinant: Double by lazy { elementAlgebra.number(lu.computeDeterminant().real) }
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
|
}?.let{
|
||||||
|
type.cast(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return raw as V?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -751,6 +793,7 @@ public object EjmlLinearSpaceDSCC : EjmlLinearSpace<Double, Float64Field, DMatri
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [EjmlLinearSpace] implementation based on [CommonOps_FSCC], [DecompositionFactory_FSCC] operations and
|
* [EjmlLinearSpace] implementation based on [CommonOps_FSCC], [DecompositionFactory_FSCC] operations and
|
||||||
* [FMatrixSparseCSC] matrices.
|
* [FMatrixSparseCSC] matrices.
|
||||||
@ -815,12 +858,12 @@ public object EjmlLinearSpaceFSCC : EjmlLinearSpace<Float, Float32Field, FMatrix
|
|||||||
val out = FMatrixSparseCSC(1, 1)
|
val out = FMatrixSparseCSC(1, 1)
|
||||||
|
|
||||||
CommonOps_FSCC.add(
|
CommonOps_FSCC.add(
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
toEjml().origin,
|
toEjml().origin,
|
||||||
elementAlgebra { -one },
|
elementAlgebra { -one },
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -841,14 +884,14 @@ public object EjmlLinearSpaceFSCC : EjmlLinearSpace<Float, Float32Field, FMatrix
|
|||||||
|
|
||||||
override fun Matrix<Float>.plus(other: Matrix<Float>): EjmlFloatMatrix<FMatrixSparseCSC> {
|
override fun Matrix<Float>.plus(other: Matrix<Float>): EjmlFloatMatrix<FMatrixSparseCSC> {
|
||||||
val out = FMatrixSparseCSC(1, 1)
|
val out = FMatrixSparseCSC(1, 1)
|
||||||
|
|
||||||
CommonOps_FSCC.add(
|
CommonOps_FSCC.add(
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
toEjml().origin,
|
toEjml().origin,
|
||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -864,7 +907,7 @@ public object EjmlLinearSpaceFSCC : EjmlLinearSpace<Float, Float32Field, FMatrix
|
|||||||
elementAlgebra.one,
|
elementAlgebra.one,
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -880,7 +923,7 @@ public object EjmlLinearSpaceFSCC : EjmlLinearSpace<Float, Float32Field, FMatrix
|
|||||||
elementAlgebra { -one },
|
elementAlgebra { -one },
|
||||||
other.toEjml().origin,
|
other.toEjml().origin,
|
||||||
out,
|
out,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -896,52 +939,65 @@ public object EjmlLinearSpaceFSCC : EjmlLinearSpace<Float, Float32Field, FMatrix
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun Float.times(v: Point<Float>): EjmlFloatVector<FMatrixSparseCSC> = v * this
|
override fun Float.times(v: Point<Float>): EjmlFloatVector<FMatrixSparseCSC> = v * this
|
||||||
override fun <V, A : StructureAttribute<V>> computeAttribute(structure: Structure2D<Float32>, attribute: A): V? {
|
|
||||||
|
@UnstableKMathAPI
|
||||||
|
override fun <F : StructureFeature> computeFeature(structure: Matrix<Float>, type: KClass<out F>): F? {
|
||||||
|
structure.getFeature(type)?.let { return it }
|
||||||
val origin = structure.toEjml().origin
|
val origin = structure.toEjml().origin
|
||||||
|
|
||||||
val raw: Any? = when (attribute) {
|
return when (type) {
|
||||||
Inverted -> {
|
QRDecompositionFeature::class -> object : QRDecompositionFeature<Float> {
|
||||||
val res = FMatrixRMaj(origin.numRows,origin.numCols)
|
private val qr by lazy {
|
||||||
CommonOps_FSCC.invert(origin,res)
|
DecompositionFactory_FSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) }
|
||||||
res.wrapMatrix()
|
}
|
||||||
|
|
||||||
|
override val q: Matrix<Float> by lazy {
|
||||||
|
qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val r: Matrix<Float> by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) }
|
||||||
}
|
}
|
||||||
|
|
||||||
Determinant -> CommonOps_FSCC.det(origin)
|
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Float> {
|
||||||
|
override val l: Matrix<Float> by lazy {
|
||||||
QR -> object : QRDecomposition<Float32> {
|
|
||||||
val ejmlQr by lazy { DecompositionFactory_FSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) } }
|
|
||||||
override val q: Matrix<Float32> get() = ejmlQr.getQ(null, false).wrapMatrix()
|
|
||||||
override val r: Matrix<Float32> get() = ejmlQr.getR(null, false).wrapMatrix()
|
|
||||||
}
|
|
||||||
|
|
||||||
Cholesky -> object : CholeskyDecomposition<Float32> {
|
|
||||||
override val l: Matrix<Float32> by lazy {
|
|
||||||
val cholesky =
|
val cholesky =
|
||||||
DecompositionFactory_FSCC.cholesky().apply { decompose(origin.copy()) }
|
DecompositionFactory_FSCC.cholesky().apply { decompose(origin.copy()) }
|
||||||
|
|
||||||
(cholesky.getT(null) as FMatrix).wrapMatrix().withAttribute(LowerTriangular)
|
(cholesky.getT(null) as FMatrix).wrapMatrix().withFeature(LFeature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LUP -> object : LupDecomposition<Float32> {
|
LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object :
|
||||||
private val lup by lazy {
|
LUDecompositionFeature<Float>, DeterminantFeature<Float>, InverseMatrixFeature<Float> {
|
||||||
|
private val lu by lazy {
|
||||||
DecompositionFactory_FSCC.lu(FillReducing.NONE).apply { decompose(origin.copy()) }
|
DecompositionFactory_FSCC.lu(FillReducing.NONE).apply { decompose(origin.copy()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val l: Matrix<Float32>
|
override val l: Matrix<Float> by lazy {
|
||||||
get() = lup.getLower(null).wrapMatrix().withAttribute(LowerTriangular)
|
lu.getLower(null).wrapMatrix().withFeature(LFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val u: Matrix<Float> by lazy {
|
||||||
|
lu.getUpper(null).wrapMatrix().withFeature(UFeature)
|
||||||
|
}
|
||||||
|
|
||||||
override val u: Matrix<Float32>
|
override val inverse: Matrix<Float> by lazy {
|
||||||
get() = lup.getUpper(null).wrapMatrix().withAttribute(UpperTriangular)
|
var a = origin
|
||||||
override val pivot: IntBuffer get() = lup.getRowPivotV(null).asBuffer()
|
val inverse = FMatrixRMaj(1, 1)
|
||||||
|
val solver = LinearSolverFactory_FSCC.lu(FillReducing.NONE)
|
||||||
|
if (solver.modifiesA()) a = a.copy()
|
||||||
|
val i = CommonOps_FDRM.identity(a.numRows)
|
||||||
|
solver.solve(i, inverse)
|
||||||
|
inverse.wrapMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val determinant: Float by lazy { elementAlgebra.number(lu.computeDeterminant().real) }
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
|
}?.let{
|
||||||
|
type.cast(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return raw as V?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
@ -58,19 +58,19 @@ internal class EjmlMatrixTest {
|
|||||||
|
|
||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
@Test
|
@Test
|
||||||
fun features() = EjmlLinearSpaceDDRM {
|
fun features() {
|
||||||
val m = randomMatrix
|
val m = randomMatrix
|
||||||
val w = EjmlDoubleMatrix(m)
|
val w = EjmlDoubleMatrix(m)
|
||||||
val det: Double = w.getOrComputeAttribute(Determinant) ?: fail()
|
val det: Determinant<Double> = EjmlLinearSpaceDDRM.attributeForOrNull(w) ?: fail()
|
||||||
assertEquals(CommonOps_DDRM.det(m), det)
|
assertEquals(CommonOps_DDRM.det(m), det.determinant)
|
||||||
val lup: LupDecomposition<Double> = w.getOrComputeAttribute(LUP) ?: fail()
|
val lup: LupDecompositionAttribute<Double> = EjmlLinearSpaceDDRM.attributeForOrNull(w) ?: fail()
|
||||||
|
|
||||||
val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows, m.numCols)
|
val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows, m.numCols)
|
||||||
.also { it.decompose(m.copy()) }
|
.also { it.decompose(m.copy()) }
|
||||||
|
|
||||||
assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getLower(null)), lup.l)
|
assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getLower(null)), lup.l)
|
||||||
assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getUpper(null)), lup.u)
|
assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getUpper(null)), lup.u)
|
||||||
assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getRowPivot(null)), lup.pivotMatrix(this))
|
assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getRowPivot(null)), lup.p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -9,8 +9,19 @@ Specialization of KMath APIs for Double numbers.
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-for-real:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-for-real:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-for-real:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -19,6 +30,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-for-real:0.4.0-dev-3")
|
implementation("space.kscience:kmath-for-real:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -6,7 +6,6 @@ kscience {
|
|||||||
jvm()
|
jvm()
|
||||||
js()
|
js()
|
||||||
native()
|
native()
|
||||||
wasm()
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(projects.kmathCore)
|
api(projects.kmathCore)
|
||||||
|
@ -7,7 +7,7 @@ package space.kscience.kmath.real
|
|||||||
|
|
||||||
import space.kscience.kmath.linear.asMatrix
|
import space.kscience.kmath.linear.asMatrix
|
||||||
import space.kscience.kmath.linear.linearSpace
|
import space.kscience.kmath.linear.linearSpace
|
||||||
import space.kscience.kmath.linear.transposed
|
import space.kscience.kmath.linear.transpose
|
||||||
import space.kscience.kmath.operations.algebra
|
import space.kscience.kmath.operations.algebra
|
||||||
import space.kscience.kmath.structures.Float64Buffer
|
import space.kscience.kmath.structures.Float64Buffer
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
@ -34,7 +34,7 @@ internal class DoubleVectorTest {
|
|||||||
val vector1 = Float64Buffer(5) { it.toDouble() }
|
val vector1 = Float64Buffer(5) { it.toDouble() }
|
||||||
val vector2 = Float64Buffer(5) { 5 - it.toDouble() }
|
val vector2 = Float64Buffer(5) { 5 - it.toDouble() }
|
||||||
val matrix1 = vector1.asMatrix()
|
val matrix1 = vector1.asMatrix()
|
||||||
val matrix2 = vector2.asMatrix().transposed()
|
val matrix2 = vector2.asMatrix().transpose()
|
||||||
val product = matrix1 dot matrix2
|
val product = matrix1 dot matrix2
|
||||||
assertEquals(5.0, product[1, 0])
|
assertEquals(5.0, product[1, 0])
|
||||||
assertEquals(6.0, product[2, 2])
|
assertEquals(6.0, product[2, 2])
|
||||||
|
@ -11,8 +11,19 @@ Functions and interpolations.
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-functions:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-functions:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-functions:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -21,6 +32,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-functions:0.4.0-dev-3")
|
implementation("space.kscience:kmath-functions:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -6,6 +6,7 @@ kscience{
|
|||||||
jvm()
|
jvm()
|
||||||
js()
|
js()
|
||||||
native()
|
native()
|
||||||
|
|
||||||
wasm()
|
wasm()
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -92,7 +92,7 @@ public inline fun <reified T : Any> GaussIntegrator<T>.integrate(
|
|||||||
range: ClosedRange<Double>,
|
range: ClosedRange<Double>,
|
||||||
order: Int = 10,
|
order: Int = 10,
|
||||||
intervals: Int = 10,
|
intervals: Int = 10,
|
||||||
attributesBuilder: AttributesBuilder<UnivariateIntegrand<T>>.() -> Unit = {},
|
attributesBuilder: AttributesBuilder<UnivariateIntegrand<T>>.() -> Unit,
|
||||||
noinline function: (Double) -> T,
|
noinline function: (Double) -> T,
|
||||||
): UnivariateIntegrand<T> {
|
): UnivariateIntegrand<T> {
|
||||||
require(range.endInclusive > range.start) { "The range upper bound should be higher than lower bound" }
|
require(range.endInclusive > range.start) { "The range upper bound should be higher than lower bound" }
|
||||||
|
@ -23,7 +23,7 @@ import space.kscience.kmath.structures.MutableBufferFactory
|
|||||||
*/
|
*/
|
||||||
public class SplineInterpolator<T : Comparable<T>>(
|
public class SplineInterpolator<T : Comparable<T>>(
|
||||||
override val algebra: Field<T>,
|
override val algebra: Field<T>,
|
||||||
public val bufferFactory: MutableBufferFactory<T> = algebra.bufferFactory,
|
public val bufferFactory: MutableBufferFactory<T>,
|
||||||
) : PolynomialInterpolator<T> {
|
) : PolynomialInterpolator<T> {
|
||||||
//TODO possibly optimize zeroed buffers
|
//TODO possibly optimize zeroed buffers
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ package space.kscience.kmath.functions.testUtils
|
|||||||
|
|
||||||
import space.kscience.kmath.operations.Ring
|
import space.kscience.kmath.operations.Ring
|
||||||
import space.kscience.kmath.operations.ScaleOperations
|
import space.kscience.kmath.operations.ScaleOperations
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
|
||||||
|
|
||||||
|
|
||||||
class IntModulo {
|
class IntModulo {
|
||||||
@ -110,17 +109,15 @@ class IntModulo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE")
|
||||||
class IntModuloRing(modulus: Int) : Ring<IntModulo>, ScaleOperations<IntModulo> {
|
class IntModuloRing : Ring<IntModulo>, ScaleOperations<IntModulo> {
|
||||||
|
|
||||||
val modulus: Int
|
val modulus: Int
|
||||||
|
|
||||||
init {
|
constructor(modulus: Int) {
|
||||||
require(modulus != 0) { "modulus can not be zero" }
|
require(modulus != 0) { "modulus can not be zero" }
|
||||||
this.modulus = if (modulus < 0) -modulus else modulus
|
this.modulus = if (modulus < 0) -modulus else modulus
|
||||||
}
|
}
|
||||||
|
|
||||||
override val bufferFactory: MutableBufferFactory<IntModulo> = MutableBufferFactory()
|
|
||||||
|
|
||||||
override inline val zero: IntModulo get() = IntModulo(0, modulus, toCheckInput = false)
|
override inline val zero: IntModulo get() = IntModulo(0, modulus, toCheckInput = false)
|
||||||
override inline val one: IntModulo get() = IntModulo(1, modulus, toCheckInput = false)
|
override inline val one: IntModulo get() = IntModulo(1, modulus, toCheckInput = false)
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ package space.kscience.kmath.functions.testUtils
|
|||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.Field
|
import space.kscience.kmath.operations.Field
|
||||||
import space.kscience.kmath.operations.NumbersAddOps
|
import space.kscience.kmath.operations.NumbersAddOps
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
|
||||||
|
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
class Rational {
|
class Rational {
|
||||||
@ -160,7 +159,6 @@ class Rational {
|
|||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE")
|
||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
object RationalField : Field<Rational>, NumbersAddOps<Rational> {
|
object RationalField : Field<Rational>, NumbersAddOps<Rational> {
|
||||||
override val bufferFactory: MutableBufferFactory<Rational> = MutableBufferFactory()
|
|
||||||
override inline val zero: Rational get() = Rational.ZERO
|
override inline val zero: Rational get() = Rational.ZERO
|
||||||
override inline val one: Rational get() = Rational.ONE
|
override inline val one: Rational get() = Rational.ONE
|
||||||
|
|
||||||
|
@ -18,15 +18,15 @@ import kotlin.test.assertEquals
|
|||||||
class SplineIntegralTest {
|
class SplineIntegralTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun integratePolynomial() {
|
fun integratePolynomial(){
|
||||||
val polynomial = Polynomial(1.0, 2.0, 3.0)
|
val polynomial = Polynomial(1.0, 2.0, 3.0)
|
||||||
val integral = polynomial.integrate(Float64Field, 1.0..2.0)
|
val integral = polynomial.integrate(Float64Field,1.0..2.0)
|
||||||
assertEquals(11.0, integral, 0.001)
|
assertEquals(11.0, integral, 0.001)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun gaussSin() {
|
fun gaussSin() {
|
||||||
val res = Float64Field.splineIntegrator.integrate(0.0..2 * PI, { IntegrandMaxCalls(5) }) { x ->
|
val res = Float64Field.splineIntegrator.integrate(0.0..2 * PI, IntegrandMaxCalls(5)) { x ->
|
||||||
sin(x)
|
sin(x)
|
||||||
}
|
}
|
||||||
assertEquals(0.0, res.value, 1e-2)
|
assertEquals(0.0, res.value, 1e-2)
|
||||||
@ -34,8 +34,8 @@ class SplineIntegralTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun gaussUniform() {
|
fun gaussUniform() {
|
||||||
val res = Float64Field.splineIntegrator.integrate(35.0..100.0, { IntegrandMaxCalls(20) }) { x ->
|
val res = Float64Field.splineIntegrator.integrate(35.0..100.0, IntegrandMaxCalls(20)) { x ->
|
||||||
if (x in 30.0..50.0) {
|
if(x in 30.0..50.0){
|
||||||
1.0
|
1.0
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
|
@ -6,8 +6,19 @@
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-geometry:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-geometry:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-geometry:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -16,6 +27,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-geometry:0.4.0-dev-3")
|
implementation("space.kscience:kmath-geometry:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -7,8 +7,8 @@ package space.kscience.kmath.geometry
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.kmath.geometry.euclidean2d.Float64Vector2D
|
import space.kscience.kmath.geometry.euclidean2d.DoubleVector2D
|
||||||
import space.kscience.kmath.geometry.euclidean3d.Float64Vector3D
|
import space.kscience.kmath.geometry.euclidean3d.DoubleVector3D
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A line formed by [start] vector of start and a [direction] vector. Direction vector is not necessarily normalized,
|
* A line formed by [start] vector of start and a [direction] vector. Direction vector is not necessarily normalized,
|
||||||
@ -25,8 +25,8 @@ private data class LineImpl<out V : Any>(override val start: V, override val dir
|
|||||||
|
|
||||||
public fun <V : Any> Line(base: V, direction: V): Line<V> = LineImpl(base, direction)
|
public fun <V : Any> Line(base: V, direction: V): Line<V> = LineImpl(base, direction)
|
||||||
|
|
||||||
public typealias Line2D = Line<Float64Vector2D>
|
public typealias Line2D = Line<DoubleVector2D>
|
||||||
public typealias Line3D = Line<Float64Vector3D>
|
public typealias Line3D = Line<DoubleVector3D>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A directed line segment between [begin] and [end]
|
* A directed line segment between [begin] and [end]
|
||||||
@ -49,5 +49,5 @@ public fun <V : Any> LineSegment<V>.line(algebra: GeometrySpace<V, *>): Line<V>
|
|||||||
Line(begin, end - begin)
|
Line(begin, end - begin)
|
||||||
}
|
}
|
||||||
|
|
||||||
public typealias LineSegment2D = LineSegment<Float64Vector2D>
|
public typealias LineSegment2D = LineSegment<DoubleVector2D>
|
||||||
public typealias LineSegment3D = LineSegment<Float64Vector3D>
|
public typealias LineSegment3D = LineSegment<DoubleVector3D>
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.geometry
|
package space.kscience.kmath.geometry
|
||||||
|
|
||||||
import space.kscience.attributes.SafeType
|
|
||||||
import space.kscience.kmath.linear.Point
|
import space.kscience.kmath.linear.Point
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
|
|
||||||
@ -34,9 +33,6 @@ public fun <T> Buffer<T>.asVector3D(): Vector3D<T> = object : Vector3D<T> {
|
|||||||
require(this@asVector3D.size == 3) { "Buffer of size 3 is required for Vector3D" }
|
require(this@asVector3D.size == 3) { "Buffer of size 3 is required for Vector3D" }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val type: SafeType<T> = this@asVector3D.type
|
|
||||||
|
|
||||||
|
|
||||||
override val x: T get() = this@asVector3D[0]
|
override val x: T get() = this@asVector3D[0]
|
||||||
override val y: T get() = this@asVector3D[1]
|
override val y: T get() = this@asVector3D[1]
|
||||||
override val z: T get() = this@asVector3D[2]
|
override val z: T get() = this@asVector3D[2]
|
||||||
|
@ -11,8 +11,6 @@ import kotlinx.serialization.builtins.serializer
|
|||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import space.kscience.kmath.operations.Group
|
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
|
||||||
import kotlin.jvm.JvmInline
|
import kotlin.jvm.JvmInline
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
@ -30,19 +28,11 @@ public sealed interface Angle : Comparable<Angle> {
|
|||||||
public operator fun div(other: Angle): Double
|
public operator fun div(other: Angle): Double
|
||||||
public operator fun unaryMinus(): Angle
|
public operator fun unaryMinus(): Angle
|
||||||
|
|
||||||
public companion object: Group<Angle> {
|
public companion object {
|
||||||
override val zero: Radians = Radians(0.0)
|
public val zero: Radians = Radians(0.0)
|
||||||
public val pi: Radians = Radians(PI)
|
public val pi: Radians = Radians(PI)
|
||||||
public val piTimes2: Radians = Radians(PI * 2)
|
public val piTimes2: Radians = Radians(PI * 2)
|
||||||
public val piDiv2: Radians = Radians(PI / 2)
|
public val piDiv2: Radians = Radians(PI / 2)
|
||||||
|
|
||||||
|
|
||||||
override fun add(left: Angle, right: Angle): Angle = left + right
|
|
||||||
|
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
|
||||||
override fun Angle.unaryMinus(): Angle = -this
|
|
||||||
|
|
||||||
override val bufferFactory: MutableBufferFactory<Angle> = MutableBufferFactory()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +43,7 @@ public object AngleSerializer : KSerializer<Angle> {
|
|||||||
override fun deserialize(decoder: Decoder): Angle = decoder.decodeDouble().degrees
|
override fun deserialize(decoder: Decoder): Angle = decoder.decodeDouble().degrees
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: Angle) {
|
override fun serialize(encoder: Encoder, value: Angle) {
|
||||||
encoder.encodeDouble(value.toDegrees().value)
|
encoder.encodeDouble(value.degrees)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,16 +56,16 @@ public value class Radians(public val value: Double) : Angle {
|
|||||||
override fun toRadians(): Radians = this
|
override fun toRadians(): Radians = this
|
||||||
override fun toDegrees(): Degrees = Degrees(value * 180 / PI)
|
override fun toDegrees(): Degrees = Degrees(value * 180 / PI)
|
||||||
|
|
||||||
public override fun plus(other: Angle): Radians = Radians(value + other.toRadians().value)
|
public override fun plus(other: Angle): Radians = Radians(value + other.radians)
|
||||||
public override fun minus(other: Angle): Radians = Radians(value - other.toRadians().value)
|
public override fun minus(other: Angle): Radians = Radians(value - other.radians)
|
||||||
|
|
||||||
public override fun times(other: Number): Radians = Radians(value * other.toDouble())
|
public override fun times(other: Number): Radians = Radians(value * other.toDouble())
|
||||||
public override fun div(other: Number): Radians = Radians(value / other.toDouble())
|
public override fun div(other: Number): Radians = Radians(value / other.toDouble())
|
||||||
override fun div(other: Angle): Double = value / other.toRadians().value
|
override fun div(other: Angle): Double = value / other.radians
|
||||||
|
|
||||||
public override fun unaryMinus(): Radians = Radians(-value)
|
public override fun unaryMinus(): Radians = Radians(-value)
|
||||||
|
|
||||||
override fun compareTo(other: Angle): Int = value.compareTo(other.toRadians().value)
|
override fun compareTo(other: Angle): Int = value.compareTo(other.radians)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun sin(angle: Angle): Double = kotlin.math.sin(angle.toRadians().value)
|
public fun sin(angle: Angle): Double = kotlin.math.sin(angle.toRadians().value)
|
||||||
@ -95,16 +85,16 @@ public value class Degrees(public val value: Double) : Angle {
|
|||||||
override fun toRadians(): Radians = Radians(value * PI / 180)
|
override fun toRadians(): Radians = Radians(value * PI / 180)
|
||||||
override fun toDegrees(): Degrees = this
|
override fun toDegrees(): Degrees = this
|
||||||
|
|
||||||
public override fun plus(other: Angle): Degrees = Degrees(value + other.toDegrees().value)
|
public override fun plus(other: Angle): Degrees = Degrees(value + other.degrees)
|
||||||
public override fun minus(other: Angle): Degrees = Degrees(value - other.toDegrees().value)
|
public override fun minus(other: Angle): Degrees = Degrees(value - other.degrees)
|
||||||
|
|
||||||
public override fun times(other: Number): Degrees = Degrees(value * other.toDouble())
|
public override fun times(other: Number): Degrees = Degrees(value * other.toDouble())
|
||||||
public override fun div(other: Number): Degrees = Degrees(value / other.toDouble())
|
public override fun div(other: Number): Degrees = Degrees(value / other.toDouble())
|
||||||
override fun div(other: Angle): Double = value / other.toDegrees().value
|
override fun div(other: Angle): Double = value / other.degrees
|
||||||
|
|
||||||
public override fun unaryMinus(): Degrees = Degrees(-value)
|
public override fun unaryMinus(): Degrees = Degrees(-value)
|
||||||
|
|
||||||
override fun compareTo(other: Angle): Int = value.compareTo(other.toDegrees().value)
|
override fun compareTo(other: Angle): Int = value.compareTo(other.degrees)
|
||||||
}
|
}
|
||||||
|
|
||||||
public val Number.degrees: Degrees get() = Degrees(toDouble())
|
public val Number.degrees: Degrees get() = Degrees(toDouble())
|
||||||
@ -116,6 +106,6 @@ public val Angle.degrees: Double get() = toDegrees().value
|
|||||||
* Normalized angle 2 PI range symmetric around [center]. By default, uses (0, 2PI) range.
|
* Normalized angle 2 PI range symmetric around [center]. By default, uses (0, 2PI) range.
|
||||||
*/
|
*/
|
||||||
public fun Angle.normalized(center: Angle = Angle.pi): Angle =
|
public fun Angle.normalized(center: Angle = Angle.pi): Angle =
|
||||||
this - Angle.piTimes2 * floor((toRadians().value + PI - center.toRadians().value) / PI / 2)
|
this - Angle.piTimes2 * floor((radians + PI - center.radians) / PI / 2)
|
||||||
|
|
||||||
public fun abs(angle: Angle): Angle = if (angle < Angle.zero) -angle else angle
|
public fun abs(angle: Angle): Angle = if (angle < Angle.zero) -angle else angle
|
@ -11,22 +11,19 @@ import kotlinx.serialization.Serializable
|
|||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import space.kscience.attributes.SafeType
|
|
||||||
import space.kscience.kmath.geometry.GeometrySpace
|
import space.kscience.kmath.geometry.GeometrySpace
|
||||||
import space.kscience.kmath.geometry.Vector2D
|
import space.kscience.kmath.geometry.Vector2D
|
||||||
import space.kscience.kmath.operations.Float32Field
|
import space.kscience.kmath.operations.Float32Field
|
||||||
import space.kscience.kmath.structures.Float32
|
import space.kscience.kmath.structures.Float32
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
@Serializable(Float32Space2D.VectorSerializer::class)
|
@Serializable(Float32Space2D.VectorSerializer::class)
|
||||||
public interface Float32Vector2D : Vector2D<Float32>{
|
public interface Float32Vector2D : Vector2D<Float>
|
||||||
override val type: SafeType<Float32> get() = Float32Field.type
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public object Float32Space2D : GeometrySpace<Float32Vector2D, Float32> {
|
public object Float32Space2D : GeometrySpace<Float32Vector2D, Float32> {
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("Float32Vector2D")
|
@SerialName("Float32Vector2D")
|
||||||
private data class Vector2DImpl(
|
private data class Vector2DImpl(
|
||||||
@ -75,8 +72,6 @@ public object Float32Space2D : GeometrySpace<Float32Vector2D, Float32> {
|
|||||||
public val yAxis: Float32Vector2D = vector(0.0, 1.0)
|
public val yAxis: Float32Vector2D = vector(0.0, 1.0)
|
||||||
|
|
||||||
override val defaultPrecision: Float32 = 1e-3f
|
override val defaultPrecision: Float32 = 1e-3f
|
||||||
|
|
||||||
override val bufferFactory: MutableBufferFactory<Float32Vector2D> = MutableBufferFactory()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Float32Vector2D(x: Number, y: Number): Float32Vector2D = Float32Space2D.vector(x, y)
|
public fun Float32Vector2D(x: Number, y: Number): Float32Vector2D = Float32Space2D.vector(x, y)
|
||||||
|
@ -11,77 +11,66 @@ import kotlinx.serialization.Serializable
|
|||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import space.kscience.attributes.SafeType
|
|
||||||
import space.kscience.kmath.geometry.GeometrySpace
|
import space.kscience.kmath.geometry.GeometrySpace
|
||||||
import space.kscience.kmath.geometry.Vector2D
|
import space.kscience.kmath.geometry.Vector2D
|
||||||
|
import space.kscience.kmath.linear.Float64LinearSpace
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.Float64Field
|
||||||
import space.kscience.kmath.operations.ScaleOperations
|
import space.kscience.kmath.operations.ScaleOperations
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
|
||||||
@Serializable(Float64Space2D.VectorSerializer::class)
|
public typealias DoubleVector2D = Vector2D<Double>
|
||||||
public interface Float64Vector2D : Vector2D<Float64> {
|
public typealias Float64Vector2D = Vector2D<Double>
|
||||||
override val type: SafeType<Float64> get() = Float64Field.type
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Use Float64Vector2D", ReplaceWith("Float64Vector2D"))
|
|
||||||
public typealias DoubleVector2D = Float64Vector2D
|
|
||||||
|
|
||||||
|
public val Vector2D<Double>.r: Double get() = Float64Space2D.norm(this)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 2D Euclidean space
|
* 2D Euclidean space
|
||||||
*/
|
*/
|
||||||
public object Float64Space2D : GeometrySpace<Float64Vector2D, Float64>, ScaleOperations<Float64Vector2D> {
|
public object Float64Space2D : GeometrySpace<DoubleVector2D>, ScaleOperations<DoubleVector2D> {
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("Float64Vector2D")
|
@SerialName("Float64Vector2D")
|
||||||
private data class Vector2DImpl(
|
private data class Vector2DImpl(
|
||||||
override val x: Double,
|
override val x: Double,
|
||||||
override val y: Double,
|
override val y: Double,
|
||||||
) : Float64Vector2D
|
) : DoubleVector2D
|
||||||
|
|
||||||
public object VectorSerializer : KSerializer<Float64Vector2D> {
|
public object VectorSerializer : KSerializer<DoubleVector2D> {
|
||||||
private val proxySerializer = Vector2DImpl.serializer()
|
private val proxySerializer = Vector2DImpl.serializer()
|
||||||
override val descriptor: SerialDescriptor get() = proxySerializer.descriptor
|
override val descriptor: SerialDescriptor get() = proxySerializer.descriptor
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): Float64Vector2D = decoder.decodeSerializableValue(proxySerializer)
|
override fun deserialize(decoder: Decoder): DoubleVector2D = decoder.decodeSerializableValue(proxySerializer)
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: Float64Vector2D) {
|
override fun serialize(encoder: Encoder, value: DoubleVector2D) {
|
||||||
val vector = value as? Vector2DImpl ?: Vector2DImpl(value.x, value.y)
|
val vector = value as? Vector2DImpl ?: Vector2DImpl(value.x, value.y)
|
||||||
encoder.encodeSerializableValue(proxySerializer, vector)
|
encoder.encodeSerializableValue(proxySerializer, vector)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun vector(x: Number, y: Number): Float64Vector2D = Vector2DImpl(x.toDouble(), y.toDouble())
|
public fun vector(x: Number, y: Number): DoubleVector2D = Vector2DImpl(x.toDouble(), y.toDouble())
|
||||||
|
|
||||||
override val zero: Float64Vector2D by lazy { vector(0.0, 0.0) }
|
override val zero: DoubleVector2D by lazy { vector(0.0, 0.0) }
|
||||||
|
|
||||||
override fun norm(arg: Float64Vector2D): Double = sqrt(arg.x.pow(2) + arg.y.pow(2))
|
override fun norm(arg: DoubleVector2D): Double = sqrt(arg.x.pow(2) + arg.y.pow(2))
|
||||||
|
|
||||||
override fun Float64Vector2D.unaryMinus(): Float64Vector2D = vector(-x, -y)
|
override fun DoubleVector2D.unaryMinus(): DoubleVector2D = vector(-x, -y)
|
||||||
|
|
||||||
override fun Float64Vector2D.distanceTo(other: Float64Vector2D): Double = norm(this - other)
|
override fun DoubleVector2D.distanceTo(other: DoubleVector2D): Double = norm(this - other)
|
||||||
override fun add(left: Float64Vector2D, right: Float64Vector2D): Float64Vector2D =
|
override fun add(left: DoubleVector2D, right: DoubleVector2D): DoubleVector2D =
|
||||||
vector(left.x + right.x, left.y + right.y)
|
vector(left.x + right.x, left.y + right.y)
|
||||||
|
|
||||||
override fun scale(a: Float64Vector2D, value: Double): Float64Vector2D = vector(a.x * value, a.y * value)
|
override fun scale(a: DoubleVector2D, value: Double): DoubleVector2D = vector(a.x * value, a.y * value)
|
||||||
override fun Float64Vector2D.dot(other: Float64Vector2D): Double = x * other.x + y * other.y
|
override fun DoubleVector2D.dot(other: DoubleVector2D): Double = x * other.x + y * other.y
|
||||||
|
|
||||||
public val xAxis: Float64Vector2D = vector(1.0, 0.0)
|
public val xAxis: DoubleVector2D = vector(1.0, 0.0)
|
||||||
public val yAxis: Float64Vector2D = vector(0.0, 1.0)
|
public val yAxis: DoubleVector2D = vector(0.0, 1.0)
|
||||||
|
|
||||||
override val defaultPrecision: Double = 1e-6
|
override val defaultPrecision: Double = 1e-6
|
||||||
|
|
||||||
override val bufferFactory: MutableBufferFactory<Float64Vector2D> = MutableBufferFactory()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Float64Vector2D(x: Number, y: Number): Float64Vector2D = Float64Space2D.vector(x, y)
|
public fun Float64Vector2D(x: Number, y: Number): Float64Vector2D = Float64Space2D.vector(x, y)
|
||||||
|
|
||||||
public val Float64Vector2D.r: Float64 get() = Float64Space2D.norm(this)
|
|
||||||
|
|
||||||
public val Float64Field.euclidean2D: Float64Space2D get() = Float64Space2D
|
public val Float64Field.euclidean2D: Float64Space2D get() = Float64Space2D
|
@ -11,19 +11,15 @@ import kotlinx.serialization.Serializable
|
|||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import space.kscience.attributes.SafeType
|
|
||||||
import space.kscience.kmath.geometry.GeometrySpace
|
import space.kscience.kmath.geometry.GeometrySpace
|
||||||
import space.kscience.kmath.geometry.Vector3D
|
import space.kscience.kmath.geometry.Vector3D
|
||||||
import space.kscience.kmath.operations.Float32Field
|
import space.kscience.kmath.operations.Float32Field
|
||||||
import space.kscience.kmath.structures.Float32
|
import space.kscience.kmath.structures.Float32
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
@Serializable(Float32Space3D.VectorSerializer::class)
|
@Serializable(Float32Space3D.VectorSerializer::class)
|
||||||
public interface Float32Vector3D : Vector3D<Float>{
|
public interface Float32Vector3D : Vector3D<Float>
|
||||||
override val type: SafeType<Float32> get() = Float32Field.type
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public object Float32Space3D : GeometrySpace<Float32Vector3D, Float32> {
|
public object Float32Space3D : GeometrySpace<Float32Vector3D, Float32> {
|
||||||
@ -105,8 +101,6 @@ public object Float32Space3D : GeometrySpace<Float32Vector3D, Float32> {
|
|||||||
public val zAxis: Float32Vector3D = vector(0.0, 0.0, 1.0)
|
public val zAxis: Float32Vector3D = vector(0.0, 0.0, 1.0)
|
||||||
|
|
||||||
override val defaultPrecision: Float32 = 1e-3f
|
override val defaultPrecision: Float32 = 1e-3f
|
||||||
|
|
||||||
override val bufferFactory: MutableBufferFactory<Float32Vector3D> = MutableBufferFactory()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Float32Vector3D(x: Number, y: Number, z: Number): Float32Vector3D = Float32Space3D.vector(x, y, z)
|
public fun Float32Vector3D(x: Number, y: Number, z: Number): Float32Vector3D = Float32Space3D.vector(x, y, z)
|
||||||
|
@ -11,13 +11,10 @@ import kotlinx.serialization.Serializable
|
|||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import space.kscience.attributes.SafeType
|
|
||||||
import space.kscience.kmath.geometry.GeometrySpace
|
import space.kscience.kmath.geometry.GeometrySpace
|
||||||
import space.kscience.kmath.geometry.Vector3D
|
import space.kscience.kmath.geometry.Vector3D
|
||||||
import space.kscience.kmath.linear.Float64LinearSpace
|
import space.kscience.kmath.linear.Float64LinearSpace
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.Float64Field
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
@ -34,16 +31,12 @@ internal fun leviCivita(i: Int, j: Int, k: Int): Int = when {
|
|||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable(Float64Space3D.VectorSerializer::class)
|
public typealias DoubleVector3D = Vector3D<Double>
|
||||||
public interface Float64Vector3D : Vector3D<Float64> {
|
public typealias Float64Vector3D = Vector3D<Double>
|
||||||
override val type: SafeType<Float64> get() = Float64Field.type
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Use Float64Vector3D", ReplaceWith("Float64Vector3D"))
|
public val DoubleVector3D.r: Double get() = Float64Space3D.norm(this)
|
||||||
public typealias DoubleVector3D = Float64Vector3D
|
|
||||||
|
|
||||||
|
public object Float64Space3D : GeometrySpace<DoubleVector3D, Double>{
|
||||||
public object Float64Space3D : GeometrySpace<Vector3D<Float64>, Double> {
|
|
||||||
|
|
||||||
public val linearSpace: Float64LinearSpace = Float64LinearSpace
|
public val linearSpace: Float64LinearSpace = Float64LinearSpace
|
||||||
|
|
||||||
@ -53,52 +46,52 @@ public object Float64Space3D : GeometrySpace<Vector3D<Float64>, Double> {
|
|||||||
override val x: Double,
|
override val x: Double,
|
||||||
override val y: Double,
|
override val y: Double,
|
||||||
override val z: Double,
|
override val z: Double,
|
||||||
) : Float64Vector3D
|
) : DoubleVector3D
|
||||||
|
|
||||||
public object VectorSerializer : KSerializer<Float64Vector3D> {
|
public object VectorSerializer : KSerializer<DoubleVector3D> {
|
||||||
private val proxySerializer = Vector3DImpl.serializer()
|
private val proxySerializer = Vector3DImpl.serializer()
|
||||||
override val descriptor: SerialDescriptor get() = proxySerializer.descriptor
|
override val descriptor: SerialDescriptor get() = proxySerializer.descriptor
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): Float64Vector3D = decoder.decodeSerializableValue(proxySerializer)
|
override fun deserialize(decoder: Decoder): DoubleVector3D = decoder.decodeSerializableValue(proxySerializer)
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: Float64Vector3D) {
|
override fun serialize(encoder: Encoder, value: DoubleVector3D) {
|
||||||
val vector = value as? Vector3DImpl ?: Vector3DImpl(value.x, value.y, value.z)
|
val vector = value as? Vector3DImpl ?: Vector3DImpl(value.x, value.y, value.z)
|
||||||
encoder.encodeSerializableValue(proxySerializer, vector)
|
encoder.encodeSerializableValue(proxySerializer, vector)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun vector(x: Double, y: Double, z: Double): Float64Vector3D =
|
public fun vector(x: Double, y: Double, z: Double): DoubleVector3D =
|
||||||
Vector3DImpl(x, y, z)
|
Vector3DImpl(x, y, z)
|
||||||
|
|
||||||
public fun vector(x: Number, y: Number, z: Number): Float64Vector3D =
|
public fun vector(x: Number, y: Number, z: Number): DoubleVector3D =
|
||||||
vector(x.toDouble(), y.toDouble(), z.toDouble())
|
vector(x.toDouble(), y.toDouble(), z.toDouble())
|
||||||
|
|
||||||
override val zero: Float64Vector3D by lazy { vector(0.0, 0.0, 0.0) }
|
override val zero: DoubleVector3D by lazy { vector(0.0, 0.0, 0.0) }
|
||||||
|
|
||||||
override fun norm(arg: Vector3D<Float64>): Double = sqrt(arg.x.pow(2) + arg.y.pow(2) + arg.z.pow(2))
|
override fun norm(arg: DoubleVector3D): Double = sqrt(arg.x.pow(2) + arg.y.pow(2) + arg.z.pow(2))
|
||||||
|
|
||||||
public fun Vector3D<Float64>.norm(): Double = norm(this)
|
public fun DoubleVector3D.norm(): Double = norm(this)
|
||||||
|
|
||||||
override fun Vector3D<Float64>.unaryMinus(): Float64Vector3D = vector(-x, -y, -z)
|
override fun DoubleVector3D.unaryMinus(): DoubleVector3D = vector(-x, -y, -z)
|
||||||
|
|
||||||
override fun Vector3D<Float64>.distanceTo(other: Vector3D<Float64>): Double = (this - other).norm()
|
override fun DoubleVector3D.distanceTo(other: DoubleVector3D): Double = (this - other).norm()
|
||||||
|
|
||||||
override fun add(left: Vector3D<Float64>, right: Vector3D<Float64>): Float64Vector3D =
|
override fun add(left: DoubleVector3D, right: DoubleVector3D): DoubleVector3D =
|
||||||
vector(left.x + right.x, left.y + right.y, left.z + right.z)
|
vector(left.x + right.x, left.y + right.y, left.z + right.z)
|
||||||
|
|
||||||
override fun scale(a: Vector3D<Float64>, value: Double): Float64Vector3D =
|
override fun scale(a: DoubleVector3D, value: Double): DoubleVector3D =
|
||||||
vector(a.x * value, a.y * value, a.z * value)
|
vector(a.x * value, a.y * value, a.z * value)
|
||||||
|
|
||||||
override fun Vector3D<Float64>.dot(other: Vector3D<Float64>): Double =
|
override fun DoubleVector3D.dot(other: DoubleVector3D): Double =
|
||||||
x * other.x + y * other.y + z * other.z
|
x * other.x + y * other.y + z * other.z
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute vector product of [first] and [second]. The basis is assumed to be right-handed.
|
* Compute vector product of [first] and [second]. The basis is assumed to be right-handed.
|
||||||
*/
|
*/
|
||||||
public fun vectorProduct(
|
public fun vectorProduct(
|
||||||
first: Vector3D<Float64>,
|
first: DoubleVector3D,
|
||||||
second: Vector3D<Float64>,
|
second: DoubleVector3D,
|
||||||
): Float64Vector3D {
|
): DoubleVector3D {
|
||||||
var x = 0.0
|
var x = 0.0
|
||||||
var y = 0.0
|
var y = 0.0
|
||||||
var z = 0.0
|
var z = 0.0
|
||||||
@ -117,18 +110,13 @@ public object Float64Space3D : GeometrySpace<Vector3D<Float64>, Double> {
|
|||||||
/**
|
/**
|
||||||
* Vector product with the right basis
|
* Vector product with the right basis
|
||||||
*/
|
*/
|
||||||
public infix fun Vector3D<Float64>.cross(other: Vector3D<Float64>): Vector3D<Double> = vectorProduct(this, other)
|
public infix fun DoubleVector3D.cross(other: DoubleVector3D): Vector3D<Double> = vectorProduct(this, other)
|
||||||
|
|
||||||
public val xAxis: Float64Vector3D = vector(1.0, 0.0, 0.0)
|
public val xAxis: DoubleVector3D = vector(1.0, 0.0, 0.0)
|
||||||
public val yAxis: Float64Vector3D = vector(0.0, 1.0, 0.0)
|
public val yAxis: DoubleVector3D = vector(0.0, 1.0, 0.0)
|
||||||
public val zAxis: Float64Vector3D = vector(0.0, 0.0, 1.0)
|
public val zAxis: DoubleVector3D = vector(0.0, 0.0, 1.0)
|
||||||
|
|
||||||
override val defaultPrecision: Double = 1e-6
|
override val defaultPrecision: Double = 1e-6
|
||||||
|
|
||||||
override val bufferFactory: MutableBufferFactory<Vector3D<Float64>> = MutableBufferFactory()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public val Float64Field.euclidean3D: Float64Space3D get() = Float64Space3D
|
public val Float64Field.euclidean3D: Float64Space3D get() = Float64Space3D
|
||||||
|
|
||||||
|
|
||||||
public val Float64Vector3D.r: Double get() = Float64Space3D.norm(this)
|
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.geometry.euclidean3d
|
package space.kscience.kmath.geometry.euclidean3d
|
||||||
|
|
||||||
import space.kscience.attributes.SafeType
|
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.complex.*
|
import space.kscience.kmath.complex.*
|
||||||
import space.kscience.kmath.geometry.*
|
import space.kscience.kmath.geometry.*
|
||||||
@ -14,7 +13,6 @@ import space.kscience.kmath.linear.Matrix
|
|||||||
import space.kscience.kmath.linear.linearSpace
|
import space.kscience.kmath.linear.linearSpace
|
||||||
import space.kscience.kmath.linear.matrix
|
import space.kscience.kmath.linear.matrix
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.Float64Field
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
public operator fun Quaternion.times(other: Quaternion): Quaternion = QuaternionAlgebra.multiply(this, other)
|
public operator fun Quaternion.times(other: Quaternion): Quaternion = QuaternionAlgebra.multiply(this, other)
|
||||||
@ -37,7 +35,7 @@ public infix fun Quaternion.dot(other: Quaternion): Double = w * other.w + x * o
|
|||||||
/**
|
/**
|
||||||
* Represent a vector as quaternion with zero a rotation angle.
|
* Represent a vector as quaternion with zero a rotation angle.
|
||||||
*/
|
*/
|
||||||
internal fun Float64Vector3D.asQuaternion(): Quaternion = Quaternion(0.0, x, y, z)
|
internal fun DoubleVector3D.asQuaternion(): Quaternion = Quaternion(0.0, x, y, z)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Angle in radians denoted by this quaternion rotation
|
* Angle in radians denoted by this quaternion rotation
|
||||||
@ -47,7 +45,7 @@ public val Quaternion.theta: Radians get() = (kotlin.math.acos(normalized().w) *
|
|||||||
/**
|
/**
|
||||||
* Create a normalized Quaternion from rotation angle and rotation vector
|
* Create a normalized Quaternion from rotation angle and rotation vector
|
||||||
*/
|
*/
|
||||||
public fun Quaternion.Companion.fromRotation(theta: Angle, vector: Float64Vector3D): Quaternion {
|
public fun Quaternion.Companion.fromRotation(theta: Angle, vector: DoubleVector3D): Quaternion {
|
||||||
val s = sin(theta / 2)
|
val s = sin(theta / 2)
|
||||||
val c = cos(theta / 2)
|
val c = cos(theta / 2)
|
||||||
val norm = with(Float64Space3D) { vector.norm() }
|
val norm = with(Float64Space3D) { vector.norm() }
|
||||||
@ -57,9 +55,9 @@ public fun Quaternion.Companion.fromRotation(theta: Angle, vector: Float64Vector
|
|||||||
/**
|
/**
|
||||||
* An axis of quaternion rotation
|
* An axis of quaternion rotation
|
||||||
*/
|
*/
|
||||||
public val Quaternion.vector: Float64Vector3D
|
public val Quaternion.vector: DoubleVector3D
|
||||||
get() {
|
get() {
|
||||||
return object : Float64Vector3D {
|
return object : DoubleVector3D {
|
||||||
private val sint2 = sqrt(1 - w * w)
|
private val sint2 = sqrt(1 - w * w)
|
||||||
override val x: Double get() = this@vector.x / sint2
|
override val x: Double get() = this@vector.x / sint2
|
||||||
override val y: Double get() = this@vector.y / sint2
|
override val y: Double get() = this@vector.y / sint2
|
||||||
@ -71,7 +69,7 @@ public val Quaternion.vector: Float64Vector3D
|
|||||||
/**
|
/**
|
||||||
* Rotate a vector in a [Float64Space3D] with [quaternion]
|
* Rotate a vector in a [Float64Space3D] with [quaternion]
|
||||||
*/
|
*/
|
||||||
public fun Float64Space3D.rotate(vector: Float64Vector3D, quaternion: Quaternion): Float64Vector3D =
|
public fun Float64Space3D.rotate(vector: DoubleVector3D, quaternion: Quaternion): DoubleVector3D =
|
||||||
with(QuaternionAlgebra) {
|
with(QuaternionAlgebra) {
|
||||||
val p = vector.asQuaternion()
|
val p = vector.asQuaternion()
|
||||||
(quaternion * p * quaternion.reciprocal).vector
|
(quaternion * p * quaternion.reciprocal).vector
|
||||||
@ -82,15 +80,15 @@ public fun Float64Space3D.rotate(vector: Float64Vector3D, quaternion: Quaternion
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public fun Float64Space3D.rotate(
|
public fun Float64Space3D.rotate(
|
||||||
vector: Float64Vector3D,
|
vector: DoubleVector3D,
|
||||||
composition: QuaternionAlgebra.() -> Quaternion,
|
composition: QuaternionAlgebra.() -> Quaternion,
|
||||||
): Float64Vector3D =
|
): DoubleVector3D =
|
||||||
rotate(vector, QuaternionAlgebra.composition())
|
rotate(vector, QuaternionAlgebra.composition())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate a [Float64] vector in 3D space with a rotation matrix
|
* Rotate a [Float64] vector in 3D space with a rotation matrix
|
||||||
*/
|
*/
|
||||||
public fun Float64Space3D.rotate(vector: Float64Vector3D, matrix: Matrix<Double>): Vector3D<Float64> {
|
public fun Float64Space3D.rotate(vector: DoubleVector3D, matrix: Matrix<Double>): DoubleVector3D {
|
||||||
require(matrix.colNum == 3 && matrix.rowNum == 3) { "Square 3x3 rotation matrix is required" }
|
require(matrix.colNum == 3 && matrix.rowNum == 3) { "Square 3x3 rotation matrix is required" }
|
||||||
return with(linearSpace) { (matrix dot vector).asVector3D() }
|
return with(linearSpace) { (matrix dot vector).asVector3D() }
|
||||||
}
|
}
|
||||||
@ -244,8 +242,6 @@ public fun Quaternion.Companion.fromEuler(
|
|||||||
* A vector consisting of angles
|
* A vector consisting of angles
|
||||||
*/
|
*/
|
||||||
public data class AngleVector(override val x: Angle, override val y: Angle, override val z: Angle) : Vector3D<Angle> {
|
public data class AngleVector(override val x: Angle, override val y: Angle, override val z: Angle) : Vector3D<Angle> {
|
||||||
override val type: SafeType<Angle> get() = Angle.type
|
|
||||||
|
|
||||||
public companion object
|
public companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.geometry
|
package space.kscience.kmath.geometry
|
||||||
|
|
||||||
import space.kscience.kmath.structures.Float64
|
import space.kscience.kmath.geometry.euclidean2d.DoubleVector2D
|
||||||
|
import space.kscience.kmath.geometry.euclidean3d.DoubleVector3D
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@ -26,12 +27,12 @@ fun grid(
|
|||||||
return xs.flatMap { x -> ys.map { y -> x to y } }
|
return xs.flatMap { x -> ys.map { y -> x to y } }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun assertVectorEquals(expected: Vector2D<Float64>, actual: Vector2D<Float64>, absoluteTolerance: Double = 1e-3) {
|
fun assertVectorEquals(expected: DoubleVector2D, actual: DoubleVector2D, absoluteTolerance: Double = 1e-3) {
|
||||||
assertEquals(expected.x, actual.x, absoluteTolerance)
|
assertEquals(expected.x, actual.x, absoluteTolerance)
|
||||||
assertEquals(expected.y, actual.y, absoluteTolerance)
|
assertEquals(expected.y, actual.y, absoluteTolerance)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun assertVectorEquals(expected: Vector3D<Float64>, actual: Vector3D<Float64>, absoluteTolerance: Double = 1e-6) {
|
fun assertVectorEquals(expected: DoubleVector3D, actual: DoubleVector3D, absoluteTolerance: Double = 1e-6) {
|
||||||
assertEquals(expected.x, actual.x, absoluteTolerance)
|
assertEquals(expected.x, actual.x, absoluteTolerance)
|
||||||
assertEquals(expected.y, actual.y, absoluteTolerance)
|
assertEquals(expected.y, actual.y, absoluteTolerance)
|
||||||
assertEquals(expected.z, actual.z, absoluteTolerance)
|
assertEquals(expected.z, actual.z, absoluteTolerance)
|
||||||
|
@ -6,8 +6,19 @@
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-histograms:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-histograms:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-histograms:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -16,6 +27,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-histograms:0.4.0-dev-3")
|
implementation("space.kscience:kmath-histograms:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -6,8 +6,6 @@ kscience{
|
|||||||
jvm()
|
jvm()
|
||||||
js()
|
js()
|
||||||
native()
|
native()
|
||||||
wasm()
|
|
||||||
useCoroutines()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//apply(plugin = "kotlinx-atomicfu")
|
//apply(plugin = "kotlinx-atomicfu")
|
||||||
@ -23,6 +21,7 @@ kotlin.sourceSets {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":kmath-for-real"))
|
implementation(project(":kmath-for-real"))
|
||||||
implementation(projects.kmath.kmathStat)
|
implementation(projects.kmath.kmathStat)
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ public interface Histogram<in T : Any, out V, out B : Bin<T, V>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface HistogramBuilder<in T, V> {
|
public interface HistogramBuilder<in T : Any, V : Any> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default value increment for a bin
|
* The default value increment for a bin
|
||||||
@ -61,9 +61,9 @@ public interface HistogramBuilder<in T, V> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T> HistogramBuilder<T, *>.put(point: Point<T>): Unit = putValue(point)
|
public fun <T : Any> HistogramBuilder<T, *>.put(point: Point<out T>): Unit = putValue(point)
|
||||||
|
|
||||||
public inline fun <reified T> HistogramBuilder<T, *>.put(vararg point: T): Unit = put(point.asList().asBuffer())
|
public fun <T : Any> HistogramBuilder<T, *>.put(vararg point: T): Unit = put(point.asBuffer())
|
||||||
|
|
||||||
public fun HistogramBuilder<Double, *>.put(vararg point: Number): Unit =
|
public fun HistogramBuilder<Double, *>.put(vararg point: Number): Unit =
|
||||||
put(Float64Buffer(point.map { it.toDouble() }.toDoubleArray()))
|
put(Float64Buffer(point.map { it.toDouble() }.toDoubleArray()))
|
||||||
|
@ -12,7 +12,6 @@ import space.kscience.kmath.operations.Ring
|
|||||||
import space.kscience.kmath.operations.ScaleOperations
|
import space.kscience.kmath.operations.ScaleOperations
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
|
||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
@ -47,8 +46,6 @@ public class UniformHistogram1DGroup<V : Any, A>(
|
|||||||
public val startPoint: Double = 0.0,
|
public val startPoint: Double = 0.0,
|
||||||
) : Group<Histogram1D<Double, V>>, ScaleOperations<Histogram1D<Double, V>> where A : Ring<V>, A : ScaleOperations<V> {
|
) : Group<Histogram1D<Double, V>>, ScaleOperations<Histogram1D<Double, V>> where A : Ring<V>, A : ScaleOperations<V> {
|
||||||
|
|
||||||
override val bufferFactory: MutableBufferFactory<Histogram1D<Double, V>> = MutableBufferFactory()
|
|
||||||
|
|
||||||
override val zero: UniformHistogram1D<V> = UniformHistogram1D(this, emptyMap())
|
override val zero: UniformHistogram1D<V> = UniformHistogram1D(this, emptyMap())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,8 +37,6 @@ public class UniformHistogramGroupND<V : Any, A : Field<V>>(
|
|||||||
require(!lower.indices.any { upper[it] - lower[it] < 0 }) { "Range for one of axis is not strictly positive" }
|
require(!lower.indices.any { upper[it] - lower[it] < 0 }) { "Range for one of axis is not strictly positive" }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val bufferFactory: MutableBufferFactory<HistogramND<Double, HyperSquareDomain, V>> = MutableBufferFactory()
|
|
||||||
|
|
||||||
public val dimension: Int get() = lower.size
|
public val dimension: Int get() = lower.size
|
||||||
|
|
||||||
override val shape: ShapeND = ShapeND(IntArray(binNums.size) { binNums[it] + 2 })
|
override val shape: ShapeND = ShapeND(IntArray(binNums.size) { binNums[it] + 2 })
|
||||||
@ -89,7 +87,7 @@ public class UniformHistogramGroupND<V : Any, A : Field<V>>(
|
|||||||
builder: HistogramBuilder<Double, V>.() -> Unit,
|
builder: HistogramBuilder<Double, V>.() -> Unit,
|
||||||
): HistogramND<Double, HyperSquareDomain, V> {
|
): HistogramND<Double, HyperSquareDomain, V> {
|
||||||
val ndCounter: BufferND<ObjectCounter<V>> =
|
val ndCounter: BufferND<ObjectCounter<V>> =
|
||||||
BufferND(shape) { Counter.of(valueAlgebraND.elementAlgebra) }
|
StructureND.buffered(shape) { Counter.of(valueAlgebraND.elementAlgebra) }
|
||||||
val hBuilder = object : HistogramBuilder<Double, V> {
|
val hBuilder = object : HistogramBuilder<Double, V> {
|
||||||
override val defaultValue: V get() = valueAlgebraND.elementAlgebra.one
|
override val defaultValue: V get() = valueAlgebraND.elementAlgebra.one
|
||||||
|
|
||||||
@ -99,8 +97,7 @@ public class UniformHistogramGroupND<V : Any, A : Field<V>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
hBuilder.apply(builder)
|
hBuilder.apply(builder)
|
||||||
val values: BufferND<V> =
|
val values: BufferND<V> = BufferND(ndCounter.indices, ndCounter.buffer.mapToBuffer(valueBufferFactory) { it.value })
|
||||||
BufferND(ndCounter.indices, ndCounter.buffer.mapToBuffer(valueBufferFactory) { it.value })
|
|
||||||
|
|
||||||
return HistogramND(this, values)
|
return HistogramND(this, values)
|
||||||
}
|
}
|
||||||
@ -131,7 +128,8 @@ public fun <V : Any, A : Field<V>> Histogram.Companion.uniformNDFromRanges(
|
|||||||
|
|
||||||
public fun Histogram.Companion.uniformDoubleNDFromRanges(
|
public fun Histogram.Companion.uniformDoubleNDFromRanges(
|
||||||
vararg ranges: ClosedFloatingPointRange<Double>,
|
vararg ranges: ClosedFloatingPointRange<Double>,
|
||||||
): UniformHistogramGroupND<Double, Float64Field> = uniformNDFromRanges(Floa64FieldOpsND, *ranges)
|
): UniformHistogramGroupND<Double, Float64Field> =
|
||||||
|
uniformNDFromRanges(Floa64FieldOpsND, *ranges, bufferFactory = ::Float64Buffer)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,18 +147,21 @@ public fun <V : Any, A : Field<V>> Histogram.Companion.uniformNDFromRanges(
|
|||||||
bufferFactory: BufferFactory<V> = valueAlgebraND.elementAlgebra.bufferFactory,
|
bufferFactory: BufferFactory<V> = valueAlgebraND.elementAlgebra.bufferFactory,
|
||||||
): UniformHistogramGroupND<V, A> = UniformHistogramGroupND(
|
): UniformHistogramGroupND<V, A> = UniformHistogramGroupND(
|
||||||
valueAlgebraND,
|
valueAlgebraND,
|
||||||
ranges
|
DoubleBuffer(
|
||||||
.map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
|
ranges
|
||||||
.map(ClosedFloatingPointRange<Double>::start)
|
.map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
|
||||||
.asBuffer(),
|
.map(ClosedFloatingPointRange<Double>::start)
|
||||||
ranges
|
),
|
||||||
.map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
|
DoubleBuffer(
|
||||||
.map(ClosedFloatingPointRange<Double>::endInclusive)
|
ranges
|
||||||
.asBuffer(),
|
.map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
|
||||||
|
.map(ClosedFloatingPointRange<Double>::endInclusive)
|
||||||
|
),
|
||||||
ranges.map(Pair<ClosedFloatingPointRange<Double>, Int>::second).toIntArray(),
|
ranges.map(Pair<ClosedFloatingPointRange<Double>, Int>::second).toIntArray(),
|
||||||
valueBufferFactory = bufferFactory
|
valueBufferFactory = bufferFactory
|
||||||
)
|
)
|
||||||
|
|
||||||
public fun Histogram.Companion.uniformDoubleNDFromRanges(
|
public fun Histogram.Companion.uniformDoubleNDFromRanges(
|
||||||
vararg ranges: Pair<ClosedFloatingPointRange<Double>, Int>,
|
vararg ranges: Pair<ClosedFloatingPointRange<Double>, Int>,
|
||||||
): UniformHistogramGroupND<Double, Float64Field> = uniformNDFromRanges(Floa64FieldOpsND, *ranges)
|
): UniformHistogramGroupND<Double, Float64Field> =
|
||||||
|
uniformNDFromRanges(Floa64FieldOpsND, *ranges, bufferFactory = ::Float64Buffer)
|
@ -14,7 +14,10 @@ import space.kscience.kmath.misc.sorted
|
|||||||
import space.kscience.kmath.operations.Group
|
import space.kscience.kmath.operations.Group
|
||||||
import space.kscience.kmath.operations.Ring
|
import space.kscience.kmath.operations.Ring
|
||||||
import space.kscience.kmath.operations.ScaleOperations
|
import space.kscience.kmath.operations.ScaleOperations
|
||||||
import space.kscience.kmath.structures.*
|
import space.kscience.kmath.structures.Buffer
|
||||||
|
import space.kscience.kmath.structures.first
|
||||||
|
import space.kscience.kmath.structures.indices
|
||||||
|
import space.kscience.kmath.structures.last
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
private fun <B : ClosedRange<Double>> TreeMap<Double, B>.getBin(value: Double): B? {
|
private fun <B : ClosedRange<Double>> TreeMap<Double, B>.getBin(value: Double): B? {
|
||||||
@ -50,8 +53,6 @@ public class TreeHistogramGroup<V : Any, A>(
|
|||||||
@PublishedApi internal val binFactory: (Double) -> DoubleDomain1D,
|
@PublishedApi internal val binFactory: (Double) -> DoubleDomain1D,
|
||||||
) : Group<TreeHistogram<V>>, ScaleOperations<TreeHistogram<V>> where A : Ring<V>, A : ScaleOperations<V> {
|
) : Group<TreeHistogram<V>>, ScaleOperations<TreeHistogram<V>> where A : Ring<V>, A : ScaleOperations<V> {
|
||||||
|
|
||||||
override val bufferFactory: MutableBufferFactory<TreeHistogram<V>> = MutableBufferFactory()
|
|
||||||
|
|
||||||
internal inner class DomainCounter(val domain: DoubleDomain1D, val counter: Counter<V> = Counter.of(valueAlgebra)) :
|
internal inner class DomainCounter(val domain: DoubleDomain1D, val counter: Counter<V> = Counter.of(valueAlgebra)) :
|
||||||
ClosedRange<Double> by domain.range
|
ClosedRange<Double> by domain.range
|
||||||
|
|
||||||
|
@ -7,8 +7,19 @@ Integration with [Jafama](https://github.com/jeffhain/jafama).
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-jafama:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-jafama:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-jafama:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -17,7 +28,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-jafama:0.4.0-dev-3")
|
implementation("space.kscience:kmath-jafama:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,128 +0,0 @@
|
|||||||
public final class space/kscience/kmath/jafama/JafamaDoubleField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/ScaleOperations {
|
|
||||||
public static final field INSTANCE Lspace/kscience/kmath/jafama/JafamaDoubleField;
|
|
||||||
public fun acos (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun acosh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun add (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun asin (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun asinh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun atan (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun atanh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
|
||||||
public fun cos (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun cosh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun div (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun divide (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun exp (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun getBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory;
|
|
||||||
public fun getOne ()Ljava/lang/Double;
|
|
||||||
public synthetic fun getOne ()Ljava/lang/Object;
|
|
||||||
public fun getZero ()Ljava/lang/Double;
|
|
||||||
public synthetic fun getZero ()Ljava/lang/Object;
|
|
||||||
public fun ln (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun minus (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun multiply (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun norm (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun number (Ljava/lang/Number;)Ljava/lang/Double;
|
|
||||||
public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
|
|
||||||
public fun plus (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun power (DLjava/lang/Number;)Ljava/lang/Double;
|
|
||||||
public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
|
|
||||||
public fun scale (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
|
|
||||||
public fun sin (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun sinh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun sqrt (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun tan (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun tanh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun times (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun unaryMinus (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/kmath/jafama/StrictJafamaDoubleField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/ScaleOperations {
|
|
||||||
public static final field INSTANCE Lspace/kscience/kmath/jafama/StrictJafamaDoubleField;
|
|
||||||
public fun acos (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun acosh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun add (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun asin (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun asinh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun atan (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun atanh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
|
||||||
public fun cos (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun cosh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun div (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun divide (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun exp (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun getBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory;
|
|
||||||
public fun getOne ()Ljava/lang/Double;
|
|
||||||
public synthetic fun getOne ()Ljava/lang/Object;
|
|
||||||
public fun getZero ()Ljava/lang/Double;
|
|
||||||
public synthetic fun getZero ()Ljava/lang/Object;
|
|
||||||
public fun ln (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun minus (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun multiply (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun norm (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun number (Ljava/lang/Number;)Ljava/lang/Double;
|
|
||||||
public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
|
|
||||||
public fun plus (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun power (DLjava/lang/Number;)Ljava/lang/Double;
|
|
||||||
public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
|
|
||||||
public fun scale (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
|
|
||||||
public fun sin (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun sinh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun sqrt (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun tan (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun tanh (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun times (DD)Ljava/lang/Double;
|
|
||||||
public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
public fun unaryMinus (D)Ljava/lang/Double;
|
|
||||||
public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object;
|
|
||||||
}
|
|
||||||
|
|
@ -6,8 +6,19 @@
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-jupyter:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-jupyter:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-jupyter:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -16,6 +27,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-jupyter:0.4.0-dev-3")
|
implementation("space.kscience:kmath-jupyter:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -8,8 +8,19 @@
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-kotlingrad:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -18,6 +29,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-kotlingrad:0.4.0-dev-3")
|
implementation("space.kscience:kmath-kotlingrad:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -7,7 +7,6 @@ package space.kscience.kmath.kotlingrad
|
|||||||
|
|
||||||
import ai.hypergraph.kotlingrad.api.SFun
|
import ai.hypergraph.kotlingrad.api.SFun
|
||||||
import ai.hypergraph.kotlingrad.api.SVar
|
import ai.hypergraph.kotlingrad.api.SVar
|
||||||
import space.kscience.attributes.SafeType
|
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
import space.kscience.kmath.operations.NumericAlgebra
|
import space.kscience.kmath.operations.NumericAlgebra
|
||||||
|
|
||||||
@ -26,8 +25,6 @@ public class KotlingradExpression<T : Number, A : NumericAlgebra<T>>(
|
|||||||
public val algebra: A,
|
public val algebra: A,
|
||||||
public val mst: MST,
|
public val mst: MST,
|
||||||
) : SpecialDifferentiableExpression<T, KotlingradExpression<T, A>> {
|
) : SpecialDifferentiableExpression<T, KotlingradExpression<T, A>> {
|
||||||
override val type: SafeType<T> = algebra.type
|
|
||||||
|
|
||||||
override fun invoke(arguments: Map<Symbol, T>): T = mst.interpret(algebra, arguments)
|
override fun invoke(arguments: Map<Symbol, T>): T = mst.interpret(algebra, arguments)
|
||||||
|
|
||||||
override fun derivativeOrNull(
|
override fun derivativeOrNull(
|
||||||
|
@ -6,8 +6,19 @@
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-memory:0.4.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-memory:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-memory:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -16,6 +27,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-memory:0.4.0-dev-3")
|
implementation("space.kscience:kmath-memory:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user