Merge pull request #219 from mipt-npm/refactor/algebra-scale

Fully refactor algebra split ScaleOperations from Space.
This commit is contained in:
Alexander Nozik 2021-03-11 11:28:54 +03:00 committed by GitHub
commit f449bdd58f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 1198 additions and 1387 deletions

View File

@ -1,6 +1,5 @@
# Based on https://github.com/touchlab/Stately/blob/main/.github/workflows/build.yml name: Gradle build
name: build
on: [ push ] on: [ push ]
jobs: jobs:

View File

@ -1,10 +1,15 @@
# Based on https://github.com/touchlab/Stately/blob/main/.github/workflows/deploy.yml name: Gradle publish
name: deploy on:
on: workflow_dispatch workflow_dispatch:
release:
types:
- created
jobs: jobs:
build: publish:
environment:
name: publish
strategy: strategy:
matrix: matrix:
os: [macOS-latest, windows-latest] os: [macOS-latest, windows-latest]
@ -33,13 +38,22 @@ jobs:
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ 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 - name: Publish Windows Artifacts
if: matrix.os == 'windows-latest' 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 }} run: >
env: ./gradlew release --no-daemon
signingKey: ${{ secrets.SIGNING_KEY }} -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 }}

View File

@ -2,12 +2,19 @@
## [Unreleased] ## [Unreleased]
### Added ### Added
- ScaleOperations interface
- Field extends ScaleOperations
### Changed ### Changed
- Exponential operations merged with hyperbolic functions
- Space is replaced by Group. Space is reserved for vector spaces.
- VectorSpace is now a vector space
### Deprecated ### Deprecated
### Removed ### Removed
- Nearest in Domain. To be implemented in geometry package.
- Number multiplication and division in main Algebra chain
### Fixed ### Fixed

View File

@ -20,7 +20,7 @@ allprojects {
} }
group = "space.kscience" group = "space.kscience"
version = "0.2.0" version = "0.3.0"
} }
subprojects { subprojects {
@ -32,9 +32,9 @@ readme {
} }
ksciencePublish { ksciencePublish {
spaceRepo = "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven" github("kmath")
bintrayRepo = "kscience" space()
githubProject = "kmath" sonatype()
} }
apiValidation { apiValidation {

View File

@ -6,10 +6,10 @@ import space.kscience.kmath.operations.RealField
fun main() { fun main() {
val expr = RealField.mstInField { val expr = RealField.mstInField {
val x = bindSymbol("x") val x = bindSymbol("x")
x * 2.0 + 2.0 / x - 16.0 x * 2.0 + number(2.0) / x - 16.0
} }
repeat(10000000){ repeat(10000000) {
expr.invoke("x" to 1.0) expr.invoke("x" to 1.0)
} }
} }

View File

@ -3,8 +3,8 @@ package space.kscience.kmath.structures
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.NumbersAddOperations
import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.RealField
import space.kscience.kmath.operations.RingWithNumbers
import java.util.* import java.util.*
import java.util.stream.IntStream import java.util.stream.IntStream
@ -15,7 +15,7 @@ import java.util.stream.IntStream
class StreamRealNDField( class StreamRealNDField(
override val shape: IntArray, override val shape: IntArray,
) : NDField<Double, RealField>, ) : NDField<Double, RealField>,
RingWithNumbers<NDStructure<Double>>, NumbersAddOperations<NDStructure<Double>>,
ExtendedField<NDStructure<Double>> { ExtendedField<NDStructure<Double>> {
private val strides = DefaultStrides(shape) private val strides = DefaultStrides(shape)
@ -79,25 +79,29 @@ class StreamRealNDField(
return NDBuffer(strides, array.asBuffer()) 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 exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { exp(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 ln(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { ln(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 sin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { sin(it) }
override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asinh(it) } override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { cos(it) }
override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acosh(it) } override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { tan(it) }
override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atanh(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) fun NDAlgebra.Companion.realWithStream(vararg shape: Int): StreamRealNDField = StreamRealNDField(shape)

View File

@ -1,9 +1,10 @@
kotlin.code.style=official kotlin.code.style=official
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.mpp.stability.nowarn=true kotlin.mpp.stability.nowarn=true
kotlin.native.enableDependencyPropagation=false
kotlin.parallel.tasks.in.project=true kotlin.parallel.tasks.in.project=true
org.gradle.configureondemand=true org.gradle.configureondemand=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m
org.gradle.parallel=true org.gradle.parallel=true
systemProp.org.gradle.internal.publish.checksums.insecure=true
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false

View File

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

View File

@ -18,25 +18,25 @@ public object MstAlgebra : NumericAlgebra<MST> {
} }
/** /**
* [Space] over [MST] nodes. * [Group] over [MST] nodes.
*/ */
public object MstSpace : Space<MST>, NumericAlgebra<MST> { public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
public override val zero: MST.Numeric by lazy { number(0.0) } public override val zero: MST.Numeric = number(0.0)
public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value)
public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value) public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value)
public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b) public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(GroupOperations.PLUS_OPERATION)(a, b)
public override operator fun MST.unaryPlus(): MST.Unary = public override operator fun MST.unaryPlus(): MST.Unary =
unaryOperationFunction(SpaceOperations.PLUS_OPERATION)(this) unaryOperationFunction(GroupOperations.PLUS_OPERATION)(this)
public override operator fun MST.unaryMinus(): MST.Unary = public override operator fun MST.unaryMinus(): MST.Unary =
unaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this) unaryOperationFunction(GroupOperations.MINUS_OPERATION)(this)
public override operator fun MST.minus(b: MST): MST.Binary = public override operator fun MST.minus(b: MST): MST.Binary =
binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b) binaryOperationFunction(GroupOperations.MINUS_OPERATION)(this, b)
public override fun multiply(a: MST, k: Number): MST.Binary = public override fun scale(a: MST, value: Double): MST.Binary =
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(k)) binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(value))
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstAlgebra.binaryOperationFunction(operation) MstAlgebra.binaryOperationFunction(operation)
@ -49,25 +49,26 @@ public object MstSpace : Space<MST>, NumericAlgebra<MST> {
* [Ring] over [MST] nodes. * [Ring] over [MST] nodes.
*/ */
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public object MstRing : Ring<MST>, RingWithNumbers<MST> { public object MstRing : Ring<MST>, NumbersAddOperations<MST>, ScaleOperations<MST> {
public override val zero: MST.Numeric public override val zero: MST.Numeric get() = MstGroup.zero
get() = MstSpace.zero public override val one: MST.Numeric = number(1.0)
public override val one: MST.Numeric by lazy { number(1.0) } public override fun number(value: Number): MST.Numeric = MstGroup.number(value)
public override fun bindSymbol(value: String): MST.Symbolic = MstGroup.bindSymbol(value)
public override fun add(a: MST, b: MST): MST.Binary = MstGroup.add(a, b)
public override fun scale(a: MST, value: Double): MST.Binary =
MstGroup.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstGroup.number(value))
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 multiply(a: MST, b: MST): MST.Binary = public override fun multiply(a: MST, b: MST): MST.Binary =
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b) binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b)
public override operator fun MST.unaryPlus(): MST.Unary = MstSpace { +this@unaryPlus } public override operator fun MST.unaryPlus(): MST.Unary = MstGroup { +this@unaryPlus }
public override operator fun MST.unaryMinus(): MST.Unary = MstSpace { -this@unaryMinus } public override operator fun MST.unaryMinus(): MST.Unary = MstGroup { -this@unaryMinus }
public override operator fun MST.minus(b: MST): MST.Binary = MstSpace { this@minus - b } public override operator fun MST.minus(b: MST): MST.Binary = MstGroup { this@minus - b }
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstSpace.binaryOperationFunction(operation) MstGroup.binaryOperationFunction(operation)
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
MstAlgebra.unaryOperationFunction(operation) MstAlgebra.unaryOperationFunction(operation)
@ -77,17 +78,18 @@ public object MstRing : Ring<MST>, RingWithNumbers<MST> {
* [Field] over [MST] nodes. * [Field] over [MST] nodes.
*/ */
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public object MstField : Field<MST>, RingWithNumbers<MST> { public object MstField : Field<MST>, NumbersAddOperations<MST>, ScaleOperations<MST> {
public override val zero: MST.Numeric public override val zero: MST.Numeric get() = MstRing.zero
get() = MstRing.zero
public override val one: MST.Numeric public override val one: MST.Numeric get() = MstRing.one
get() = MstRing.one
public override fun bindSymbol(value: String): MST.Symbolic = MstRing.bindSymbol(value) 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 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 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 =
MstGroup.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstGroup.number(value))
public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b)
public override fun divide(a: MST, b: MST): MST.Binary = public override fun divide(a: MST, b: MST): MST.Binary =
binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b) binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b)
@ -107,11 +109,8 @@ public object MstField : Field<MST>, RingWithNumbers<MST> {
* [ExtendedField] over [MST] nodes. * [ExtendedField] over [MST] nodes.
*/ */
public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> { public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
public override val zero: MST.Numeric public override val zero: MST.Numeric get() = MstField.zero
get() = MstField.zero public override val one: MST.Numeric get() = MstField.one
public override val one: MST.Numeric
get() = MstField.one
public override fun bindSymbol(value: String): MST.Symbolic = MstField.bindSymbol(value) public override fun bindSymbol(value: String): MST.Symbolic = MstField.bindSymbol(value)
public override fun number(value: Number): MST.Numeric = MstRing.number(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 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 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 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 sinh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.SINH_OPERATION)(arg)
public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.COSH_OPERATION)(arg) public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.COSH_OPERATION)(arg)
public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.TANH_OPERATION)(arg) public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.TANH_OPERATION)(arg)
public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ASINH_OPERATION)(arg) public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ASINH_OPERATION)(arg)
public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ACOSH_OPERATION)(arg) public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg)
public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ATANH_OPERATION)(arg) public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg)
public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b)
public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k)
public override fun scale(a: MST, value: Double): MST =
binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value))
public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) 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 fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b)
public override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus } public override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus }

View File

