Shapeless ND and Buffer algebras

This commit is contained in:
Alexander Nozik 2021-10-17 13:09:21 +03:00
parent 688382eed6
commit 4513b06e87
7 changed files with 130 additions and 131 deletions

View File

@ -1,6 +0,0 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="Copyright 2018-2021 KMath contributors.&#10;Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file." />
<option name="myName" value="kmath" />
</copyright>
</component>

View File

@ -1,21 +0,0 @@
<component name="CopyrightManager">
<settings default="kmath">
<module2copyright>
<element module="Apply copyright" copyright="kmath" />
</module2copyright>
<LanguageOptions name="Groovy">
<option name="fileTypeOverride" value="1" />
</LanguageOptions>
<LanguageOptions name="HTML">
<option name="fileTypeOverride" value="1" />
<option name="prefixLines" value="false" />
</LanguageOptions>
<LanguageOptions name="Properties">
<option name="fileTypeOverride" value="1" />
</LanguageOptions>
<LanguageOptions name="XML">
<option name="fileTypeOverride" value="1" />
<option name="prefixLines" value="false" />
</LanguageOptions>
</settings>
</component>

View File

@ -1,4 +0,0 @@
<component name="DependencyValidationManager">
<scope name="Apply copyright"
pattern="!file[*]:*//testData//*&amp;&amp;!file[*]:testData//*&amp;&amp;!file[*]:*.gradle.kts&amp;&amp;!file[*]:*.gradle&amp;&amp;!file[group:kotlin-ultimate]:*/&amp;&amp;!file[kotlin.libraries]:stdlib/api//*"/>
</component>

View File

