Fully refactor algebra split ScaleOperations from Space. #219
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -1,6 +1,5 @@
|
||||
# Based on https://github.com/touchlab/Stately/blob/main/.github/workflows/build.yml
|
||||
name: Gradle build
|
||||
|
||||
name: build
|
||||
on: [ push ]
|
||||
|
||||
jobs:
|
||||
|
@ -1,10 +1,15 @@
|
||||
# Based on https://github.com/touchlab/Stately/blob/main/.github/workflows/deploy.yml
|
||||
name: Gradle publish
|
||||
|
||||
name: deploy
|
||||
on: workflow_dispatch
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
jobs:
|
||||
build:
|
||||
publish:
|
||||
environment:
|
||||
name: publish
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macOS-latest, windows-latest]
|
||||
@ -33,13 +38,22 @@ jobs:
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Publish Mac Artifacts
|
||||
if: matrix.os == 'macOS-latest'
|
||||
run: ./gradlew publishAllPublicationsToSpaceRepository publishAllPublicationsToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} -PspaceUser=${{ secrets.SPACE_USERNAME }} -PspacePassword=${{ secrets.SPACE_PASSWORD }}
|
||||
env:
|
||||
signingKey: ${{ secrets.SIGNING_KEY }}
|
||||
- name: Publish Windows Artifacts
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: ./gradlew publishAllPublicationsToSpaceRepository publishAllPublicationsToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} -PspaceUser=${{ secrets.SPACE_USERNAME }} -PspacePassword=${{ secrets.SPACE_PASSWORD }}
|
||||
env:
|
||||
signingKey: ${{ secrets.SIGNING_KEY }}
|
||||
run: >
|
||||
./gradlew release --no-daemon
|
||||
-Ppublishing.enabled=true
|
||||
-Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }}
|
||||
-Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
|
||||
-Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
|
||||
-Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
|
||||
- name: Publish Mac Artifacts
|
||||
if: matrix.os == 'macOS-latest'
|
||||
run: >
|
||||
./gradlew release --no-daemon
|
||||
-Ppublishing.enabled=true
|
||||
-Ppublishing.platform=macosX64
|
||||
-Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }}
|
||||
-Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
|
||||
-Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
|
||||
-Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
|
@ -2,12 +2,17 @@
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- Intrinsic value `two` for ExtendedField to work with hyperbolic functions
|
||||
- ScaleOperations interface
|
||||
|
||||
### Changed
|
||||
- Exponential operations merged with hyperbolic functions
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
- Nearest in Domain. To be implemented in geometry package.
|
||||
- Number multiplication and division in main Algebra chain
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -20,7 +20,7 @@ allprojects {
|
||||
}
|
||||
|
||||
group = "space.kscience"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
@ -32,9 +32,8 @@ readme {
|
||||
}
|
||||
|
||||
ksciencePublish {
|
||||
spaceRepo = "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven"
|
||||
bintrayRepo = "kscience"
|
||||
githubProject = "kmath"
|
||||
github("kmath")
|
||||
space()
|
||||
}
|
||||
|
||||
apiValidation {
|
||||
|
@ -6,10 +6,10 @@ import space.kscience.kmath.operations.RealField
|
||||
fun main() {
|
||||
val expr = RealField.mstInField {
|
||||
val x = bindSymbol("x")
|
||||
x * 2.0 + 2.0 / x - 16.0
|
||||
x * 2.0 + 2.0 * one / x - 16.0
|
||||
}
|
||||
|
||||
repeat(10000000){
|
||||
repeat(10000000) {
|
||||
expr.invoke("x" to 1.0)
|
||||
}
|
||||
}
|
@ -3,8 +3,8 @@ package space.kscience.kmath.structures
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.NumbersAddOperations
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.operations.RingWithNumbers
|
||||
import java.util.*
|
||||
import java.util.stream.IntStream
|
||||
|
||||
@ -15,7 +15,7 @@ import java.util.stream.IntStream
|
||||
class StreamRealNDField(
|
||||
override val shape: IntArray,
|
||||
) : NDField<Double, RealField>,
|
||||
RingWithNumbers<NDStructure<Double>>,
|
||||
NumbersAddOperations<NDStructure<Double>>,
|
||||
ExtendedField<NDStructure<Double>> {
|
||||
|
||||
private val strides = DefaultStrides(shape)
|
||||
@ -79,25 +79,29 @@ class StreamRealNDField(
|
||||
return NDBuffer(strides, array.asBuffer())
|
||||
}
|
||||
|
||||
override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = arg.map() { power(it, pow) }
|
||||
override fun NDStructure<Double>.unaryMinus(): NDStructure<Double> = map { -it }
|
||||
|
||||
override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { exp(it) }
|
||||
override fun scale(a: NDStructure<Double>, value: Double): NDStructure<Double> = a.map { it * value }
|
||||
|
||||
override fun ln(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { ln(it) }
|
||||
override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = arg.map { power(it, pow) }
|
||||
|
||||
override fun sin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { sin(it) }
|
||||
override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { cos(it) }
|
||||
override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { tan(it) }
|
||||
override fun asin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asin(it) }
|
||||
override fun acos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acos(it) }
|
||||
override fun atan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atan(it) }
|
||||
override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { exp(it) }
|
||||
|
||||
override fun sinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { sinh(it) }
|
||||
override fun cosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { cosh(it) }
|
||||
override fun tanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { tanh(it) }
|
||||
override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asinh(it) }
|
||||
override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acosh(it) }
|
||||
override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atanh(it) }
|
||||
override fun ln(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { ln(it) }
|
||||
|
||||
override fun sin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { sin(it) }
|
||||
override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { cos(it) }
|
||||
override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { tan(it) }
|
||||
override fun asin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { asin(it) }
|
||||
override fun acos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { acos(it) }
|
||||
override fun atan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { atan(it) }
|
||||
|
||||
override fun sinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { sinh(it) }
|
||||
override fun cosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { cosh(it) }
|
||||
override fun tanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { tanh(it) }
|
||||
override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { asinh(it) }
|
||||
override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { acosh(it) }
|
||||
override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { atanh(it) }
|
||||
}
|
||||
|
||||
fun NDAlgebra.Companion.realWithStream(vararg shape: Int): StreamRealNDField = StreamRealNDField(shape)
|
@ -1,9 +1,10 @@
|
||||
kotlin.code.style=official
|
||||
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
||||
kotlin.mpp.stability.nowarn=true
|
||||
kotlin.native.enableDependencyPropagation=false
|
||||
kotlin.parallel.tasks.in.project=true
|
||||
org.gradle.configureondemand=true
|
||||
org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m
|
||||
org.gradle.parallel=true
|
||||
systemProp.org.gradle.internal.publish.checksums.insecure=true
|
||||
|
||||
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
||||
kotlin.native.enableDependencyPropagation=false
|
||||
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -20,8 +20,8 @@ public object MstAlgebra : NumericAlgebra<MST> {
|
||||
/**
|
||||
* [Space] over [MST] nodes.
|
||||
*/
|
||||
public object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
||||
public override val zero: MST.Numeric by lazy { number(0.0) }
|
||||
public object MstSpace : Space<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
|
||||
public override val zero: MST.Numeric = number(0.0)
|
||||
|
||||
public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value)
|
||||
public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value)
|
||||
@ -35,8 +35,8 @@ public object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
||||
public override operator fun MST.minus(b: MST): MST.Binary =
|
||||
binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b)
|
||||
|
||||
public override fun multiply(a: MST, k: Number): MST.Binary =
|
||||
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(k))
|
||||
public override fun scale(a: MST, value: Double): MST.Binary =
|
||||
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(value))
|
||||
|
||||
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
||||
MstAlgebra.binaryOperationFunction(operation)
|
||||
@ -49,16 +49,17 @@ public object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
||||
* [Ring] over [MST] nodes.
|
||||
*/
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
public object MstRing : Ring<MST>, RingWithNumbers<MST> {
|
||||
public override val zero: MST.Numeric
|
||||
get() = MstSpace.zero
|
||||
|
||||
public override val one: MST.Numeric by lazy { number(1.0) }
|
||||
public object MstRing : Ring<MST>, NumbersAddOperations<MST>, ScaleOperations<MST> {
|
||||
public override val zero: MST.Numeric = MstSpace.zero
|
||||
public override val one: MST.Numeric = number(1.0)
|
||||
|
||||
public override fun number(value: Number): MST.Numeric = MstSpace.number(value)
|
||||
public override fun bindSymbol(value: String): MST.Symbolic = MstSpace.bindSymbol(value)
|
||||
public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b)
|
||||
public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k)
|
||||
|
||||
public override fun scale(a: MST, value: Double): MST.Binary =
|
||||
MstSpace.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstSpace.number(value))
|
||||
|
||||
public override fun multiply(a: MST, b: MST): MST.Binary =
|
||||
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b)
|
||||
|
||||
@ -77,17 +78,18 @@ public object MstRing : Ring<MST>, RingWithNumbers<MST> {
|
||||
* [Field] over [MST] nodes.
|
||||
*/
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
public object MstField : Field<MST>, RingWithNumbers<MST> {
|
||||
public override val zero: MST.Numeric
|
||||
get() = MstRing.zero
|
||||
public object MstField : Field<MST>, NumbersAddOperations<MST>, ScaleOperations<MST> {
|
||||
public override val zero: MST.Numeric get() = MstRing.zero
|
||||
|
||||
public override val one: MST.Numeric
|
||||
get() = MstRing.one
|
||||
public override val one: MST.Numeric get() = MstRing.one
|
||||
|
||||
public override fun bindSymbol(value: String): MST.Symbolic = MstRing.bindSymbol(value)
|
||||
public override fun number(value: Number): MST.Numeric = MstRing.number(value)
|
||||
public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b)
|
||||
public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k)
|
||||
|
||||
public override fun scale(a: MST, value: Double): MST.Binary =
|
||||
MstSpace.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstSpace.number(value))
|
||||
|
||||
public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b)
|
||||
public override fun divide(a: MST, b: MST): MST.Binary =
|
||||
binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b)
|
||||
@ -107,11 +109,8 @@ public object MstField : Field<MST>, RingWithNumbers<MST> {
|
||||
* [ExtendedField] over [MST] nodes.
|
||||
*/
|
||||
public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
|
||||
public override val zero: MST.Numeric
|
||||
get() = MstField.zero
|
||||
|
||||
public override val one: MST.Numeric
|
||||
get() = MstField.one
|
||||
public override val zero: MST.Numeric = MstField.zero
|
||||
public override val one: MST.Numeric = MstField.one
|
||||
|
||||
public override fun bindSymbol(value: String): MST.Symbolic = MstField.bindSymbol(value)
|
||||
public override fun number(value: Number): MST.Numeric = MstRing.number(value)
|
||||
@ -121,14 +120,17 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
|
||||
public override fun asin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ASIN_OPERATION)(arg)
|
||||
public override fun acos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ACOS_OPERATION)(arg)
|
||||
public override fun atan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ATAN_OPERATION)(arg)
|
||||
public override fun sinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.SINH_OPERATION)(arg)
|
||||
public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.COSH_OPERATION)(arg)
|
||||
public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.TANH_OPERATION)(arg)
|
||||
public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ASINH_OPERATION)(arg)
|
||||
public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ACOSH_OPERATION)(arg)
|
||||
public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ATANH_OPERATION)(arg)
|
||||
public override fun sinh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.SINH_OPERATION)(arg)
|
||||
public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.COSH_OPERATION)(arg)
|
||||
public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.TANH_OPERATION)(arg)
|
||||
public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ASINH_OPERATION)(arg)
|
||||
public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg)
|
||||
public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg)
|
||||
public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b)
|
||||
public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k)
|
||||
|
||||
public override fun scale(a: MST, value: Double): MST =
|
||||
binaryOperation(SpaceOperations.PLUS_OPERATION, a, number(value))
|
||||
|
||||
public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b)
|
||||
public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b)
|
||||
public override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus }
|
||||
|
@ -15,9 +15,9 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
val res1 = MstSpace.mstInSpace {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
number(3.toByte()) - (number(2.toByte()) + (multiply(
|
||||
number(3.toByte()) - (number(2.toByte()) + (scale(
|
||||
add(number(1), number(1)),
|
||||
2
|
||||
2.0
|
||||
) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
|
||||
),
|
||||
|
||||
@ -28,9 +28,9 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
val res2 = MstSpace.mstInSpace {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
number(3.toByte()) - (number(2.toByte()) + (multiply(
|
||||
number(3.toByte()) - (number(2.toByte()) + (scale(
|
||||
add(number(1), number(1)),
|
||||
2
|
||||
2.0
|
||||
) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
|
||||
),
|
||||
|
||||
@ -46,9 +46,9 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
val res1 = ByteRing.mstInRing {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
(bindSymbol("x") - (2.toByte() + (multiply(
|
||||
(bindSymbol("x") - (2.toByte() + (scale(
|
||||
add(number(1), number(1)),
|
||||
2
|
||||
2.0
|
||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||
),
|
||||
|
||||
@ -59,9 +59,9 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
val res2 = ByteRing.mstInRing {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
(bindSymbol("x") - (2.toByte() + (multiply(
|
||||
(bindSymbol("x") - (2.toByte() + (scale(
|
||||
add(number(1), number(1)),
|
||||
2
|
||||
2.0
|
||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||
),
|
||||
number(1)
|
||||
@ -75,7 +75,7 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
fun realField() {
|
||||
val res1 = RealField.mstInField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
@ -83,7 +83,7 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
|
||||
val res2 = RealField.mstInField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
@ -96,7 +96,7 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
fun complexField() {
|
||||
val res1 = ComplexField.mstInField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
@ -104,7 +104,7 @@ internal class TestESTreeConsistencyWithInterpreter {
|
||||
|
||||
val res2 = ComplexField.mstInField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
|
@ -15,9 +15,9 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
val res1 = MstSpace.mstInSpace {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
number(3.toByte()) - (number(2.toByte()) + (multiply(
|
||||
number(3.toByte()) - (number(2.toByte()) + (scale(
|
||||
add(number(1), number(1)),
|
||||
2
|
||||
2.0
|
||||
) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
|
||||
),
|
||||
|
||||
@ -28,9 +28,9 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
val res2 = MstSpace.mstInSpace {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
number(3.toByte()) - (number(2.toByte()) + (multiply(
|
||||
number(3.toByte()) - (number(2.toByte()) + (scale(
|
||||
add(number(1), number(1)),
|
||||
2
|
||||
2.0
|
||||
) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
|
||||
),
|
||||
|
||||
@ -46,9 +46,9 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
val res1 = ByteRing.mstInRing {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
(bindSymbol("x") - (2.toByte() + (multiply(
|
||||
(bindSymbol("x") - (2.toByte() + (scale(
|
||||
add(number(1), number(1)),
|
||||
2
|
||||
2.0
|
||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||
),
|
||||
|
||||
@ -59,9 +59,9 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
val res2 = ByteRing.mstInRing {
|
||||
binaryOperationFunction("+")(
|
||||
unaryOperationFunction("+")(
|
||||
(bindSymbol("x") - (2.toByte() + (multiply(
|
||||
(bindSymbol("x") - (2.toByte() + (scale(
|
||||
add(number(1), number(1)),
|
||||
2
|
||||
2.0
|
||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||
),
|
||||
number(1)
|
||||
@ -75,7 +75,7 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
fun realField() {
|
||||
val res1 = RealField.mstInField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
@ -83,7 +83,7 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
|
||||
val res2 = RealField.mstInField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
@ -96,7 +96,7 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
fun complexField() {
|
||||
val res1 = ComplexField.mstInField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
@ -104,7 +104,7 @@ internal class TestAsmConsistencyWithInterpreter {
|
||||
|
||||
val res2 = ComplexField.mstInField {
|
||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||
(3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0
|
||||
(3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||
+ number(1),
|
||||
number(1) / 2 + number(2.0) * one
|
||||
) + zero
|
||||
|
@ -4,7 +4,7 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.RingWithNumbers
|
||||
import space.kscience.kmath.operations.NumbersAddOperations
|
||||
|
||||
/**
|
||||
* A field over commons-math [DerivativeStructure].
|
||||
@ -16,7 +16,8 @@ import space.kscience.kmath.operations.RingWithNumbers
|
||||
public class DerivativeStructureField(
|
||||
public val order: Int,
|
||||
bindings: Map<Symbol, Double>,
|
||||
) : ExtendedField<DerivativeStructure>, ExpressionAlgebra<Double, DerivativeStructure>, RingWithNumbers<DerivativeStructure> {
|
||||
) : ExtendedField<DerivativeStructure>, ExpressionAlgebra<Double, DerivativeStructure>,
|
||||
NumbersAddOperations<DerivativeStructure> {
|
||||
public val numberOfVariables: Int = bindings.size
|
||||
|
||||
public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) }
|
||||
@ -62,13 +63,11 @@ public class DerivativeStructureField(
|
||||
|
||||
public fun DerivativeStructure.derivative(vararg symbols: Symbol): Double = derivative(symbols.toList())
|
||||
|
||||
override fun DerivativeStructure.unaryMinus(): DerivativeStructure = negate()
|
||||
|
||||
public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b)
|
||||
|
||||
public override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) {
|
||||
is Double -> a.multiply(k)
|
||||
is Int -> a.multiply(k)
|
||||
else -> a.multiply(k.toDouble())
|
||||
}
|
||||
public override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure = a.multiply(value)
|
||||
|
||||
public override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b)
|
||||
public override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b)
|
||||
|
@ -101,8 +101,8 @@ public object CMMatrixContext : MatrixContext<Double, CMMatrix> {
|
||||
public override operator fun Matrix<Double>.minus(b: Matrix<Double>): CMMatrix =
|
||||
CMMatrix(toCM().origin.subtract(b.toCM().origin))
|
||||
|
||||
public override fun multiply(a: Matrix<Double>, k: Number): CMMatrix =
|
||||
CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble()))
|
||||
// public override fun multiply(a: Matrix<Double>, k: Number): CMMatrix =
|
||||
// CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble()))
|
||||
|
||||
public override operator fun Matrix<Double>.times(value: Double): CMMatrix =
|
||||
produce(rowNum, colNum) { i, j -> get(i, j) * value }
|
||||
|
@ -4,10 +4,7 @@ import space.kscience.kmath.memory.MemoryReader
|
||||
import space.kscience.kmath.memory.MemorySpec
|
||||
import space.kscience.kmath.memory.MemoryWriter
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.FieldElement
|
||||
import space.kscience.kmath.operations.Norm
|
||||
import space.kscience.kmath.operations.RingWithNumbers
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.MemoryBuffer
|
||||
import space.kscience.kmath.structures.MutableBuffer
|
||||
@ -47,7 +44,8 @@ private val PI_DIV_2 = Complex(PI / 2, 0)
|
||||
* A field of [Complex].
|
||||
*/
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, RingWithNumbers<Complex> {
|
||||
public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, NumbersAddOperations<Complex>,
|
||||
ScaleOperations<Complex> {
|
||||
public override val zero: Complex = 0.0.toComplex()
|
||||
public override val one: Complex = 1.0.toComplex()
|
||||
|
||||
@ -56,8 +54,14 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, Rin
|
||||
*/
|
||||
public val i: Complex by lazy { Complex(0.0, 1.0) }
|
||||
|
||||
override fun Complex.unaryMinus(): Complex = Complex(-re, -im)
|
||||
|
||||
override fun number(value: Number): Complex = Complex(value.toDouble(), 0.0)
|
||||
|
||||
override fun scale(a: Complex, value: Double): Complex = Complex(a.re * value, a.im * value)
|
||||
|
||||
public override fun add(a: Complex, b: Complex): Complex = Complex(a.re + b.re, a.im + b.im)
|
||||
public override fun multiply(a: Complex, k: Number): Complex = Complex(a.re * k.toDouble(), a.im * k.toDouble())
|
||||
// public override fun multiply(a: Complex, k: Number): Complex = Complex(a.re * k.toDouble(), a.im * k.toDouble())
|
||||
|
||||
public override fun multiply(a: Complex, b: Complex): Complex =
|
||||
Complex(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re)
|
||||
@ -86,8 +90,10 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, Rin
|
||||
}
|
||||
}
|
||||
|
||||
public override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2
|
||||
public override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2
|
||||
override operator fun Complex.div(k: Number): Complex = Complex(re / k.toDouble(), im / k.toDouble())
|
||||
|
||||
public override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2.0
|
||||
public override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2.0
|
||||
|
||||
public override fun tan(arg: Complex): Complex {
|
||||
val e1 = exp(-i * arg)
|
||||
@ -159,7 +165,8 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, Rin
|
||||
|
||||
public override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg)
|
||||
|
||||
public override fun bindSymbol(value: String): Complex = if (value == "i") i else super<ExtendedField>.bindSymbol(value)
|
||||
public override fun bindSymbol(value: String): Complex =
|
||||
if (value == "i") i else super<ExtendedField>.bindSymbol(value)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,7 +188,8 @@ public data class Complex(val re: Double, val im: Double) : FieldElement<Complex
|
||||
public override val objectSize: Int
|
||||
get() = 16
|
||||
|
||||
public override fun MemoryReader.read(offset: Int): Complex = Complex(readDouble(offset), readDouble(offset + 8))
|
||||
public override fun MemoryReader.read(offset: Int): Complex =
|
||||
Complex(readDouble(offset), readDouble(offset + 8))
|
||||
|
||||
public override fun MemoryWriter.write(offset: Int, value: Complex) {
|
||||
writeDouble(offset, value.re)
|
||||
|
@ -6,7 +6,7 @@ import space.kscience.kmath.nd.NDAlgebra
|
||||
import space.kscience.kmath.nd.NDBuffer
|
||||
import space.kscience.kmath.nd.NDStructure
|
||||
import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.RingWithNumbers
|
||||
import space.kscience.kmath.operations.NumbersAddOperations
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
@ -19,7 +19,7 @@ import kotlin.contracts.contract
|
||||
public class ComplexNDField(
|
||||
shape: IntArray,
|
||||
) : BufferedNDField<Complex, ComplexField>(shape, ComplexField, Buffer.Companion::complex),
|
||||
RingWithNumbers<NDStructure<Complex>>,
|
||||
NumbersAddOperations<NDStructure<Complex>>,
|
||||
ExtendedField<NDStructure<Complex>> {
|
||||
|
||||
override val zero: NDBuffer<Complex> by lazy { produce { zero } }
|
||||
@ -29,6 +29,7 @@ public class ComplexNDField(
|
||||
val d = value.toComplex() // minimize conversions
|
||||
return produce { d }
|
||||
}
|
||||
|
||||
//
|
||||
// @Suppress("OVERRIDE_BY_INLINE")
|
||||
// override inline fun map(
|
||||
@ -75,25 +76,25 @@ public class ComplexNDField(
|
||||
// return BufferedNDFieldElement(this, buffer)
|
||||
// }
|
||||
|
||||
override fun power(arg: NDStructure<Complex>, pow: Number): NDBuffer<Complex> = arg.map() { power(it, pow) }
|
||||
override fun power(arg: NDStructure<Complex>, pow: Number): NDBuffer<Complex> = arg.map { power(it, pow) }
|
||||
|
||||
override fun exp(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { exp(it) }
|
||||
override fun exp(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { exp(it) }
|
||||
|
||||
override fun ln(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { ln(it) }
|
||||
override fun ln(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { ln(it) }
|
||||
|
||||
override fun sin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { sin(it) }
|
||||
override fun cos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { cos(it) }
|
||||
override fun tan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { tan(it) }
|
||||
override fun asin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { asin(it) }
|
||||
override fun acos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { acos(it) }
|
||||
override fun atan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { atan(it) }
|
||||
override fun sin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { sin(it) }
|
||||
override fun cos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { cos(it) }
|
||||
override fun tan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { tan(it) }
|
||||
override fun asin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { asin(it) }
|
||||
override fun acos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { acos(it) }
|
||||
override fun atan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { atan(it) }
|
||||
|
||||
override fun sinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { sinh(it) }
|
||||
override fun cosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { cosh(it) }
|
||||
override fun tanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { tanh(it) }
|
||||
override fun asinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { asinh(it) }
|
||||
override fun acosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { acosh(it) }
|
||||
override fun atanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { atanh(it) }
|
||||
override fun sinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { sinh(it) }
|
||||
override fun cosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { cosh(it) }
|
||||
override fun tanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { tanh(it) }
|
||||
override fun asinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { asinh(it) }
|
||||
override fun acosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { acosh(it) }
|
||||
override fun atanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { atanh(it) }
|
||||
}
|
||||
|
||||
|
||||
|
@ -37,7 +37,7 @@ public val Quaternion.r: Double
|
||||
*/
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>, PowerOperations<Quaternion>,
|
||||
ExponentialOperations<Quaternion>, RingWithNumbers<Quaternion> {
|
||||
ExponentialOperations<Quaternion>, NumbersAddOperations<Quaternion>, ScaleOperations<Quaternion> {
|
||||
override val zero: Quaternion = 0.toQuaternion()
|
||||
override val one: Quaternion = 1.toQuaternion()
|
||||
|
||||
@ -59,10 +59,8 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
|
||||
public override fun add(a: Quaternion, b: Quaternion): Quaternion =
|
||||
Quaternion(a.w + b.w, a.x + b.x, a.y + b.y, a.z + b.z)
|
||||
|
||||
public override fun multiply(a: Quaternion, k: Number): Quaternion {
|
||||
val d = k.toDouble()
|
||||
return Quaternion(a.w * d, a.x * d, a.y * d, a.z * d)
|
||||
}
|
||||
public override fun scale(a: Quaternion, value: Double): Quaternion =
|
||||
Quaternion(a.w * value, a.x * value, a.y * value, a.z * value)
|
||||
|
||||
public override fun multiply(a: Quaternion, b: Quaternion): Quaternion = Quaternion(
|
||||
a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
|
||||
@ -173,6 +171,15 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
|
||||
"k" -> k
|
||||
else -> super<Field>.bindSymbol(value)
|
||||
}
|
||||
|
||||
override fun number(value: Number): Quaternion =value.toQuaternion()
|
||||
|
||||
public override fun sinh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / 2.0
|
||||
public override fun cosh(arg: Quaternion): Quaternion = (exp(arg) + exp(-arg)) / 2.0
|
||||
public override fun tanh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
|
||||
public override fun asinh(arg: Quaternion): Quaternion = ln(sqrt(arg * arg + one) + arg)
|
||||
public override fun acosh(arg: Quaternion): Quaternion = ln(arg + sqrt((arg - one) * (arg + one)))
|
||||
public override fun atanh(arg: Quaternion): Quaternion = (ln(arg + one) - ln(one - arg)) / 2.0
|
||||
}
|
||||
|
||||
/**
|
||||
@ -207,8 +214,7 @@ public data class Quaternion(
|
||||
require(!z.isNaN()) { "x-component of quaternion is not-a-number" }
|
||||
}
|
||||
|
||||
public override val context: QuaternionField
|
||||
get() = QuaternionField
|
||||
public override val context: QuaternionField get() = QuaternionField
|
||||
|
||||
/**
|
||||
* Returns a string representation of this quaternion.
|
||||
|
@ -4,7 +4,6 @@ import space.kscience.kmath.expressions.FunctionalExpressionField
|
||||
import space.kscience.kmath.expressions.bindSymbol
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.expressions.symbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@ -13,14 +12,11 @@ internal class ExpressionFieldForComplexTest {
|
||||
|
||||
@Test
|
||||
fun testComplex() {
|
||||
val context = FunctionalExpressionField(ComplexField)
|
||||
|
||||
val expression = context {
|
||||
val expression = FunctionalExpressionField(ComplexField).run {
|
||||
val x = bindSymbol(x)
|
||||
x * x + 2 * x + one
|
||||
}
|
||||
|
||||
assertEquals(expression(x to Complex(1.0, 0.0)), Complex(4.0, 0.0))
|
||||
//assertEquals(expression(), Complex(9.0, 0.0))
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +0,0 @@
|
||||
# The Core Module (`kmath-core`)
|
||||
|
||||
The core features of KMath:
|
||||
|
||||
- [algebras](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields.
|
||||
- [nd](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them.
|
||||
- [linear](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition.
|
||||
- [buffers](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure
|
||||
- [expressions](src/commonMain/kotlin/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of
|
||||
objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high
|
||||
performance calculations to code generation.
|
||||
- [domains](src/commonMain/kotlin/kscience/kmath/domains) : Domains
|
||||
- [autodif](src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
||||
|
||||
|
||||
> #### Artifact:
|
||||
>
|
||||
> This module artifact: `space.kscience:kmath-core:0.2.0`.
|
||||
>
|
||||
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion)
|
||||
>
|
||||
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion)
|
||||
>
|
||||
> **Gradle:**
|
||||
>
|
||||
> ```gradle
|
||||
> repositories {
|
||||
> maven { url 'https://repo.kotlin.link' }
|
||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||
>// Uncomment if repo.kotlin.link is unavailable
|
||||
>// maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
||||
>// maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation 'space.kscience:kmath-core:0.2.0'
|
||||
> }
|
||||
> ```
|
||||
> **Gradle Kotlin DSL:**
|
||||
>
|
||||
> ```kotlin
|
||||
> repositories {
|
||||
> maven("https://repo.kotlin.link")
|
||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||
> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||
>// Uncomment if repo.kotlin.link is unavailable
|
||||
>// maven("https://dl.bintray.com/mipt-npm/kscience")
|
||||
>// maven("https://dl.bintray.com/mipt-npm/dev")
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation("space.kscience:kmath-core:0.2.0")
|
||||
> }
|
||||
> ```
|
File diff suppressed because it is too large
Load Diff
@ -16,8 +16,8 @@
|
||||
package space.kscience.kmath.domains
|
||||
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.RealBuffer
|
||||
import space.kscience.kmath.structures.indices
|
||||
|
||||
/**
|
||||
@ -26,6 +26,7 @@ import space.kscience.kmath.structures.indices
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public class HyperSquareDomain(private val lower: Buffer<Double>, private val upper: Buffer<Double>) : RealDomain {
|
||||
public override val dimension: Int get() = lower.size
|
||||
|
||||
@ -33,26 +34,10 @@ public class HyperSquareDomain(private val lower: Buffer<Double>, private val up
|
||||
point[i] in lower[i]..upper[i]
|
||||
}
|
||||
|
||||
public override fun getLowerBound(num: Int, point: Point<Double>): Double = lower[num]
|
||||
|
||||
public override fun getLowerBound(num: Int): Double = lower[num]
|
||||
|
||||
public override fun getUpperBound(num: Int, point: Point<Double>): Double = upper[num]
|
||||
|
||||
public override fun getUpperBound(num: Int): Double = upper[num]
|
||||
|
||||
public override fun nearestInDomain(point: Point<Double>): Point<Double> {
|
||||
val res = DoubleArray(point.size) { i ->
|
||||
when {
|
||||
point[i] < lower[i] -> lower[i]
|
||||
point[i] > upper[i] -> upper[i]
|
||||
else -> point[i]
|
||||
}
|
||||
}
|
||||
|
||||
return RealBuffer(*res)
|
||||
}
|
||||
|
||||
public override fun volume(): Double {
|
||||
var res = 1.0
|
||||
|
||||
|
@ -15,45 +15,27 @@
|
||||
*/
|
||||
package space.kscience.kmath.domains
|
||||
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
|
||||
/**
|
||||
* n-dimensional volume
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public interface RealDomain : Domain<Double> {
|
||||
public fun nearestInDomain(point: Point<Double>): Point<Double>
|
||||
|
||||
/**
|
||||
* The lower edge for the domain going down from point
|
||||
* @param num
|
||||
* @param point
|
||||
* @return
|
||||
*/
|
||||
public fun getLowerBound(num: Int, point: Point<Double>): Double?
|
||||
|
||||
/**
|
||||
* The upper edge of the domain going up from point
|
||||
* @param num
|
||||
* @param point
|
||||
* @return
|
||||
*/
|
||||
public fun getUpperBound(num: Int, point: Point<Double>): Double?
|
||||
|
||||
/**
|
||||
* Global lower edge
|
||||
* @param num
|
||||
* @return
|
||||
* @param num axis number
|
||||
*/
|
||||
public fun getLowerBound(num: Int): Double?
|
||||
public fun getLowerBound(num: Int): Double
|
||||
|
||||
/**
|
||||
* Global upper edge
|
||||
* @param num
|
||||
* @return
|
||||
* @param num axis number
|
||||
*/
|
||||
public fun getUpperBound(num: Int): Double?
|
||||
public fun getUpperBound(num: Int): Double
|
||||
|
||||
/**
|
||||
* Hyper volume
|
||||
|
@ -16,19 +16,15 @@
|
||||
package space.kscience.kmath.domains
|
||||
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
|
||||
@UnstableKMathAPI
|
||||
public class UnconstrainedDomain(public override val dimension: Int) : RealDomain {
|
||||
public override operator fun contains(point: Point<Double>): Boolean = true
|
||||
|
||||
public override fun getLowerBound(num: Int, point: Point<Double>): Double? = Double.NEGATIVE_INFINITY
|
||||
public override fun getLowerBound(num: Int): Double = Double.NEGATIVE_INFINITY
|
||||
|
||||
public override fun getLowerBound(num: Int): Double? = Double.NEGATIVE_INFINITY
|
||||
|
||||
public override fun getUpperBound(num: Int, point: Point<Double>): Double? = Double.POSITIVE_INFINITY
|
||||
|
||||
public override fun getUpperBound(num: Int): Double? = Double.POSITIVE_INFINITY
|
||||
|
||||
public override fun nearestInDomain(point: Point<Double>): Point<Double> = point
|
||||
public override fun getUpperBound(num: Int): Double = Double.POSITIVE_INFINITY
|
||||
|
||||
public override fun volume(): Double = Double.POSITIVE_INFINITY
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package space.kscience.kmath.domains
|
||||
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.structures.asBuffer
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
|
||||
@UnstableKMathAPI
|
||||
public inline class UnivariateDomain(public val range: ClosedFloatingPointRange<Double>) : RealDomain {
|
||||
public override val dimension: Int
|
||||
get() = 1
|
||||
public override val dimension: Int get() = 1
|
||||
|
||||
public operator fun contains(d: Double): Boolean = range.contains(d)
|
||||
|
||||
@ -14,33 +14,12 @@ public inline class UnivariateDomain(public val range: ClosedFloatingPointRange<
|
||||
return contains(point[0])
|
||||
}
|
||||
|
||||
public override fun nearestInDomain(point: Point<Double>): Point<Double> {
|
||||
require(point.size == 1)
|
||||
val value = point[0]
|
||||
|
||||
return when {
|
||||
value in range -> point
|
||||
value >= range.endInclusive -> doubleArrayOf(range.endInclusive).asBuffer()
|
||||
else -> doubleArrayOf(range.start).asBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
public override fun getLowerBound(num: Int, point: Point<Double>): Double? {
|
||||
public override fun getLowerBound(num: Int): Double {
|
||||
require(num == 0)
|
||||
return range.start
|
||||
}
|
||||
|
||||
public override fun getUpperBound(num: Int, point: Point<Double>): Double? {
|
||||
require(num == 0)
|
||||
return range.endInclusive
|
||||
}
|
||||
|
||||
public override fun getLowerBound(num: Int): Double? {
|
||||
require(num == 0)
|
||||
return range.start
|
||||
}
|
||||
|
||||
public override fun getUpperBound(num: Int): Double? {
|
||||
public override fun getUpperBound(num: Int): Double {
|
||||
require(num == 0)
|
||||
return range.endInclusive
|
||||
}
|
||||
|
@ -48,18 +48,21 @@ public open class FunctionalExpressionSpace<T, A : Space<T>>(
|
||||
) : FunctionalExpressionAlgebra<T, A>(algebra), Space<Expression<T>> {
|
||||
public override val zero: Expression<T> get() = const(algebra.zero)
|
||||
|
||||
override fun Expression<T>.unaryMinus(): Expression<T> =
|
||||
unaryOperation(SpaceOperations.MINUS_OPERATION, this)
|
||||
|
||||
/**
|
||||
* Builds an Expression of addition of two another expressions.
|
||||
*/
|
||||
public override fun add(a: Expression<T>, b: Expression<T>): Expression<T> =
|
||||
binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b)
|
||||
binaryOperation(SpaceOperations.PLUS_OPERATION, a, b)
|
||||
|
||||
/**
|
||||
* Builds an Expression of multiplication of expression by number.
|
||||
*/
|
||||
public override fun multiply(a: Expression<T>, k: Number): Expression<T> = Expression { arguments ->
|
||||
algebra.multiply(a.invoke(arguments), k)
|
||||
}
|
||||
// /**
|
||||
// * Builds an Expression of multiplication of expression by number.
|
||||
// */
|
||||
// public override fun multiply(a: Expression<T>, k: Number): Expression<T> = Expression { arguments ->
|
||||
// algebra.multiply(a.invoke(arguments), k)
|
||||
// }
|
||||
|
||||
public operator fun Expression<T>.plus(arg: T): Expression<T> = this + const(arg)
|
||||
public operator fun Expression<T>.minus(arg: T): Expression<T> = this - const(arg)
|
||||
@ -71,13 +74,13 @@ public open class FunctionalExpressionSpace<T, A : Space<T>>(
|
||||
|
||||
public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
|
||||
super<FunctionalExpressionAlgebra>.binaryOperationFunction(operation)
|
||||
|
||||
}
|
||||
|
||||
public open class FunctionalExpressionRing<T, A : Ring<T>>(
|
||||
algebra: A,
|
||||
) : FunctionalExpressionSpace<T, A>(algebra), Ring<Expression<T>> {
|
||||
public override val one: Expression<T>
|
||||
get() = const(algebra.one)
|
||||
public override val one: Expression<T> get() = const(algebra.one)
|
||||
|
||||
/**
|
||||
* Builds an Expression of multiplication of two expressions.
|
||||
@ -95,9 +98,10 @@ public open class FunctionalExpressionRing<T, A : Ring<T>>(
|
||||
super<FunctionalExpressionSpace>.binaryOperationFunction(operation)
|
||||
}
|
||||
|
||||
public open class FunctionalExpressionField<T, A : Field<T>>(
|
||||
public open class FunctionalExpressionField<T, A: Field<T>>(
|
||||
algebra: A,
|
||||
) : FunctionalExpressionRing<T, A>(algebra), Field<Expression<T>> {
|
||||
) : FunctionalExpressionRing<T, A>(algebra), Field<Expression<T>>,
|
||||
ScaleOperations<Expression<T>> {
|
||||
/**
|
||||
* Builds an Expression of division an expression by another one.
|
||||
*/
|
||||
@ -112,6 +116,10 @@ public open class FunctionalExpressionField<T, A : Field<T>>(
|
||||
|
||||
public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
|
||||
super<FunctionalExpressionRing>.binaryOperationFunction(operation)
|
||||
|
||||
override fun scale(a: Expression<T>, value: Double): Expression<T> = algebra {
|
||||
Expression { args -> a(args) * value }
|
||||
}
|
||||
}
|
||||
|
||||
public open class FunctionalExpressionExtendedField<T, A : ExtendedField<T>>(
|
||||
@ -160,5 +168,6 @@ public inline fun <T, A : Ring<T>> A.expressionInRing(block: FunctionalExpressio
|
||||
public inline fun <T, A : Field<T>> A.expressionInField(block: FunctionalExpressionField<T, A>.() -> Expression<T>): Expression<T> =
|
||||
FunctionalExpressionField(this).block()
|
||||
|
||||
public inline fun <T, A : ExtendedField<T>> A.expressionInExtendedField(block: FunctionalExpressionExtendedField<T, A>.() -> Expression<T>): Expression<T> =
|
||||
FunctionalExpressionExtendedField(this).block()
|
||||
public inline fun <T, A : ExtendedField<T>> A.expressionInExtendedField(
|
||||
block: FunctionalExpressionExtendedField<T, A>.() -> Expression<T>,
|
||||
): Expression<T> = FunctionalExpressionExtendedField(this).block()
|
||||
|
@ -47,36 +47,6 @@ public fun <T : Any> DerivationResult<T>.grad(vararg variables: Symbol): Point<T
|
||||
return variables.map(::derivative).asBuffer()
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs differentiation and establishes [SimpleAutoDiffField] context inside the block of code.
|
||||
*
|
||||
* The partial derivatives are placed in argument `d` variable
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* val x by symbol // define variable(s) and their values
|
||||
* val y = RealField.withAutoDiff() { sqr(x) + 5 * x + 3 } // write formulate in deriv context
|
||||
* assertEquals(17.0, y.x) // the value of result (y)
|
||||
* assertEquals(9.0, x.d) // dy/dx
|
||||
* ```
|
||||
*
|
||||
* @param body the action in [SimpleAutoDiffField] context returning [AutoDiffVariable] to differentiate with respect to.
|
||||
* @return the result of differentiation.
|
||||
*/
|
||||
public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
|
||||
bindings: Map<Symbol, T>,
|
||||
body: SimpleAutoDiffField<T, F>.() -> AutoDiffValue<T>,
|
||||
): DerivationResult<T> {
|
||||
contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) }
|
||||
|
||||
return SimpleAutoDiffField(this, bindings).differentiate(body)
|
||||
}
|
||||
|
||||
public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
|
||||
vararg bindings: Pair<Symbol, T>,
|
||||
body: SimpleAutoDiffField<T, F>.() -> AutoDiffValue<T>,
|
||||
): DerivationResult<T> = simpleAutoDiff(bindings.toMap(), body)
|
||||
|
||||
/**
|
||||
* Represents field in context of which functions can be derived.
|
||||
*/
|
||||
@ -84,12 +54,9 @@ public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
|
||||
public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
|
||||
public val context: F,
|
||||
bindings: Map<Symbol, T>,
|
||||
) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, RingWithNumbers<AutoDiffValue<T>> {
|
||||
public override val zero: AutoDiffValue<T>
|
||||
get() = const(context.zero)
|
||||
|
||||
public override val one: AutoDiffValue<T>
|
||||
get() = const(context.one)
|
||||
) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, NumbersAddOperations<AutoDiffValue<T>> {
|
||||
public override val zero: AutoDiffValue<T> get() = const(context.zero)
|
||||
public override val one: AutoDiffValue<T> get() = const(context.one)
|
||||
|
||||
// this stack contains pairs of blocks and values to apply them to
|
||||
private var stack: Array<Any?> = arrayOfNulls<Any?>(8)
|
||||
@ -137,6 +104,8 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
|
||||
|
||||
override fun const(value: T): AutoDiffValue<T> = AutoDiffValue(value)
|
||||
|
||||
override fun number(value: Number): AutoDiffValue<T> = const { one * value }
|
||||
|
||||
/**
|
||||
* A variable accessing inner state of derivatives.
|
||||
* Use this value in inner builders to avoid creating additional derivative bindings.
|
||||
@ -175,21 +144,24 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
|
||||
return DerivationResult(result.value, bindings.mapValues { it.value.d }, context)
|
||||
}
|
||||
|
||||
// Overloads for Double constants
|
||||
// // Overloads for Double constants
|
||||
//
|
||||
// public override operator fun Number.plus(b: AutoDiffValue<T>): AutoDiffValue<T> =
|
||||
// derive(const { this@plus.toDouble() * one + b.value }) { z ->
|
||||
// b.d += z.d
|
||||
// }
|
||||
//
|
||||
// public override operator fun AutoDiffValue<T>.plus(b: Number): AutoDiffValue<T> = b.plus(this)
|
||||
//
|
||||
// public override operator fun Number.minus(b: AutoDiffValue<T>): AutoDiffValue<T> =
|
||||
// derive(const { this@minus.toDouble() * one - b.value }) { z -> b.d -= z.d }
|
||||
//
|
||||
// public override operator fun AutoDiffValue<T>.minus(b: Number): AutoDiffValue<T> =
|
||||
// derive(const { this@minus.value - one * b.toDouble() }) { z -> d += z.d }
|
||||
|
||||
public override operator fun Number.plus(b: AutoDiffValue<T>): AutoDiffValue<T> =
|
||||
derive(const { this@plus.toDouble() * one + b.value }) { z ->
|
||||
b.d += z.d
|
||||
}
|
||||
|
||||
public override operator fun AutoDiffValue<T>.plus(b: Number): AutoDiffValue<T> = b.plus(this)
|
||||
|
||||
public override operator fun Number.minus(b: AutoDiffValue<T>): AutoDiffValue<T> =
|
||||
derive(const { this@minus.toDouble() * one - b.value }) { z -> b.d -= z.d }
|
||||
|
||||
public override operator fun AutoDiffValue<T>.minus(b: Number): AutoDiffValue<T> =
|
||||
derive(const { this@minus.value - one * b.toDouble() }) { z -> this@minus.d += z.d }
|
||||
|
||||
override fun AutoDiffValue<T>.unaryMinus(): AutoDiffValue<T> =
|
||||
derive(const { -value }) { z -> d -= z.d }
|
||||
|
||||
// Basic math (+, -, *, /)
|
||||
|
||||
@ -211,12 +183,44 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
|
||||
b.d -= z.d * a.value / (b.value * b.value)
|
||||
}
|
||||
|
||||
public override fun multiply(a: AutoDiffValue<T>, k: Number): AutoDiffValue<T> =
|
||||
derive(const { k.toDouble() * a.value }) { z ->
|
||||
a.d += z.d * k.toDouble()
|
||||
public override fun scale(a: AutoDiffValue<T>, value: Double): AutoDiffValue<T> =
|
||||
derive(const { value * a.value }) { z ->
|
||||
a.d += z.d * value
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs differentiation and establishes [SimpleAutoDiffField] context inside the block of code.
|
||||
*
|
||||
* The partial derivatives are placed in argument `d` variable
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* val x by symbol // define variable(s) and their values
|
||||
* val y = RealField.withAutoDiff() { sqr(x) + 5 * x + 3 } // write formulate in deriv context
|
||||
* assertEquals(17.0, y.x) // the value of result (y)
|
||||
* assertEquals(9.0, x.d) // dy/dx
|
||||
* ```
|
||||
*
|
||||
* @param body the action in [SimpleAutoDiffField] context returning [AutoDiffVariable] to differentiate with respect to.
|
||||
* @return the result of differentiation.
|
||||
*/
|
||||
public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
|
||||
bindings: Map<Symbol, T>,
|
||||
body: SimpleAutoDiffField<T, F>.() -> AutoDiffValue<T>,
|
||||
): DerivationResult<T> {
|
||||
contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) }
|
||||
|
||||
return SimpleAutoDiffField(this, bindings).differentiate(body)
|
||||
}
|
||||
|
||||
public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
|
||||
vararg bindings: Pair<Symbol, T>,
|
||||
body: SimpleAutoDiffField<T, F>.() -> AutoDiffValue<T>,
|
||||
): DerivationResult<T> = simpleAutoDiff(bindings.toMap(), body)
|
||||
|
||||
|
||||
/**
|
||||
* A constructs that creates a derivative structure with required order on-demand
|
||||
*/
|
||||
@ -247,19 +251,20 @@ public fun <T : Any, F : Field<T>> simpleAutoDiff(field: F): AutoDiffProcessor<T
|
||||
// Extensions for differentiation of various basic mathematical functions
|
||||
|
||||
// x ^ 2
|
||||
public fun <T : Any, F : Field<T>> SimpleAutoDiffField<T, F>.sqr(x: AutoDiffValue<T>): AutoDiffValue<T> =
|
||||
derive(const { x.value * x.value }) { z -> x.d += z.d * 2 * x.value }
|
||||
public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.sqr(x: AutoDiffValue<T>): AutoDiffValue<T> =
|
||||
derive(const { x.value * x.value }) { z -> x.d += z.d * 2.0 * x.value }
|
||||
|
||||
// x ^ 1/2
|
||||
public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.sqrt(x: AutoDiffValue<T>): AutoDiffValue<T> =
|
||||
derive(const { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value }
|
||||
derive(const { sqrt(x.value) }) { z -> x.d += z.d / 2.0 / z.value }
|
||||
|
||||
// x ^ y (const)
|
||||
public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.pow(
|
||||
x: AutoDiffValue<T>,
|
||||
y: Double,
|
||||
): AutoDiffValue<T> =
|
||||
derive(const { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) }
|
||||
): AutoDiffValue<T> = derive(const { power(x.value, y) }) { z ->
|
||||
x.d += z.d * y * power(x.value, y - 1)
|
||||
}
|
||||
|
||||
public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.pow(
|
||||
x: AutoDiffValue<T>,
|
||||
@ -328,7 +333,13 @@ public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.atanh(x: Au
|
||||
public class SimpleAutoDiffExtendedField<T : Any, F : ExtendedField<T>>(
|
||||
context: F,
|
||||
bindings: Map<Symbol, T>,
|
||||
) : ExtendedField<AutoDiffValue<T>>, SimpleAutoDiffField<T, F>(context, bindings) {
|
||||
) : ExtendedField<AutoDiffValue<T>>, ScaleOperations<AutoDiffValue<T>>,
|
||||
SimpleAutoDiffField<T, F>(context, bindings) {
|
||||
|
||||
override fun number(value: Number): AutoDiffValue<T> = const { number(value) }
|
||||
|
||||
override fun scale(a: AutoDiffValue<T>, value: Double): AutoDiffValue<T> = a * number(value)
|
||||
|
||||
// x ^ 2
|
||||
public fun sqr(x: AutoDiffValue<T>): AutoDiffValue<T> =
|
||||
(this as SimpleAutoDiffField<T, F>).sqr(x)
|
||||
|
@ -78,12 +78,12 @@ public class BufferMatrixContext<T : Any, R : Ring<T>>(
|
||||
}
|
||||
}
|
||||
|
||||
override fun multiply(a: Matrix<T>, k: Number): BufferMatrix<T> {
|
||||
val aBufferMatrix = a.toBufferMatrix()
|
||||
return elementContext {
|
||||
produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() }
|
||||
}
|
||||
}
|
||||
// override fun multiply(a: Matrix<T>, k: Number): BufferMatrix<T> {
|
||||
// val aBufferMatrix = a.toBufferMatrix()
|
||||
// return elementContext {
|
||||
// produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() }
|
||||
// }
|
||||
// }
|
||||
|
||||
public companion object
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import space.kscience.kmath.operations.SpaceOperations
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.operations.sum
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.BufferFactory
|
||||
import space.kscience.kmath.structures.asSequence
|
||||
@ -167,9 +164,9 @@ public interface GenericMatrixContext<T : Any, R : Ring<T>, out M : Matrix<T>> :
|
||||
|
||||
return produce(rowNum, colNum) { i, j -> elementContext { get(i, j) + b[i, j] } }
|
||||
}
|
||||
|
||||
public override fun multiply(a: Matrix<T>, k: Number): M =
|
||||
produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } }
|
||||
//
|
||||
// public override fun multiply(a: Matrix<T>, k: Number): M =
|
||||
// produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } }
|
||||
|
||||
public override operator fun Matrix<T>.times(value: T): M =
|
||||
produce(rowNum, colNum) { i, j -> elementContext { get(i, j) * value } }
|
||||
|
@ -21,6 +21,8 @@ public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
|
||||
if (i == j) 1.0 else 0.0
|
||||
} + DiagonalFeature
|
||||
|
||||
override fun Matrix<Double>.unaryMinus(): Matrix<Double> = produce(rowNum, colNum) { i, j -> -get(i, j) }
|
||||
|
||||
public override infix fun Matrix<Double>.dot(other: Matrix<Double>): BufferMatrix<Double> {
|
||||
require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
|
||||
val bufferMatrix = toBufferMatrix()
|
||||
@ -60,12 +62,16 @@ public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
|
||||
val bufferMatrix = toBufferMatrix()
|
||||
return produce(rowNum, colNum) { i, j -> bufferMatrix[i, j] * value }
|
||||
}
|
||||
|
||||
|
||||
override fun multiply(a: Matrix<Double>, k: Number): BufferMatrix<Double> {
|
||||
val aBufferMatrix = a.toBufferMatrix()
|
||||
return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() }
|
||||
}
|
||||
//
|
||||
// override fun multiply(a: Matrix<Double>, k: Number): BufferMatrix<Double> {
|
||||
// val aBufferMatrix = a.toBufferMatrix()
|
||||
// return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() }
|
||||
// }
|
||||
//
|
||||
// override fun divide(a: Matrix<Double>, k: Number): BufferMatrix<Double> {
|
||||
// val aBufferMatrix = a.toBufferMatrix()
|
||||
// return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] / k.toDouble() }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import space.kscience.kmath.operations.Space
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
@ -10,21 +11,18 @@ import space.kscience.kmath.structures.BufferFactory
|
||||
* A linear space for vectors.
|
||||
* Could be used on any point-like structure
|
||||
*/
|
||||
public interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
|
||||
public interface VectorSpace<T : Any, A : Ring<T>> : Space<Point<T>> {
|
||||
public val size: Int
|
||||
public val space: S
|
||||
override val zero: Point<T> get() = produce { space.zero }
|
||||
public val algebra: A
|
||||
override val zero: Point<T> get() = produce { algebra.zero }
|
||||
|
||||
public fun produce(initializer: S.(Int) -> T): Point<T>
|
||||
public fun produce(initializer: A.(Int) -> T): Point<T>
|
||||
|
||||
/**
|
||||
* Produce a space-element of this vector space for expressions
|
||||
*/
|
||||
//fun produceElement(initializer: (Int) -> T): Vector<T, S>
|
||||
override fun add(a: Point<T>, b: Point<T>): Point<T> = produce { algebra { a[it] + b[it] } }
|
||||
|
||||
override fun add(a: Point<T>, b: Point<T>): Point<T> = produce { space { a[it] + b[it] } }
|
||||
public fun scale(a: Point<T>, scale: T): Point<T> = produce { algebra { a[it] * scale } }
|
||||
|
||||
override fun multiply(a: Point<T>, k: Number): Point<T> = produce { space { a[it] * k } }
|
||||
override fun Point<T>.unaryMinus(): Point<T> = produce { -get(it) }
|
||||
|
||||
//TODO add basis
|
||||
|
||||
@ -45,26 +43,25 @@ public interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
|
||||
/**
|
||||
* A structured vector space with custom buffer
|
||||
*/
|
||||
public fun <T : Any, S : Space<T>> buffered(
|
||||
public fun <T : Any, A : Ring<T>> buffered(
|
||||
size: Int,
|
||||
space: S,
|
||||
space: A,
|
||||
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
|
||||
): BufferVectorSpace<T, S> = BufferVectorSpace(size, space, bufferFactory)
|
||||
): BufferVectorSpace<T, A> = BufferVectorSpace(size, space, bufferFactory)
|
||||
|
||||
/**
|
||||
* Automatic buffered vector, unboxed if it is possible
|
||||
*/
|
||||
public inline fun <reified T : Any, S : Space<T>> auto(size: Int, space: S): VectorSpace<T, S> =
|
||||
public inline fun <reified T : Any, A : Ring<T>> auto(size: Int, space: A): VectorSpace<T, A> =
|
||||
buffered(size, space, Buffer.Companion::auto)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class BufferVectorSpace<T : Any, S : Space<T>>(
|
||||
public class BufferVectorSpace<T : Any, A : Ring<T>>(
|
||||
override val size: Int,
|
||||
override val space: S,
|
||||
override val algebra: A,
|
||||
public val bufferFactory: BufferFactory<T>,
|
||||
) : VectorSpace<T, S> {
|
||||
override fun produce(initializer: S.(Int) -> T): Buffer<T> = bufferFactory(size) { space.initializer(it) }
|
||||
//override fun produceElement(initializer: (Int) -> T): Vector<T, S> = BufferVector(this, produce(initializer))
|
||||
) : VectorSpace<T, A> {
|
||||
override fun produce(initializer: A.(Int) -> T): Buffer<T> = bufferFactory(size) { algebra.initializer(it) }
|
||||
}
|
||||
|
@ -1,19 +1,16 @@
|
||||
package space.kscience.kmath.nd
|
||||
|
||||
import space.kscience.kmath.operations.Field
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import space.kscience.kmath.operations.Space
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.BufferFactory
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
|
||||
public interface BufferNDAlgebra<T, A : Algebra<T>> : NDAlgebra<T, A> {
|
||||
public val strides: Strides
|
||||
public val bufferFactory: BufferFactory<T>
|
||||
|
||||
override fun produce(initializer: C.(IntArray) -> T): NDBuffer<T> = NDBuffer(
|
||||
override fun produce(initializer: A.(IntArray) -> T): NDBuffer<T> = NDBuffer(
|
||||
strides,
|
||||
bufferFactory(strides.linearSize) { offset ->
|
||||
elementContext.initializer(strides.index(offset))
|
||||
@ -30,14 +27,14 @@ public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
|
||||
else -> bufferFactory(strides.linearSize) { offset -> get(strides.index(offset)) }
|
||||
}
|
||||
|
||||
override fun NDStructure<T>.map(transform: C.(T) -> T): NDBuffer<T> {
|
||||
override fun NDStructure<T>.map(transform: A.(T) -> T): NDBuffer<T> {
|
||||
val buffer = bufferFactory(strides.linearSize) { offset ->
|
||||
elementContext.transform(buffer[offset])
|
||||
}
|
||||
return NDBuffer(strides, buffer)
|
||||
}
|
||||
|
||||
override fun NDStructure<T>.mapIndexed(transform: C.(index: IntArray, T) -> T): NDBuffer<T> {
|
||||
override fun NDStructure<T>.mapIndexed(transform: A.(index: IntArray, T) -> T): NDBuffer<T> {
|
||||
val buffer = bufferFactory(strides.linearSize) { offset ->
|
||||
elementContext.transform(
|
||||
strides.index(offset),
|
||||
@ -47,7 +44,7 @@ public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
|
||||
return NDBuffer(strides, buffer)
|
||||
}
|
||||
|
||||
override fun combine(a: NDStructure<T>, b: NDStructure<T>, transform: C.(T, T) -> T): NDBuffer<T> {
|
||||
override fun combine(a: NDStructure<T>, b: NDStructure<T>, transform: A.(T, T) -> T): NDBuffer<T> {
|
||||
val buffer = bufferFactory(strides.linearSize) { offset ->
|
||||
elementContext.transform(a.buffer[offset], b.buffer[offset])
|
||||
}
|
||||
@ -55,13 +52,14 @@ public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
|
||||
}
|
||||
}
|
||||
|
||||
public open class BufferedNDSpace<T, R : Space<T>>(
|
||||
public open class BufferedNDSpace<T, A : Space<T>>(
|
||||
final override val shape: IntArray,
|
||||
final override val elementContext: R,
|
||||
final override val elementContext: A,
|
||||
final override val bufferFactory: BufferFactory<T>,
|
||||
) : NDSpace<T, R>, BufferNDAlgebra<T, R> {
|
||||
) : NDSpace<T, A>, BufferNDAlgebra<T, A> {
|
||||
override val strides: Strides = DefaultStrides(shape)
|
||||
override val zero: NDBuffer<T> by lazy { produce { zero } }
|
||||
override fun NDStructure<T>.unaryMinus(): NDStructure<T> = produce { -get(it) }
|
||||
}
|
||||
|
||||
public open class BufferedNDRing<T, R : Ring<T>>(
|
||||
@ -76,7 +74,10 @@ public open class BufferedNDField<T, R : Field<T>>(
|
||||
shape: IntArray,
|
||||
elementContext: R,
|
||||
bufferFactory: BufferFactory<T>,
|
||||
) : BufferedNDRing<T, R>(shape, elementContext, bufferFactory), NDField<T, R>
|
||||
) : BufferedNDRing<T, R>(shape, elementContext, bufferFactory), NDField<T, R> {
|
||||
|
||||
override fun scale(a: NDStructure<T>, value: Double): NDStructure<T> = a.map { it * value }
|
||||
}
|
||||
|
||||
// space factories
|
||||
public fun <T, A : Space<T>> NDAlgebra.Companion.space(
|
||||
|
@ -1,8 +1,6 @@
|
||||
package space.kscience.kmath.nd
|
||||
|
||||
import space.kscience.kmath.operations.Field
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import space.kscience.kmath.operations.Space
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.*
|
||||
|
||||
/**
|
||||
@ -21,7 +19,7 @@ public class ShapeMismatchException(public val expected: IntArray, public val ac
|
||||
* @param C the type of the element context.
|
||||
* @param N the type of the structure.
|
||||
*/
|
||||
public interface NDAlgebra<T, C> {
|
||||
public interface NDAlgebra<T, C: Algebra<T>> {
|
||||
/**
|
||||
* The shape of ND-structures this algebra operates on.
|
||||
*/
|
||||
@ -33,7 +31,7 @@ public interface NDAlgebra<T, C> {
|
||||
public val elementContext: C
|
||||
|
||||
/**
|
||||
* Produces a new [N] structure using given initializer function.
|
||||
* Produces a new NDStructure using given initializer function.
|
||||
*/
|
||||
public fun produce(initializer: C.(IntArray) -> T): NDStructure<T>
|
||||
|
||||
@ -67,7 +65,7 @@ public interface NDAlgebra<T, C> {
|
||||
* @param structures the structures to check.
|
||||
* @return the array of valid structures.
|
||||
*/
|
||||
internal fun <T, C> NDAlgebra<T, C>.checkShape(vararg structures: NDStructure<T>): Array<out NDStructure<T>> = structures
|
||||
internal fun <T, C: Algebra<T>> NDAlgebra<T, C>.checkShape(vararg structures: NDStructure<T>): Array<out NDStructure<T>> = structures
|
||||
.map(NDStructure<T>::shape)
|
||||
.singleOrNull { !shape.contentEquals(it) }
|
||||
?.let<IntArray, Array<out NDStructure<T>>> { throw ShapeMismatchException(shape, it) }
|
||||
@ -79,7 +77,7 @@ internal fun <T, C> NDAlgebra<T, C>.checkShape(vararg structures: NDStructure<T>
|
||||
* @param element the structure to check.
|
||||
* @return the valid structure.
|
||||
*/
|
||||
internal fun <T, C> NDAlgebra<T, C>.checkShape(element: NDStructure<T>): NDStructure<T> {
|
||||
internal fun <T, C: Algebra<T>> NDAlgebra<T, C>.checkShape(element: NDStructure<T>): NDStructure<T> {
|
||||
if (!element.shape.contentEquals(shape)) throw ShapeMismatchException(shape, element.shape)
|
||||
return element
|
||||
}
|
||||
@ -102,14 +100,14 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
|
||||
public override fun add(a: NDStructure<T>, b: NDStructure<T>): NDStructure<T> =
|
||||
combine(a, b) { aValue, bValue -> add(aValue, bValue) }
|
||||
|
||||
/**
|
||||
* Element-wise multiplication by scalar.
|
||||
*
|
||||
* @param a the multiplicand.
|
||||
* @param k the multiplier.
|
||||
* @return the product.
|
||||
*/
|
||||
public override fun multiply(a: NDStructure<T>, k: Number): NDStructure<T> = a.map() { multiply(it, k) }
|
||||
// /**
|
||||
// * Element-wise multiplication by scalar.
|
||||
// *
|
||||
// * @param a the multiplicand.
|
||||
// * @param k the multiplier.
|
||||
// * @return the product.
|
||||
// */
|
||||
// public override fun multiply(a: NDStructure<T>, k: Number): NDStructure<T> = a.map { multiply(it, k) }
|
||||
|
||||
// TODO move to extensions after KEEP-176
|
||||
|
||||
@ -120,7 +118,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
|
||||
* @param arg the augend.
|
||||
* @return the sum.
|
||||
*/
|
||||
public operator fun NDStructure<T>.plus(arg: T): NDStructure<T> = this.map() { value -> add(arg, value) }
|
||||
public operator fun NDStructure<T>.plus(arg: T): NDStructure<T> = this.map { value -> add(arg, value) }
|
||||
|
||||
/**
|
||||
* Subtracts an element from ND structure of it.
|
||||
@ -200,7 +198,7 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDSpace<T, R> {
|
||||
* @param N the type of ND structure.
|
||||
* @param F the type field of structure elements.
|
||||
*/
|
||||
public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F> {
|
||||
public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F>, ScaleOperations<NDStructure<T>> {
|
||||
/**
|
||||
* Element-wise division.
|
||||
*
|
||||
|
@ -2,8 +2,9 @@ package space.kscience.kmath.nd
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.NumbersAddOperations
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.operations.RingWithNumbers
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.RealBuffer
|
||||
import kotlin.contracts.InvocationKind
|
||||
@ -13,7 +14,8 @@ import kotlin.contracts.contract
|
||||
public class RealNDField(
|
||||
shape: IntArray,
|
||||
) : BufferedNDField<Double, RealField>(shape, RealField, Buffer.Companion::real),
|
||||
RingWithNumbers<NDStructure<Double>>,
|
||||
NumbersAddOperations<NDStructure<Double>>,
|
||||
ScaleOperations<NDStructure<Double>>,
|
||||
ExtendedField<NDStructure<Double>> {
|
||||
|
||||
override val zero: NDBuffer<Double> by lazy { produce { zero } }
|
||||
@ -75,6 +77,8 @@ public class RealNDField(
|
||||
return NDBuffer(strides, buffer)
|
||||
}
|
||||
|
||||
override fun scale(a: NDStructure<Double>, value: Double): NDStructure<Double> = a.map { it * value }
|
||||
|
||||
override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = arg.map { power(it, pow) }
|
||||
|
||||
override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { exp(it) }
|
||||
|
@ -1,7 +1,7 @@
|
||||
package space.kscience.kmath.nd
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.RingWithNumbers
|
||||
import space.kscience.kmath.operations.NumbersAddOperations
|
||||
import space.kscience.kmath.operations.ShortRing
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.ShortBuffer
|
||||
@ -12,7 +12,7 @@ import kotlin.contracts.contract
|
||||
public class ShortNDRing(
|
||||
shape: IntArray,
|
||||
) : BufferedNDRing<Short, ShortRing>(shape, ShortRing, Buffer.Companion::auto),
|
||||
RingWithNumbers<NDStructure<Short>> {
|
||||
NumbersAddOperations<NDStructure<Short>> {
|
||||
|
||||
override val zero: NDBuffer<Short> by lazy { produce { zero } }
|
||||
override val one: NDBuffer<Short> by lazy { produce { one } }
|
||||
|
@ -87,10 +87,11 @@ public interface Algebra<T> {
|
||||
* @param right the second argument of operation.
|
||||
* @return a result of operation.
|
||||
*/
|
||||
public fun binaryOperation(operation: String, left: T, right: T): T = binaryOperationFunction(operation)(left, right)
|
||||
public fun binaryOperation(operation: String, left: T, right: T): T =
|
||||
binaryOperationFunction(operation)(left, right)
|
||||
}
|
||||
|
||||
public fun <T: Any> Algebra<T>.bindSymbol(symbol: Symbol): T = bindSymbol(symbol.identity)
|
||||
public fun <T : Any> Algebra<T>.bindSymbol(symbol: Symbol): T = bindSymbol(symbol.identity)
|
||||
|
||||
/**
|
||||
* Call a block with an [Algebra] as receiver.
|
||||
@ -114,15 +115,6 @@ public interface SpaceOperations<T> : Algebra<T> {
|
||||
*/
|
||||
public fun add(a: T, b: T): T
|
||||
|
||||
/**
|
||||
* Multiplication of element by scalar.
|
||||
*
|
||||
* @param a the multiplier.
|
||||
* @param k the multiplicand.
|
||||
* @return the produce.
|
||||
*/
|
||||
public fun multiply(a: T, k: Number): T
|
||||
|
||||
// Operations to be performed in this context. Could be moved to extensions in case of KEEP-176
|
||||
|
||||
/**
|
||||
@ -131,7 +123,7 @@ public interface SpaceOperations<T> : Algebra<T> {
|
||||
* @receiver this value.
|
||||
* @return the additive inverse of this value.
|
||||
*/
|
||||
public operator fun T.unaryMinus(): T = multiply(this, -1.0)
|
||||
public operator fun T.unaryMinus(): T
|
||||
|
||||
/**
|
||||
* Returns this value.
|
||||
@ -159,34 +151,6 @@ public interface SpaceOperations<T> : Algebra<T> {
|
||||
*/
|
||||
public operator fun T.minus(b: T): T = add(this, -b)
|
||||
|
||||
/**
|
||||
* Multiplication of this element by a scalar.
|
||||
*
|
||||
* @receiver the multiplier.
|
||||
* @param k the multiplicand.
|
||||
* @return the product.
|
||||
*/
|
||||
public operator fun T.times(k: Number): T = multiply(this, k)
|
||||
|
||||
/**
|
||||
* Division of this element by scalar.
|
||||
*
|
||||
* @receiver the dividend.
|
||||
* @param k the divisor.
|
||||
* @return the quotient.
|
||||
*/
|
||||
@Deprecated("Dividing not allowed in a Ring")
|
||||
public operator fun T.div(k: Number): T = multiply(this, 1.0 / k.toDouble())
|
||||
|
||||
/**
|
||||
* Multiplication of this number by element.
|
||||
*
|
||||
* @receiver the multiplier.
|
||||
* @param b the multiplicand.
|
||||
* @return the product.
|
||||
*/
|
||||
public operator fun Number.times(b: T): T = b * this
|
||||
|
||||
public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) {
|
||||
PLUS_OPERATION -> { arg -> arg }
|
||||
MINUS_OPERATION -> { arg -> -arg }
|
||||
@ -318,13 +282,6 @@ public interface FieldOperations<T> : RingOperations<T> {
|
||||
*
|
||||
* @param T the type of element of this semifield.
|
||||
*/
|
||||
public interface Field<T> : Ring<T>, FieldOperations<T> {
|
||||
/**
|
||||
* Division of element by scalar.
|
||||
*
|
||||
* @receiver the dividend.
|
||||
* @param b the divisor.
|
||||
* @return the quotient.
|
||||
*/
|
||||
public operator fun Number.div(b: T): T = this * divide(one, b)
|
||||
public interface Field<T> : Ring<T>, FieldOperations<T>, ScaleOperations<T>, NumericAlgebra<T> {
|
||||
override fun number(value: Number): T = scale(one, value.toDouble())
|
||||
}
|
@ -14,24 +14,24 @@ public interface AlgebraElement<T, C : Algebra<T>> {
|
||||
*/
|
||||
public val context: C
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides this element by number.
|
||||
*
|
||||
* @param k the divisor.
|
||||
* @return the quotient.
|
||||
*/
|
||||
public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.div(k: Number): T =
|
||||
context.multiply(this, 1.0 / k.toDouble())
|
||||
|
||||
/**
|
||||
* Multiplies this element by number.
|
||||
*
|
||||
* @param k the multiplicand.
|
||||
* @return the product.
|
||||
*/
|
||||
public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.times(k: Number): T =
|
||||
context.multiply(this, k.toDouble())
|
||||
//
|
||||
///**
|
||||
// * Divides this element by number.
|
||||
// *
|
||||
// * @param k the divisor.
|
||||
// * @return the quotient.
|
||||
// */
|
||||
//public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.div(k: Number): T =
|
||||
// context.multiply(this, 1.0 / k.toDouble())
|
||||
//
|
||||
///**
|
||||
// * Multiplies this element by number.
|
||||
// *
|
||||
// * @param k the multiplicand.
|
||||
// * @return the product.
|
||||
// */
|
||||
//public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.times(k: Number): T =
|
||||
// context.multiply(this, k.toDouble())
|
||||
|
||||
/**
|
||||
* Subtracts element from this one.
|
||||
@ -39,8 +39,9 @@ public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.times(k: Number):
|
||||
* @param b the subtrahend.
|
||||
* @return the difference.
|
||||
*/
|
||||
public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.minus(b: T): T =
|
||||
context.add(this, context.multiply(b, -1.0))
|
||||
@UnstableKMathAPI
|
||||
public operator fun <T : AlgebraElement<T, S>, S : NumbersAddOperations<T>> T.minus(b: T): T =
|
||||
context.add(this, context.run { -b})
|
||||
|
||||
/**
|
||||
* Adds element to this one.
|
||||
@ -51,11 +52,11 @@ public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.minus(b: T): T =
|
||||
public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.plus(b: T): T =
|
||||
context.add(this, b)
|
||||
|
||||
/**
|
||||
* Number times element
|
||||
*/
|
||||
public operator fun <T : AlgebraElement<T, S>, S : Space<T>> Number.times(element: T): T =
|
||||
element.times(this)
|
||||
///**
|
||||
// * Number times element
|
||||
// */
|
||||
//public operator fun <T : AlgebraElement<T, S>, S : Space<T>> Number.times(element: T): T =
|
||||
// element.times(this)
|
||||
|
||||
|
||||
/**
|
||||
|
@ -21,29 +21,28 @@ public typealias TBase = ULong
|
||||
* @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai)
|
||||
*/
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
public object BigIntField : Field<BigInt>, RingWithNumbers<BigInt> {
|
||||
public object BigIntField : Field<BigInt>, NumbersAddOperations<BigInt>, ScaleOperations<BigInt> {
|
||||
override val zero: BigInt = BigInt.ZERO
|
||||
override val one: BigInt = BigInt.ONE
|
||||
|
||||
override fun add(a: BigInt, b: BigInt): BigInt = a.plus(b)
|
||||
override fun number(value: Number): BigInt = value.toLong().toBigInt()
|
||||
|
||||
override fun multiply(a: BigInt, k: Number): BigInt = a.times(number(k))
|
||||
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
||||
override fun BigInt.unaryMinus(): BigInt = -this
|
||||
override fun add(a: BigInt, b: BigInt): BigInt = a.plus(b)
|
||||
override fun scale(a: BigInt, value: Double): BigInt = a.times(number(value))
|
||||
override fun multiply(a: BigInt, b: BigInt): BigInt = a.times(b)
|
||||
override fun divide(a: BigInt, b: BigInt): BigInt = a.div(b)
|
||||
|
||||
public operator fun String.unaryPlus(): BigInt = this.parseBigInteger() ?: error("Can't parse $this as big integer")
|
||||
|
||||
public operator fun String.unaryMinus(): BigInt =
|
||||
-(this.parseBigInteger() ?: error("Can't parse $this as big integer"))
|
||||
|
||||
override fun divide(a: BigInt, b: BigInt): BigInt = a.div(b)
|
||||
}
|
||||
|
||||
public class BigInt internal constructor(
|
||||
private val sign: Byte,
|
||||
private val magnitude: Magnitude
|
||||
) : Comparable<BigInt> {
|
||||
private val magnitude: Magnitude,
|
||||
) : Comparable<BigInt> {
|
||||
public override fun compareTo(other: BigInt): Int = when {
|
||||
(sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0
|
||||
sign < other.sign -> -1
|
||||
|
@ -81,14 +81,53 @@ public interface NumericAlgebra<T> : Algebra<T> {
|
||||
rightSideNumberOperationFunction(operation)(left, right)
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by scalar operations
|
||||
*/
|
||||
public interface ScaleOperations<T> : Algebra<T> {
|
||||
/**
|
||||
* Scaling of element by scalar.
|
||||
*
|
||||
* @param a the multiplier.
|
||||
* @param value the multiplicand.
|
||||
* @return the produce.
|
||||
*/
|
||||
public fun scale(a: T, value: Double): T
|
||||
|
||||
/**
|
||||
* Multiplication of this element by a scalar.
|
||||
*
|
||||
* @receiver the multiplier.
|
||||
* @param k the multiplicand.
|
||||
* @return the product.
|
||||
*/
|
||||
public operator fun T.times(k: Number): T = scale(this, k.toDouble())
|
||||
|
||||
/**
|
||||
* Division of this element by scalar.
|
||||
*
|
||||
* @receiver the dividend.
|
||||
* @param k the divisor.
|
||||
* @return the quotient.
|
||||
*/
|
||||
public operator fun T.div(k: Number): T = scale(this, 1.0 / k.toDouble())
|
||||
|
||||
/**
|
||||
* Multiplication of this number by element.
|
||||
*
|
||||
* @receiver the multiplier.
|
||||
* @param b the multiplicand.
|
||||
* @return the product.
|
||||
*/
|
||||
public operator fun Number.times(b: T): T = b * this
|
||||
}
|
||||
|
||||
/**
|
||||
* A combination of [NumericAlgebra] and [Ring] that adds intrinsic simple operations on numbers like `T+1`
|
||||
* TODO to be removed and replaced by extensions after multiple receivers are there
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public interface RingWithNumbers<T>: Ring<T>, NumericAlgebra<T>{
|
||||
public override fun number(value: Number): T = one * value
|
||||
|
||||
public interface NumbersAddOperations<T> : Space<T>, NumericAlgebra<T> {
|
||||
/**
|
||||
* Addition of element and scalar.
|
||||
*
|
||||
|
@ -107,111 +107,6 @@ public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> acos(arg: T):
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> atan(arg: T): T = arg.context.atan(arg)
|
||||
|
||||
/**
|
||||
* A container for hyperbolic trigonometric operations for specific type.
|
||||
*
|
||||
* @param T the type of element of this structure.
|
||||
*/
|
||||
public interface HyperbolicOperations<T> : Algebra<T> {
|
||||
/**
|
||||
* Computes the hyperbolic sine of [arg].
|
||||
*/
|
||||
public fun sinh(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic cosine of [arg].
|
||||
*/
|
||||
public fun cosh(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic tangent of [arg].
|
||||
*/
|
||||
public fun tanh(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic sine of [arg].
|
||||
*/
|
||||
public fun asinh(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic cosine of [arg].
|
||||
*/
|
||||
public fun acosh(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic tangent of [arg].
|
||||
*/
|
||||
public fun atanh(arg: T): T
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The identifier of hyperbolic sine.
|
||||
*/
|
||||
public const val SINH_OPERATION: String = "sinh"
|
||||
|
||||
/**
|
||||
* The identifier of hyperbolic cosine.
|
||||
*/
|
||||
public const val COSH_OPERATION: String = "cosh"
|
||||
|
||||
/**
|
||||
* The identifier of hyperbolic tangent.
|
||||
*/
|
||||
public const val TANH_OPERATION: String = "tanh"
|
||||
|
||||
/**
|
||||
* The identifier of inverse hyperbolic sine.
|
||||
*/
|
||||
public const val ASINH_OPERATION: String = "asinh"
|
||||
|
||||
/**
|
||||
* The identifier of inverse hyperbolic cosine.
|
||||
*/
|
||||
public const val ACOSH_OPERATION: String = "acosh"
|
||||
|
||||
/**
|
||||
* The identifier of inverse hyperbolic tangent.
|
||||
*/
|
||||
public const val ATANH_OPERATION: String = "atanh"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic sine of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> sinh(arg: T): T = arg.context.sinh(arg)
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic cosine of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> cosh(arg: T): T = arg.context.cosh(arg)
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic tangent of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> tanh(arg: T): T = arg.context.tanh(arg)
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic sine of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> asinh(arg: T): T = arg.context.asinh(arg)
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic cosine of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> acosh(arg: T): T = arg.context.acosh(arg)
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic tangent of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out HyperbolicOperations<T>>> atanh(arg: T): T = arg.context.atanh(arg)
|
||||
|
||||
/**
|
||||
* A context extension to include power operations based on exponentiation.
|
||||
*
|
||||
@ -284,6 +179,36 @@ public interface ExponentialOperations<T> : Algebra<T> {
|
||||
*/
|
||||
public fun ln(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic sine of [arg].
|
||||
*/
|
||||
public fun sinh(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic cosine of [arg].
|
||||
*/
|
||||
public fun cosh(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic tangent of [arg].
|
||||
*/
|
||||
public fun tanh(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic sine of [arg].
|
||||
*/
|
||||
public fun asinh(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic cosine of [arg].
|
||||
*/
|
||||
public fun acosh(arg: T): T
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic tangent of [arg].
|
||||
*/
|
||||
public fun atanh(arg: T): T
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* The identifier of exponential function.
|
||||
@ -294,6 +219,36 @@ public interface ExponentialOperations<T> : Algebra<T> {
|
||||
* The identifier of natural logarithm.
|
||||
*/
|
||||
public const val LN_OPERATION: String = "ln"
|
||||
|
||||
/**
|
||||
* The identifier of hyperbolic sine.
|
||||
*/
|
||||
public const val SINH_OPERATION: String = "sinh"
|
||||
|
||||
/**
|
||||
* The identifier of hyperbolic cosine.
|
||||
*/
|
||||
public const val COSH_OPERATION: String = "cosh"
|
||||
|
||||
/**
|
||||
* The identifier of hyperbolic tangent.
|
||||
*/
|
||||
public const val TANH_OPERATION: String = "tanh"
|
||||
|
||||
/**
|
||||
* The identifier of inverse hyperbolic sine.
|
||||
*/
|
||||
public const val ASINH_OPERATION: String = "asinh"
|
||||
|
||||
/**
|
||||
* The identifier of inverse hyperbolic cosine.
|
||||
*/
|
||||
public const val ACOSH_OPERATION: String = "acosh"
|
||||
|
||||
/**
|
||||
* The identifier of inverse hyperbolic tangent.
|
||||
*/
|
||||
public const val ATANH_OPERATION: String = "atanh"
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,6 +264,43 @@ public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> exp(arg: T): T
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> ln(arg: T): T = arg.context.ln(arg)
|
||||
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic sine of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> sinh(arg: T): T = arg.context.sinh(arg)
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic cosine of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> cosh(arg: T): T = arg.context.cosh(arg)
|
||||
|
||||
/**
|
||||
* Computes the hyperbolic tangent of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> tanh(arg: T): T = arg.context.tanh(arg)
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic sine of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> asinh(arg: T): T = arg.context.asinh(arg)
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic cosine of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> acosh(arg: T): T = arg.context.acosh(arg)
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic tangent of [arg].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> atanh(arg: T): T = arg.context.atanh(arg)
|
||||
|
||||
/**
|
||||
* A container for norm functional on element.
|
||||
*
|
||||
|
@ -26,7 +26,8 @@ public fun <T> Space<T>.sum(data: Sequence<T>): T = data.fold(zero) { left, righ
|
||||
* @return the average value.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
|
||||
public fun <T, S> S.average(data: Iterable<T>): T where S : Space<T>, S : ScaleOperations<T> =
|
||||
sum(data) / data.count()
|
||||
|
||||
/**
|
||||
* Returns an average value of elements in the sequence in this [Space].
|
||||
@ -36,7 +37,8 @@ public fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
|
||||
* @return the average value.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun <T> Space<T>.average(data: Sequence<T>): T = sum(data) / data.count()
|
||||
public fun <T, S> S.average(data: Sequence<T>): T where S : Space<T>, S : ScaleOperations<T> =
|
||||
sum(data) / data.count()
|
||||
|
||||
/**
|
||||
* Absolute of the comparable [value]
|
||||
@ -69,7 +71,8 @@ public fun <T> Sequence<T>.sumWith(space: Space<T>): T = space.sum(this)
|
||||
* @return the average value.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
|
||||
public fun <T, S> Iterable<T>.averageWith(space: S): T where S : Space<T>, S : ScaleOperations<T> =
|
||||
space.average(this)
|
||||
|
||||
/**
|
||||
* Returns an average value of elements in the sequence in this [Space].
|
||||
@ -79,7 +82,8 @@ public fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
|
||||
* @return the average value.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public fun <T> Sequence<T>.averageWith(space: Space<T>): T = space.average(this)
|
||||
public fun <T, S> Sequence<T>.averageWith(space: S): T where S : Space<T>, S : ScaleOperations<T> =
|
||||
space.average(this)
|
||||
|
||||
//TODO optimized power operation
|
||||
|
||||
|
@ -8,7 +8,6 @@ import kotlin.math.pow as kpow
|
||||
public interface ExtendedFieldOperations<T> :
|
||||
FieldOperations<T>,
|
||||
TrigonometricOperations<T>,
|
||||
HyperbolicOperations<T>,
|
||||
PowerOperations<T>,
|
||||
ExponentialOperations<T> {
|
||||
public override fun tan(arg: T): T = sin(arg) / cos(arg)
|
||||
@ -21,15 +20,15 @@ public interface ExtendedFieldOperations<T> :
|
||||
TrigonometricOperations.ACOS_OPERATION -> ::acos
|
||||
TrigonometricOperations.ASIN_OPERATION -> ::asin
|
||||
TrigonometricOperations.ATAN_OPERATION -> ::atan
|
||||
HyperbolicOperations.COSH_OPERATION -> ::cosh
|
||||
HyperbolicOperations.SINH_OPERATION -> ::sinh
|
||||
HyperbolicOperations.TANH_OPERATION -> ::tanh
|
||||
HyperbolicOperations.ACOSH_OPERATION -> ::acosh
|
||||
HyperbolicOperations.ASINH_OPERATION -> ::asinh
|
||||
HyperbolicOperations.ATANH_OPERATION -> ::atanh
|
||||
PowerOperations.SQRT_OPERATION -> ::sqrt
|
||||
ExponentialOperations.EXP_OPERATION -> ::exp
|
||||
ExponentialOperations.LN_OPERATION -> ::ln
|
||||
ExponentialOperations.COSH_OPERATION -> ::cosh
|
||||
ExponentialOperations.SINH_OPERATION -> ::sinh
|
||||
ExponentialOperations.TANH_OPERATION -> ::tanh
|
||||
ExponentialOperations.ACOSH_OPERATION -> ::acosh
|
||||
ExponentialOperations.ASINH_OPERATION -> ::asinh
|
||||
ExponentialOperations.ATANH_OPERATION -> ::atanh
|
||||
else -> super<FieldOperations>.unaryOperationFunction(operation)
|
||||
}
|
||||
}
|
||||
@ -37,18 +36,18 @@ public interface ExtendedFieldOperations<T> :
|
||||
/**
|
||||
* Advanced Number-like field that implements basic operations.
|
||||
*/
|
||||
public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T>, NumericAlgebra<T> {
|
||||
public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2
|
||||
public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2
|
||||
public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T>, NumericAlgebra<T>, ScaleOperations<T> {
|
||||
public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2.0
|
||||
public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2.0
|
||||
public override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
|
||||
public override fun asinh(arg: T): T = ln(sqrt(arg * arg + one) + arg)
|
||||
public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one)))
|
||||
public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2
|
||||
public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2.0
|
||||
|
||||
public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T =
|
||||
when (operation) {
|
||||
PowerOperations.POW_OPERATION -> ::power
|
||||
else -> super.rightSideNumberOperationFunction(operation)
|
||||
else -> super<Field>.rightSideNumberOperationFunction(operation)
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,28 +55,27 @@ public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T>, Numeri
|
||||
* A field for [Double] without boxing. Does not produce appropriate field element.
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||
public object RealField : ExtendedField<Double>, Norm<Double, Double> {
|
||||
public override val zero: Double
|
||||
get() = 0.0
|
||||
|
||||
public override val one: Double
|
||||
get() = 1.0
|
||||
public object RealField : ExtendedField<Double>, Norm<Double, Double>, ScaleOperations<Double> {
|
||||
public override val zero: Double = 0.0
|
||||
public override val one: Double = 1.0
|
||||
|
||||
override fun number(value: Number): Double = value.toDouble()
|
||||
|
||||
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
|
||||
when (operation) {
|
||||
PowerOperations.POW_OPERATION -> ::power
|
||||
else -> super.binaryOperationFunction(operation)
|
||||
else -> super<ExtendedField>.binaryOperationFunction(operation)
|
||||
}
|
||||
|
||||
public override inline fun add(a: Double, b: Double): Double = a + b
|
||||
public override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble()
|
||||
// public override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble()
|
||||
// override fun divide(a: Double, k: Number): Double = a / k.toDouble()
|
||||
|
||||
public override inline fun multiply(a: Double, b: Double): Double = a * b
|
||||
|
||||
public override inline fun divide(a: Double, b: Double): Double = a / b
|
||||
|
||||
override fun scale(a: Double, value: Double): Double = a * value
|
||||
|
||||
public override inline fun sin(arg: Double): Double = kotlin.math.sin(arg)
|
||||
public override inline fun cos(arg: Double): Double = kotlin.math.cos(arg)
|
||||
public override inline fun tan(arg: Double): Double = kotlin.math.tan(arg)
|
||||
@ -110,11 +108,8 @@ public object RealField : ExtendedField<Double>, Norm<Double, Double> {
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||
public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
|
||||
public override val zero: Float
|
||||
get() = 0.0f
|
||||
|
||||
public override val one: Float
|
||||
get() = 1.0f
|
||||
public override val zero: Float = 0.0f
|
||||
public override val one: Float = 1.0f
|
||||
|
||||
override fun number(value: Number): Float = value.toFloat()
|
||||
|
||||
@ -125,7 +120,7 @@ public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
|
||||
}
|
||||
|
||||
public override inline fun add(a: Float, b: Float): Float = a + b
|
||||
public override inline fun multiply(a: Float, k: Number): Float = a * k.toFloat()
|
||||
override fun scale(a: Float, value: Double): Float = a * value.toFloat()
|
||||
|
||||
public override inline fun multiply(a: Float, b: Float): Float = a * b
|
||||
|
||||
@ -170,12 +165,8 @@ public object IntRing : Ring<Int>, Norm<Int, Int>, NumericAlgebra<Int> {
|
||||
get() = 1
|
||||
|
||||
override fun number(value: Number): Int = value.toInt()
|
||||
|
||||
public override inline fun add(a: Int, b: Int): Int = a + b
|
||||
public override inline fun multiply(a: Int, k: Number): Int = k.toInt() * a
|
||||
|
||||
public override inline fun multiply(a: Int, b: Int): Int = a * b
|
||||
|
||||
public override inline fun norm(arg: Int): Int = abs(arg)
|
||||
|
||||
public override inline fun Int.unaryMinus(): Int = -this
|
||||
@ -196,12 +187,8 @@ public object ShortRing : Ring<Short>, Norm<Short, Short>, NumericAlgebra<Short>
|
||||
get() = 1
|
||||
|
||||
override fun number(value: Number): Short = value.toShort()
|
||||
|
||||
public override inline fun add(a: Short, b: Short): Short = (a + b).toShort()
|
||||
public override inline fun multiply(a: Short, k: Number): Short = (a * k.toShort()).toShort()
|
||||
|
||||
public override inline fun multiply(a: Short, b: Short): Short = (a * b).toShort()
|
||||
|
||||
public override fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort()
|
||||
|
||||
public override inline fun Short.unaryMinus(): Short = (-this).toShort()
|
||||
@ -222,12 +209,8 @@ public object ByteRing : Ring<Byte>, Norm<Byte, Byte>, NumericAlgebra<Byte> {
|
||||
get() = 1
|
||||
|
||||
override fun number(value: Number): Byte = value.toByte()
|
||||
|
||||
public override inline fun add(a: Byte, b: Byte): Byte = (a + b).toByte()
|
||||
public override inline fun multiply(a: Byte, k: Number): Byte = (a * k.toByte()).toByte()
|
||||
|
||||
public override inline fun multiply(a: Byte, b: Byte): Byte = (a * b).toByte()
|
||||
|
||||
public override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte()
|
||||
|
||||
public override inline fun Byte.unaryMinus(): Byte = (-this).toByte()
|
||||
@ -248,12 +231,8 @@ public object LongRing : Ring<Long>, Norm<Long, Long>, NumericAlgebra<Long> {
|
||||
get() = 1L
|
||||
|
||||
override fun number(value: Number): Long = value.toLong()
|
||||
|
||||
public override inline fun add(a: Long, b: Long): Long = a + b
|
||||
public override inline fun multiply(a: Long, k: Number): Long = a * k.toLong()
|
||||
|
||||
public override inline fun multiply(a: Long, b: Long): Long = a * b
|
||||
|
||||
public override fun norm(arg: Long): Long = abs(arg)
|
||||
|
||||
public override inline fun Long.unaryMinus(): Long = (-this)
|
||||
|
@ -8,6 +8,12 @@ import kotlin.math.*
|
||||
* [ExtendedFieldOperations] over [RealBuffer].
|
||||
*/
|
||||
public object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
|
||||
override fun Buffer<Double>.unaryMinus(): RealBuffer = if (this is RealBuffer) {
|
||||
RealBuffer(size) { -array[it] }
|
||||
} else {
|
||||
RealBuffer(size) { -get(it) }
|
||||
}
|
||||
|
||||
public override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
require(b.size == a.size) {
|
||||
"The size of the first buffer ${a.size} should be the same as for second one: ${b.size} "
|
||||
@ -19,15 +25,24 @@ public object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>
|
||||
RealBuffer(DoubleArray(a.size) { aArray[it] + bArray[it] })
|
||||
} else RealBuffer(DoubleArray(a.size) { a[it] + b[it] })
|
||||
}
|
||||
|
||||
public override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
|
||||
val kValue = k.toDouble()
|
||||
|
||||
return if (a is RealBuffer) {
|
||||
val aArray = a.array
|
||||
RealBuffer(DoubleArray(a.size) { aArray[it] * kValue })
|
||||
} else RealBuffer(DoubleArray(a.size) { a[it] * kValue })
|
||||
}
|
||||
//
|
||||
// public override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
|
||||
// val kValue = k.toDouble()
|
||||
//
|
||||
// return if (a is RealBuffer) {
|
||||
// val aArray = a.array
|
||||
// RealBuffer(DoubleArray(a.size) { aArray[it] * kValue })
|
||||
// } else RealBuffer(DoubleArray(a.size) { a[it] * kValue })
|
||||
// }
|
||||
//
|
||||
// public override fun divide(a: Buffer<Double>, k: Number): RealBuffer {
|
||||
// val kValue = k.toDouble()
|
||||
//
|
||||
// return if (a is RealBuffer) {
|
||||
// val aArray = a.array
|
||||
// RealBuffer(DoubleArray(a.size) { aArray[it] / kValue })
|
||||
// } else RealBuffer(DoubleArray(a.size) { a[it] / kValue })
|
||||
// }
|
||||
|
||||
public override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
require(b.size == a.size) {
|
||||
@ -152,14 +167,22 @@ public class RealBufferField(public val size: Int) : ExtendedField<Buffer<Double
|
||||
|
||||
override fun number(value: Number): Buffer<Double> = RealBuffer(size) { value.toDouble() }
|
||||
|
||||
override fun Buffer<Double>.unaryMinus(): Buffer<Double> = RealBufferFieldOperations.run {
|
||||
-this@unaryMinus
|
||||
}
|
||||
|
||||
public override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.add(a, b)
|
||||
}
|
||||
|
||||
public override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
|
||||
public override fun scale(a: Buffer<Double>, value: Double): RealBuffer {
|
||||
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.multiply(a, k)
|
||||
|
||||
return if (a is RealBuffer) {
|
||||
val aArray = a.array
|
||||
RealBuffer(DoubleArray(a.size) { aArray[it] * value })
|
||||
} else RealBuffer(DoubleArray(a.size) { a[it] * value })
|
||||
}
|
||||
|
||||
public override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
|
@ -11,9 +11,7 @@ class ExpressionFieldTest {
|
||||
|
||||
@Test
|
||||
fun testExpression() {
|
||||
val context = FunctionalExpressionField(RealField)
|
||||
|
||||
val expression = context {
|
||||
val expression = FunctionalExpressionField(RealField).invoke {
|
||||
val x by binding()
|
||||
x * x + 2 * x + one
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotEquals
|
||||
|
||||
internal class FieldVerifier<T>(override val algebra: Field<T>, a: T, b: T, c: T, x: Number) :
|
||||
RingVerifier<T>(algebra, a, b, c, x) {
|
||||
internal class FieldVerifier<T, A : Field<T>>(
|
||||
algebra: A, a: T, b: T, c: T, x: Number,
|
||||
) : RingVerifier<T, A>(algebra, a, b, c, x) {
|
||||
|
||||
override fun verify() {
|
||||
super.verify()
|
||||
|
@ -1,11 +1,13 @@
|
||||
package space.kscience.kmath.testutils
|
||||
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal open class RingVerifier<T>(override val algebra: Ring<T>, a: T, b: T, c: T, x: Number) :
|
||||
SpaceVerifier<T>(algebra, a, b, c, x) {
|
||||
internal open class RingVerifier<T, A>(algebra: A, a: T, b: T, c: T, x: Number) :
|
||||
SpaceVerifier<T, A>(algebra, a, b, c, x) where A : Ring<T>, A : ScaleOperations<T> {
|
||||
|
||||
override fun verify() {
|
||||
super.verify()
|
||||
|
||||
|
@ -1,18 +1,18 @@
|
||||
package space.kscience.kmath.testutils
|
||||
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.operations.Space
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotEquals
|
||||
|
||||
internal open class SpaceVerifier<T>(
|
||||
override val algebra: Space<T>,
|
||||
internal open class SpaceVerifier<T, out S>(
|
||||
override val algebra: S,
|
||||
val a: T,
|
||||
val b: T,
|
||||
val c: T,
|
||||
val x: Number
|
||||
) :
|
||||
AlgebraicVerifier<T, Space<T>> {
|
||||
val x: Number,
|
||||
) : AlgebraicVerifier<T, Space<T>> where S : Space<T>, S : ScaleOperations<T> {
|
||||
override fun verify() {
|
||||
algebra {
|
||||
assertEquals(a + b + c, a + (b + c), "Addition in $algebra is not associative.")
|
||||
|
@ -7,19 +7,16 @@ import java.math.MathContext
|
||||
/**
|
||||
* A field over [BigInteger].
|
||||
*/
|
||||
public object JBigIntegerField : Field<BigInteger>, NumericAlgebra<BigInteger> {
|
||||
public override val zero: BigInteger
|
||||
get() = BigInteger.ZERO
|
||||
public object JBigIntegerField : Ring<BigInteger>, NumericAlgebra<BigInteger> {
|
||||
public override val zero: BigInteger get() = BigInteger.ZERO
|
||||
|
||||
public override val one: BigInteger
|
||||
get() = BigInteger.ONE
|
||||
public override val one: BigInteger get() = BigInteger.ONE
|
||||
|
||||
public override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong())
|
||||
public override fun divide(a: BigInteger, b: BigInteger): BigInteger = a.div(b)
|
||||
public override fun add(a: BigInteger, b: BigInteger): BigInteger = a.add(b)
|
||||
public override operator fun BigInteger.minus(b: BigInteger): BigInteger = subtract(b)
|
||||
public override fun multiply(a: BigInteger, k: Number): BigInteger = a.multiply(k.toInt().toBigInteger())
|
||||
public override fun multiply(a: BigInteger, b: BigInteger): BigInteger = a.multiply(b)
|
||||
|
||||
public override operator fun BigInteger.unaryMinus(): BigInteger = negate()
|
||||
}
|
||||
|
||||
@ -30,7 +27,7 @@ public object JBigIntegerField : Field<BigInteger>, NumericAlgebra<BigInteger> {
|
||||
*/
|
||||
public abstract class JBigDecimalFieldBase internal constructor(
|
||||
private val mathContext: MathContext = MathContext.DECIMAL64,
|
||||
) : Field<BigDecimal>, PowerOperations<BigDecimal>, NumericAlgebra<BigDecimal> {
|
||||
) : Field<BigDecimal>, PowerOperations<BigDecimal>, NumericAlgebra<BigDecimal>, ScaleOperations<BigDecimal> {
|
||||
public override val zero: BigDecimal
|
||||
get() = BigDecimal.ZERO
|
||||
|
||||
@ -41,8 +38,8 @@ public abstract class JBigDecimalFieldBase internal constructor(
|
||||
public override operator fun BigDecimal.minus(b: BigDecimal): BigDecimal = subtract(b)
|
||||
public override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble())
|
||||
|
||||
public override fun multiply(a: BigDecimal, k: Number): BigDecimal =
|
||||
a.multiply(k.toDouble().toBigDecimal(mathContext), mathContext)
|
||||
public override fun scale(a: BigDecimal, value: Double): BigDecimal =
|
||||
a.multiply(value.toBigDecimal(mathContext), mathContext)
|
||||
|
||||
public override fun multiply(a: BigDecimal, b: BigDecimal): BigDecimal = a.multiply(b, mathContext)
|
||||
public override fun divide(a: BigDecimal, b: BigDecimal): BigDecimal = a.divide(b, mathContext)
|
||||
|
@ -5,16 +5,16 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.runningReduce
|
||||
import kotlinx.coroutines.flow.scan
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.operations.Space
|
||||
import space.kscience.kmath.operations.SpaceOperations
|
||||
import space.kscience.kmath.operations.invoke
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
public fun <T> Flow<T>.cumulativeSum(space: SpaceOperations<T>): Flow<T> =
|
||||
space { runningReduce { sum, element -> sum + element } }
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
public fun <T> Flow<T>.mean(space: Space<T>): Flow<T> = space {
|
||||
public fun <T, S> Flow<T>.mean(algebra: S): Flow<T> where S : Space<T>, S : ScaleOperations<T> = algebra {
|
||||
data class Accumulator(var sum: T, var num: Int)
|
||||
|
||||
scan(Accumulator(zero, 0)) { sum, element ->
|
||||
|
@ -4,13 +4,14 @@ import org.ejml.simple.SimpleMatrix
|
||||
import space.kscience.kmath.linear.*
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.getFeature
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
|
||||
/**
|
||||
* Represents context of basic operations operating with [EjmlMatrix].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
public object EjmlMatrixContext : MatrixContext<Double, EjmlMatrix> {
|
||||
public object EjmlMatrixContext : MatrixContext<Double, EjmlMatrix>, ScaleOperations<Matrix<Double>> {
|
||||
|
||||
/**
|
||||
* Converts this matrix to EJML one.
|
||||
@ -41,6 +42,9 @@ public object EjmlMatrixContext : MatrixContext<Double, EjmlMatrix> {
|
||||
(0 until it.numRows()).forEach { row -> it[row, 0] = initializer(row) }
|
||||
})
|
||||
|
||||
|
||||
override fun Matrix<Double>.unaryMinus(): Matrix<Double> = this*(-1)
|
||||
|
||||
public override fun Matrix<Double>.dot(other: Matrix<Double>): EjmlMatrix =
|
||||
EjmlMatrix(toEjml().origin.mult(other.toEjml().origin))
|
||||
|
||||
@ -53,8 +57,8 @@ public object EjmlMatrixContext : MatrixContext<Double, EjmlMatrix> {
|
||||
public override operator fun Matrix<Double>.minus(b: Matrix<Double>): EjmlMatrix =
|
||||
EjmlMatrix(toEjml().origin - b.toEjml().origin)
|
||||
|
||||
public override fun multiply(a: Matrix<Double>, k: Number): EjmlMatrix =
|
||||
produce(a.rowNum, a.colNum) { i, j -> a[i, j] * k.toDouble() }
|
||||
public override fun scale(a: Matrix<Double>, value: Double): EjmlMatrix =
|
||||
produce(a.rowNum, a.colNum) { i, j -> a[i, j] * value }
|
||||
|
||||
public override operator fun Matrix<Double>.times(value: Double): EjmlMatrix =
|
||||
EjmlMatrix(toEjml().origin.scale(value))
|
||||
|
@ -1,6 +1,7 @@
|
||||
package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.operations.Space
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.contracts.InvocationKind
|
||||
@ -41,9 +42,15 @@ public fun <T : Any, C : Ring<T>> Polynomial<T>.asFunction(ring: C): (T) -> T =
|
||||
/**
|
||||
* An algebra for polynomials
|
||||
*/
|
||||
public class PolynomialSpace<T : Any, C : Ring<T>>(private val ring: C) : Space<Polynomial<T>> {
|
||||
public class PolynomialSpace<T : Any, C >(
|
||||
private val ring: C,
|
||||
) : Space<Polynomial<T>>, ScaleOperations<Polynomial<T>> where C: Ring<T>, C: ScaleOperations<T>{
|
||||
public override val zero: Polynomial<T> = Polynomial(emptyList())
|
||||
|
||||
override fun Polynomial<T>.unaryMinus(): Polynomial<T> = with(ring) {
|
||||
Polynomial(coefficients.map { -it })
|
||||
}
|
||||
|
||||
public override fun add(a: Polynomial<T>, b: Polynomial<T>): Polynomial<T> {
|
||||
val dim = max(a.coefficients.size, b.coefficients.size)
|
||||
|
||||
@ -54,13 +61,13 @@ public class PolynomialSpace<T : Any, C : Ring<T>>(private val ring: C) : Space<
|
||||
}
|
||||
}
|
||||
|
||||
public override fun multiply(a: Polynomial<T>, k: Number): Polynomial<T> =
|
||||
ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * k }) }
|
||||
public override fun scale(a: Polynomial<T>, value: Double): Polynomial<T> =
|
||||
ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) }
|
||||
|
||||
public operator fun Polynomial<T>.invoke(arg: T): T = value(ring, arg)
|
||||
}
|
||||
|
||||
public inline fun <T : Any, C : Ring<T>, R> C.polynomial(block: PolynomialSpace<T, C>.() -> R): R {
|
||||
public inline fun <T : Any, C, R> C.polynomial(block: PolynomialSpace<T, C>.() -> R): R where C: Ring<T>, C: ScaleOperations<T>{
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return PolynomialSpace(this).block()
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import space.kscience.kmath.structures.MutableBufferFactory
|
||||
* Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type specific ones.
|
||||
* Based on https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java
|
||||
*/
|
||||
public class SplineInterpolator<T : Comparable<T>>(
|
||||
public override val algebra: Field<T>,
|
||||
public val bufferFactory: MutableBufferFactory<T>
|
||||
public class SplineInterpolator<T : Comparable<T>, F : Field<T>>(
|
||||
public override val algebra: F,
|
||||
public val bufferFactory: MutableBufferFactory<T>,
|
||||
) : PolynomialInterpolator<T> {
|
||||
//TODO possibly optimize zeroed buffers
|
||||
|
||||
|
@ -2,6 +2,7 @@ package space.kscience.kmath.geometry
|
||||
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.operations.SpaceElement
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.math.sqrt
|
||||
@ -30,18 +31,20 @@ public fun Vector2D(x: Double, y: Double): Vector2D = Vector2DImpl(x, y)
|
||||
|
||||
private data class Vector2DImpl(
|
||||
override val x: Double,
|
||||
override val y: Double
|
||||
override val y: Double,
|
||||
) : Vector2D
|
||||
|
||||
/**
|
||||
* 2D Euclidean space
|
||||
*/
|
||||
public object Euclidean2DSpace : GeometrySpace<Vector2D> {
|
||||
public object Euclidean2DSpace : GeometrySpace<Vector2D>, ScaleOperations<Vector2D> {
|
||||
public override val zero: Vector2D by lazy { Vector2D(0.0, 0.0) }
|
||||
|
||||
public fun Vector2D.norm(): Double = sqrt(x * x + y * y)
|
||||
override fun Vector2D.unaryMinus(): Vector2D = Vector2D(-x, -y)
|
||||
|
||||
public override fun Vector2D.distanceTo(other: Vector2D): Double = (this - other).norm()
|
||||
public override fun add(a: Vector2D, b: Vector2D): Vector2D = Vector2D(a.x + b.x, a.y + b.y)
|
||||
public override fun multiply(a: Vector2D, k: Number): Vector2D = Vector2D(a.x * k.toDouble(), a.y * k.toDouble())
|
||||
public override fun scale(a: Vector2D, value: Double): Vector2D = Vector2D(a.x * value, a.y * value)
|
||||
public override fun Vector2D.dot(other: Vector2D): Double = x * other.x + y * other.y
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package space.kscience.kmath.geometry
|
||||
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.operations.SpaceElement
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.math.sqrt
|
||||
@ -32,21 +33,22 @@ public val Vector3D.r: Double get() = Euclidean3DSpace { sqrt(norm()) }
|
||||
private data class Vector3DImpl(
|
||||
override val x: Double,
|
||||
override val y: Double,
|
||||
override val z: Double
|
||||
override val z: Double,
|
||||
) : Vector3D
|
||||
|
||||
public object Euclidean3DSpace : GeometrySpace<Vector3D> {
|
||||
public object Euclidean3DSpace : GeometrySpace<Vector3D>, ScaleOperations<Vector3D> {
|
||||
public override val zero: Vector3D by lazy { Vector3D(0.0, 0.0, 0.0) }
|
||||
|
||||
public fun Vector3D.norm(): Double = sqrt(x * x + y * y + z * z)
|
||||
override fun Vector3D.unaryMinus(): Vector3D = Vector3D(-x, -y, -z)
|
||||
|
||||
public override fun Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm()
|
||||
|
||||
public override fun add(a: Vector3D, b: Vector3D): Vector3D =
|
||||
Vector3D(a.x + b.x, a.y + b.y, a.z + b.z)
|
||||
|
||||
public override fun multiply(a: Vector3D, k: Number): Vector3D =
|
||||
Vector3D(a.x * k.toDouble(), a.y * k.toDouble(), a.z * k.toDouble())
|
||||
public override fun scale(a: Vector3D, value: Double): Vector3D =
|
||||
Vector3D(a.x * value, a.y * value, a.z * value)
|
||||
|
||||
public override fun Vector3D.dot(other: Vector3D): Double =
|
||||
x * other.x + y * other.y + z * other.z
|
||||
|
@ -3,9 +3,10 @@ package space.kscience.kmath.histogram
|
||||
import space.kscience.kmath.domains.Domain
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.NDSpace
|
||||
import space.kscience.kmath.nd.NDField
|
||||
import space.kscience.kmath.nd.NDStructure
|
||||
import space.kscience.kmath.nd.Strides
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.operations.Space
|
||||
import space.kscience.kmath.operations.SpaceElement
|
||||
import space.kscience.kmath.operations.invoke
|
||||
@ -41,10 +42,11 @@ public class IndexedHistogram<T : Comparable<T>, V : Any>(
|
||||
/**
|
||||
* A space for producing histograms with values in a NDStructure
|
||||
*/
|
||||
public interface IndexedHistogramSpace<T : Comparable<T>, V : Any> : Space<IndexedHistogram<T, V>> {
|
||||
public interface IndexedHistogramSpace<T : Comparable<T>, V : Any>
|
||||
: Space<IndexedHistogram<T, V>>, ScaleOperations<IndexedHistogram<T, V>> {
|
||||
//public val valueSpace: Space<V>
|
||||
public val strides: Strides
|
||||
public val histogramValueSpace: NDSpace<V, *> //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape),
|
||||
public val histogramValueSpace: NDField<V, *> //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape),
|
||||
|
||||
/**
|
||||
* Resolve index of the bin including given [point]
|
||||
@ -63,12 +65,12 @@ public interface IndexedHistogramSpace<T : Comparable<T>, V : Any> : Space<Index
|
||||
override fun add(a: IndexedHistogram<T, V>, b: IndexedHistogram<T, V>): IndexedHistogram<T, V> {
|
||||
require(a.context == this) { "Can't operate on a histogram produced by external space" }
|
||||
require(b.context == this) { "Can't operate on a histogram produced by external space" }
|
||||
return IndexedHistogram(this, histogramValueSpace.invoke { a.values + b.values })
|
||||
return IndexedHistogram(this, histogramValueSpace { a.values + b.values })
|
||||
}
|
||||
|
||||
override fun multiply(a: IndexedHistogram<T, V>, k: Number): IndexedHistogram<T, V> {
|
||||
override fun scale(a: IndexedHistogram<T, V>, value: Double): IndexedHistogram<T, V> {
|
||||
require(a.context == this) { "Can't operate on a histogram produced by external space" }
|
||||
return IndexedHistogram(this, histogramValueSpace.invoke { a.values * k })
|
||||
return IndexedHistogram(this, histogramValueSpace { a.values * value })
|
||||
}
|
||||
|
||||
override val zero: IndexedHistogram<T, V> get() = produce { }
|
||||
|
@ -2,6 +2,7 @@ package space.kscience.kmath.histogram
|
||||
|
||||
import space.kscience.kmath.domains.Domain
|
||||
import space.kscience.kmath.domains.HyperSquareDomain
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.structures.*
|
||||
import kotlin.math.floor
|
||||
@ -40,6 +41,7 @@ public class RealHistogramSpace(
|
||||
getIndex(it, point[it])
|
||||
}
|
||||
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
override fun getDomain(index: IntArray): Domain<Double> {
|
||||
val lowerBoundary = index.mapIndexed { axis, i ->
|
||||
when (i) {
|
||||
@ -77,6 +79,8 @@ public class RealHistogramSpace(
|
||||
return IndexedHistogram(this, values)
|
||||
}
|
||||
|
||||
override fun IndexedHistogram<Double, Double>.unaryMinus(): IndexedHistogram<Double, Double> = this * (-1)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* Use it like
|
||||
|
@ -2,6 +2,7 @@ package space.kscience.kmath.histogram
|
||||
|
||||
import space.kscience.kmath.domains.UnivariateDomain
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.operations.Space
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import java.util.*
|
||||
@ -36,7 +37,7 @@ public class TreeHistogram(
|
||||
@UnstableKMathAPI
|
||||
public class TreeHistogramSpace(
|
||||
public val binFactory: (Double) -> UnivariateDomain,
|
||||
) : Space<UnivariateHistogram> {
|
||||
) : Space<UnivariateHistogram>, ScaleOperations<UnivariateHistogram> {
|
||||
|
||||
private class BinCounter(val domain: UnivariateDomain, val counter: Counter<Double> = Counter.real()) :
|
||||
ClosedFloatingPointRange<Double> by domain.range
|
||||
@ -97,14 +98,14 @@ public class TreeHistogramSpace(
|
||||
return TreeHistogram(this, bins)
|
||||
}
|
||||
|
||||
override fun multiply(a: UnivariateHistogram, k: Number): UnivariateHistogram {
|
||||
override fun scale(a: UnivariateHistogram, value: Double): UnivariateHistogram {
|
||||
val bins = TreeMap<Double, UnivariateBin>().apply {
|
||||
a.bins.forEach { bin ->
|
||||
put(bin.domain.center,
|
||||
UnivariateBin(
|
||||
bin.domain,
|
||||
value = bin.value * k.toDouble(),
|
||||
standardDeviation = abs(bin.standardDeviation * k.toDouble())
|
||||
value = bin.value * value.toDouble(),
|
||||
standardDeviation = abs(bin.standardDeviation * value.toDouble())
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -113,6 +114,8 @@ public class TreeHistogramSpace(
|
||||
return TreeHistogram(this, bins)
|
||||
}
|
||||
|
||||
override fun UnivariateHistogram.unaryMinus(): UnivariateHistogram = this * (-1)
|
||||
|
||||
override val zero: UnivariateHistogram = produce { }
|
||||
|
||||
public companion object {
|
||||
|
@ -8,6 +8,7 @@ import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.asSequence
|
||||
|
||||
|
||||
@UnstableKMathAPI
|
||||
public val UnivariateDomain.center: Double get() = (range.endInclusive - range.start) / 2
|
||||
|
||||
/**
|
||||
@ -15,6 +16,7 @@ public val UnivariateDomain.center: Double get() = (range.endInclusive - range.s
|
||||
* @param value The value of histogram including weighting
|
||||
* @param standardDeviation Standard deviation of the bin value. Zero or negative if not applicable
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public class UnivariateBin(
|
||||
public val domain: UnivariateDomain,
|
||||
override val value: Double,
|
||||
|
@ -20,7 +20,7 @@ internal fun NDAlgebra<*, *>.checkShape(array: INDArray): INDArray {
|
||||
* @param T the type of ND-structure element.
|
||||
* @param C the type of the element context.
|
||||
*/
|
||||
public interface Nd4jArrayAlgebra<T, C> : NDAlgebra<T, C> {
|
||||
public interface Nd4jArrayAlgebra<T, C : Algebra<T>> : NDAlgebra<T, C> {
|
||||
/**
|
||||
* Wraps [INDArray] to [N].
|
||||
*/
|
||||
@ -92,18 +92,9 @@ public interface Nd4jArraySpace<T, S : Space<T>> : NDSpace<T, S>, Nd4jArrayAlgeb
|
||||
return ndArray.neg().wrap()
|
||||
}
|
||||
|
||||
public override fun multiply(a: NDStructure<T>, k: Number): Nd4jArrayStructure<T> {
|
||||
public fun multiply(a: NDStructure<T>, k: Number): Nd4jArrayStructure<T> {
|
||||
return a.ndArray.mul(k).wrap()
|
||||
}
|
||||
|
||||
@Deprecated("Avoid using this method, underlying array get casted to Doubles")
|
||||
public override operator fun NDStructure<T>.div(k: Number): Nd4jArrayStructure<T> {
|
||||
return ndArray.div(k).wrap()
|
||||
}
|
||||
|
||||
public override operator fun NDStructure<T>.times(k: Number): Nd4jArrayStructure<T> {
|
||||
return ndArray.mul(k).wrap()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,8 +171,7 @@ public interface Nd4jArrayField<T, F : Field<T>> : NDField<T, F>, Nd4jArrayRing<
|
||||
public override fun divide(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> =
|
||||
a.ndArray.div(b.ndArray).wrap()
|
||||
|
||||
public override operator fun Number.div(b: NDStructure<T>): Nd4jArrayStructure<T> = b.ndArray.rdiv(this).wrap()
|
||||
|
||||
public operator fun Number.div(b: NDStructure<T>): Nd4jArrayStructure<T> = b.ndArray.rdiv(this).wrap()
|
||||
|
||||
public companion object {
|
||||
private val floatNd4jArrayFieldCache: ThreadLocal<MutableMap<IntArray, FloatNd4jArrayField>> =
|
||||
@ -218,11 +208,14 @@ public interface Nd4jArrayField<T, F : Field<T>> : NDField<T, F>, Nd4jArrayRing<
|
||||
* Represents [NDField] over [Nd4jArrayRealStructure].
|
||||
*/
|
||||
public class RealNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField<Double, RealField> {
|
||||
public override val elementContext: RealField
|
||||
get() = RealField
|
||||
public override val elementContext: RealField get() = RealField
|
||||
|
||||
public override fun INDArray.wrap(): Nd4jArrayStructure<Double> = checkShape(this).asRealStructure()
|
||||
|
||||
override fun scale(a: NDStructure<Double>, value: Double): Nd4jArrayStructure<Double> {
|
||||
return a.ndArray.mul(value).wrap()
|
||||
}
|
||||
|
||||
public override operator fun NDStructure<Double>.div(arg: Double): Nd4jArrayStructure<Double> {
|
||||
return ndArray.div(arg).wrap()
|
||||
}
|
||||
@ -257,6 +250,10 @@ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArra
|
||||
|
||||
public override fun INDArray.wrap(): Nd4jArrayStructure<Float> = checkShape(this).asFloatStructure()
|
||||
|
||||
override fun scale(a: NDStructure<Float>, value: Double): NDStructure<Float> {
|
||||
return a.ndArray.mul(value).wrap()
|
||||
}
|
||||
|
||||
public override operator fun NDStructure<Float>.div(arg: Float): Nd4jArrayStructure<Float> {
|
||||
return ndArray.div(arg).wrap()
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import space.kscience.kmath.chains.Chain
|
||||
import space.kscience.kmath.chains.ConstantChain
|
||||
import space.kscience.kmath.chains.map
|
||||
import space.kscience.kmath.chains.zip
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.operations.Space
|
||||
import space.kscience.kmath.operations.invoke
|
||||
|
||||
@ -18,14 +19,18 @@ public class ConstantSampler<T : Any>(public val value: T) : Sampler<T> {
|
||||
/**
|
||||
* A space for samplers. Allows to perform simple operations on distributions
|
||||
*/
|
||||
public class SamplerSpace<T : Any>(public val space: Space<T>) : Space<Sampler<T>> {
|
||||
public override val zero: Sampler<T> = ConstantSampler(space.zero)
|
||||
public class SamplerSpace<T : Any, S>(public val algebra: S) : Space<Sampler<T>>,
|
||||
ScaleOperations<Sampler<T>> where S : Space<T>, S : ScaleOperations<T> {
|
||||
|
||||
public override val zero: Sampler<T> = ConstantSampler(algebra.zero)
|
||||
|
||||
public override fun add(a: Sampler<T>, b: Sampler<T>): Sampler<T> = BasicSampler { generator ->
|
||||
a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> space { aValue + bValue } }
|
||||
a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> algebra { aValue + bValue } }
|
||||
}
|
||||
|
||||
public override fun multiply(a: Sampler<T>, k: Number): Sampler<T> = BasicSampler { generator ->
|
||||
a.sample(generator).map { space { it * k.toDouble() } }
|
||||
public override fun scale(a: Sampler<T>, value: Double): Sampler<T> = BasicSampler { generator ->
|
||||
a.sample(generator).map { algebra { it * value } }
|
||||
}
|
||||
|
||||
override fun Sampler<T>.unaryMinus(): Sampler<T> = scale(this, -1.0)
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public interface ComposableStatistic<T, I, R> : Statistic<T, R> {
|
||||
@ExperimentalCoroutinesApi
|
||||
private fun <T, I, R> ComposableStatistic<T, I, R>.flowIntermediate(
|
||||
flow: Flow<Buffer<T>>,
|
||||
dispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||
dispatcher: CoroutineDispatcher = Dispatchers.Default,
|
||||
): Flow<I> = flow
|
||||
.mapParallel(dispatcher) { computeIntermediate(it) }
|
||||
.runningReduce(::composeIntermediate)
|
||||
@ -59,27 +59,31 @@ private fun <T, I, R> ComposableStatistic<T, I, R>.flowIntermediate(
|
||||
@ExperimentalCoroutinesApi
|
||||
public fun <T, I, R> ComposableStatistic<T, I, R>.flow(
|
||||
flow: Flow<Buffer<T>>,
|
||||
dispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||
dispatcher: CoroutineDispatcher = Dispatchers.Default,
|
||||
): Flow<R> = flowIntermediate(flow, dispatcher).map(::toResult)
|
||||
|
||||
/**
|
||||
* Arithmetic mean
|
||||
*/
|
||||
public class Mean<T>(public val space: Space<T>) : ComposableStatistic<T, Pair<T, Int>, T> {
|
||||
public class Mean<T>(
|
||||
private val space: Space<T>,
|
||||
private val division: (sum: T, count: Int) -> T,
|
||||
) : ComposableStatistic<T, Pair<T, Int>, T> {
|
||||
public override suspend fun computeIntermediate(data: Buffer<T>): Pair<T, Int> =
|
||||
space { sum(data.asIterable()) } to data.size
|
||||
|
||||
public override suspend fun composeIntermediate(first: Pair<T, Int>, second: Pair<T, Int>): Pair<T, Int> =
|
||||
space { first.first + second.first } to (first.second + second.second)
|
||||
|
||||
public override suspend fun toResult(intermediate: Pair<T, Int>): T =
|
||||
space { intermediate.first / intermediate.second }
|
||||
public override suspend fun toResult(intermediate: Pair<T, Int>): T = space {
|
||||
division(intermediate.first, intermediate.second)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
//TODO replace with optimized version which respects overflow
|
||||
public val real: Mean<Double> = Mean(RealField)
|
||||
public val int: Mean<Int> = Mean(IntRing)
|
||||
public val long: Mean<Long> = Mean(LongRing)
|
||||
public val real: Mean<Double> = Mean(RealField) { sum, count -> sum / count }
|
||||
public val int: Mean<Int> = Mean(IntRing) { sum, count -> sum / count }
|
||||
public val long: Mean<Long> = Mean(LongRing) { sum, count -> sum / count }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ public final class space/kscience/kmath/viktor/ViktorBuffer : space/kscience/kma
|
||||
public final synthetic fun unbox-impl ()Lorg/jetbrains/bio/viktor/F64FlatArray;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/kmath/nd/NDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/RingWithNumbers {
|
||||
public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/kmath/nd/NDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations {
|
||||
public fun <init> ([I)V
|
||||
public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun acos-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
|
||||
@ -55,8 +55,6 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km
|
||||
public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun cosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
public fun div (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun div (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
|
||||
public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public synthetic fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
@ -68,7 +66,7 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km
|
||||
public fun divide (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun exp-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
|
||||
public synthetic fun getElementContext ()Ljava/lang/Object;
|
||||
public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra;
|
||||
public fun getElementContext ()Lspace/kscience/kmath/operations/RealField;
|
||||
public final fun getF64Buffer (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
|
||||
public synthetic fun getOne ()Ljava/lang/Object;
|
||||
@ -96,11 +94,8 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km
|
||||
public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
public synthetic fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
public fun minus-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
|
||||
public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
|
||||
public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public synthetic fun multiply (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
public fun multiply-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array;
|
||||
public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
|
||||
public fun number-Q7Xurp0 (Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array;
|
||||
public fun plus (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
@ -122,6 +117,8 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km
|
||||
public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object;
|
||||
public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure;
|
||||
public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
||||
public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object;
|
||||
public fun scale-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;D)Lorg/jetbrains/bio/viktor/F64Array;
|
||||
public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun sin-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
|
||||
public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
|
@ -4,8 +4,9 @@ import org.jetbrains.bio.viktor.F64Array
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.NumbersAddOperations
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.operations.RingWithNumbers
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
|
||||
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||
public inline class ViktorNDStructure(public val f64Buffer: F64Array) : MutableNDStructure<Double> {
|
||||
@ -26,7 +27,8 @@ public fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this)
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||
public class ViktorNDField(public override val shape: IntArray) : NDField<Double, RealField>,
|
||||
RingWithNumbers<NDStructure<Double>>, ExtendedField<NDStructure<Double>> {
|
||||
NumbersAddOperations<NDStructure<Double>>, ExtendedField<NDStructure<Double>>,
|
||||
ScaleOperations<NDStructure<Double>> {
|
||||
|
||||
public val NDStructure<Double>.f64Buffer: F64Array
|
||||
get() = when {
|
||||
@ -55,6 +57,8 @@ public class ViktorNDField(public override val shape: IntArray) : NDField<Double
|
||||
}
|
||||
}.asStructure()
|
||||
|
||||
override fun NDStructure<Double>.unaryMinus(): NDStructure<Double> = this * (-1)
|
||||
|
||||
public override fun NDStructure<Double>.map(transform: RealField.(Double) -> Double): ViktorNDStructure =
|
||||
F64Array(*this@ViktorNDField.shape).apply {
|
||||
this@ViktorNDField.strides.indices().forEach { index ->
|
||||
@ -83,8 +87,8 @@ public class ViktorNDField(public override val shape: IntArray) : NDField<Double
|
||||
public override fun add(a: NDStructure<Double>, b: NDStructure<Double>): ViktorNDStructure =
|
||||
(a.f64Buffer + b.f64Buffer).asStructure()
|
||||
|
||||
public override fun multiply(a: NDStructure<Double>, k: Number): ViktorNDStructure =
|
||||
(a.f64Buffer * k.toDouble()).asStructure()
|
||||
public override fun scale(a: NDStructure<Double>, value: Double): ViktorNDStructure =
|
||||
(a.f64Buffer * value.toDouble()).asStructure()
|
||||
|
||||
public override inline fun NDStructure<Double>.plus(b: NDStructure<Double>): ViktorNDStructure =
|
||||
(f64Buffer + b.f64Buffer).asStructure()
|
||||
|
@ -1,14 +1,15 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
mavenLocal()
|
||||
gradlePluginPortal()
|
||||
jcenter()
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
||||
maven("https://dl.bintray.com/kotlin/kotlinx")
|
||||
}
|
||||
|
||||
val toolsVersion = "0.8.1"
|
||||
val kotlinVersion = "1.4.30"
|
||||
val toolsVersion = "0.9.1"
|
||||
val kotlinVersion = "1.4.31"
|
||||
|
||||
plugins {
|
||||
id("kotlinx.benchmark") version "0.2.0-dev-20"
|
||||
|
Loading…
Reference in New Issue
Block a user