@ -54,13 +54,13 @@ public inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
): MstExpression<T, A> = MstExpression(this, mstAlgebra.block()) ): MstExpression<T, A> = MstExpression(this, mstAlgebra.block())
/** /**
* Builds [MstExpression] over [Space]. * Builds [MstExpression] over [Group].
* *
* @author Alexander Nozik * @author Alexander Nozik
*/ */
public inline fun <reified T : Any, A : Space<T>> A.mstInSpace(block: MstSpace.() -> MST): MstExpression<T, A> { public inline fun <reified T : Any, A : Group<T>> A.mstInGroup(block: MstGroup.() -> MST): MstExpression<T, A> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return MstExpression(this, MstSpace.block()) return MstExpression(this, MstGroup.block())
} }
/** /**
@ -94,13 +94,13 @@ public inline fun <reified T : Any, A : ExtendedField<T>> A.mstInExtendedField(b
} }
/** /**
* Builds [MstExpression] over [FunctionalExpressionSpace]. * Builds [MstExpression] over [FunctionalExpressionGroup].
* *
* @author Alexander Nozik * @author Alexander Nozik
*/ */
public inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T, A> { public inline fun <reified T : Any, A : Group<T>> FunctionalExpressionGroup<T, A>.mstInGroup(block: MstGroup.() -> MST): MstExpression<T, A> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return algebra.mstInSpace(block) return algebra.mstInGroup(block)
} }
/** /**

View File

@ -12,12 +12,12 @@ import kotlin.test.assertEquals
internal class TestESTreeConsistencyWithInterpreter { internal class TestESTreeConsistencyWithInterpreter {
@Test @Test
fun mstSpace() { fun mstSpace() {
val res1 = MstSpace.mstInSpace { val res1 = MstGroup.mstInGroup {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
), ),
@ -25,12 +25,12 @@ internal class TestESTreeConsistencyWithInterpreter {
) + bindSymbol("x") + zero ) + bindSymbol("x") + zero
}("x" to MST.Numeric(2)) }("x" to MST.Numeric(2))
val res2 = MstSpace.mstInSpace { val res2 = MstGroup.mstInGroup {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
), ),
@ -46,9 +46,9 @@ internal class TestESTreeConsistencyWithInterpreter {
val res1 = ByteRing.mstInRing { val res1 = ByteRing.mstInRing {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
(bindSymbol("x") - (2.toByte() + (multiply( (bindSymbol("x") - (2.toByte() + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + 1.toByte()))) * 3.0 - 1.toByte() ) + 1.toByte()))) * 3.0 - 1.toByte()
), ),
@ -59,9 +59,9 @@ internal class TestESTreeConsistencyWithInterpreter {
val res2 = ByteRing.mstInRing { val res2 = ByteRing.mstInRing {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
(bindSymbol("x") - (2.toByte() + (multiply( (bindSymbol("x") - (2.toByte() + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + 1.toByte()))) * 3.0 - 1.toByte() ) + 1.toByte()))) * 3.0 - 1.toByte()
), ),
number(1) number(1)
@ -75,7 +75,7 @@ internal class TestESTreeConsistencyWithInterpreter {
fun realField() { fun realField() {
val res1 = RealField.mstInField { val res1 = RealField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(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),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
@ -83,7 +83,7 @@ internal class TestESTreeConsistencyWithInterpreter {
val res2 = RealField.mstInField { val res2 = RealField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(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),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
@ -96,7 +96,7 @@ internal class TestESTreeConsistencyWithInterpreter {
fun complexField() { fun complexField() {
val res1 = ComplexField.mstInField { val res1 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(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),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
@ -104,7 +104,7 @@ internal class TestESTreeConsistencyWithInterpreter {
val res2 = ComplexField.mstInField { val res2 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(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),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero

View File

@ -2,7 +2,7 @@ package space.kscience.kmath.estree
import space.kscience.kmath.ast.mstInExtendedField import space.kscience.kmath.ast.mstInExtendedField
import space.kscience.kmath.ast.mstInField import space.kscience.kmath.ast.mstInField
import space.kscience.kmath.ast.mstInSpace import space.kscience.kmath.ast.mstInGroup
import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.RealField
import kotlin.random.Random import kotlin.random.Random
@ -12,14 +12,14 @@ import kotlin.test.assertEquals
internal class TestESTreeOperationsSupport { internal class TestESTreeOperationsSupport {
@Test @Test
fun testUnaryOperationInvocation() { fun testUnaryOperationInvocation() {
val expression = RealField.mstInSpace { -bindSymbol("x") }.compile() val expression = RealField.mstInGroup { -bindSymbol("x") }.compile()
val res = expression("x" to 2.0) val res = expression("x" to 2.0)
assertEquals(-2.0, res) assertEquals(-2.0, res)
} }
@Test @Test
fun testBinaryOperationInvocation() { fun testBinaryOperationInvocation() {
val expression = RealField.mstInSpace { -bindSymbol("x") + number(1.0) }.compile() val expression = RealField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile()
val res = expression("x" to 2.0) val res = expression("x" to 2.0)
assertEquals(-1.0, res) assertEquals(-1.0, res)
} }

View File

@ -14,9 +14,9 @@ import com.github.h0tk3y.betterParse.lexer.regexToken
import com.github.h0tk3y.betterParse.parser.ParseResult import com.github.h0tk3y.betterParse.parser.ParseResult
import com.github.h0tk3y.betterParse.parser.Parser import com.github.h0tk3y.betterParse.parser.Parser
import space.kscience.kmath.operations.FieldOperations import space.kscience.kmath.operations.FieldOperations
import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.PowerOperations import space.kscience.kmath.operations.PowerOperations
import space.kscience.kmath.operations.RingOperations import space.kscience.kmath.operations.RingOperations
import space.kscience.kmath.operations.SpaceOperations
/** /**
* better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4. * better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4.
@ -55,7 +55,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
.or(binaryFunction) .or(binaryFunction)
.or(unaryFunction) .or(unaryFunction)
.or(singular) .or(singular)
.or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(SpaceOperations.MINUS_OPERATION, it) }) .or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(GroupOperations.MINUS_OPERATION, it) })
.or(-lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar) .or(-lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
private val powChain: Parser<MST> by leftAssociative(term = term, operator = pow) { a, _, b -> private val powChain: Parser<MST> by leftAssociative(term = term, operator = pow) { a, _, b ->
@ -77,9 +77,9 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
operator = plus or minus use TokenMatch::type operator = plus or minus use TokenMatch::type
) { a, op, b -> ) { a, op, b ->
if (op == plus) if (op == plus)
MST.Binary(SpaceOperations.PLUS_OPERATION, a, b) MST.Binary(GroupOperations.PLUS_OPERATION, a, b)
else else
MST.Binary(SpaceOperations.MINUS_OPERATION, a, b) MST.Binary(GroupOperations.MINUS_OPERATION, a, b)
} }
override val rootParser: Parser<MST> by subSumChain override val rootParser: Parser<MST> by subSumChain

View File

@ -12,12 +12,12 @@ import kotlin.test.assertEquals
internal class TestAsmConsistencyWithInterpreter { internal class TestAsmConsistencyWithInterpreter {
@Test @Test
fun mstSpace() { fun mstSpace() {
val res1 = MstSpace.mstInSpace { val res1 = MstGroup.mstInGroup {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
), ),
@ -25,12 +25,12 @@ internal class TestAsmConsistencyWithInterpreter {
) + bindSymbol("x") + zero ) + bindSymbol("x") + zero
}("x" to MST.Numeric(2)) }("x" to MST.Numeric(2))
val res2 = MstSpace.mstInSpace { val res2 = MstGroup.mstInGroup {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
), ),
@ -46,9 +46,9 @@ internal class TestAsmConsistencyWithInterpreter {
val res1 = ByteRing.mstInRing { val res1 = ByteRing.mstInRing {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
(bindSymbol("x") - (2.toByte() + (multiply( (bindSymbol("x") - (2.toByte() + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + 1.toByte()))) * 3.0 - 1.toByte() ) + 1.toByte()))) * 3.0 - 1.toByte()
), ),
@ -59,9 +59,9 @@ internal class TestAsmConsistencyWithInterpreter {
val res2 = ByteRing.mstInRing { val res2 = ByteRing.mstInRing {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
(bindSymbol("x") - (2.toByte() + (multiply( (bindSymbol("x") - (2.toByte() + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + 1.toByte()))) * 3.0 - 1.toByte() ) + 1.toByte()))) * 3.0 - 1.toByte()
), ),
number(1) number(1)
@ -75,7 +75,7 @@ internal class TestAsmConsistencyWithInterpreter {
fun realField() { fun realField() {
val res1 = RealField.mstInField { val res1 = RealField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(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),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
@ -83,7 +83,7 @@ internal class TestAsmConsistencyWithInterpreter {
val res2 = RealField.mstInField { val res2 = RealField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(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),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
@ -96,7 +96,7 @@ internal class TestAsmConsistencyWithInterpreter {
fun complexField() { fun complexField() {
val res1 = ComplexField.mstInField { val res1 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(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),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
@ -104,7 +104,7 @@ internal class TestAsmConsistencyWithInterpreter {
val res2 = ComplexField.mstInField { val res2 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(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),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero

View File

@ -2,7 +2,7 @@ package space.kscience.kmath.asm
import space.kscience.kmath.ast.mstInExtendedField import space.kscience.kmath.ast.mstInExtendedField
import space.kscience.kmath.ast.mstInField import space.kscience.kmath.ast.mstInField
import space.kscience.kmath.ast.mstInSpace import space.kscience.kmath.ast.mstInGroup
import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.RealField
import kotlin.random.Random import kotlin.random.Random
@ -12,14 +12,14 @@ import kotlin.test.assertEquals
internal class TestAsmOperationsSupport { internal class TestAsmOperationsSupport {
@Test @Test
fun testUnaryOperationInvocation() { fun testUnaryOperationInvocation() {
val expression = RealField.mstInSpace { -bindSymbol("x") }.compile() val expression = RealField.mstInGroup { -bindSymbol("x") }.compile()
val res = expression("x" to 2.0) val res = expression("x" to 2.0)
assertEquals(-2.0, res) assertEquals(-2.0, res)
} }
@Test @Test
fun testBinaryOperationInvocation() { fun testBinaryOperationInvocation() {
val expression = RealField.mstInSpace { -bindSymbol("x") + number(1.0) }.compile() val expression = RealField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile()
val res = expression("x" to 2.0) val res = expression("x" to 2.0)
assertEquals(-1.0, res) assertEquals(-1.0, res)
} }

View File

@ -4,7 +4,7 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
import space.kscience.kmath.expressions.* import space.kscience.kmath.expressions.*
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.RingWithNumbers import space.kscience.kmath.operations.NumbersAddOperations
/** /**
* A field over commons-math [DerivativeStructure]. * A field over commons-math [DerivativeStructure].
@ -16,7 +16,8 @@ import space.kscience.kmath.operations.RingWithNumbers
public class DerivativeStructureField( public class DerivativeStructureField(
public val order: Int, public val order: Int,
bindings: Map<Symbol, Double>, 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 val numberOfVariables: Int = bindings.size
public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) } 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()) 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 add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b)
public override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) { public override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure = a.multiply(value)
is Double -> a.multiply(k)
is Int -> a.multiply(k)
else -> a.multiply(k.toDouble())
}
public override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b) public override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b)
public override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b) public override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b)

View File

@ -86,6 +86,9 @@ public object CMMatrixContext : MatrixContext<Double, CMMatrix> {
} }
} }
override fun scale(a: Matrix<Double>, value: Double): Matrix<Double> = a.toCM().times(value)
public override fun Matrix<Double>.dot(other: Matrix<Double>): CMMatrix = public override fun Matrix<Double>.dot(other: Matrix<Double>): CMMatrix =
CMMatrix(toCM().origin.multiply(other.toCM().origin)) CMMatrix(toCM().origin.multiply(other.toCM().origin))
@ -101,8 +104,8 @@ public object CMMatrixContext : MatrixContext<Double, CMMatrix> {
public override operator fun Matrix<Double>.minus(b: Matrix<Double>): CMMatrix = public override operator fun Matrix<Double>.minus(b: Matrix<Double>): CMMatrix =
CMMatrix(toCM().origin.subtract(b.toCM().origin)) CMMatrix(toCM().origin.subtract(b.toCM().origin))
public override fun multiply(a: Matrix<Double>, k: Number): CMMatrix = // public override fun multiply(a: Matrix<Double>, k: Number): CMMatrix =
CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble())) // CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble()))
public override operator fun Matrix<Double>.times(value: Double): CMMatrix = public override operator fun Matrix<Double>.times(value: Double): CMMatrix =
produce(rowNum, colNum) { i, j -> get(i, j) * value } produce(rowNum, colNum) { i, j -> get(i, j) * value }

View File

@ -4,10 +4,7 @@ import space.kscience.kmath.memory.MemoryReader
import space.kscience.kmath.memory.MemorySpec import space.kscience.kmath.memory.MemorySpec
import space.kscience.kmath.memory.MemoryWriter import space.kscience.kmath.memory.MemoryWriter
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.FieldElement
import space.kscience.kmath.operations.Norm
import space.kscience.kmath.operations.RingWithNumbers
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.MemoryBuffer import space.kscience.kmath.structures.MemoryBuffer
import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableBuffer
@ -47,7 +44,8 @@ private val PI_DIV_2 = Complex(PI / 2, 0)
* A field of [Complex]. * A field of [Complex].
*/ */
@OptIn(UnstableKMathAPI::class) @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 zero: Complex = 0.0.toComplex()
public override val one: Complex = 1.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) } 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 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 = 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) 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 override operator fun Complex.div(k: Number): Complex = Complex(re / k.toDouble(), im / k.toDouble())
public override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2
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 { public override fun tan(arg: Complex): Complex {
val e1 = exp(-i * arg) 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 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 public override val objectSize: Int
get() = 16 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) { public override fun MemoryWriter.write(offset: Int, value: Complex) {
writeDouble(offset, value.re) writeDouble(offset, value.re)

View File

@ -6,7 +6,7 @@ import space.kscience.kmath.nd.NDAlgebra
import space.kscience.kmath.nd.NDBuffer import space.kscience.kmath.nd.NDBuffer
import space.kscience.kmath.nd.NDStructure import space.kscience.kmath.nd.NDStructure
import space.kscience.kmath.operations.ExtendedField 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 space.kscience.kmath.structures.Buffer
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
@ -19,7 +19,7 @@ import kotlin.contracts.contract
public class ComplexNDField( public class ComplexNDField(
shape: IntArray, shape: IntArray,
) : BufferedNDField<Complex, ComplexField>(shape, ComplexField, Buffer.Companion::complex), ) : BufferedNDField<Complex, ComplexField>(shape, ComplexField, Buffer.Companion::complex),
RingWithNumbers<NDStructure<Complex>>, NumbersAddOperations<NDStructure<Complex>>,
ExtendedField<NDStructure<Complex>> { ExtendedField<NDStructure<Complex>> {
override val zero: NDBuffer<Complex> by lazy { produce { zero } } override val zero: NDBuffer<Complex> by lazy { produce { zero } }
@ -29,6 +29,7 @@ public class ComplexNDField(
val d = value.toComplex() // minimize conversions val d = value.toComplex() // minimize conversions
return produce { d } return produce { d }
} }
// //
// @Suppress("OVERRIDE_BY_INLINE") // @Suppress("OVERRIDE_BY_INLINE")
// override inline fun map( // override inline fun map(
@ -75,25 +76,25 @@ public class ComplexNDField(
// return BufferedNDFieldElement(this, buffer) // 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 sin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { sin(it) }
override fun cos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { cos(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 tan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { tan(it) }
override fun asin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { asin(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 acos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { acos(it) }
override fun atan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { atan(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 sinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { sinh(it) }
override fun cosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { cosh(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 tanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { tanh(it) }
override fun asinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { asinh(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 acosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { acosh(it) }
override fun atanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { atanh(it) } override fun atanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map { atanh(it) }
} }

View File

@ -37,7 +37,7 @@ public val Quaternion.r: Double
*/ */
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>, PowerOperations<Quaternion>, 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 zero: Quaternion = 0.toQuaternion()
override val one: Quaternion = 1.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 = 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) 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 { public override fun scale(a: Quaternion, value: Double): Quaternion =
val d = k.toDouble() Quaternion(a.w * value, a.x * value, a.y * value, a.z * value)
return Quaternion(a.w * d, a.x * d, a.y * d, a.z * d)
}
public override fun multiply(a: Quaternion, b: Quaternion): Quaternion = Quaternion( 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, 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 "k" -> k
else -> super<Field>.bindSymbol(value) 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" } require(!z.isNaN()) { "x-component of quaternion is not-a-number" }
} }
public override val context: QuaternionField public override val context: QuaternionField get() = QuaternionField
get() = QuaternionField
/** /**
* Returns a string representation of this quaternion. * Returns a string representation of this quaternion.

View File

@ -4,7 +4,6 @@ import space.kscience.kmath.expressions.FunctionalExpressionField
import space.kscience.kmath.expressions.bindSymbol import space.kscience.kmath.expressions.bindSymbol
import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.expressions.symbol import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.invoke
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -13,14 +12,11 @@ internal class ExpressionFieldForComplexTest {
@Test @Test
fun testComplex() { fun testComplex() {
val context = FunctionalExpressionField(ComplexField) val expression = FunctionalExpressionField(ComplexField).run {
val expression = context {
val x = bindSymbol(x) val x = bindSymbol(x)
x * x + 2 * x + one x * x + 2 * x + one
} }
assertEquals(expression(x to Complex(1.0, 0.0)), Complex(4.0, 0.0)) assertEquals(expression(x to Complex(1.0, 0.0)), Complex(4.0, 0.0))
//assertEquals(expression(), Complex(9.0, 0.0))
} }
} }

View File

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

View File

@ -16,8 +16,8 @@
package space.kscience.kmath.domains package space.kscience.kmath.domains
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.RealBuffer
import space.kscience.kmath.structures.indices import space.kscience.kmath.structures.indices
/** /**
@ -26,6 +26,7 @@ import space.kscience.kmath.structures.indices
* *
* @author Alexander Nozik * @author Alexander Nozik
*/ */
@UnstableKMathAPI
public class HyperSquareDomain(private val lower: Buffer<Double>, private val upper: Buffer<Double>) : RealDomain { public class HyperSquareDomain(private val lower: Buffer<Double>, private val upper: Buffer<Double>) : RealDomain {
public override val dimension: Int get() = lower.size 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] 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 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 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 { public override fun volume(): Double {
var res = 1.0 var res = 1.0

View File

@ -15,45 +15,27 @@
*/ */
package space.kscience.kmath.domains package space.kscience.kmath.domains
import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI
/** /**
* n-dimensional volume * n-dimensional volume
* *
* @author Alexander Nozik * @author Alexander Nozik
*/ */
@UnstableKMathAPI
public interface RealDomain : Domain<Double> { 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 * Global lower edge
* @param num * @param num axis number
* @return
*/ */
public fun getLowerBound(num: Int): Double? public fun getLowerBound(num: Int): Double
/** /**
* Global upper edge * Global upper edge
* @param num * @param num axis number
* @return
*/ */
public fun getUpperBound(num: Int): Double? public fun getUpperBound(num: Int): Double
/** /**
* Hyper volume * Hyper volume

View File

@ -16,19 +16,15 @@
package space.kscience.kmath.domains package space.kscience.kmath.domains
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI
@UnstableKMathAPI
public class UnconstrainedDomain(public override val dimension: Int) : RealDomain { public class UnconstrainedDomain(public override val dimension: Int) : RealDomain {
public override operator fun contains(point: Point<Double>): Boolean = true 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): Double = Double.POSITIVE_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 volume(): Double = Double.POSITIVE_INFINITY public override fun volume(): Double = Double.POSITIVE_INFINITY
} }

View File

@ -1,11 +1,11 @@
package space.kscience.kmath.domains package space.kscience.kmath.domains
import space.kscience.kmath.linear.Point 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 inline class UnivariateDomain(public val range: ClosedFloatingPointRange<Double>) : RealDomain {
public override val dimension: Int public override val dimension: Int get() = 1
get() = 1
public operator fun contains(d: Double): Boolean = range.contains(d) 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]) return contains(point[0])
} }
public override fun nearestInDomain(point: Point<Double>): Point<Double> { public override fun getLowerBound(num: Int): 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? {
require(num == 0) require(num == 0)
return range.start return range.start
} }
public override fun getUpperBound(num: Int, point: Point<Double>): Double? { public override fun getUpperBound(num: Int): 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? {
require(num == 0) require(num == 0)
return range.endInclusive return range.endInclusive
} }

View File

@ -41,25 +41,28 @@ public abstract class FunctionalExpressionAlgebra<T, A : Algebra<T>>(
} }
/** /**
* A context class for [Expression] construction for [Space] algebras. * A context class for [Expression] construction for [Group] algebras.
*/ */
public open class FunctionalExpressionSpace<T, A : Space<T>>( public open class FunctionalExpressionGroup<T, A : Group<T>>(
algebra: A, algebra: A,
) : FunctionalExpressionAlgebra<T, A>(algebra), Space<Expression<T>> { ) : FunctionalExpressionAlgebra<T, A>(algebra), Group<Expression<T>> {
public override val zero: Expression<T> get() = const(algebra.zero) public override val zero: Expression<T> get() = const(algebra.zero)
override fun Expression<T>.unaryMinus(): Expression<T> =
unaryOperation(GroupOperations.MINUS_OPERATION, this)
/** /**
* Builds an Expression of addition of two another expressions. * Builds an Expression of addition of two another expressions.
*/ */
public override fun add(a: Expression<T>, b: Expression<T>): Expression<T> = public override fun add(a: Expression<T>, b: Expression<T>): Expression<T> =
binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b) binaryOperation(GroupOperations.PLUS_OPERATION, a, b)
/** // /**
* Builds an Expression of multiplication of expression by number. // * Builds an Expression of multiplication of expression by number.
*/ // */
public override fun multiply(a: Expression<T>, k: Number): Expression<T> = Expression { arguments -> // public override fun multiply(a: Expression<T>, k: Number): Expression<T> = Expression { arguments ->
algebra.multiply(a.invoke(arguments), k) // algebra.multiply(a.invoke(arguments), k)
} // }
public operator fun Expression<T>.plus(arg: T): Expression<T> = this + const(arg) 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) 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> = public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
super<FunctionalExpressionAlgebra>.binaryOperationFunction(operation) super<FunctionalExpressionAlgebra>.binaryOperationFunction(operation)
} }
public open class FunctionalExpressionRing<T, A : Ring<T>>( public open class FunctionalExpressionRing<T, A : Ring<T>>(
algebra: A, algebra: A,
) : FunctionalExpressionSpace<T, A>(algebra), Ring<Expression<T>> { ) : FunctionalExpressionGroup<T, A>(algebra), Ring<Expression<T>> {
public override val one: Expression<T> public override val one: Expression<T> get() = const(algebra.one)
get() = const(algebra.one)
/** /**
* Builds an Expression of multiplication of two expressions. * Builds an Expression of multiplication of two expressions.
@ -89,15 +92,16 @@ public open class FunctionalExpressionRing<T, A : Ring<T>>(
public operator fun T.times(arg: Expression<T>): Expression<T> = arg * this public operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
public override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> = public override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
super<FunctionalExpressionSpace>.unaryOperationFunction(operation) super<FunctionalExpressionGroup>.unaryOperationFunction(operation)
public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> = public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
super<FunctionalExpressionSpace>.binaryOperationFunction(operation) super<FunctionalExpressionGroup>.binaryOperationFunction(operation)
} }
public open class FunctionalExpressionField<T, A : Field<T>>( public open class FunctionalExpressionField<T, A: Field<T>>(
algebra: A, 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. * 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> = public override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
super<FunctionalExpressionRing>.binaryOperationFunction(operation) 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>>( public open class FunctionalExpressionExtendedField<T, A : ExtendedField<T>>(
@ -151,8 +159,8 @@ public open class FunctionalExpressionExtendedField<T, A : ExtendedField<T>>(
super<FunctionalExpressionField>.binaryOperationFunction(operation) super<FunctionalExpressionField>.binaryOperationFunction(operation)
} }
public inline fun <T, A : Space<T>> A.expressionInSpace(block: FunctionalExpressionSpace<T, A>.() -> Expression<T>): Expression<T> = public inline fun <T, A : Group<T>> A.expressionInSpace(block: FunctionalExpressionGroup<T, A>.() -> Expression<T>): Expression<T> =
FunctionalExpressionSpace(this).block() FunctionalExpressionGroup(this).block()
public inline fun <T, A : Ring<T>> A.expressionInRing(block: FunctionalExpressionRing<T, A>.() -> Expression<T>): Expression<T> = public inline fun <T, A : Ring<T>> A.expressionInRing(block: FunctionalExpressionRing<T, A>.() -> Expression<T>): Expression<T> =
FunctionalExpressionRing(this).block() FunctionalExpressionRing(this).block()
@ -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> = public inline fun <T, A : Field<T>> A.expressionInField(block: FunctionalExpressionField<T, A>.() -> Expression<T>): Expression<T> =
FunctionalExpressionField(this).block() FunctionalExpressionField(this).block()
public inline fun <T, A : ExtendedField<T>> A.expressionInExtendedField(block: FunctionalExpressionExtendedField<T, A>.() -> Expression<T>): Expression<T> = public inline fun <T, A : ExtendedField<T>> A.expressionInExtendedField(
FunctionalExpressionExtendedField(this).block() block: FunctionalExpressionExtendedField<T, A>.() -> Expression<T>,
): Expression<T> = FunctionalExpressionExtendedField(this).block()

View File

@ -47,36 +47,6 @@ public fun <T : Any> DerivationResult<T>.grad(vararg variables: Symbol): Point<T
return variables.map(::derivative).asBuffer() 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. * 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 open class SimpleAutoDiffField<T : Any, F : Field<T>>(
public val context: F, public val context: F,
bindings: Map<Symbol, T>, bindings: Map<Symbol, T>,
) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, RingWithNumbers<AutoDiffValue<T>> { ) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, NumbersAddOperations<AutoDiffValue<T>> {
public override val zero: AutoDiffValue<T> public override val zero: AutoDiffValue<T> get() = const(context.zero)
get() = const(context.zero) public override val one: AutoDiffValue<T> get() = const(context.one)
public override val one: AutoDiffValue<T>
get() = const(context.one)
// this stack contains pairs of blocks and values to apply them to // this stack contains pairs of blocks and values to apply them to
private var stack: Array<Any?> = arrayOfNulls<Any?>(8) 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 const(value: T): AutoDiffValue<T> = AutoDiffValue(value)
override fun number(value: Number): AutoDiffValue<T> = const { one * value }
/** /**
* A variable accessing inner state of derivatives. * A variable accessing inner state of derivatives.
* Use this value in inner builders to avoid creating additional derivative bindings. * 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) 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 (+, -, *, /) // 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) b.d -= z.d * a.value / (b.value * b.value)
} }
public override fun multiply(a: AutoDiffValue<T>, k: Number): AutoDiffValue<T> = public override fun scale(a: AutoDiffValue<T>, value: Double): AutoDiffValue<T> =
derive(const { k.toDouble() * a.value }) { z -> derive(const { value * a.value }) { z ->
a.d += z.d * k.toDouble() 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 * 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 // Extensions for differentiation of various basic mathematical functions
// x ^ 2 // x ^ 2
public fun <T : Any, F : Field<T>> SimpleAutoDiffField<T, F>.sqr(x: AutoDiffValue<T>): AutoDiffValue<T> = 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 * x.value } derive(const { x.value * x.value }) { z -> x.d += z.d * 2.0 * x.value }
// x ^ 1/2 // x ^ 1/2
public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.sqrt(x: AutoDiffValue<T>): AutoDiffValue<T> = 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) // x ^ y (const)
public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.pow( public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.pow(
x: AutoDiffValue<T>, x: AutoDiffValue<T>,
y: Double, y: Double,
): AutoDiffValue<T> = ): AutoDiffValue<T> = derive(const { power(x.value, y) }) { z ->
derive(const { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) } x.d += z.d * y * power(x.value, y - 1)
}
public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.pow( public fun <T : Any, F : ExtendedField<T>> SimpleAutoDiffField<T, F>.pow(
x: AutoDiffValue<T>, 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>>( public class SimpleAutoDiffExtendedField<T : Any, F : ExtendedField<T>>(
context: F, context: F,
bindings: Map<Symbol, T>, 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 // x ^ 2
public fun sqr(x: AutoDiffValue<T>): AutoDiffValue<T> = public fun sqr(x: AutoDiffValue<T>): AutoDiffValue<T> =
(this as SimpleAutoDiffField<T, F>).sqr(x) (this as SimpleAutoDiffField<T, F>).sqr(x)

View File

@ -2,18 +2,18 @@ package space.kscience.kmath.expressions
import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.Space
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
/** /**
* Creates a functional expression with this [Space]. * Creates a functional expression with this [Group].
*/ */
public inline fun <T> Space<T>.spaceExpression(block: FunctionalExpressionSpace<T, Space<T>>.() -> Expression<T>): Expression<T> { public inline fun <T> Group<T>.spaceExpression(block: FunctionalExpressionGroup<T, Group<T>>.() -> Expression<T>): Expression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return FunctionalExpressionSpace(this).block() return FunctionalExpressionGroup(this).block()
} }
/** /**

View File

@ -3,6 +3,7 @@ package space.kscience.kmath.linear
import space.kscience.kmath.nd.NDStructure import space.kscience.kmath.nd.NDStructure
import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory
@ -18,15 +19,22 @@ public typealias Matrix<T> = Structure2D<T>
/** /**
* Basic implementation of Matrix space based on [NDStructure] * Basic implementation of Matrix space based on [NDStructure]
*/ */
public class BufferMatrixContext<T : Any, R : Ring<T>>( public class BufferMatrixContext<T : Any, A>(
public override val elementContext: R, public override val elementContext: A,
private val bufferFactory: BufferFactory<T>, private val bufferFactory: BufferFactory<T>,
) : GenericMatrixContext<T, R, BufferMatrix<T>> { ) : GenericMatrixContext<T, A, BufferMatrix<T>> where A : Ring<T>, A : ScaleOperations<T> {
public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix<T> { public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix<T> {
val buffer = bufferFactory(rows * columns) { offset -> initializer(offset / columns, offset % columns) } val buffer = bufferFactory(rows * columns) { offset -> initializer(offset / columns, offset % columns) }
return BufferMatrix(rows, columns, buffer) return BufferMatrix(rows, columns, buffer)
} }
override fun scale(a: Matrix<T>, value: Double): Matrix<T> = elementContext {
produce(a.rowNum, a.colNum) { i, j ->
a[i, j] * value
}
}
public override fun point(size: Int, initializer: (Int) -> T): Point<T> = bufferFactory(size, initializer) public override fun point(size: Int, initializer: (Int) -> T): Point<T> = bufferFactory(size, initializer)
private fun Matrix<T>.toBufferMatrix(): BufferMatrix<T> = if (this is BufferMatrix) this else { private fun Matrix<T>.toBufferMatrix(): BufferMatrix<T> = if (this is BufferMatrix) this else {
@ -78,12 +86,12 @@ public class BufferMatrixContext<T : Any, R : Ring<T>>(
} }
} }
override fun multiply(a: Matrix<T>, k: Number): BufferMatrix<T> { // override fun multiply(a: Matrix<T>, k: Number): BufferMatrix<T> {
val aBufferMatrix = a.toBufferMatrix() // val aBufferMatrix = a.toBufferMatrix()
return elementContext { // return elementContext {
produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() } // produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() }
} // }
} // }
public companion object public companion object
} }

View File

@ -1,10 +1,7 @@
package space.kscience.kmath.linear package space.kscience.kmath.linear
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.SpaceOperations
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.sum
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory
import space.kscience.kmath.structures.asSequence import space.kscience.kmath.structures.asSequence
@ -16,7 +13,7 @@ import kotlin.reflect.KClass
* @param T the type of items in the matrices. * @param T the type of items in the matrices.
* @param M the type of operated matrices. * @param M the type of operated matrices.
*/ */
public interface MatrixContext<T : Any, out M : Matrix<T>> : SpaceOperations<Matrix<T>> { public interface MatrixContext<T : Any, out M : Matrix<T>> : GroupOperations<Matrix<T>>, ScaleOperations<Matrix<T>> {
/** /**
* Produces a matrix with this context and given dimensions. * Produces a matrix with this context and given dimensions.
*/ */
@ -31,7 +28,7 @@ public interface MatrixContext<T : Any, out M : Matrix<T>> : SpaceOperations<Mat
public override fun binaryOperationFunction(operation: String): (left: Matrix<T>, right: Matrix<T>) -> M = public override fun binaryOperationFunction(operation: String): (left: Matrix<T>, right: Matrix<T>) -> M =
when (operation) { when (operation) {
"dot" -> { left, right -> left dot right } "dot" -> { left, right -> left dot right }
else -> super.binaryOperationFunction(operation) as (Matrix<T>, Matrix<T>) -> M else -> super<GroupOperations>.binaryOperationFunction(operation) as (Matrix<T>, Matrix<T>) -> M
} }
/** /**
@ -87,15 +84,15 @@ public interface MatrixContext<T : Any, out M : Matrix<T>> : SpaceOperations<Mat
/** /**
* A structured matrix with custom buffer * A structured matrix with custom buffer
*/ */
public fun <T : Any, R : Ring<T>> buffered( public fun <T : Any, A> buffered(
ring: R, ring: A,
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing, bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
): GenericMatrixContext<T, R, BufferMatrix<T>> = BufferMatrixContext(ring, bufferFactory) ): GenericMatrixContext<T, A, BufferMatrix<T>> where A : Ring<T>, A: ScaleOperations<T> = BufferMatrixContext(ring, bufferFactory)
/** /**
* Automatic buffered matrix, unboxed if it is possible * Automatic buffered matrix, unboxed if it is possible
*/ */
public inline fun <reified T : Any, R : Ring<T>> auto(ring: R): GenericMatrixContext<T, R, BufferMatrix<T>> = public inline fun <reified T : Any, A> auto(ring: A): GenericMatrixContext<T, A, BufferMatrix<T>> where A : Ring<T>, A: ScaleOperations<T> =
buffered(ring, Buffer.Companion::auto) buffered(ring, Buffer.Companion::auto)
} }
} }
@ -119,14 +116,14 @@ public inline fun <T : Any, reified F : Any> MatrixContext<T, *>.getFeature(m: M
* Partial implementation of [MatrixContext] for matrices of [Ring]. * Partial implementation of [MatrixContext] for matrices of [Ring].
* *
* @param T the type of items in the matrices. * @param T the type of items in the matrices.
* @param R the type of ring of matrix elements. * @param A the type of ring of matrix elements.
* @param M the type of operated matrices. * @param M the type of operated matrices.
*/ */
public interface GenericMatrixContext<T : Any, R : Ring<T>, out M : Matrix<T>> : MatrixContext<T, M> { public interface GenericMatrixContext<T : Any, A, out M : Matrix<T>> : MatrixContext<T, M> where A : Ring<T>, A : ScaleOperations<T>{
/** /**
* The ring over matrix elements. * The ring over matrix elements.
*/ */
public val elementContext: R public val elementContext: A
public override infix fun Matrix<T>.dot(other: Matrix<T>): M { public override infix fun Matrix<T>.dot(other: Matrix<T>): M {
//TODO add typed error //TODO add typed error
@ -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] } } return produce(rowNum, colNum) { i, j -> elementContext { get(i, j) + b[i, j] } }
} }
//
public override fun multiply(a: Matrix<T>, k: Number): M = // public override fun multiply(a: Matrix<T>, k: Number): M =
produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } } // produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } }
public override operator fun Matrix<T>.times(value: T): M = public override operator fun Matrix<T>.times(value: T): M =
produce(rowNum, colNum) { i, j -> elementContext { get(i, j) * value } } produce(rowNum, colNum) { i, j -> elementContext { get(i, j) * value } }

View File

@ -4,6 +4,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.nd.getFeature import space.kscience.kmath.nd.getFeature
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.asBuffer
import kotlin.math.sqrt import kotlin.math.sqrt
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -14,7 +15,7 @@ import kotlin.reflect.safeCast
* *
* @param T the type of items. * @param T the type of items.
*/ */
public class MatrixWrapper<T : Any> internal constructor( public class MatrixWrapper<T : Any> internal constructor(
public val origin: Matrix<T>, public val origin: Matrix<T>,
public val features: Set<MatrixFeature>, public val features: Set<MatrixFeature>,
) : Matrix<T> by origin { ) : Matrix<T> by origin {
@ -73,17 +74,23 @@ public fun <T : Any> Structure2D.Companion.square(vararg elements: T): Matrix<T>
/** /**
* Diagonal matrix of ones. The matrix is virtual no actual matrix is created * Diagonal matrix of ones. The matrix is virtual no actual matrix is created
*/ */
public fun <T : Any, R : Ring<T>> GenericMatrixContext<T, R, *>.one(rows: Int, columns: Int): Matrix<T> = public fun <T : Any, A> GenericMatrixContext<T, A, *>.one(
VirtualMatrix(rows, columns) { i, j -> rows: Int,
if (i == j) elementContext.one else elementContext.zero columns: Int,
} + UnitFeature ): Matrix<T> where A : Ring<T>, A : ScaleOperations<T> = VirtualMatrix(rows, columns) { i, j ->
if (i == j) elementContext.one else elementContext.zero
} + UnitFeature
/** /**
* A virtual matrix of zeroes * A virtual matrix of zeroes
*/ */
public fun <T : Any, R : Ring<T>> GenericMatrixContext<T, R, *>.zero(rows: Int, columns: Int): Matrix<T> = public fun <T : Any, A> GenericMatrixContext<T, A, *>.zero(
VirtualMatrix(rows, columns) { _, _ -> elementContext.zero } + ZeroFeature rows: Int,
columns: Int,
): Matrix<T> where A : Ring<T>, A : ScaleOperations<T> = VirtualMatrix(rows, columns) { _, _ ->
elementContext.zero
} + ZeroFeature
public class TransposedFeature<T : Any>(public val original: Matrix<T>) : MatrixFeature public class TransposedFeature<T : Any>(public val original: Matrix<T>) : MatrixFeature
@ -91,9 +98,7 @@ public class TransposedFeature<T : Any>(public val original: Matrix<T>) : Matrix
* Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A` * Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A`
*/ */
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public fun <T : Any> Matrix<T>.transpose(): Matrix<T> { public fun <T : Any> Matrix<T>.transpose(): Matrix<T> = getFeature<TransposedFeature<T>>()?.original ?: VirtualMatrix(
return getFeature<TransposedFeature<T>>()?.original ?: VirtualMatrix( colNum,
colNum, rowNum,
rowNum, ) { i, j -> get(j, i) } + TransposedFeature(this)
) { i, j -> get(j, i) } + TransposedFeature(this)
}

View File

@ -1,8 +1,9 @@
package space.kscience.kmath.linear package space.kscience.kmath.linear
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.RealBuffer
public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> { public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>>, ScaleOperations<Matrix<Double>> {
public override fun produce( public override fun produce(
rows: Int, rows: Int,
@ -21,6 +22,8 @@ public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
if (i == j) 1.0 else 0.0 if (i == j) 1.0 else 0.0
} + DiagonalFeature } + 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> { 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})" } require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
val bufferMatrix = toBufferMatrix() val bufferMatrix = toBufferMatrix()
@ -56,16 +59,23 @@ public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
} }
} }
override fun Matrix<Double>.times(value: Double): BufferMatrix<Double> { override fun scale(a: Matrix<Double>, value: Double): BufferMatrix<Double> {
val bufferMatrix = toBufferMatrix() val bufferMatrix = a.toBufferMatrix()
return produce(rowNum, colNum) { i, j -> bufferMatrix[i, j] * value } return produce(a.rowNum, a.colNum) { i, j -> bufferMatrix[i, j] * value }
} }
override fun Matrix<Double>.times(value: Double): BufferMatrix<Double> = scale(this, value)
override fun multiply(a: Matrix<Double>, k: Number): BufferMatrix<Double> { //
val aBufferMatrix = a.toBufferMatrix() // override fun multiply(a: Matrix<Double>, k: Number): BufferMatrix<Double> {
return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() } // 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() }
// }
} }

View File

@ -1,7 +1,8 @@
package space.kscience.kmath.linear package space.kscience.kmath.linear
import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.RealField
import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory
@ -10,21 +11,19 @@ import space.kscience.kmath.structures.BufferFactory
* A linear space for vectors. * A linear space for vectors.
* Could be used on any point-like structure * 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> : Group<Point<T>>, ScaleOperations<Point<T>>
where A : Group<T>, A : ScaleOperations<T> {
public val size: Int public val size: Int
public val space: S public val algebra: A
override val zero: Point<T> get() = produce { space.zero } 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>
/** override fun add(a: Point<T>, b: Point<T>): Point<T> = produce { algebra { a[it] + b[it] } }
* 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 { space { a[it] + b[it] } } override fun scale(a: Point<T>, value: Double): Point<T> = produce { algebra.scale(a[it], value) }
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 //TODO add basis
@ -45,26 +44,29 @@ public interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
/** /**
* A structured vector space with custom buffer * A structured vector space with custom buffer
*/ */
public fun <T : Any, S : Space<T>> buffered( public fun <T : Any, A> buffered(
size: Int, size: Int,
space: S, space: A,
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing, bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
): BufferVectorSpace<T, S> = BufferVectorSpace(size, space, bufferFactory) ): BufferVectorSpace<T, A> where A : Group<T>, A : ScaleOperations<T> =
BufferVectorSpace(size, space, bufferFactory)
/** /**
* Automatic buffered vector, unboxed if it is possible * 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> auto(
size: Int,
space: A,
): VectorSpace<T, A> where A : Group<T>, A : ScaleOperations<T> =
buffered(size, space, Buffer.Companion::auto) buffered(size, space, Buffer.Companion::auto)
} }
} }
public class BufferVectorSpace<T : Any, S : Space<T>>( public class BufferVectorSpace<T : Any, A>(
override val size: Int, override val size: Int,
override val space: S, override val algebra: A,
public val bufferFactory: BufferFactory<T>, public val bufferFactory: BufferFactory<T>,
) : VectorSpace<T, S> { ) : VectorSpace<T, A> where A : Group<T>, A : ScaleOperations<T> {
override fun produce(initializer: S.(Int) -> T): Buffer<T> = bufferFactory(size) { space.initializer(it) } override fun produce(initializer: A.(Int) -> T): Buffer<T> = bufferFactory(size) { algebra.initializer(it) }
//override fun produceElement(initializer: (Int) -> T): Vector<T, S> = BufferVector(this, produce(initializer))
} }

View File

@ -1,6 +1,6 @@
package space.kscience.kmath.misc package space.kscience.kmath.misc
import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
@ -37,7 +37,7 @@ public fun <T, R> List<T>.cumulative(initial: R, operation: (R, T) -> R): List<R
/** /**
* Cumulative sum with custom space * Cumulative sum with custom space
*/ */
public fun <T> Iterable<T>.cumulativeSum(space: Space<T>): Iterable<T> = public fun <T> Iterable<T>.cumulativeSum(space: Group<T>): Iterable<T> =
space { cumulative(zero) { element: T, sum: T -> sum + element } } space { cumulative(zero) { element: T, sum: T -> sum + element } }
@JvmName("cumulativeSumOfDouble") @JvmName("cumulativeSumOfDouble")
@ -49,7 +49,7 @@ public fun Iterable<Int>.cumulativeSum(): Iterable<Int> = cumulative(0) { elemen
@JvmName("cumulativeSumOfLong") @JvmName("cumulativeSumOfLong")
public fun Iterable<Long>.cumulativeSum(): Iterable<Long> = cumulative(0L) { element, sum -> sum + element } public fun Iterable<Long>.cumulativeSum(): Iterable<Long> = cumulative(0L) { element, sum -> sum + element }
public fun <T> Sequence<T>.cumulativeSum(space: Space<T>): Sequence<T> = public fun <T> Sequence<T>.cumulativeSum(space: Group<T>): Sequence<T> =
space { cumulative(zero) { element: T, sum: T -> sum + element } } space { cumulative(zero) { element: T, sum: T -> sum + element } }
@JvmName("cumulativeSumOfDouble") @JvmName("cumulativeSumOfDouble")
@ -61,7 +61,7 @@ public fun Sequence<Int>.cumulativeSum(): Sequence<Int> = cumulative(0) { elemen
@JvmName("cumulativeSumOfLong") @JvmName("cumulativeSumOfLong")
public fun Sequence<Long>.cumulativeSum(): Sequence<Long> = cumulative(0L) { element, sum -> sum + element } public fun Sequence<Long>.cumulativeSum(): Sequence<Long> = cumulative(0L) { element, sum -> sum + element }
public fun <T> List<T>.cumulativeSum(space: Space<T>): List<T> = public fun <T> List<T>.cumulativeSum(space: Group<T>): List<T> =
space { cumulative(zero) { element: T, sum: T -> sum + element } } space { cumulative(zero) { element: T, sum: T -> sum + element } }
@JvmName("cumulativeSumOfDouble") @JvmName("cumulativeSumOfDouble")

View File

@ -1,19 +1,16 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.RealField
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.Space
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract 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 strides: Strides
public val bufferFactory: BufferFactory<T> 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, strides,
bufferFactory(strides.linearSize) { offset -> bufferFactory(strides.linearSize) { offset ->
elementContext.initializer(strides.index(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)) } 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 -> val buffer = bufferFactory(strides.linearSize) { offset ->
elementContext.transform(buffer[offset]) elementContext.transform(buffer[offset])
} }
return NDBuffer(strides, buffer) 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 -> val buffer = bufferFactory(strides.linearSize) { offset ->
elementContext.transform( elementContext.transform(
strides.index(offset), strides.index(offset),
@ -47,7 +44,7 @@ public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
return NDBuffer(strides, buffer) 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 -> val buffer = bufferFactory(strides.linearSize) { offset ->
elementContext.transform(a.buffer[offset], b.buffer[offset]) elementContext.transform(a.buffer[offset], b.buffer[offset])
} }
@ -55,20 +52,21 @@ public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
} }
} }
public open class BufferedNDSpace<T, R : Space<T>>( public open class BufferedNDGroup<T, A : Group<T>>(
final override val shape: IntArray, final override val shape: IntArray,
final override val elementContext: R, final override val elementContext: A,
final override val bufferFactory: BufferFactory<T>, final override val bufferFactory: BufferFactory<T>,
) : NDSpace<T, R>, BufferNDAlgebra<T, R> { ) : NDGroup<T, A>, BufferNDAlgebra<T, A> {
override val strides: Strides = DefaultStrides(shape) override val strides: Strides = DefaultStrides(shape)
override val zero: NDBuffer<T> by lazy { produce { zero } } 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>>( public open class BufferedNDRing<T, R : Ring<T>>(
shape: IntArray, shape: IntArray,
elementContext: R, elementContext: R,
bufferFactory: BufferFactory<T>, bufferFactory: BufferFactory<T>,
) : BufferedNDSpace<T, R>(shape, elementContext, bufferFactory), NDRing<T, R> { ) : BufferedNDGroup<T, R>(shape, elementContext, bufferFactory), NDRing<T, R> {
override val one: NDBuffer<T> by lazy { produce { one } } override val one: NDBuffer<T> by lazy { produce { one } }
} }
@ -76,19 +74,22 @@ public open class BufferedNDField<T, R : Field<T>>(
shape: IntArray, shape: IntArray,
elementContext: R, elementContext: R,
bufferFactory: BufferFactory<T>, 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 // space factories
public fun <T, A : Space<T>> NDAlgebra.Companion.space( public fun <T, A : Group<T>> NDAlgebra.Companion.space(
space: A, space: A,
bufferFactory: BufferFactory<T>, bufferFactory: BufferFactory<T>,
vararg shape: Int, vararg shape: Int,
): BufferedNDSpace<T, A> = BufferedNDSpace(shape, space, bufferFactory) ): BufferedNDGroup<T, A> = BufferedNDGroup(shape, space, bufferFactory)
public inline fun <T, A : Space<T>, R> A.ndSpace( public inline fun <T, A : Group<T>, R> A.ndSpace(
noinline bufferFactory: BufferFactory<T>, noinline bufferFactory: BufferFactory<T>,
vararg shape: Int, vararg shape: Int,
action: BufferedNDSpace<T, A>.() -> R, action: BufferedNDGroup<T, A>.() -> R,
): R { ): R {
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
return NDAlgebra.space(this, bufferFactory, *shape).run(action) return NDAlgebra.space(this, bufferFactory, *shape).run(action)

View File

@ -1,8 +1,6 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.Space
import space.kscience.kmath.structures.* 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 C the type of the element context.
* @param N the type of the structure. * @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. * The shape of ND-structures this algebra operates on.
*/ */
@ -33,7 +31,7 @@ public interface NDAlgebra<T, C> {
public val elementContext: 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> public fun produce(initializer: C.(IntArray) -> T): NDStructure<T>
@ -56,7 +54,7 @@ public interface NDAlgebra<T, C> {
* Element-wise invocation of function working on [T] on a [NDStructure]. * Element-wise invocation of function working on [T] on a [NDStructure].
*/ */
public operator fun Function1<T, T>.invoke(structure: NDStructure<T>): NDStructure<T> = public operator fun Function1<T, T>.invoke(structure: NDStructure<T>): NDStructure<T> =
structure.map() { value -> this@invoke(value) } structure.map { value -> this@invoke(value) }
public companion object public companion object
} }
@ -67,7 +65,7 @@ public interface NDAlgebra<T, C> {
* @param structures the structures to check. * @param structures the structures to check.
* @return the array of valid structures. * @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) .map(NDStructure<T>::shape)
.singleOrNull { !shape.contentEquals(it) } .singleOrNull { !shape.contentEquals(it) }
?.let<IntArray, Array<out NDStructure<T>>> { throw ShapeMismatchException(shape, 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. * @param element the structure to check.
* @return the valid structure. * @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) if (!element.shape.contentEquals(shape)) throw ShapeMismatchException(shape, element.shape)
return element return element
} }
@ -91,7 +89,7 @@ internal fun <T, C> NDAlgebra<T, C>.checkShape(element: NDStructure<T>): NDStruc
* @param N the type of ND structure. * @param N the type of ND structure.
* @param S the type of space of structure elements. * @param S the type of space of structure elements.
*/ */
public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T, S> { public interface NDGroup<T, S : Group<T>> : Group<NDStructure<T>>, NDAlgebra<T, S> {
/** /**
* Element-wise addition. * Element-wise addition.
* *
@ -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> = public override fun add(a: NDStructure<T>, b: NDStructure<T>): NDStructure<T> =
combine(a, b) { aValue, bValue -> add(aValue, bValue) } combine(a, b) { aValue, bValue -> add(aValue, bValue) }
/** // /**
* Element-wise multiplication by scalar. // * Element-wise multiplication by scalar.
* // *
* @param a the multiplicand. // * @param a the multiplicand.
* @param k the multiplier. // * @param k the multiplier.
* @return the product. // * @return the product.
*/ // */
public override fun multiply(a: NDStructure<T>, k: Number): NDStructure<T> = a.map() { multiply(it, k) } // public override fun multiply(a: NDStructure<T>, k: Number): NDStructure<T> = a.map { multiply(it, k) }
// TODO move to extensions after KEEP-176 // 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. * @param arg the augend.
* @return the sum. * @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. * Subtracts an element from ND structure of it.
@ -129,7 +127,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
public operator fun NDStructure<T>.minus(arg: T): NDStructure<T> = this.map() { value -> add(arg, -value) } public operator fun NDStructure<T>.minus(arg: T): NDStructure<T> = this.map { value -> add(arg, -value) }
/** /**
* Adds an element to ND structure of it. * Adds an element to ND structure of it.
@ -138,7 +136,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
* @param arg the augend. * @param arg the augend.
* @return the sum. * @return the sum.
*/ */
public operator fun T.plus(arg: NDStructure<T>): NDStructure<T> = arg.map() { value -> add(this@plus, value) } public operator fun T.plus(arg: NDStructure<T>): NDStructure<T> = arg.map { value -> add(this@plus, value) }
/** /**
* Subtracts an ND structure from an element of it. * Subtracts an ND structure from an element of it.
@ -147,7 +145,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
public operator fun T.minus(arg: NDStructure<T>): NDStructure<T> = arg.map() { value -> add(-this@minus, value) } public operator fun T.minus(arg: NDStructure<T>): NDStructure<T> = arg.map { value -> add(-this@minus, value) }
public companion object public companion object
} }
@ -159,7 +157,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
* @param N the type of ND structure. * @param N the type of ND structure.
* @param R the type of ring of structure elements. * @param R the type of ring of structure elements.
*/ */
public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDSpace<T, R> { public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDGroup<T, R> {
/** /**
* Element-wise multiplication. * Element-wise multiplication.
* *
@ -179,7 +177,7 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDSpace<T, R> {
* @param arg the multiplier. * @param arg the multiplier.
* @return the product. * @return the product.
*/ */
public operator fun NDStructure<T>.times(arg: T): NDStructure<T> = this.map() { value -> multiply(arg, value) } public operator fun NDStructure<T>.times(arg: T): NDStructure<T> = this.map { value -> multiply(arg, value) }
/** /**
* Multiplies an element by a ND structure of it. * Multiplies an element by a ND structure of it.
@ -188,7 +186,7 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDSpace<T, R> {
* @param arg the multiplier. * @param arg the multiplier.
* @return the product. * @return the product.
*/ */
public operator fun T.times(arg: NDStructure<T>): NDStructure<T> = arg.map() { value -> multiply(this@times, value) } public operator fun T.times(arg: NDStructure<T>): NDStructure<T> = arg.map { value -> multiply(this@times, value) }
public companion object public companion object
} }
@ -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 N the type of ND structure.
* @param F the type field of structure elements. * @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. * Element-wise division.
* *
@ -219,7 +217,7 @@ public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F>
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
public operator fun NDStructure<T>.div(arg: T): NDStructure<T> = this.map() { value -> divide(arg, value) } public operator fun NDStructure<T>.div(arg: T): NDStructure<T> = this.map { value -> divide(arg, value) }
/** /**
* Divides an element by an ND structure of it. * Divides an element by an ND structure of it.
@ -228,7 +226,7 @@ public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F>
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
public operator fun T.div(arg: NDStructure<T>): NDStructure<T> = arg.map() { divide(it, this@div) } public operator fun T.div(arg: NDStructure<T>): NDStructure<T> = arg.map { divide(it, this@div) }
// @ThreadLocal // @ThreadLocal
// public companion object { // public companion object {

View File

@ -2,8 +2,9 @@ package space.kscience.kmath.nd
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.NumbersAddOperations
import space.kscience.kmath.operations.RealField 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.Buffer
import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.RealBuffer
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
@ -13,7 +14,8 @@ import kotlin.contracts.contract
public class RealNDField( public class RealNDField(
shape: IntArray, shape: IntArray,
) : BufferedNDField<Double, RealField>(shape, RealField, Buffer.Companion::real), ) : BufferedNDField<Double, RealField>(shape, RealField, Buffer.Companion::real),
RingWithNumbers<NDStructure<Double>>, NumbersAddOperations<NDStructure<Double>>,
ScaleOperations<NDStructure<Double>>,
ExtendedField<NDStructure<Double>> { ExtendedField<NDStructure<Double>> {
override val zero: NDBuffer<Double> by lazy { produce { zero } } override val zero: NDBuffer<Double> by lazy { produce { zero } }
@ -75,6 +77,8 @@ public class RealNDField(
return NDBuffer(strides, buffer) 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 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) } override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { exp(it) }

View File

@ -1,7 +1,7 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.kmath.misc.UnstableKMathAPI 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.operations.ShortRing
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.ShortBuffer import space.kscience.kmath.structures.ShortBuffer
@ -12,7 +12,7 @@ import kotlin.contracts.contract
public class ShortNDRing( public class ShortNDRing(
shape: IntArray, shape: IntArray,
) : BufferedNDRing<Short, ShortRing>(shape, ShortRing, Buffer.Companion::auto), ) : 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 zero: NDBuffer<Short> by lazy { produce { zero } }
override val one: NDBuffer<Short> by lazy { produce { one } } override val one: NDBuffer<Short> by lazy { produce { one } }

View File

@ -87,10 +87,11 @@ public interface Algebra<T> {
* @param right the second argument of operation. * @param right the second argument of operation.
* @return a result 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. * Call a block with an [Algebra] as receiver.
@ -104,7 +105,7 @@ public inline operator fun <A : Algebra<*>, R> A.invoke(block: A.() -> R): R = r
* *
* @param T the type of element of this semispace. * @param T the type of element of this semispace.
*/ */
public interface SpaceOperations<T> : Algebra<T> { public interface GroupOperations<T> : Algebra<T> {
/** /**
* Addition of two elements. * Addition of two elements.
* *
@ -114,15 +115,6 @@ public interface SpaceOperations<T> : Algebra<T> {
*/ */
public fun add(a: T, b: T): 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 // 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. * @receiver this value.
* @return the additive inverse of 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. * Returns this value.
@ -159,34 +151,6 @@ public interface SpaceOperations<T> : Algebra<T> {
*/ */
public operator fun T.minus(b: T): T = add(this, -b) 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) { public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) {
PLUS_OPERATION -> { arg -> +arg } PLUS_OPERATION -> { arg -> +arg }
MINUS_OPERATION -> { arg -> -arg } MINUS_OPERATION -> { arg -> -arg }
@ -213,12 +177,11 @@ public interface SpaceOperations<T> : Algebra<T> {
} }
/** /**
* Represents linear space with neutral element, i.e. algebraic structure with associative, binary operation [add] and * Represents linear space with neutral element, i.e. algebraic structure with associative, binary operation [add].
* scalar multiplication [multiply].
* *
* @param T the type of element of this semispace. * @param T the type of element of this semispace.
*/ */
public interface Space<T> : SpaceOperations<T> { public interface Group<T> : GroupOperations<T> {
/** /**
* The neutral element of addition. * The neutral element of addition.
*/ */
@ -231,7 +194,7 @@ public interface Space<T> : SpaceOperations<T> {
* *
* @param T the type of element of this semiring. * @param T the type of element of this semiring.
*/ */
public interface RingOperations<T> : SpaceOperations<T> { public interface RingOperations<T> : GroupOperations<T> {
/** /**
* Multiplies two elements. * Multiplies two elements.
* *
@ -267,7 +230,7 @@ public interface RingOperations<T> : SpaceOperations<T> {
* *
* @param T the type of element of this ring. * @param T the type of element of this ring.
*/ */
public interface Ring<T> : Space<T>, RingOperations<T> { public interface Ring<T> : Group<T>, RingOperations<T> {
/** /**
* neutral operation for multiplication * neutral operation for multiplication
*/ */
@ -318,13 +281,6 @@ public interface FieldOperations<T> : RingOperations<T> {
* *
* @param T the type of element of this semifield. * @param T the type of element of this semifield.
*/ */
public interface Field<T> : Ring<T>, FieldOperations<T> { public interface Field<T> : Ring<T>, FieldOperations<T>, ScaleOperations<T>, NumericAlgebra<T> {
/** override fun number(value: Number): T = scale(one, value.toDouble())
* 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)
}

View File

@ -14,24 +14,24 @@ public interface AlgebraElement<T, C : Algebra<T>> {
*/ */
public val context: C public val context: C
} }
//
/** ///**
* Divides this element by number. // * Divides this element by number.
* // *
* @param k the divisor. // * @param k the divisor.
* @return the quotient. // * @return the quotient.
*/ // */
public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.div(k: Number): T = //public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.div(k: Number): T =
context.multiply(this, 1.0 / k.toDouble()) // context.multiply(this, 1.0 / k.toDouble())
//
/** ///**
* Multiplies this element by number. // * Multiplies this element by number.
* // *
* @param k the multiplicand. // * @param k the multiplicand.
* @return the product. // * @return the product.
*/ // */
public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.times(k: Number): T = //public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.times(k: Number): T =
context.multiply(this, k.toDouble()) // context.multiply(this, k.toDouble())
/** /**
* Subtracts element from this one. * 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. * @param b the subtrahend.
* @return the difference. * @return the difference.
*/ */
public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.minus(b: T): T = @UnstableKMathAPI
context.add(this, context.multiply(b, -1.0)) 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. * Adds element to this one.
@ -48,14 +49,14 @@ public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.minus(b: T): T =
* @param b the augend. * @param b the augend.
* @return the sum. * @return the sum.
*/ */
public operator fun <T : AlgebraElement<T, S>, S : Space<T>> T.plus(b: T): T = public operator fun <T : AlgebraElement<T, S>, S : Group<T>> T.plus(b: T): T =
context.add(this, b) context.add(this, b)
/** ///**
* Number times element // * Number times element
*/ // */
public operator fun <T : AlgebraElement<T, S>, S : Space<T>> Number.times(element: T): T = //public operator fun <T : AlgebraElement<T, S>, S : Space<T>> Number.times(element: T): T =
element.times(this) // element.times(this)
/** /**
@ -79,14 +80,14 @@ public operator fun <T : AlgebraElement<T, F>, F : Field<T>> T.div(b: T): T =
/** /**
* The element of [Space]. * The element of [Group].
* *
* @param T the type of space operation results. * @param T the type of space operation results.
* @param I self type of the element. Needed for static type checking. * @param I self type of the element. Needed for static type checking.
* @param S the type of space. * @param S the type of space.
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public interface SpaceElement<T : SpaceElement<T, S>, S : Space<T>> : AlgebraElement<T, S> public interface SpaceElement<T : SpaceElement<T, S>, S : Group<T>> : AlgebraElement<T, S>
/** /**
* The element of [Ring]. * The element of [Ring].

View File

@ -21,29 +21,28 @@ public typealias TBase = ULong
* @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai) * @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai)
*/ */
@OptIn(UnstableKMathAPI::class) @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 zero: BigInt = BigInt.ZERO
override val one: BigInt = BigInt.ONE 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 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 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.unaryPlus(): BigInt = this.parseBigInteger() ?: error("Can't parse $this as big integer")
public operator fun String.unaryMinus(): BigInt = public operator fun String.unaryMinus(): BigInt =
-(this.parseBigInteger() ?: error("Can't parse $this as big integer")) -(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( public class BigInt internal constructor(
private val sign: Byte, private val sign: Byte,
private val magnitude: Magnitude private val magnitude: Magnitude,
) : Comparable<BigInt> { ) : Comparable<BigInt> {
public override fun compareTo(other: BigInt): Int = when { public override fun compareTo(other: BigInt): Int = when {
(sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0 (sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0
sign < other.sign -> -1 sign < other.sign -> -1

View File

@ -81,14 +81,53 @@ public interface NumericAlgebra<T> : Algebra<T> {
rightSideNumberOperationFunction(operation)(left, right) rightSideNumberOperationFunction(operation)(left, right)
} }
/**
* Scale by scalar operations
*/
public interface ScaleOperations<T> : Algebra<T> {
/**
* Scaling an element by a 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` * 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 * TODO to be removed and replaced by extensions after multiple receivers are there
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public interface RingWithNumbers<T>: Ring<T>, NumericAlgebra<T>{ public interface NumbersAddOperations<T> : Group<T>, NumericAlgebra<T> {
public override fun number(value: Number): T = one * value
/** /**
* Addition of element and scalar. * Addition of element and scalar.
* *

View File

@ -107,111 +107,6 @@ public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> acos(arg: T):
@UnstableKMathAPI @UnstableKMathAPI
public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> atan(arg: T): T = arg.context.atan(arg) public fun <T : AlgebraElement<T, out TrigonometricOperations<T>>> atan(arg: T): T = arg.context.atan(arg)
/**
* 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. * 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 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 { public companion object {
/** /**
* The identifier of exponential function. * The identifier of exponential function.
@ -294,6 +219,36 @@ public interface ExponentialOperations<T> : Algebra<T> {
* The identifier of natural logarithm. * The identifier of natural logarithm.
*/ */
public const val LN_OPERATION: String = "ln" 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 @UnstableKMathAPI
public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> ln(arg: T): T = arg.context.ln(arg) public fun <T : AlgebraElement<T, out ExponentialOperations<T>>> ln(arg: T): T = arg.context.ln(arg)
/**
* 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. * A container for norm functional on element.
* *

View File

@ -1,47 +1,49 @@
package space.kscience.kmath.operations package space.kscience.kmath.operations
/** /**
* Returns the sum of all elements in the iterable in this [Space]. * Returns the sum of all elements in the iterable in this [Group].
* *
* @receiver the algebra that provides addition. * @receiver the algebra that provides addition.
* @param data the iterable to sum up. * @param data the iterable to sum up.
* @return the sum. * @return the sum.
*/ */
public fun <T> Space<T>.sum(data: Iterable<T>): T = data.fold(zero) { left, right -> add(left, right) } public fun <T> Group<T>.sum(data: Iterable<T>): T = data.fold(zero) { left, right -> add(left, right) }
/** /**
* Returns the sum of all elements in the sequence in this [Space]. * Returns the sum of all elements in the sequence in this [Group].
* *
* @receiver the algebra that provides addition. * @receiver the algebra that provides addition.
* @param data the sequence to sum up. * @param data the sequence to sum up.
* @return the sum. * @return the sum.
*/ */
public fun <T> Space<T>.sum(data: Sequence<T>): T = data.fold(zero) { left, right -> add(left, right) } public fun <T> Group<T>.sum(data: Sequence<T>): T = data.fold(zero) { left, right -> add(left, right) }
/** /**
* Returns an average value of elements in the iterable in this [Space]. * Returns an average value of elements in the iterable in this [Group].
* *
* @receiver the algebra that provides addition and division. * @receiver the algebra that provides addition and division.
* @param data the iterable to find average. * @param data the iterable to find average.
* @return the average value. * @return the average value.
* @author Iaroslav Postovalov * @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 : Group<T>, S : ScaleOperations<T> =
sum(data) / data.count()
/** /**
* Returns an average value of elements in the sequence in this [Space]. * Returns an average value of elements in the sequence in this [Group].
* *
* @receiver the algebra that provides addition and division. * @receiver the algebra that provides addition and division.
* @param data the sequence to find average. * @param data the sequence to find average.
* @return the average value. * @return the average value.
* @author Iaroslav Postovalov * @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 : Group<T>, S : ScaleOperations<T> =
sum(data) / data.count()
/** /**
* Absolute of the comparable [value] * Absolute of the comparable [value]
*/ */
public fun <T : Comparable<T>> Space<T>.abs(value: T): T = if (value > zero) value else -value public fun <T : Comparable<T>> Group<T>.abs(value: T): T = if (value > zero) value else -value
/** /**
* Returns the sum of all elements in the iterable in provided space. * Returns the sum of all elements in the iterable in provided space.
@ -50,7 +52,7 @@ public fun <T : Comparable<T>> Space<T>.abs(value: T): T = if (value > zero) val
* @param space the algebra that provides addition. * @param space the algebra that provides addition.
* @return the sum. * @return the sum.
*/ */
public fun <T> Iterable<T>.sumWith(space: Space<T>): T = space.sum(this) public fun <T> Iterable<T>.sumWith(space: Group<T>): T = space.sum(this)
/** /**
* Returns the sum of all elements in the sequence in provided space. * Returns the sum of all elements in the sequence in provided space.
@ -59,27 +61,29 @@ public fun <T> Iterable<T>.sumWith(space: Space<T>): T = space.sum(this)
* @param space the algebra that provides addition. * @param space the algebra that provides addition.
* @return the sum. * @return the sum.
*/ */
public fun <T> Sequence<T>.sumWith(space: Space<T>): T = space.sum(this) public fun <T> Sequence<T>.sumWith(space: Group<T>): T = space.sum(this)
/** /**
* Returns an average value of elements in the iterable in this [Space]. * Returns an average value of elements in the iterable in this [Group].
* *
* @receiver the iterable to find average. * @receiver the iterable to find average.
* @param space the algebra that provides addition and division. * @param space the algebra that provides addition and division.
* @return the average value. * @return the average value.
* @author Iaroslav Postovalov * @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 : Group<T>, S : ScaleOperations<T> =
space.average(this)
/** /**
* Returns an average value of elements in the sequence in this [Space]. * Returns an average value of elements in the sequence in this [Group].
* *
* @receiver the sequence to find average. * @receiver the sequence to find average.
* @param space the algebra that provides addition and division. * @param space the algebra that provides addition and division.
* @return the average value. * @return the average value.
* @author Iaroslav Postovalov * @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 : Group<T>, S : ScaleOperations<T> =
space.average(this)
//TODO optimized power operation //TODO optimized power operation

View File

@ -8,7 +8,6 @@ import kotlin.math.pow as kpow
public interface ExtendedFieldOperations<T> : public interface ExtendedFieldOperations<T> :
FieldOperations<T>, FieldOperations<T>,
TrigonometricOperations<T>, TrigonometricOperations<T>,
HyperbolicOperations<T>,
PowerOperations<T>, PowerOperations<T>,
ExponentialOperations<T> { ExponentialOperations<T> {
public override fun tan(arg: T): T = sin(arg) / cos(arg) public override fun tan(arg: T): T = sin(arg) / cos(arg)
@ -21,15 +20,15 @@ public interface ExtendedFieldOperations<T> :
TrigonometricOperations.ACOS_OPERATION -> ::acos TrigonometricOperations.ACOS_OPERATION -> ::acos
TrigonometricOperations.ASIN_OPERATION -> ::asin TrigonometricOperations.ASIN_OPERATION -> ::asin
TrigonometricOperations.ATAN_OPERATION -> ::atan 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 PowerOperations.SQRT_OPERATION -> ::sqrt
ExponentialOperations.EXP_OPERATION -> ::exp ExponentialOperations.EXP_OPERATION -> ::exp
ExponentialOperations.LN_OPERATION -> ::ln 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) else -> super<FieldOperations>.unaryOperationFunction(operation)
} }
} }
@ -37,18 +36,18 @@ public interface ExtendedFieldOperations<T> :
/** /**
* Advanced Number-like field that implements basic operations. * Advanced Number-like field that implements basic operations.
*/ */
public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T>, NumericAlgebra<T> { public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T>, NumericAlgebra<T>, ScaleOperations<T> {
public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2 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 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 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 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 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 = public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T =
when (operation) { when (operation) {
PowerOperations.POW_OPERATION -> ::power 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. * A field for [Double] without boxing. Does not produce appropriate field element.
*/ */
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
public object RealField : ExtendedField<Double>, Norm<Double, Double> { public object RealField : ExtendedField<Double>, Norm<Double, Double>, ScaleOperations<Double> {
public override val zero: Double public override val zero: Double = 0.0
get() = 0.0 public override val one: Double = 1.0
public override val one: Double
get() = 1.0
override fun number(value: Number): Double = value.toDouble() override fun number(value: Number): Double = value.toDouble()
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double = public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
when (operation) { when (operation) {
PowerOperations.POW_OPERATION -> ::power 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 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 multiply(a: Double, b: Double): Double = a * b
public override inline fun divide(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 sin(arg: Double): Double = kotlin.math.sin(arg)
public override inline fun cos(arg: Double): Double = kotlin.math.cos(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) 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") @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
public object FloatField : ExtendedField<Float>, Norm<Float, Float> { public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
public override val zero: Float public override val zero: Float = 0.0f
get() = 0.0f public override val one: Float = 1.0f
public override val one: Float
get() = 1.0f
override fun number(value: Number): Float = value.toFloat() 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 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 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 get() = 1
override fun number(value: Number): Int = value.toInt() override fun number(value: Number): Int = value.toInt()
public override inline fun add(a: Int, b: Int): Int = a + b 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 multiply(a: Int, b: Int): Int = a * b
public override inline fun norm(arg: Int): Int = abs(arg) public override inline fun norm(arg: Int): Int = abs(arg)
public override inline fun Int.unaryMinus(): Int = -this public override inline fun Int.unaryMinus(): Int = -this
@ -196,12 +187,8 @@ public object ShortRing : Ring<Short>, Norm<Short, Short>, NumericAlgebra<Short>
get() = 1 get() = 1
override fun number(value: Number): Short = value.toShort() 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 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 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 fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort()
public override inline fun Short.unaryMinus(): Short = (-this).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 get() = 1
override fun number(value: Number): Byte = value.toByte() 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 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 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 fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte()
public override inline fun Byte.unaryMinus(): Byte = (-this).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 get() = 1L
override fun number(value: Number): Long = value.toLong() override fun number(value: Number): Long = value.toLong()
public override inline fun add(a: Long, b: Long): Long = a + b 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 inline fun multiply(a: Long, b: Long): Long = a * b
public override fun norm(arg: Long): Long = abs(arg) public override fun norm(arg: Long): Long = abs(arg)
public override inline fun Long.unaryMinus(): Long = (-this) public override inline fun Long.unaryMinus(): Long = (-this)

View File

@ -8,6 +8,12 @@ import kotlin.math.*
* [ExtendedFieldOperations] over [RealBuffer]. * [ExtendedFieldOperations] over [RealBuffer].
*/ */
public object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> { 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 { public override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
require(b.size == a.size) { require(b.size == a.size) {
"The size of the first buffer ${a.size} should be the same as for second one: ${b.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] }) RealBuffer(DoubleArray(a.size) { aArray[it] + bArray[it] })
} else RealBuffer(DoubleArray(a.size) { a[it] + b[it] }) } else RealBuffer(DoubleArray(a.size) { a[it] + b[it] })
} }
//
public override fun multiply(a: Buffer<Double>, k: Number): RealBuffer { // public override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
val kValue = k.toDouble() // val kValue = k.toDouble()
//
return if (a is RealBuffer) { // return if (a is RealBuffer) {
val aArray = a.array // val aArray = a.array
RealBuffer(DoubleArray(a.size) { aArray[it] * kValue }) // RealBuffer(DoubleArray(a.size) { aArray[it] * kValue })
} else RealBuffer(DoubleArray(a.size) { a[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 { public override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
require(b.size == a.size) { 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 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 { 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" } require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
return RealBufferFieldOperations.add(a, b) 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" } 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 { public override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {

View File

@ -11,9 +11,7 @@ class ExpressionFieldTest {
@Test @Test
fun testExpression() { fun testExpression() {
val context = FunctionalExpressionField(RealField) val expression = FunctionalExpressionField(RealField).invoke {
val expression = context {
val x by binding() val x by binding()
x * x + 2 * x + one x * x + 2 * x + one
} }

View File

@ -5,8 +5,9 @@ import space.kscience.kmath.operations.invoke
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotEquals import kotlin.test.assertNotEquals
internal class FieldVerifier<T>(override val algebra: Field<T>, a: T, b: T, c: T, x: Number) : internal class FieldVerifier<T, A : Field<T>>(
RingVerifier<T>(algebra, a, b, c, x) { algebra: A, a: T, b: T, c: T, x: Number,
) : RingVerifier<T, A>(algebra, a, b, c, x) {
override fun verify() { override fun verify() {
super.verify() super.verify()

View File

@ -1,11 +1,13 @@
package space.kscience.kmath.testutils package space.kscience.kmath.testutils
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal open class RingVerifier<T>(override val algebra: Ring<T>, a: T, b: T, c: T, x: Number) : internal open class RingVerifier<T, A>(algebra: A, a: T, b: T, c: T, x: Number) :
SpaceVerifier<T>(algebra, a, b, c, x) { SpaceVerifier<T, A>(algebra, a, b, c, x) where A : Ring<T>, A : ScaleOperations<T> {
override fun verify() { override fun verify() {
super.verify() super.verify()

View File

@ -1,18 +1,18 @@
package space.kscience.kmath.testutils package space.kscience.kmath.testutils
import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotEquals import kotlin.test.assertNotEquals
internal open class SpaceVerifier<T>( internal open class SpaceVerifier<T, out S>(
override val algebra: Space<T>, override val algebra: S,
val a: T, val a: T,
val b: T, val b: T,
val c: T, val c: T,
val x: Number val x: Number,
) : ) : AlgebraicVerifier<T, Group<T>> where S : Group<T>, S : ScaleOperations<T> {
AlgebraicVerifier<T, Space<T>> {
override fun verify() { override fun verify() {
algebra { algebra {
assertEquals(a + b + c, a + (b + c), "Addition in $algebra is not associative.") assertEquals(a + b + c, a + (b + c), "Addition in $algebra is not associative.")

View File

@ -7,19 +7,16 @@ import java.math.MathContext
/** /**
* A field over [BigInteger]. * A field over [BigInteger].
*/ */
public object JBigIntegerField : Field<BigInteger>, NumericAlgebra<BigInteger> { public object JBigIntegerField : Ring<BigInteger>, NumericAlgebra<BigInteger> {
public override val zero: BigInteger public override val zero: BigInteger get() = BigInteger.ZERO
get() = BigInteger.ZERO
public override val one: BigInteger public override val one: BigInteger get() = BigInteger.ONE
get() = BigInteger.ONE
public override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong()) 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 fun add(a: BigInteger, b: BigInteger): BigInteger = a.add(b)
public override operator fun BigInteger.minus(b: BigInteger): BigInteger = subtract(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 fun multiply(a: BigInteger, b: BigInteger): BigInteger = a.multiply(b)
public override operator fun BigInteger.unaryMinus(): BigInteger = negate() 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( public abstract class JBigDecimalFieldBase internal constructor(
private val mathContext: MathContext = MathContext.DECIMAL64, 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 public override val zero: BigDecimal
get() = BigDecimal.ZERO 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 operator fun BigDecimal.minus(b: BigDecimal): BigDecimal = subtract(b)
public override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble()) public override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble())
public override fun multiply(a: BigDecimal, k: Number): BigDecimal = public override fun scale(a: BigDecimal, value: Double): BigDecimal =
a.multiply(k.toDouble().toBigDecimal(mathContext), mathContext) a.multiply(value.toBigDecimal(mathContext), mathContext)
public override fun multiply(a: BigDecimal, b: BigDecimal): BigDecimal = a.multiply(b, 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) public override fun divide(a: BigDecimal, b: BigDecimal): BigDecimal = a.divide(b, mathContext)

View File

@ -5,16 +5,16 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.runningReduce import kotlinx.coroutines.flow.runningReduce
import kotlinx.coroutines.flow.scan import kotlinx.coroutines.flow.scan
import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.SpaceOperations import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
@ExperimentalCoroutinesApi public fun <T> Flow<T>.cumulativeSum(group: GroupOperations<T>): Flow<T> =
public fun <T> Flow<T>.cumulativeSum(space: SpaceOperations<T>): Flow<T> = group { runningReduce { sum, element -> sum + element } }
space { runningReduce { sum, element -> sum + element } }
@ExperimentalCoroutinesApi @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 : Group<T>, S : ScaleOperations<T> = algebra {
data class Accumulator(var sum: T, var num: Int) data class Accumulator(var sum: T, var num: Int)
scan(Accumulator(zero, 0)) { sum, element -> scan(Accumulator(zero, 0)) { sum, element ->

View File

@ -4,13 +4,14 @@ import org.ejml.simple.SimpleMatrix
import space.kscience.kmath.linear.* import space.kscience.kmath.linear.*
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.getFeature import space.kscience.kmath.nd.getFeature
import space.kscience.kmath.operations.ScaleOperations
/** /**
* Represents context of basic operations operating with [EjmlMatrix]. * Represents context of basic operations operating with [EjmlMatrix].
* *
* @author Iaroslav Postovalov * @author Iaroslav Postovalov
*/ */
public object EjmlMatrixContext : MatrixContext<Double, EjmlMatrix> { public object EjmlMatrixContext : MatrixContext<Double, EjmlMatrix>, ScaleOperations<Matrix<Double>> {
/** /**
* Converts this matrix to EJML one. * 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) } (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 = public override fun Matrix<Double>.dot(other: Matrix<Double>): EjmlMatrix =
EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) 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 = public override operator fun Matrix<Double>.minus(b: Matrix<Double>): EjmlMatrix =
EjmlMatrix(toEjml().origin - b.toEjml().origin) EjmlMatrix(toEjml().origin - b.toEjml().origin)
public override fun multiply(a: Matrix<Double>, k: Number): EjmlMatrix = public override fun scale(a: Matrix<Double>, value: Double): EjmlMatrix =
produce(a.rowNum, a.colNum) { i, j -> a[i, j] * k.toDouble() } produce(a.rowNum, a.colNum) { i, j -> a[i, j] * value }
public override operator fun Matrix<Double>.times(value: Double): EjmlMatrix = public override operator fun Matrix<Double>.times(value: Double): EjmlMatrix =
EjmlMatrix(toEjml().origin.scale(value)) EjmlMatrix(toEjml().origin.scale(value))

View File

@ -1,7 +1,8 @@
package space.kscience.kmath.functions package space.kscience.kmath.functions
import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
@ -41,9 +42,15 @@ public fun <T : Any, C : Ring<T>> Polynomial<T>.asFunction(ring: C): (T) -> T =
/** /**
* An algebra for polynomials * 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,
) : Group<Polynomial<T>>, ScaleOperations<Polynomial<T>> where C : Ring<T>, C : ScaleOperations<T> {
public override val zero: Polynomial<T> = Polynomial(emptyList()) 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> { public override fun add(a: Polynomial<T>, b: Polynomial<T>): Polynomial<T> {
val dim = max(a.coefficients.size, b.coefficients.size) 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> = public override fun scale(a: Polynomial<T>, value: Double): Polynomial<T> =
ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * k }) } ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) }
public operator fun Polynomial<T>.invoke(arg: T): T = value(ring, arg) 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) } contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return PolynomialSpace(this).block() return PolynomialSpace(this).block()
} }

View File

@ -13,7 +13,7 @@ import space.kscience.kmath.structures.MutableBufferFactory
*/ */
public class SplineInterpolator<T : Comparable<T>>( public class SplineInterpolator<T : Comparable<T>>(
public override val algebra: Field<T>, public override val algebra: Field<T>,
public val bufferFactory: MutableBufferFactory<T> public val bufferFactory: MutableBufferFactory<T>,
) : PolynomialInterpolator<T> { ) : PolynomialInterpolator<T> {
//TODO possibly optimize zeroed buffers //TODO possibly optimize zeroed buffers

View File

@ -2,6 +2,7 @@ package space.kscience.kmath.geometry
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.SpaceElement
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import kotlin.math.sqrt import kotlin.math.sqrt
@ -30,18 +31,20 @@ public fun Vector2D(x: Double, y: Double): Vector2D = Vector2DImpl(x, y)
private data class Vector2DImpl( private data class Vector2DImpl(
override val x: Double, override val x: Double,
override val y: Double override val y: Double,
) : Vector2D ) : Vector2D
/** /**
* 2D Euclidean space * 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 override val zero: Vector2D by lazy { Vector2D(0.0, 0.0) }
public fun Vector2D.norm(): Double = sqrt(x * x + y * y) 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 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 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 public override fun Vector2D.dot(other: Vector2D): Double = x * other.x + y * other.y
} }

View File

@ -2,6 +2,7 @@ package space.kscience.kmath.geometry
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.SpaceElement
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import kotlin.math.sqrt import kotlin.math.sqrt
@ -32,21 +33,22 @@ public val Vector3D.r: Double get() = Euclidean3DSpace { sqrt(norm()) }
private data class Vector3DImpl( private data class Vector3DImpl(
override val x: Double, override val x: Double,
override val y: Double, override val y: Double,
override val z: Double override val z: Double,
) : Vector3D ) : 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 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) 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 Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm()
public override fun add(a: Vector3D, b: Vector3D): Vector3D = public override fun add(a: Vector3D, b: Vector3D): Vector3D =
Vector3D(a.x + b.x, a.y + b.y, a.z + b.z) Vector3D(a.x + b.x, a.y + b.y, a.z + b.z)
public override fun multiply(a: Vector3D, k: Number): Vector3D = public override fun scale(a: Vector3D, value: Double): Vector3D =
Vector3D(a.x * k.toDouble(), a.y * k.toDouble(), a.z * k.toDouble()) Vector3D(a.x * value, a.y * value, a.z * value)
public override fun Vector3D.dot(other: Vector3D): Double = public override fun Vector3D.dot(other: Vector3D): Double =
x * other.x + y * other.y + z * other.z x * other.x + y * other.y + z * other.z

View File

@ -1,10 +1,11 @@
package space.kscience.kmath.geometry package space.kscience.kmath.geometry
import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.ScaleOperations
public interface Vector public interface Vector
public interface GeometrySpace<V : Vector> : Space<V> { public interface GeometrySpace<V : Vector> : Group<V>, ScaleOperations<V> {
/** /**
* L2 distance * L2 distance
*/ */

View File

@ -2,8 +2,8 @@ package space.kscience.kmath.histogram
import kotlinx.atomicfu.atomic import kotlinx.atomicfu.atomic
import kotlinx.atomicfu.getAndUpdate import kotlinx.atomicfu.getAndUpdate
import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.RealField
import space.kscience.kmath.operations.Space
/** /**
* Common representation for atomic counters * Common representation for atomic counters
@ -36,7 +36,7 @@ public class LongCounter : Counter<Long> {
override val value: Long get() = innerValue.value override val value: Long get() = innerValue.value
} }
public class ObjectCounter<T : Any>(public val space: Space<T>) : Counter<T> { public class ObjectCounter<T : Any>(public val space: Group<T>) : Counter<T> {
private val innerValue = atomic(space.zero) private val innerValue = atomic(space.zero)
override fun add(delta: T) { override fun add(delta: T) {

View File

@ -3,10 +3,11 @@ package space.kscience.kmath.histogram
import space.kscience.kmath.domains.Domain import space.kscience.kmath.domains.Domain
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI 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.NDStructure
import space.kscience.kmath.nd.Strides import space.kscience.kmath.nd.Strides
import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.SpaceElement
import space.kscience.kmath.operations.invoke 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 * 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>
: Group<IndexedHistogram<T, V>>, ScaleOperations<IndexedHistogram<T, V>> {
//public val valueSpace: Space<V> //public val valueSpace: Space<V>
public val strides: Strides 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] * 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> { 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(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" } 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" } 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 { } override val zero: IndexedHistogram<T, V> get() = produce { }

View File

@ -2,6 +2,7 @@ package space.kscience.kmath.histogram
import space.kscience.kmath.domains.Domain import space.kscience.kmath.domains.Domain
import space.kscience.kmath.domains.HyperSquareDomain import space.kscience.kmath.domains.HyperSquareDomain
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.*
import space.kscience.kmath.structures.* import space.kscience.kmath.structures.*
import kotlin.math.floor import kotlin.math.floor
@ -40,6 +41,7 @@ public class RealHistogramSpace(
getIndex(it, point[it]) getIndex(it, point[it])
} }
@OptIn(UnstableKMathAPI::class)
override fun getDomain(index: IntArray): Domain<Double> { override fun getDomain(index: IntArray): Domain<Double> {
val lowerBoundary = index.mapIndexed { axis, i -> val lowerBoundary = index.mapIndexed { axis, i ->
when (i) { when (i) {
@ -77,6 +79,8 @@ public class RealHistogramSpace(
return IndexedHistogram(this, values) return IndexedHistogram(this, values)
} }
override fun IndexedHistogram<Double, Double>.unaryMinus(): IndexedHistogram<Double, Double> = this * (-1)
public companion object { public companion object {
/** /**
* Use it like * Use it like

View File

@ -2,7 +2,8 @@ package space.kscience.kmath.histogram
import space.kscience.kmath.domains.UnivariateDomain import space.kscience.kmath.domains.UnivariateDomain
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import java.util.* import java.util.*
import kotlin.math.abs import kotlin.math.abs
@ -36,7 +37,7 @@ public class TreeHistogram(
@UnstableKMathAPI @UnstableKMathAPI
public class TreeHistogramSpace( public class TreeHistogramSpace(
public val binFactory: (Double) -> UnivariateDomain, public val binFactory: (Double) -> UnivariateDomain,
) : Space<UnivariateHistogram> { ) : Group<UnivariateHistogram>, ScaleOperations<UnivariateHistogram> {
private class BinCounter(val domain: UnivariateDomain, val counter: Counter<Double> = Counter.real()) : private class BinCounter(val domain: UnivariateDomain, val counter: Counter<Double> = Counter.real()) :
ClosedFloatingPointRange<Double> by domain.range ClosedFloatingPointRange<Double> by domain.range
@ -97,14 +98,14 @@ public class TreeHistogramSpace(
return TreeHistogram(this, bins) 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 { val bins = TreeMap<Double, UnivariateBin>().apply {
a.bins.forEach { bin -> a.bins.forEach { bin ->
put(bin.domain.center, put(bin.domain.center,
UnivariateBin( UnivariateBin(
bin.domain, bin.domain,
value = bin.value * k.toDouble(), value = bin.value * value.toDouble(),
standardDeviation = abs(bin.standardDeviation * k.toDouble()) standardDeviation = abs(bin.standardDeviation * value.toDouble())
) )
) )
} }
@ -113,6 +114,8 @@ public class TreeHistogramSpace(
return TreeHistogram(this, bins) return TreeHistogram(this, bins)
} }
override fun UnivariateHistogram.unaryMinus(): UnivariateHistogram = this * (-1)
override val zero: UnivariateHistogram = produce { } override val zero: UnivariateHistogram = produce { }
public companion object { public companion object {

View File

@ -2,12 +2,13 @@ package space.kscience.kmath.histogram
import space.kscience.kmath.domains.UnivariateDomain import space.kscience.kmath.domains.UnivariateDomain
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.SpaceElement
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.asSequence import space.kscience.kmath.structures.asSequence
@UnstableKMathAPI
public val UnivariateDomain.center: Double get() = (range.endInclusive - range.start) / 2 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 value The value of histogram including weighting
* @param standardDeviation Standard deviation of the bin value. Zero or negative if not applicable * @param standardDeviation Standard deviation of the bin value. Zero or negative if not applicable
*/ */
@UnstableKMathAPI
public class UnivariateBin( public class UnivariateBin(
public val domain: UnivariateDomain, public val domain: UnivariateDomain,
override val value: Double, override val value: Double,
@ -28,7 +30,7 @@ public class UnivariateBin(
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public interface UnivariateHistogram : Histogram<Double, UnivariateBin>, public interface UnivariateHistogram : Histogram<Double, UnivariateBin>,
SpaceElement<UnivariateHistogram, Space<UnivariateHistogram>> { SpaceElement<UnivariateHistogram, Group<UnivariateHistogram>> {
public operator fun get(value: Double): UnivariateBin? public operator fun get(value: Double): UnivariateBin?
public override operator fun get(point: Buffer<Double>): UnivariateBin? = get(point[0]) public override operator fun get(point: Buffer<Double>): UnivariateBin? = get(point[0])

View File

@ -102,8 +102,8 @@ public fun <X : SFun<X>> MST.toSFun(): SFun<X> = when (this) {
is MST.Symbolic -> toSVar() is MST.Symbolic -> toSVar()
is MST.Unary -> when (operation) { is MST.Unary -> when (operation) {
SpaceOperations.PLUS_OPERATION -> +value.toSFun<X>() GroupOperations.PLUS_OPERATION -> +value.toSFun<X>()
SpaceOperations.MINUS_OPERATION -> -value.toSFun<X>() GroupOperations.MINUS_OPERATION -> -value.toSFun<X>()
TrigonometricOperations.SIN_OPERATION -> sin(value.toSFun()) TrigonometricOperations.SIN_OPERATION -> sin(value.toSFun())
TrigonometricOperations.COS_OPERATION -> cos(value.toSFun()) TrigonometricOperations.COS_OPERATION -> cos(value.toSFun())
TrigonometricOperations.TAN_OPERATION -> tan(value.toSFun()) TrigonometricOperations.TAN_OPERATION -> tan(value.toSFun())
@ -114,8 +114,8 @@ public fun <X : SFun<X>> MST.toSFun(): SFun<X> = when (this) {
} }
is MST.Binary -> when (operation) { is MST.Binary -> when (operation) {
SpaceOperations.PLUS_OPERATION -> left.toSFun<X>() + right.toSFun() GroupOperations.PLUS_OPERATION -> left.toSFun<X>() + right.toSFun()
SpaceOperations.MINUS_OPERATION -> left.toSFun<X>() - right.toSFun() GroupOperations.MINUS_OPERATION -> left.toSFun<X>() - right.toSFun()
RingOperations.TIMES_OPERATION -> left.toSFun<X>() * right.toSFun() RingOperations.TIMES_OPERATION -> left.toSFun<X>() * right.toSFun()
FieldOperations.DIV_OPERATION -> left.toSFun<X>() / right.toSFun() FieldOperations.DIV_OPERATION -> left.toSFun<X>() / right.toSFun()
PowerOperations.POW_OPERATION -> left.toSFun<X>() pow (right as MST.Numeric).toSConst() PowerOperations.POW_OPERATION -> left.toSFun<X>() pow (right as MST.Numeric).toSConst()

View File

@ -20,7 +20,7 @@ internal fun NDAlgebra<*, *>.checkShape(array: INDArray): INDArray {
* @param T the type of ND-structure element. * @param T the type of ND-structure element.
* @param C the type of the element context. * @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]. * Wraps [INDArray] to [N].
*/ */
@ -70,40 +70,27 @@ public interface Nd4jArrayAlgebra<T, C> : NDAlgebra<T, C> {
} }
/** /**
* Represents [NDSpace] over [Nd4jArrayStructure]. * Represents [NDGroup] over [Nd4jArrayStructure].
* *
* @param T the type of the element contained in ND structure. * @param T the type of the element contained in ND structure.
* @param S the type of space of structure elements. * @param S the type of space of structure elements.
*/ */
public interface Nd4jArraySpace<T, S : Space<T>> : NDSpace<T, S>, Nd4jArrayAlgebra<T, S> { public interface Nd4JArrayGroup<T, S : Group<T>> : NDGroup<T, S>, Nd4jArrayAlgebra<T, S> {
public override val zero: Nd4jArrayStructure<T> public override val zero: Nd4jArrayStructure<T>
get() = Nd4j.zeros(*shape).wrap() get() = Nd4j.zeros(*shape).wrap()
public override fun add(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> { public override fun add(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> =
return a.ndArray.add(b.ndArray).wrap() a.ndArray.add(b.ndArray).wrap()
}
public override operator fun NDStructure<T>.minus(b: NDStructure<T>): Nd4jArrayStructure<T> { public override operator fun NDStructure<T>.minus(b: NDStructure<T>): Nd4jArrayStructure<T> =
return ndArray.sub(b.ndArray).wrap() ndArray.sub(b.ndArray).wrap()
}
public override operator fun NDStructure<T>.unaryMinus(): Nd4jArrayStructure<T> { public override operator fun NDStructure<T>.unaryMinus(): Nd4jArrayStructure<T> =
return ndArray.neg().wrap() 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() 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()
}
} }
/** /**
@ -113,14 +100,13 @@ public interface Nd4jArraySpace<T, S : Space<T>> : NDSpace<T, S>, Nd4jArrayAlgeb
* @param R the type of ring of structure elements. * @param R the type of ring of structure elements.
*/ */
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public interface Nd4jArrayRing<T, R : Ring<T>> : NDRing<T, R>, Nd4jArraySpace<T, R> { public interface Nd4jArrayRing<T, R : Ring<T>> : NDRing<T, R>, Nd4JArrayGroup<T, R> {
public override val one: Nd4jArrayStructure<T> public override val one: Nd4jArrayStructure<T>
get() = Nd4j.ones(*shape).wrap() get() = Nd4j.ones(*shape).wrap()
public override fun multiply(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> { public override fun multiply(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> =
return a.ndArray.mul(b.ndArray).wrap() a.ndArray.mul(b.ndArray).wrap()
}
// //
// public override operator fun Nd4jArrayStructure<T>.minus(b: Number): Nd4jArrayStructure<T> { // public override operator fun Nd4jArrayStructure<T>.minus(b: Number): Nd4jArrayStructure<T> {
// check(this) // check(this)
@ -180,8 +166,7 @@ public interface Nd4jArrayField<T, F : Field<T>> : NDField<T, F>, Nd4jArrayRing<
public override fun divide(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> = public override fun divide(a: NDStructure<T>, b: NDStructure<T>): Nd4jArrayStructure<T> =
a.ndArray.div(b.ndArray).wrap() 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 { public companion object {
private val floatNd4jArrayFieldCache: ThreadLocal<MutableMap<IntArray, FloatNd4jArrayField>> = private val floatNd4jArrayFieldCache: ThreadLocal<MutableMap<IntArray, FloatNd4jArrayField>> =
@ -218,11 +203,14 @@ public interface Nd4jArrayField<T, F : Field<T>> : NDField<T, F>, Nd4jArrayRing<
* Represents [NDField] over [Nd4jArrayRealStructure]. * Represents [NDField] over [Nd4jArrayRealStructure].
*/ */
public class RealNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField<Double, RealField> { public class RealNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField<Double, RealField> {
public override val elementContext: RealField public override val elementContext: RealField get() = RealField
get() = RealField
public override fun INDArray.wrap(): Nd4jArrayStructure<Double> = checkShape(this).asRealStructure() 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> { public override operator fun NDStructure<Double>.div(arg: Double): Nd4jArrayStructure<Double> {
return ndArray.div(arg).wrap() return ndArray.div(arg).wrap()
} }
@ -257,29 +245,26 @@ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArra
public override fun INDArray.wrap(): Nd4jArrayStructure<Float> = checkShape(this).asFloatStructure() public override fun INDArray.wrap(): Nd4jArrayStructure<Float> = checkShape(this).asFloatStructure()
public override operator fun NDStructure<Float>.div(arg: Float): Nd4jArrayStructure<Float> { override fun scale(a: NDStructure<Float>, value: Double): NDStructure<Float> =
return ndArray.div(arg).wrap() a.ndArray.mul(value).wrap()
}
public override operator fun NDStructure<Float>.plus(arg: Float): Nd4jArrayStructure<Float> { public override operator fun NDStructure<Float>.div(arg: Float): Nd4jArrayStructure<Float> =
return ndArray.add(arg).wrap() ndArray.div(arg).wrap()
}
public override operator fun NDStructure<Float>.minus(arg: Float): Nd4jArrayStructure<Float> { public override operator fun NDStructure<Float>.plus(arg: Float): Nd4jArrayStructure<Float> =
return ndArray.sub(arg).wrap() ndArray.add(arg).wrap()
}
public override operator fun NDStructure<Float>.times(arg: Float): Nd4jArrayStructure<Float> { public override operator fun NDStructure<Float>.minus(arg: Float): Nd4jArrayStructure<Float> =
return ndArray.mul(arg).wrap() ndArray.sub(arg).wrap()
}
public override operator fun Float.div(arg: NDStructure<Float>): Nd4jArrayStructure<Float> { public override operator fun NDStructure<Float>.times(arg: Float): Nd4jArrayStructure<Float> =
return arg.ndArray.rdiv(this).wrap() ndArray.mul(arg).wrap()
}
public override operator fun Float.minus(arg: NDStructure<Float>): Nd4jArrayStructure<Float> { public override operator fun Float.div(arg: NDStructure<Float>): Nd4jArrayStructure<Float> =
return arg.ndArray.rsub(this).wrap() arg.ndArray.rdiv(this).wrap()
}
public override operator fun Float.minus(arg: NDStructure<Float>): Nd4jArrayStructure<Float> =
arg.ndArray.rsub(this).wrap()
} }
/** /**
@ -291,21 +276,17 @@ public class IntNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRi
public override fun INDArray.wrap(): Nd4jArrayStructure<Int> = checkShape(this).asIntStructure() public override fun INDArray.wrap(): Nd4jArrayStructure<Int> = checkShape(this).asIntStructure()
public override operator fun NDStructure<Int>.plus(arg: Int): Nd4jArrayStructure<Int> { public override operator fun NDStructure<Int>.plus(arg: Int): Nd4jArrayStructure<Int> =
return ndArray.add(arg).wrap() ndArray.add(arg).wrap()
}
public override operator fun NDStructure<Int>.minus(arg: Int): Nd4jArrayStructure<Int> { public override operator fun NDStructure<Int>.minus(arg: Int): Nd4jArrayStructure<Int> =
return ndArray.sub(arg).wrap() ndArray.sub(arg).wrap()
}
public override operator fun NDStructure<Int>.times(arg: Int): Nd4jArrayStructure<Int> { public override operator fun NDStructure<Int>.times(arg: Int): Nd4jArrayStructure<Int> =
return ndArray.mul(arg).wrap() ndArray.mul(arg).wrap()
}
public override operator fun Int.minus(arg: NDStructure<Int>): Nd4jArrayStructure<Int> { public override operator fun Int.minus(arg: NDStructure<Int>): Nd4jArrayStructure<Int> =
return arg.ndArray.rsub(this).wrap() arg.ndArray.rsub(this).wrap()
}
} }
/** /**
@ -317,19 +298,15 @@ public class LongNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayR
public override fun INDArray.wrap(): Nd4jArrayStructure<Long> = checkShape(this).asLongStructure() public override fun INDArray.wrap(): Nd4jArrayStructure<Long> = checkShape(this).asLongStructure()
public override operator fun NDStructure<Long>.plus(arg: Long): Nd4jArrayStructure<Long> { public override operator fun NDStructure<Long>.plus(arg: Long): Nd4jArrayStructure<Long> =
return ndArray.add(arg).wrap() ndArray.add(arg).wrap()
}
public override operator fun NDStructure<Long>.minus(arg: Long): Nd4jArrayStructure<Long> { public override operator fun NDStructure<Long>.minus(arg: Long): Nd4jArrayStructure<Long> =
return ndArray.sub(arg).wrap() ndArray.sub(arg).wrap()
}
public override operator fun NDStructure<Long>.times(arg: Long): Nd4jArrayStructure<Long> { public override operator fun NDStructure<Long>.times(arg: Long): Nd4jArrayStructure<Long> =
return ndArray.mul(arg).wrap() ndArray.mul(arg).wrap()
}
public override operator fun Long.minus(arg: NDStructure<Long>): Nd4jArrayStructure<Long> { public override operator fun Long.minus(arg: NDStructure<Long>): Nd4jArrayStructure<Long> =
return arg.ndArray.rsub(this).wrap() arg.ndArray.rsub(this).wrap()
}
} }

View File

@ -4,7 +4,8 @@ import space.kscience.kmath.chains.Chain
import space.kscience.kmath.chains.ConstantChain import space.kscience.kmath.chains.ConstantChain
import space.kscience.kmath.chains.map import space.kscience.kmath.chains.map
import space.kscience.kmath.chains.zip import space.kscience.kmath.chains.zip
import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
public class BasicSampler<T : Any>(public val chainBuilder: (RandomGenerator) -> Chain<T>) : Sampler<T> { public class BasicSampler<T : Any>(public val chainBuilder: (RandomGenerator) -> Chain<T>) : Sampler<T> {
@ -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 * 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 class SamplerSpace<T : Any, S>(public val algebra: S) : Group<Sampler<T>>,
public override val zero: Sampler<T> = ConstantSampler(space.zero) ScaleOperations<Sampler<T>> where S : Group<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 -> 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 -> public override fun scale(a: Sampler<T>, value: Double): Sampler<T> = BasicSampler { generator ->
a.sample(generator).map { space { it * k.toDouble() } } a.sample(generator).map { algebra { it * value } }
} }
override fun Sampler<T>.unaryMinus(): Sampler<T> = scale(this, -1.0)
} }

View File

@ -43,7 +43,7 @@ public interface ComposableStatistic<T, I, R> : Statistic<T, R> {
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
private fun <T, I, R> ComposableStatistic<T, I, R>.flowIntermediate( private fun <T, I, R> ComposableStatistic<T, I, R>.flowIntermediate(
flow: Flow<Buffer<T>>, flow: Flow<Buffer<T>>,
dispatcher: CoroutineDispatcher = Dispatchers.Default dispatcher: CoroutineDispatcher = Dispatchers.Default,
): Flow<I> = flow ): Flow<I> = flow
.mapParallel(dispatcher) { computeIntermediate(it) } .mapParallel(dispatcher) { computeIntermediate(it) }
.runningReduce(::composeIntermediate) .runningReduce(::composeIntermediate)
@ -59,27 +59,31 @@ private fun <T, I, R> ComposableStatistic<T, I, R>.flowIntermediate(
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
public fun <T, I, R> ComposableStatistic<T, I, R>.flow( public fun <T, I, R> ComposableStatistic<T, I, R>.flow(
flow: Flow<Buffer<T>>, flow: Flow<Buffer<T>>,
dispatcher: CoroutineDispatcher = Dispatchers.Default dispatcher: CoroutineDispatcher = Dispatchers.Default,
): Flow<R> = flowIntermediate(flow, dispatcher).map(::toResult) ): Flow<R> = flowIntermediate(flow, dispatcher).map(::toResult)
/** /**
* Arithmetic mean * Arithmetic mean
*/ */
public class Mean<T>(public val space: Space<T>) : ComposableStatistic<T, Pair<T, Int>, T> { public class Mean<T>(
private val space: Group<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> = public override suspend fun computeIntermediate(data: Buffer<T>): Pair<T, Int> =
space { sum(data.asIterable()) } to data.size space { sum(data.asIterable()) } to data.size
public override suspend fun composeIntermediate(first: Pair<T, Int>, second: Pair<T, Int>): Pair<T, Int> = 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) space { first.first + second.first } to (first.second + second.second)
public override suspend fun toResult(intermediate: Pair<T, Int>): T = public override suspend fun toResult(intermediate: Pair<T, Int>): T = space {
space { intermediate.first / intermediate.second } division(intermediate.first, intermediate.second)
}
public companion object { public companion object {
//TODO replace with optimized version which respects overflow //TODO replace with optimized version which respects overflow
public val real: Mean<Double> = Mean(RealField) public val real: Mean<Double> = Mean(RealField) { sum, count -> sum / count }
public val int: Mean<Int> = Mean(IntRing) public val int: Mean<Int> = Mean(IntRing) { sum, count -> sum / count }
public val long: Mean<Long> = Mean(LongRing) public val long: Mean<Long> = Mean(LongRing) { sum, count -> sum / count }
} }
} }

View File

@ -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 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 fun <init> ([I)V
public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
public fun acos-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; 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 synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
public fun cosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; 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 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/Number;)Ljava/lang/Object;
public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)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; 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 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 synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object;
public fun exp-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; 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 fun getElementContext ()Lspace/kscience/kmath/operations/RealField;
public final fun getF64Buffer (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; public final fun getF64Buffer (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
public synthetic fun getOne ()Ljava/lang/Object; 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 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 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 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 (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 (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 synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
public fun number-Q7Xurp0 (Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; 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; 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 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 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 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 synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object;
public fun sin-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; public fun sin-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array;
public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;

View File

@ -4,8 +4,9 @@ import org.jetbrains.bio.viktor.F64Array
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.NumbersAddOperations
import space.kscience.kmath.operations.RealField 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") @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
public inline class ViktorNDStructure(public val f64Buffer: F64Array) : MutableNDStructure<Double> { public inline class ViktorNDStructure(public val f64Buffer: F64Array) : MutableNDStructure<Double> {
@ -26,7 +27,8 @@ public fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this)
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
public class ViktorNDField(public override val shape: IntArray) : NDField<Double, RealField>, 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 public val NDStructure<Double>.f64Buffer: F64Array
get() = when { get() = when {
@ -38,11 +40,9 @@ public class ViktorNDField(public override val shape: IntArray) : NDField<Double
else -> produce { this@f64Buffer[it] }.f64Buffer else -> produce { this@f64Buffer[it] }.f64Buffer
} }
public override val zero: ViktorNDStructure public override val zero: ViktorNDStructure by lazy { F64Array.full(init = 0.0, shape = shape).asStructure() }
get() = F64Array.full(init = 0.0, shape = shape).asStructure()
public override val one: ViktorNDStructure public override val one: ViktorNDStructure by lazy { F64Array.full(init = 1.0, shape = shape).asStructure() }
get() = F64Array.full(init = 1.0, shape = shape).asStructure()
private val strides: Strides = DefaultStrides(shape) private val strides: Strides = DefaultStrides(shape)
@ -55,6 +55,8 @@ public class ViktorNDField(public override val shape: IntArray) : NDField<Double
} }
}.asStructure() }.asStructure()
override fun NDStructure<Double>.unaryMinus(): NDStructure<Double> = -1 * this
public override fun NDStructure<Double>.map(transform: RealField.(Double) -> Double): ViktorNDStructure = public override fun NDStructure<Double>.map(transform: RealField.(Double) -> Double): ViktorNDStructure =
F64Array(*this@ViktorNDField.shape).apply { F64Array(*this@ViktorNDField.shape).apply {
this@ViktorNDField.strides.indices().forEach { index -> this@ViktorNDField.strides.indices().forEach { index ->
@ -83,8 +85,8 @@ public class ViktorNDField(public override val shape: IntArray) : NDField<Double
public override fun add(a: NDStructure<Double>, b: NDStructure<Double>): ViktorNDStructure = public override fun add(a: NDStructure<Double>, b: NDStructure<Double>): ViktorNDStructure =
(a.f64Buffer + b.f64Buffer).asStructure() (a.f64Buffer + b.f64Buffer).asStructure()
public override fun multiply(a: NDStructure<Double>, k: Number): ViktorNDStructure = public override fun scale(a: NDStructure<Double>, value: Double): ViktorNDStructure =
(a.f64Buffer * k.toDouble()).asStructure() (a.f64Buffer * value.toDouble()).asStructure()
public override inline fun NDStructure<Double>.plus(b: NDStructure<Double>): ViktorNDStructure = public override inline fun NDStructure<Double>.plus(b: NDStructure<Double>): ViktorNDStructure =
(f64Buffer + b.f64Buffer).asStructure() (f64Buffer + b.f64Buffer).asStructure()

View File

@ -1,14 +1,15 @@
pluginManagement { pluginManagement {
repositories { repositories {
maven("https://repo.kotlin.link")
mavenLocal()
gradlePluginPortal() gradlePluginPortal()
jcenter() jcenter()
maven("https://repo.kotlin.link")
maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlin-eap")
maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/kotlin/kotlinx")
} }
val toolsVersion = "0.8.1" val toolsVersion = "0.9.1"
val kotlinVersion = "1.4.30" val kotlinVersion = "1.4.31"
plugins { plugins {
id("kotlinx.benchmark") version "0.2.0-dev-20" id("kotlinx.benchmark") version "0.2.0-dev-20"