From 4513b06e87d4bb2a16266eb5cba5e96167c0e0cd Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 17 Oct 2021 13:09:21 +0300 Subject: [PATCH] Shapeless ND and Buffer algebras --- .idea/copyright/kmath.xml | 6 - .idea/copyright/profiles_settings.xml | 21 --- .idea/scopes/Apply_copyright.xml | 4 - .../space/kscience/kmath/nd/AlgebraND.kt | 4 +- .../kmath/operations/NumericAlgebra.kt | 2 +- .../kscience/kmath/viktor/ViktorFieldOpsND.kt | 124 ++++++++++++++++++ .../kmath/viktor/ViktorStructureND.kt | 100 +------------- 7 files changed, 130 insertions(+), 131 deletions(-) delete mode 100644 .idea/copyright/kmath.xml delete mode 100644 .idea/copyright/profiles_settings.xml delete mode 100644 .idea/scopes/Apply_copyright.xml create mode 100644 kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt diff --git a/.idea/copyright/kmath.xml b/.idea/copyright/kmath.xml deleted file mode 100644 index 1070e5d33..000000000 --- a/.idea/copyright/kmath.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index b538bdf41..000000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/scopes/Apply_copyright.xml b/.idea/scopes/Apply_copyright.xml deleted file mode 100644 index 0eb589133..000000000 --- a/.idea/scopes/Apply_copyright.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt index 3f9b43f03..b4e8b7487 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt @@ -203,7 +203,9 @@ public interface RingND> : Ring>, RingOpsND> : FieldOps>, RingOpsND, +public interface FieldOpsND> : + FieldOps>, + RingOpsND, ScaleOperations> { /** * Element-wise division. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index ca88ad42d..5f6848211 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -150,7 +150,7 @@ public interface ScaleOperations : Algebra { * TODO to be removed and replaced by extensions after multiple receivers are there */ @UnstableKMathAPI -public interface NumbersAddOps : Ring, NumericAlgebra { +public interface NumbersAddOps : RingOps, NumericAlgebra { /** * Addition of element and scalar. * diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt new file mode 100644 index 000000000..c72553a64 --- /dev/null +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt @@ -0,0 +1,124 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ + +package space.kscience.kmath.viktor + +import org.jetbrains.bio.viktor.F64Array +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.* +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.ExtendedFieldOps +import space.kscience.kmath.operations.NumbersAddOps + +@OptIn(UnstableKMathAPI::class) +@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +public open class ViktorFieldOpsND : + FieldOpsND, + ExtendedFieldOps> { + + public val StructureND.f64Buffer: F64Array + get() = when (this) { + is ViktorStructureND -> this.f64Buffer + else -> produce(shape) { this@f64Buffer[it] }.f64Buffer + } + + override val elementAlgebra: DoubleField get() = DoubleField + + override fun produce(shape: IntArray, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = + F64Array(*shape).apply { + DefaultStrides(shape).indices().forEach { index -> + set(value = DoubleField.initializer(index), indices = index) + } + }.asStructure() + + override fun StructureND.unaryMinus(): StructureND = -1 * this + + override fun StructureND.map(transform: DoubleField.(Double) -> Double): ViktorStructureND = + F64Array(*shape).apply { + DefaultStrides(shape).indices().forEach { index -> + set(value = DoubleField.transform(this@map[index]), indices = index) + } + }.asStructure() + + override fun StructureND.mapIndexed( + transform: DoubleField.(index: IntArray, Double) -> Double, + ): ViktorStructureND = F64Array(*shape).apply { + DefaultStrides(shape).indices().forEach { index -> + set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index) + } + }.asStructure() + + override fun zip( + left: StructureND, + right: StructureND, + transform: DoubleField.(Double, Double) -> Double, + ): ViktorStructureND { + require(left.shape.contentEquals(right.shape)) + return F64Array(*left.shape).apply { + DefaultStrides(left.shape).indices().forEach { index -> + set(value = DoubleField.transform(left[index], right[index]), indices = index) + } + }.asStructure() + } + + override fun add(left: StructureND, right: StructureND): ViktorStructureND = + (left.f64Buffer + right.f64Buffer).asStructure() + + override fun scale(a: StructureND, value: Double): ViktorStructureND = + (a.f64Buffer * value).asStructure() + + override fun StructureND.plus(other: StructureND): ViktorStructureND = + (f64Buffer + other.f64Buffer).asStructure() + + override fun StructureND.minus(other: StructureND): ViktorStructureND = + (f64Buffer - other.f64Buffer).asStructure() + + override fun StructureND.times(k: Number): ViktorStructureND = + (f64Buffer * k.toDouble()).asStructure() + + override fun StructureND.plus(arg: Double): ViktorStructureND = + (f64Buffer.plus(arg)).asStructure() + + override fun sin(arg: StructureND): ViktorStructureND = arg.map { sin(it) } + override fun cos(arg: StructureND): ViktorStructureND = arg.map { cos(it) } + override fun tan(arg: StructureND): ViktorStructureND = arg.map { tan(it) } + override fun asin(arg: StructureND): ViktorStructureND = arg.map { asin(it) } + override fun acos(arg: StructureND): ViktorStructureND = arg.map { acos(it) } + override fun atan(arg: StructureND): ViktorStructureND = arg.map { atan(it) } + + override fun power(arg: StructureND, pow: Number): ViktorStructureND = arg.map { it.pow(pow) } + + override fun exp(arg: StructureND): ViktorStructureND = arg.f64Buffer.exp().asStructure() + + override fun ln(arg: StructureND): ViktorStructureND = arg.f64Buffer.log().asStructure() + + override fun sinh(arg: StructureND): ViktorStructureND = arg.map { sinh(it) } + + override fun cosh(arg: StructureND): ViktorStructureND = arg.map { cosh(it) } + + override fun asinh(arg: StructureND): ViktorStructureND = arg.map { asinh(it) } + + override fun acosh(arg: StructureND): ViktorStructureND = arg.map { acosh(it) } + + override fun atanh(arg: StructureND): ViktorStructureND = arg.map { atanh(it) } + + public companion object : ViktorFieldOpsND() +} + +public val DoubleField.viktorAlgebra: ViktorFieldOpsND get() = ViktorFieldOpsND + +public open class ViktorFieldND( + override val shape: Shape +) : ViktorFieldOpsND(), FieldND, NumbersAddOps> { + override val zero: ViktorStructureND by lazy { F64Array.full(init = 0.0, shape = shape).asStructure() } + override val one: ViktorStructureND by lazy { F64Array.full(init = 1.0, shape = shape).asStructure() } + + override fun number(value: Number): ViktorStructureND = + F64Array.full(init = value.toDouble(), shape = shape).asStructure() +} + +public fun DoubleField.viktorAlgebra(vararg shape: Int): ViktorFieldND = ViktorFieldND(shape) + +public fun ViktorFieldND(vararg shape: Int): ViktorFieldND = ViktorFieldND(shape) \ No newline at end of file diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt index a914542bc..0d29983f9 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -7,12 +7,8 @@ package space.kscience.kmath.viktor import org.jetbrains.bio.viktor.F64Array import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.* -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.ExtendedField -import space.kscience.kmath.operations.NumbersAddOps -import space.kscience.kmath.operations.ScaleOperations +import space.kscience.kmath.nd.DefaultStrides +import space.kscience.kmath.nd.MutableStructureND @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND { @@ -31,96 +27,4 @@ public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructur public fun F64Array.asStructure(): ViktorStructureND = ViktorStructureND(this) -@OptIn(UnstableKMathAPI::class) -@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public class ViktorFieldND(override val shape: IntArray) : FieldND, - NumbersAddOps>, ExtendedField>, - ScaleOperations> { - public val StructureND.f64Buffer: F64Array - get() = when { - !shape.contentEquals(this@ViktorFieldND.shape) -> throw ShapeMismatchException( - this@ViktorFieldND.shape, - shape - ) - this is ViktorStructureND && this.f64Buffer.shape.contentEquals(this@ViktorFieldND.shape) -> this.f64Buffer - else -> produce(shape) { this@f64Buffer[it] }.f64Buffer - } - - override val zero: ViktorStructureND by lazy { F64Array.full(init = 0.0, shape = shape).asStructure() } - override val one: ViktorStructureND by lazy { F64Array.full(init = 1.0, shape = shape).asStructure() } - - private val strides: Strides = DefaultStrides(shape) - - override val elementAlgebra: DoubleField get() = DoubleField - - override fun produce(shape: IntArray, initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = - F64Array(*shape).apply { - this@ViktorFieldND.strides.indices().forEach { index -> - set(value = DoubleField.initializer(index), indices = index) - } - }.asStructure() - - override fun StructureND.unaryMinus(): StructureND = -1 * this - - override fun StructureND.map(transform: DoubleField.(Double) -> Double): ViktorStructureND = - F64Array(*this@ViktorFieldND.shape).apply { - this@ViktorFieldND.strides.indices().forEach { index -> - set(value = DoubleField.transform(this@map[index]), indices = index) - } - }.asStructure() - - override fun StructureND.mapIndexed( - transform: DoubleField.(index: IntArray, Double) -> Double, - ): ViktorStructureND = F64Array(*this@ViktorFieldND.shape).apply { - this@ViktorFieldND.strides.indices().forEach { index -> - set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index) - } - }.asStructure() - - override fun zip( - left: StructureND, - right: StructureND, - transform: DoubleField.(Double, Double) -> Double, - ): ViktorStructureND = F64Array(*shape).apply { - this@ViktorFieldND.strides.indices().forEach { index -> - set(value = DoubleField.transform(left[index], right[index]), indices = index) - } - }.asStructure() - - override fun add(left: StructureND, right: StructureND): ViktorStructureND = - (left.f64Buffer + right.f64Buffer).asStructure() - - override fun scale(a: StructureND, value: Double): ViktorStructureND = - (a.f64Buffer * value).asStructure() - - override inline fun StructureND.plus(other: StructureND): ViktorStructureND = - (f64Buffer + other.f64Buffer).asStructure() - - override inline fun StructureND.minus(other: StructureND): ViktorStructureND = - (f64Buffer - other.f64Buffer).asStructure() - - override inline fun StructureND.times(k: Number): ViktorStructureND = - (f64Buffer * k.toDouble()).asStructure() - - override inline fun StructureND.plus(arg: Double): ViktorStructureND = - (f64Buffer.plus(arg)).asStructure() - - override fun number(value: Number): ViktorStructureND = - F64Array.full(init = value.toDouble(), shape = shape).asStructure() - - override fun sin(arg: StructureND): ViktorStructureND = arg.map { sin(it) } - override fun cos(arg: StructureND): ViktorStructureND = arg.map { cos(it) } - override fun tan(arg: StructureND): ViktorStructureND = arg.map { tan(it) } - override fun asin(arg: StructureND): ViktorStructureND = arg.map { asin(it) } - override fun acos(arg: StructureND): ViktorStructureND = arg.map { acos(it) } - override fun atan(arg: StructureND): ViktorStructureND = arg.map { atan(it) } - - override fun power(arg: StructureND, pow: Number): ViktorStructureND = arg.map { it.pow(pow) } - - override fun exp(arg: StructureND): ViktorStructureND = arg.f64Buffer.exp().asStructure() - - override fun ln(arg: StructureND): ViktorStructureND = arg.f64Buffer.log().asStructure() -} - -public fun ViktorFieldND(vararg shape: Int): ViktorFieldND = ViktorFieldND(shape)