@ -203,7 +203,9 @@ public interface RingND<T, out A : Ring<T>> : Ring<StructureND<T>>, RingOpsND<T,
* @param T the type of the element contained in ND structure. * @param T the type of the element contained in ND structure.
* @param A the type field over structure elements. * @param A the type field over structure elements.
*/ */
public interface FieldOpsND<T, out A : Field<T>> : FieldOps<StructureND<T>>, RingOpsND<T, A>, public interface FieldOpsND<T, out A : Field<T>> :
FieldOps<StructureND<T>>,
RingOpsND<T, A>,
ScaleOperations<StructureND<T>> { ScaleOperations<StructureND<T>> {
/** /**
* Element-wise division. * Element-wise division.

View File

@ -150,7 +150,7 @@ public interface ScaleOperations<T> : Algebra<T> {
* 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 NumbersAddOps<T> : Ring<T>, NumericAlgebra<T> { public interface NumbersAddOps<T> : RingOps<T>, NumericAlgebra<T> {
/** /**
* Addition of element and scalar. * Addition of element and scalar.
* *

View File

@ -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<Double, DoubleField>,
ExtendedFieldOps<StructureND<Double>> {
public val StructureND<Double>.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<Double>.unaryMinus(): StructureND<Double> = -1 * this
override fun StructureND<Double>.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<Double>.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<Double>,
right: StructureND<Double>,
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<Double>, right: StructureND<Double>): ViktorStructureND =
(left.f64Buffer + right.f64Buffer).asStructure()
override fun scale(a: StructureND<Double>, value: Double): ViktorStructureND =
(a.f64Buffer * value).asStructure()
override fun StructureND<Double>.plus(other: StructureND<Double>): ViktorStructureND =
(f64Buffer + other.f64Buffer).asStructure()
override fun StructureND<Double>.minus(other: StructureND<Double>): ViktorStructureND =
(f64Buffer - other.f64Buffer).asStructure()
override fun StructureND<Double>.times(k: Number): ViktorStructureND =
(f64Buffer * k.toDouble()).asStructure()
override fun StructureND<Double>.plus(arg: Double): ViktorStructureND =
(f64Buffer.plus(arg)).asStructure()
override fun sin(arg: StructureND<Double>): ViktorStructureND = arg.map { sin(it) }
override fun cos(arg: StructureND<Double>): ViktorStructureND = arg.map { cos(it) }
override fun tan(arg: StructureND<Double>): ViktorStructureND = arg.map { tan(it) }
override fun asin(arg: StructureND<Double>): ViktorStructureND = arg.map { asin(it) }
override fun acos(arg: StructureND<Double>): ViktorStructureND = arg.map { acos(it) }
override fun atan(arg: StructureND<Double>): ViktorStructureND = arg.map { atan(it) }
override fun power(arg: StructureND<Double>, pow: Number): ViktorStructureND = arg.map { it.pow(pow) }
override fun exp(arg: StructureND<Double>): ViktorStructureND = arg.f64Buffer.exp().asStructure()
override fun ln(arg: StructureND<Double>): ViktorStructureND = arg.f64Buffer.log().asStructure()
override fun sinh(arg: StructureND<Double>): ViktorStructureND = arg.map { sinh(it) }
override fun cosh(arg: StructureND<Double>): ViktorStructureND = arg.map { cosh(it) }
override fun asinh(arg: StructureND<Double>): ViktorStructureND = arg.map { asinh(it) }
override fun acosh(arg: StructureND<Double>): ViktorStructureND = arg.map { acosh(it) }
override fun atanh(arg: StructureND<Double>): 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<Double, DoubleField>, NumbersAddOps<StructureND<Double>> {
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)

View File

@ -7,12 +7,8 @@ package space.kscience.kmath.viktor
import org.jetbrains.bio.viktor.F64Array import org.jetbrains.bio.viktor.F64Array
import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.DefaultStrides
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.MutableStructureND
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.NumbersAddOps
import space.kscience.kmath.operations.ScaleOperations
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND<Double> { public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND<Double> {
@ -31,96 +27,4 @@ public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructur
public fun F64Array.asStructure(): ViktorStructureND = ViktorStructureND(this) 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<Double, DoubleField>,
NumbersAddOps<StructureND<Double>>, ExtendedField<StructureND<Double>>,
ScaleOperations<StructureND<Double>> {
public val StructureND<Double>.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<Double>.unaryMinus(): StructureND<Double> = -1 * this
override fun StructureND<Double>.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<Double>.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<Double>,
right: StructureND<Double>,
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<Double>, right: StructureND<Double>): ViktorStructureND =
(left.f64Buffer + right.f64Buffer).asStructure()
override fun scale(a: StructureND<Double>, value: Double): ViktorStructureND =
(a.f64Buffer * value).asStructure()
override inline fun StructureND<Double>.plus(other: StructureND<Double>): ViktorStructureND =
(f64Buffer + other.f64Buffer).asStructure()
override inline fun StructureND<Double>.minus(other: StructureND<Double>): ViktorStructureND =
(f64Buffer - other.f64Buffer).asStructure()
override inline fun StructureND<Double>.times(k: Number): ViktorStructureND =
(f64Buffer * k.toDouble()).asStructure()
override inline fun StructureND<Double>.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<Double>): ViktorStructureND = arg.map { sin(it) }
override fun cos(arg: StructureND<Double>): ViktorStructureND = arg.map { cos(it) }
override fun tan(arg: StructureND<Double>): ViktorStructureND = arg.map { tan(it) }
override fun asin(arg: StructureND<Double>): ViktorStructureND = arg.map { asin(it) }
override fun acos(arg: StructureND<Double>): ViktorStructureND = arg.map { acos(it) }
override fun atan(arg: StructureND<Double>): ViktorStructureND = arg.map { atan(it) }
override fun power(arg: StructureND<Double>, pow: Number): ViktorStructureND = arg.map { it.pow(pow) }
override fun exp(arg: StructureND<Double>): ViktorStructureND = arg.f64Buffer.exp().asStructure()
override fun ln(arg: StructureND<Double>): ViktorStructureND = arg.f64Buffer.log().asStructure()
}
public fun ViktorFieldND(vararg shape: Int): ViktorFieldND = ViktorFieldND(shape)