Apply context receivers to operator extension functions in main algebras #473

Closed
CommanderTvis wants to merge 1 commits from commandertvis/kotlin-1.6.20 into dev
118 changed files with 989 additions and 939 deletions

View File

@ -18,9 +18,10 @@ repositories {
kotlin {
jvm()
js(IR) {
nodejs()
}
// Testing multi-receiver!
// js(IR) {
// nodejs()
// }
sourceSets {
all {
@ -74,7 +75,8 @@ benchmark {
// Setup configurations
targets {
register("jvm")
register("js")
// Testing multi-receiver!
// register("js")
}
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
@ -158,7 +160,7 @@ kotlin.sourceSets.all {
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
kotlinOptions {
jvmTarget = "11"
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xlambdas=indy"
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xlambdas=indy" + "-Xcontext-receivers"
}
}

View File

@ -11,10 +11,7 @@ import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.asm.compileToExpression
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import kotlin.math.sin
import kotlin.random.Random

View File

@ -11,7 +11,7 @@ allprojects {
}
group = "space.kscience"
version = "0.3.0-dev-21"
version = "0.4.0-dev-1"
}
subprojects {

View File

@ -4,4 +4,4 @@
#
kotlin.code.style=official
toolsVersion=0.11.2-kotlin-1.6.10
toolsVersion=0.11.2-kotlin-1.6.20

View File

@ -207,7 +207,7 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
structure.getFeature(type)?.let { return it }
val origin = structure.toEjml().origin
return when (type) {
return type.cast(when (type) {
${
if (isDense)
""" InverseMatrixFeature::class -> object : InverseMatrixFeature<${type}> {
@ -318,8 +318,8 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
}"""
}
else -> null
}?.let(type::cast)
else -> return null
})
}
/**

View File

@ -62,10 +62,6 @@ val c2 = ComplexField { c1 - 1.0 } // Returns: Complex(re=0.0, im=2.0)
val c3 = ComplexField { c1 - i * 2.0 }
```
**Note**: In theory it is possible to add behaviors directly to the context, but as for now Kotlin does not support
that. Watch [KT-10468](https://youtrack.jetbrains.com/issue/KT-10468) and
[KEEP-176](https://github.com/Kotlin/KEEP/pull/176) for updates.
## Nested fields
Contexts allow one to build more complex structures. For example, it is possible to create a `Matrix` from complex

View File

@ -61,7 +61,8 @@ kotlin.sourceSets.all {
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
kotlinOptions {
jvmTarget = "11"
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy"
freeCompilerArgs =
freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy" + "-Xcontext-receivers"
}
}

View File

@ -8,8 +8,7 @@ package space.kscience.kmath.ast
import space.kscience.kmath.asm.compileToExpression
import space.kscience.kmath.expressions.MstExtendedField
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
fun main() {
val expr = MstExtendedField {

View File

@ -13,6 +13,8 @@ import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.expressions.chiSquaredExpression
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.asIterable
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import space.kscience.kmath.operations.toList
import space.kscience.kmath.optimization.FunctionOptimizationTarget
import space.kscience.kmath.optimization.optimizeWith

View File

@ -14,6 +14,8 @@ import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.expressions.binding
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.asIterable
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import space.kscience.kmath.operations.toList
import space.kscience.kmath.optimization.QowOptimizer
import space.kscience.kmath.optimization.chiSquaredOrNull

View File

@ -13,6 +13,7 @@ import space.kscience.kmath.nd.structureND
import space.kscience.kmath.nd.withNdAlgebra
import space.kscience.kmath.operations.algebra
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.times
fun main(): Unit = Double.algebra {
withNdAlgebra(2, 2) {
@ -31,4 +32,4 @@ fun main(): Unit = Double.algebra {
//the value is nullable because in some cases the integration could not succeed
println(result.value)
}
}
}

View File

@ -7,7 +7,6 @@ package space.kscience.kmath.operations
import space.kscience.kmath.commons.linear.CMLinearSpace
import space.kscience.kmath.linear.matrix
import space.kscience.kmath.nd.DoubleBufferND
import space.kscience.kmath.nd.Shape
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.nd.ndAlgebra
@ -21,7 +20,7 @@ fun main() {
val cmMatrix: Structure2D<Double> = CMLinearSpace.matrix(2, 2)(0.0, 1.0, 0.0, 3.0)
val res: DoubleBufferND = DoubleField.ndAlgebra {
val res = DoubleField.ndAlgebra {
exp(viktorStructure) + 2.0 * cmMatrix
}

View File

@ -15,6 +15,8 @@ import space.kscience.kmath.nd.ndAlgebra
import space.kscience.kmath.nd.structureND
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import kotlin.system.measureTimeMillis
fun main() {

View File

@ -80,7 +80,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND<Double, Double
return BufferND(strides, array.asBuffer())
}
override fun StructureND<Double>.unaryMinus(): StructureND<Double> = map { -it }
override fun negate(arg: StructureND<Double>): StructureND<Double> = arg.map { -it }
override fun scale(a: StructureND<Double>, value: Double): StructureND<Double> = a.map { it * value }

View File

@ -5,10 +5,7 @@
package space.kscience.kmath.structures
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.buffer
import space.kscience.kmath.operations.bufferAlgebra
import space.kscience.kmath.operations.withSize
import space.kscience.kmath.operations.*
inline fun <reified R : Any> MutableBuffer.Companion.same(
n: Int,

View File

@ -5,12 +5,13 @@
package space.kscience.kmath.tensors
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.operations.abs
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.tensors.core.DoubleTensor
import space.kscience.kmath.operations.minus
import space.kscience.kmath.operations.plus
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
import kotlin.math.abs
// OLS estimator using SVD
fun main() {
@ -48,14 +49,16 @@ fun main() {
// inverse Sigma matrix can be restored from singular values with diagonalEmbedding function
val sigma = diagonalEmbedding(singValues.map{ if (abs(it) < 1e-3) 0.0 else 1.0/it })
val sigma = diagonalEmbedding(singValues.map { if (abs(it) < 1e-3) 0.0 else 1.0 / it })
val alphaOLS = v dot sigma dot u.transpose() dot y
println("Estimated alpha:\n" +
"$alphaOLS")
println(
"Estimated alpha:\n" +
"$alphaOLS"
)
// figure out MSE of approximation
fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double {
fun mse(yTrue: StructureND<Double>, yPred: StructureND<Double>): Double {
require(yTrue.shape.size == 1)
require(yTrue.shape contentEquals yPred.shape)

View File

@ -5,10 +5,11 @@
package space.kscience.kmath.tensors
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import space.kscience.kmath.tensors.core.tensorAlgebra
import space.kscience.kmath.tensors.core.withBroadcast
// simple PCA
fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods

View File

@ -5,10 +5,11 @@
package space.kscience.kmath.tensors
import space.kscience.kmath.operations.div
import space.kscience.kmath.operations.minus
import space.kscience.kmath.tensors.core.tensorAlgebra
import space.kscience.kmath.tensors.core.withBroadcast
// Dataset normalization
fun main() = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods

View File

@ -10,6 +10,8 @@ import org.jetbrains.kotlinx.multik.api.ndarray
import space.kscience.kmath.multik.multikAlgebra
import space.kscience.kmath.nd.one
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.minus
import space.kscience.kmath.operations.plus
fun main(): Unit = with(DoubleField.multikAlgebra) {
val a = Multik.ndarray(intArrayOf(1, 2, 3)).asType<Double>().wrap()

View File

@ -5,11 +5,9 @@
package space.kscience.kmath.tensors
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
import space.kscience.kmath.tensors.core.DoubleTensor
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
import space.kscience.kmath.tensors.core.copyArray
import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.operations.*
import space.kscience.kmath.tensors.core.*
import kotlin.math.sqrt
const val seed = 100500L
@ -27,13 +25,10 @@ open class Activation(
val activation: (DoubleTensor) -> DoubleTensor,
val activationDer: (DoubleTensor) -> DoubleTensor,
) : Layer {
override fun forward(input: DoubleTensor): DoubleTensor {
return activation(input)
}
override fun forward(input: DoubleTensor): DoubleTensor = activation(input)
override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor {
return DoubleTensorAlgebra { outputError * activationDer(input) }
}
override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor =
DoubleTensorAlgebra { outputError * activationDer(input) }
}
fun relu(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra {
@ -106,8 +101,8 @@ fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double {
}
// neural network class
@OptIn(ExperimentalStdlibApi::class)
class NeuralNetwork(private val layers: List<Layer>) {
@OptIn(PerformancePitfall::class)
private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra {
val onesForAnswers = yPred.zeroesLike()
@ -174,7 +169,7 @@ class NeuralNetwork(private val layers: List<Layer>) {
}
@OptIn(ExperimentalStdlibApi::class)
@OptIn(PerformancePitfall::class)
fun main() = BroadcastDoubleTensorAlgebra {
val features = 5
val sampleSize = 250

View File

@ -84,3 +84,8 @@ readme {
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt"
) { "Extendable MST rendering" }
}
// Testing multi-receiver!
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
enabled = false
}

View File

@ -9,9 +9,7 @@ import space.kscience.kmath.expressions.MstField
import space.kscience.kmath.expressions.MstRing
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -8,8 +8,7 @@ package space.kscience.kmath.ast
import space.kscience.kmath.expressions.MstExtendedField
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -68,7 +68,7 @@ public class DerivativeStructureField(
public fun DerivativeStructure.derivative(vararg symbols: Symbol): Double = derivative(symbols.toList())
override fun DerivativeStructure.unaryMinus(): DerivativeStructure = negate()
override fun negate(arg: DerivativeStructure): DerivativeStructure = arg.negate()
override fun add(left: DerivativeStructure, right: DerivativeStructure): DerivativeStructure = left.add(right)

View File

@ -6,6 +6,9 @@
package space.kscience.kmath.commons.expressions
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import space.kscience.kmath.operations.unaryMinus
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.test.Test

View File

@ -13,7 +13,7 @@ import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.Symbol.Companion.y
import space.kscience.kmath.expressions.chiSquaredExpression
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.map
import space.kscience.kmath.operations.*
import space.kscience.kmath.optimization.*
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.structures.DoubleBuffer

View File

@ -1,7 +1,7 @@
plugins {
kotlin("multiplatform")
id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native")
// id("ru.mipt.npm.gradle.native")
}
kotlin.sourceSets {
@ -29,3 +29,8 @@ readme {
ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt"
)
}
// Testing multi-receiver!
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
enabled = false
}

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.complex
import space.kscience.kmath.complex.ComplexField.plus
import space.kscience.kmath.memory.MemoryReader
import space.kscience.kmath.memory.MemorySpec
import space.kscience.kmath.memory.MemoryWriter
@ -71,14 +72,13 @@ public object ComplexField :
*/
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)
override fun add(left: Complex, right: Complex): Complex = Complex(left.re + right.re, left.im + right.im)
// override fun multiply(a: Complex, k: Number): Complex = Complex(a.re * k.toDouble(), a.im * k.toDouble())
override fun negate(arg: Complex): Complex = Complex(-arg.re, -arg.im)
override fun multiply(left: Complex, right: Complex): Complex =
Complex(left.re * right.re - left.im * right.im, left.re * right.im + left.im * right.re)
@ -107,8 +107,6 @@ public object ComplexField :
}
}
override operator fun Complex.div(k: Number): Complex = Complex(re / k.toDouble(), im / k.toDouble())
override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2.0
override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2.0
@ -139,61 +137,65 @@ public object ComplexField :
override fun ln(arg: Complex): Complex = ln(arg.r) + i * atan2(arg.im, arg.re)
/**
* Adds complex number to real one.
*
* @receiver the augend.
* @param c the addend.
* @return the sum.
*/
public operator fun Double.plus(c: Complex): Complex = add(this.toComplex(), c)
/**
* Subtracts complex number from real one.
*
* @receiver the minuend.
* @param c the subtrahend.
* @return the difference.
*/
public operator fun Double.minus(c: Complex): Complex = add(this.toComplex(), -c)
/**
* Adds real number to complex one.
*
* @receiver the augend.
* @param d the addend.
* @return the sum.
*/
public operator fun Complex.plus(d: Double): Complex = d + this
/**
* Subtracts real number from complex one.
*
* @receiver the minuend.
* @param d the subtrahend.
* @return the difference.
*/
public operator fun Complex.minus(d: Double): Complex = add(this, -d.toComplex())
/**
* Multiplies real number by complex one.
*
* @receiver the multiplier.
* @param c the multiplicand.
* @receiver the product.
*/
public operator fun Double.times(c: Complex): Complex = Complex(c.re * this, c.im * this)
override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg)
}
/**
* Adds complex number to real one.
*
* @receiver the augend.
* @param c the addend.
* @return the sum.
*/
context(ComplexField)
public operator fun Double.plus(c: Complex): Complex = add(toComplex(), c)
/**
* Adds real number to complex one.
*
* @receiver the augend.
* @param d the addend.
* @return the sum.
*/
context(ComplexField)
public operator fun Complex.plus(d: Double): Complex = d + this
/**
* Subtracts complex number from real one.
*
* @receiver the minuend.
* @param c the subtrahend.
* @return the difference.
*/
context(ComplexField)
public operator fun Double.minus(c: Complex): Complex = add(toComplex(), -c)
/**
* Subtracts real number from complex one.
*
* @receiver the minuend.
* @param d the subtrahend.
* @return the difference.
*/
context(ComplexField)
public operator fun Complex.minus(d: Double): Complex = add(this, -d.toComplex())
/**
* Multiplies real number by complex one.
*
* @receiver the multiplier.
* @param c the multiplicand.
* @receiver the product.
*/
context(ComplexField)
public operator fun Double.times(c: Complex): Complex = Complex(c.re * this, c.im * this)
/**
* Represents `double`-based complex number.
*
* @property re The real part.
* @property im The imaginary part.
*/
@OptIn(UnstableKMathAPI::class)
public data class Complex(val re: Double, val im: Double) {
public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble())
public constructor(re: Number) : this(re.toDouble(), 0.0)

View File

@ -166,10 +166,7 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
override operator fun Quaternion.plus(other: Number): Quaternion = Quaternion(w + other.toDouble(), x, y, z)
override operator fun Quaternion.minus(other: Number): Quaternion = Quaternion(w - other.toDouble(), x, y, z)
override operator fun Number.times(arg: Quaternion): Quaternion =
Quaternion(toDouble() * arg.w, toDouble() * arg.x, toDouble() * arg.y, toDouble() * arg.z)
override fun Quaternion.unaryMinus(): Quaternion = Quaternion(-w, -x, -y, -z)
override fun negate(arg: Quaternion): Quaternion = Quaternion(-arg.w, -arg.x, -arg.y, -arg.z)
override fun norm(arg: Quaternion): Quaternion = sqrt(arg.conjugate * arg)
override fun bindSymbolOrNull(value: String): Quaternion? = when (value) {

View File

@ -5,7 +5,7 @@
package space.kscience.kmath.complex
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import kotlin.math.PI
import kotlin.math.abs
import kotlin.test.Test

View File

@ -6,6 +6,8 @@
package space.kscience.kmath.complex
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.minus
import space.kscience.kmath.operations.plus
import kotlin.math.sqrt
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -9,6 +9,8 @@ import space.kscience.kmath.expressions.FunctionalExpressionField
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -6,6 +6,8 @@
package space.kscience.kmath.complex
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -1,7 +1,7 @@
plugins {
kotlin("multiplatform")
id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native")
// id("ru.mipt.npm.gradle.native")
// id("com.xcporter.metaview") version "0.0.5"
}
@ -72,3 +72,8 @@ readme {
ref = "src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt"
) { "Automatic differentiation" }
}
// Testing multi-receiver!
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
enabled = false
}

View File

@ -51,8 +51,8 @@ public open class FunctionalExpressionGroup<T, out A : Group<T>>(
) : FunctionalExpressionAlgebra<T, A>(algebra), Group<Expression<T>> {
override val zero: Expression<T> get() = const(algebra.zero)
override fun Expression<T>.unaryMinus(): Expression<T> =
unaryOperation(GroupOps.MINUS_OPERATION, this)
override fun negate(arg: Expression<T>): Expression<T> =
unaryOperation(GroupOps.MINUS_OPERATION, arg)
/**
* Builds an Expression of addition of two another expressions.
@ -60,26 +60,25 @@ public open class FunctionalExpressionGroup<T, out A : Group<T>>(
override fun add(left: Expression<T>, right: Expression<T>): Expression<T> =
binaryOperation(GroupOps.PLUS_OPERATION, left, right)
// /**
// * Builds an Expression of multiplication of expression by number.
// */
// override fun multiply(a: Expression<T>, k: Number): Expression<T> = Expression { arguments ->
// algebra.multiply(a.invoke(arguments), k)
// }
public operator fun Expression<T>.plus(arg: T): Expression<T> = this + const(arg)
public operator fun Expression<T>.minus(arg: T): Expression<T> = this - const(arg)
public operator fun T.plus(arg: Expression<T>): Expression<T> = arg + this
public operator fun T.minus(arg: Expression<T>): Expression<T> = arg - this
override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
super<FunctionalExpressionAlgebra>.unaryOperationFunction(operation)
override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
super<FunctionalExpressionAlgebra>.binaryOperationFunction(operation)
}
context(FunctionalExpressionGroup<T, A>)
public operator fun <T, A : Group<T>> Expression<T>.plus(arg: T): Expression<T> = this + const(arg)
context(FunctionalExpressionGroup<T, A>)
public operator fun <T, A : Group<T>> Expression<T>.minus(arg: T): Expression<T> = this - const(arg)
context(FunctionalExpressionGroup<T, A>)
public operator fun <T, A : Group<T>> T.plus(arg: Expression<T>): Expression<T> = arg + this
context(FunctionalExpressionGroup<T, A>)
public operator fun <T, A : Group<T>> T.minus(arg: Expression<T>): Expression<T> = arg - this
public open class FunctionalExpressionRing<T, out A : Ring<T>>(
algebra: A,
) : FunctionalExpressionGroup<T, A>(algebra), Ring<Expression<T>> {
@ -91,9 +90,6 @@ public open class FunctionalExpressionRing<T, out A : Ring<T>>(
override fun multiply(left: Expression<T>, right: Expression<T>): Expression<T> =
binaryOperationFunction(RingOps.TIMES_OPERATION)(left, right)
public operator fun Expression<T>.times(arg: T): Expression<T> = this * const(arg)
public operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
super<FunctionalExpressionGroup>.unaryOperationFunction(operation)
@ -101,6 +97,12 @@ public open class FunctionalExpressionRing<T, out A : Ring<T>>(
super<FunctionalExpressionGroup>.binaryOperationFunction(operation)
}
context(FunctionalExpressionRing<T, A>)
public operator fun <T, A : Ring<T>> Expression<T>.times(arg: T): Expression<T> = this * const(arg)
context(FunctionalExpressionRing<T, A>)
public operator fun <T, A : Ring<T>> T.times(arg: Expression<T>): Expression<T> = arg * this
public open class FunctionalExpressionField<T, out A : Field<T>>(
algebra: A,
) : FunctionalExpressionRing<T, A>(algebra), Field<Expression<T>>, ScaleOperations<Expression<T>> {
@ -110,9 +112,6 @@ public open class FunctionalExpressionField<T, out A : Field<T>>(
override fun divide(left: Expression<T>, right: Expression<T>): Expression<T> =
binaryOperationFunction(FieldOps.DIV_OPERATION)(left, right)
public operator fun Expression<T>.div(arg: T): Expression<T> = this / const(arg)
public operator fun T.div(arg: Expression<T>): Expression<T> = arg / this
override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
super<FunctionalExpressionRing>.unaryOperationFunction(operation)
@ -127,6 +126,12 @@ public open class FunctionalExpressionField<T, out A : Field<T>>(
super<FunctionalExpressionRing>.bindSymbolOrNull(value)
}
context(FunctionalExpressionField<T, A>)
public operator fun <T, A : Field<T>> Expression<T>.div(arg: T): Expression<T> = this / const(arg)
context(FunctionalExpressionField<T, A>)
public operator fun <T, A : Field<T>> T.div(arg: Expression<T>): Expression<T> = arg / this
public open class FunctionalExpressionExtendedField<T, out A : ExtendedField<T>>(
algebra: A,
) : FunctionalExpressionField<T, A>(algebra), ExtendedField<Expression<T>> {

View File

@ -32,14 +32,12 @@ public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
override fun number(value: Number): MST.Numeric = MstNumericAlgebra.number(value)
override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
override fun add(left: MST, right: MST): MST.Binary = binaryOperationFunction(GroupOps.PLUS_OPERATION)(left, right)
override operator fun MST.unaryPlus(): MST.Unary =
unaryOperationFunction(GroupOps.PLUS_OPERATION)(this)
override operator fun MST.unaryMinus(): MST.Unary =
unaryOperationFunction(GroupOps.MINUS_OPERATION)(this)
override fun negate(arg: MST): MST.Unary =
unaryOperationFunction(GroupOps.MINUS_OPERATION)(arg)
override operator fun MST.minus(arg: MST): MST.Binary =
binaryOperationFunction(GroupOps.MINUS_OPERATION)(this, arg)
override fun subtract(left: MST, right: MST): MST.Binary =
binaryOperationFunction(GroupOps.MINUS_OPERATION)(left, right)
override fun scale(a: MST, value: Double): MST.Binary =
binaryOperationFunction(RingOps.TIMES_OPERATION)(a, number(value))
@ -70,9 +68,8 @@ public object MstRing : Ring<MST>, NumbersAddOps<MST>, ScaleOperations<MST> {
override fun multiply(left: MST, right: MST): MST.Binary =
binaryOperationFunction(RingOps.TIMES_OPERATION)(left, right)
override operator fun MST.unaryPlus(): MST.Unary = MstGroup { +this@unaryPlus }
override operator fun MST.unaryMinus(): MST.Unary = MstGroup { -this@unaryMinus }
override operator fun MST.minus(arg: MST): MST.Binary = MstGroup { this@minus - arg }
override fun negate(arg: MST): MST.Unary = MstGroup.negate(arg)
override fun subtract(left: MST, right: MST): MST.Binary = MstGroup.subtract(left, right)
override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstGroup.binaryOperationFunction(operation)
@ -101,9 +98,8 @@ public object MstField : Field<MST>, NumbersAddOps<MST>, ScaleOperations<MST> {
override fun divide(left: MST, right: MST): MST.Binary =
binaryOperationFunction(FieldOps.DIV_OPERATION)(left, right)
override operator fun MST.unaryPlus(): MST.Unary = MstRing { +this@unaryPlus }
override operator fun MST.unaryMinus(): MST.Unary = MstRing { -this@unaryMinus }
override operator fun MST.minus(arg: MST): MST.Binary = MstRing { this@minus - arg }
override fun negate(arg: MST): MST.Unary = MstRing.negate(arg)
override fun subtract(left: MST, right: MST): MST.Binary = MstRing.subtract(left, right)
override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstRing.binaryOperationFunction(operation)
@ -142,9 +138,8 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
override fun multiply(left: MST, right: MST): MST.Binary = MstField.multiply(left, right)
override fun divide(left: MST, right: MST): MST.Binary = MstField.divide(left, right)
override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus }
override operator fun MST.unaryMinus(): MST.Unary = MstField { -this@unaryMinus }
override operator fun MST.minus(arg: MST): MST.Binary = MstField { this@minus - arg }
override fun negate(arg: MST): MST.Unary = MstField.negate(arg)
override fun subtract(left: MST, right: MST): MST.Binary = MstField.subtract(left, right)
override fun power(arg: MST, pow: Number): MST.Binary =
binaryOperationFunction(PowerOperations.POW_OPERATION)(arg, number(pow))

View File

@ -163,8 +163,8 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
// derive(const { this@minus.value - one * b.toDouble() }) { z -> d += z.d }
override fun AutoDiffValue<T>.unaryMinus(): AutoDiffValue<T> =
derive(const { -value }) { z -> d -= z.d }
override fun negate(arg: AutoDiffValue<T>): AutoDiffValue<T> =
derive(const { -arg.value }) { z -> arg.d -= z.d }
// Basic math (+, -, *, /)

View File

@ -5,8 +5,7 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.asIterable
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.indices
import kotlin.jvm.JvmName

View File

@ -9,9 +9,7 @@ import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.nd.DoubleFieldOpsND
import space.kscience.kmath.nd.as2D
import space.kscience.kmath.nd.asND
import space.kscience.kmath.operations.DoubleBufferOps
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.DoubleBuffer

View File

@ -10,10 +10,7 @@ import space.kscience.kmath.nd.MutableStructure2D
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.nd.StructureFeature
import space.kscience.kmath.nd.as1D
import space.kscience.kmath.operations.BufferRingOps
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory
import space.kscience.kmath.structures.DoubleBuffer

View File

@ -89,6 +89,5 @@ public class TransposedFeature<out T : Any>(public val original: Matrix<T>) : Ma
* Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A`
*/
@Suppress("UNCHECKED_CAST")
@OptIn(UnstableKMathAPI::class)
public fun <T : Any> Matrix<T>.transpose(): Matrix<T> = getFeature(TransposedFeature::class)?.original as? Matrix<T>
?: VirtualMatrix(colNum, rowNum) { i, j -> get(j, i) }.withFeature(TransposedFeature(this))

View File

@ -7,6 +7,7 @@ package space.kscience.kmath.misc
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.plus
import kotlin.jvm.JvmName
/**

View File

@ -127,51 +127,54 @@ public interface GroupOpsND<T, out A : GroupOps<T>> : GroupOps<StructureND<T>>,
override fun add(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
zip(left, right) { aValue, bValue -> add(aValue, bValue) }
// TODO move to extensions after KEEP-176
/**
* Adds an ND structure to an element of it.
*
* @receiver the augend.
* @param arg the addend.
* @return the sum.
*/
@OptIn(PerformancePitfall::class)
public operator fun StructureND<T>.plus(arg: T): StructureND<T> = this.map { value -> add(arg, value) }
/**
* Subtracts an element from ND structure of it.
*
* @receiver the dividend.
* @param arg the divisor.
* @return the quotient.
*/
@OptIn(PerformancePitfall::class)
public operator fun StructureND<T>.minus(arg: T): StructureND<T> = this.map { value -> add(arg, -value) }
/**
* Adds an element to ND structure of it.
*
* @receiver the augend.
* @param arg the addend.
* @return the sum.
*/
@OptIn(PerformancePitfall::class)
public operator fun T.plus(arg: StructureND<T>): StructureND<T> = arg.map { value -> add(this@plus, value) }
/**
* Subtracts an ND structure from an element of it.
*
* @receiver the dividend.
* @param arg the divisor.
* @return the quotient.
*/
@OptIn(PerformancePitfall::class)
public operator fun T.minus(arg: StructureND<T>): StructureND<T> = arg.map { value -> add(-this@minus, value) }
public companion object
}
/**
* Adds an ND structure to an element of it.
*
* @receiver the augend.
* @param arg the addend.
* @return the sum.
*/
context(GroupOpsND<T, A>)
@OptIn(PerformancePitfall::class)
public operator fun <T, A : GroupOps<T>> StructureND<T>.plus(arg: T): StructureND<T> = this.map { value -> add(arg, value) }
/**
* Subtracts an element from ND structure of it.
*
* @receiver the dividend.
* @param arg the divisor.
* @return the quotient.
*/
context(GroupOpsND<T, A>)
@OptIn(PerformancePitfall::class)
public operator fun <T, A : GroupOps<T>> StructureND<T>.minus(arg: T): StructureND<T> = this.map { value -> add(arg, -value) }
/**
* Adds an element to ND structure of it.
*
* @receiver the augend.
* @param arg the addend.
* @return the sum.
*/
context(GroupOpsND<T, A>)
@OptIn(PerformancePitfall::class)
public operator fun <T, A : GroupOps<T>> T.plus(arg: StructureND<T>): StructureND<T> = arg.map { value -> add(this@plus, value) }
/**
* Subtracts an ND structure from an element of it.
*
* @receiver the dividend.
* @param arg the divisor.
* @return the quotient.
*/
context(GroupOpsND<T, A>)
@OptIn(PerformancePitfall::class)
public operator fun <T, A : GroupOps<T>> T.minus(arg: StructureND<T>): StructureND<T> = arg.map { value -> add(-this@minus, value) }
public interface GroupND<T, out A : Group<T>> : Group<StructureND<T>>, GroupOpsND<T, A>, WithShape {
override val zero: StructureND<T> get() = structureND(shape) { elementAlgebra.zero }
}
@ -194,31 +197,34 @@ public interface RingOpsND<T, out A : RingOps<T>> : RingOps<StructureND<T>>, Gro
override fun multiply(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
zip(left, right) { aValue, bValue -> multiply(aValue, bValue) }
//TODO move to extensions with context receivers
/**
* Multiplies an ND structure by an element of it.
*
* @receiver the multiplicand.
* @param arg the multiplier.
* @return the product.
*/
@OptIn(PerformancePitfall::class)
public operator fun StructureND<T>.times(arg: T): StructureND<T> = this.map { value -> multiply(arg, value) }
/**
* Multiplies an element by a ND structure of it.
*
* @receiver the multiplicand.
* @param arg the multiplier.
* @return the product.
*/
@OptIn(PerformancePitfall::class)
public operator fun T.times(arg: StructureND<T>): StructureND<T> = arg.map { value -> multiply(this@times, value) }
public companion object
}
/**
* Multiplies an ND structure by an element of it.
*
* @receiver the multiplicand.
* @param arg the multiplier.
* @return the product.
*/
context(RingOpsND<T, A>)
@OptIn(PerformancePitfall::class)
public operator fun <T, A : RingOps<T>> StructureND<T>.times(arg: T): StructureND<T> =
this.map { value -> multiply(arg, value) }
/**
* Multiplies an element by a ND structure of it.
*
* @receiver the multiplicand.
* @param arg the multiplier.
* @return the product.
*/
context(RingOpsND<T, A>)
@OptIn(PerformancePitfall::class)
public operator fun <T, A : RingOps<T>> T.times(arg: StructureND<T>): StructureND<T> =
arg.map { value -> multiply(this@times, value) }
public interface RingND<T, out A : Ring<T>> : Ring<StructureND<T>>, RingOpsND<T, A>, GroupND<T, A>, WithShape {
override val one: StructureND<T> get() = structureND(shape) { elementAlgebra.one }
}
@ -245,31 +251,33 @@ public interface FieldOpsND<T, out A : Field<T>> :
override fun divide(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
zip(left, right) { aValue, bValue -> divide(aValue, bValue) }
//TODO move to extensions after https://github.com/Kotlin/KEEP/blob/master/proposals/context-receivers.md
/**
* Divides an ND structure by an element of it.
*
* @receiver the dividend.
* @param arg the divisor.
* @return the quotient.
*/
@OptIn(PerformancePitfall::class)
public operator fun StructureND<T>.div(arg: T): StructureND<T> = this.map { value -> divide(arg, value) }
/**
* Divides an element by an ND structure of it.
*
* @receiver the dividend.
* @param arg the divisor.
* @return the quotient.
*/
@OptIn(PerformancePitfall::class)
public operator fun T.div(arg: StructureND<T>): StructureND<T> = arg.map { divide(it, this@div) }
@OptIn(PerformancePitfall::class)
override fun scale(a: StructureND<T>, value: Double): StructureND<T> = a.map { scale(it, value) }
}
/**
* Divides an ND structure by an element of it.
*
* @receiver the dividend.
* @param arg the divisor.
* @return the quotient.
*/
context(FieldOpsND<T, A>)
@OptIn(PerformancePitfall::class)
public operator fun <T, A : Field<T>> StructureND<T>.div(arg: T): StructureND<T> = this.map { value -> divide(arg, value) }
/**
* Divides an element by an ND structure of it.
*
* @receiver the dividend.
* @param arg the divisor.
* @return the quotient.
*/
context(FieldOpsND<T, A>)
@OptIn(PerformancePitfall::class)
public operator fun <T, A : Field<T>> T.div(arg: StructureND<T>): StructureND<T> = arg.map { divide(it, this@div) }
public interface FieldND<T, out A : Field<T>> : Field<StructureND<T>>, FieldOpsND<T, A>, RingND<T, A>, WithShape {
override val one: StructureND<T> get() = structureND(shape) { elementAlgebra.one }
}
}

View File

@ -101,7 +101,7 @@ public open class BufferedGroupNDOps<T, out A : Group<T>>(
override val bufferAlgebra: BufferAlgebra<T, A>,
override val indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
) : GroupOpsND<T, A>, BufferAlgebraND<T, A> {
override fun StructureND<T>.unaryMinus(): StructureND<T> = map { -it }
override fun negate(arg: StructureND<T>): StructureND<T> = arg.map { -it }
}
public open class BufferedRingOpsND<T, out A : Ring<T>>(

View File

@ -76,50 +76,17 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND<Double, DoubleField>(D
override fun add(left: StructureND<Double>, right: StructureND<Double>): DoubleBufferND =
zipInline(left.toBufferND(), right.toBufferND()) { l, r -> l + r }
override fun negate(arg: StructureND<Double>): DoubleBufferND = mapInline(arg.toBufferND()) { -it }
override fun subtract(left: StructureND<Double>, right: StructureND<Double>): DoubleBufferND =
zipInline(left.toBufferND(), right.toBufferND()) { l: Double, r: Double -> l - r }
override fun multiply(left: StructureND<Double>, right: StructureND<Double>): DoubleBufferND =
zipInline(left.toBufferND(), right.toBufferND()) { l, r -> l * r }
override fun StructureND<Double>.unaryMinus(): DoubleBufferND = mapInline(toBufferND()) { -it }
override fun StructureND<Double>.div(arg: StructureND<Double>): DoubleBufferND =
zipInline(toBufferND(), arg.toBufferND()) { l, r -> l / r }
override fun divide(left: StructureND<Double>, right: StructureND<Double>): DoubleBufferND =
zipInline(left.toBufferND(), right.toBufferND()) { l: Double, r: Double -> l / r }
override fun StructureND<Double>.div(arg: Double): DoubleBufferND =
mapInline(toBufferND()) { it / arg }
override fun Double.div(arg: StructureND<Double>): DoubleBufferND =
mapInline(arg.toBufferND()) { this / it }
override fun StructureND<Double>.unaryPlus(): DoubleBufferND = toBufferND()
override fun StructureND<Double>.plus(arg: StructureND<Double>): DoubleBufferND =
zipInline(toBufferND(), arg.toBufferND()) { l: Double, r: Double -> l + r }
override fun StructureND<Double>.minus(arg: StructureND<Double>): DoubleBufferND =
zipInline(toBufferND(), arg.toBufferND()) { l: Double, r: Double -> l - r }
override fun StructureND<Double>.times(arg: StructureND<Double>): DoubleBufferND =
zipInline(toBufferND(), arg.toBufferND()) { l: Double, r: Double -> l * r }
override fun StructureND<Double>.times(k: Number): DoubleBufferND =
mapInline(toBufferND()) { it * k.toDouble() }
override fun StructureND<Double>.div(k: Number): DoubleBufferND =
mapInline(toBufferND()) { it / k.toDouble() }
override fun Number.times(arg: StructureND<Double>): DoubleBufferND = arg * this
override fun StructureND<Double>.plus(arg: Double): DoubleBufferND = mapInline(toBufferND()) { it + arg }
override fun StructureND<Double>.minus(arg: Double): StructureND<Double> = mapInline(toBufferND()) { it - arg }
override fun Double.plus(arg: StructureND<Double>): StructureND<Double> = arg + this
override fun Double.minus(arg: StructureND<Double>): StructureND<Double> = mapInline(arg.toBufferND()) { this - it }
override fun scale(a: StructureND<Double>, value: Double): DoubleBufferND =
mapInline(a.toBufferND()) { it * value }
@ -181,7 +148,7 @@ public class DoubleFieldND(override val shape: Shape) :
it.kpow(pow)
}
override fun power(arg: StructureND<Double>, pow: Number): DoubleBufferND = if(pow.isInteger()){
override fun power(arg: StructureND<Double>, pow: Number): DoubleBufferND = if (pow.isInteger()) {
power(arg, pow.toInt())
} else {
val dpow = pow.toDouble()

View File

@ -11,6 +11,7 @@ import space.kscience.kmath.misc.Featured
import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.minus
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory
import kotlin.jvm.JvmName

View File

@ -9,12 +9,6 @@ import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Ring.Companion.optimizedPower
/**
* Stub for DSL the [Algebra] is.
*/
@DslMarker
public annotation class KMathContext
/**
* Represents an algebraic structure.
*
@ -137,46 +131,26 @@ public interface GroupOps<T> : Algebra<T> {
*/
public fun add(left: T, right: T): T
// Operations to be performed in this context. Could be moved to extensions in case of KEEP-176.
/**
* The negation of this element.
*
* @receiver this value.
* @param arg the element.
* @return the additive inverse of this value.
*/
public operator fun T.unaryMinus(): T
/**
* Returns this value.
*
* @receiver this value.
* @return this value.
*/
public operator fun T.unaryPlus(): T = this
/**
* Addition of two elements.
*
* @receiver the augend.
* @param arg the addend.
* @return the sum.
*/
public operator fun T.plus(arg: T): T = add(this, arg)
public fun negate(arg: T): T
/**
* Subtraction of two elements.
*
* @receiver the minuend.
* @param arg the subtrahend.
* @parm left the minuend.
* @param right the subtrahend.
* @return the difference.
*/
public operator fun T.minus(arg: T): T = add(this, -arg)
public fun subtract(left: T, right: T): T = add(left, -right)
// Dynamic dispatch of operations
override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) {
PLUS_OPERATION -> { arg -> +arg }
MINUS_OPERATION -> { arg -> -arg }
PLUS_OPERATION -> { arg -> arg }
MINUS_OPERATION -> ::negate
else -> super.unaryOperationFunction(operation)
}
@ -199,6 +173,44 @@ public interface GroupOps<T> : Algebra<T> {
}
}
/**
* The negation of this element.
*
* @receiver the element.
* @return the additive inverse of this value.
*/
context(GroupOps<T>)
public operator fun <T> T.unaryMinus(): T = negate(this)
/**
* Returns this value.
*
* @receiver this value.
* @return this value.
*/
context(GroupOps<T>)
public operator fun <T> T.unaryPlus(): T = this
/**
* Addition of two elements.
*
* @receiver the augend.
* @param arg the addend.
* @return the sum.
*/
context(GroupOps<T>)
public operator fun <T> T.plus(arg: T): T = add(this, arg)
/**
* Subtraction of two elements.
*
* @receiver the minuend.
* @param arg the subtrahend.
* @return the difference.
*/
context(GroupOps<T>)
public operator fun <T> T.minus(arg: T): T = subtract(this, arg)
/**
* Represents group i.e., algebraic structure with associative, binary operation [add].
*
@ -226,14 +238,6 @@ public interface RingOps<T> : GroupOps<T> {
*/
public fun multiply(left: T, right: T): T
/**
* Multiplies this element by scalar.
*
* @receiver the multiplier.
* @param arg the multiplicand.
*/
public operator fun T.times(arg: T): T = multiply(this, arg)
override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) {
TIMES_OPERATION -> ::multiply
else -> super.binaryOperationFunction(operation)
@ -247,6 +251,15 @@ public interface RingOps<T> : GroupOps<T> {
}
}
/**
* Multiplies two elements.
*
* @receiver the multiplier.
* @param arg the multiplicand.
*/
context(RingOps<T>)
public operator fun <T> T.times(arg: T): T = multiply(this, arg)
/**
* Represents ring i.e., algebraic structure with two associative binary operations called "addition" and
* "multiplication" and their neutral elements.
@ -264,7 +277,7 @@ public interface Ring<T> : Group<T>, RingOps<T> {
*/
public fun power(arg: T, pow: UInt): T = optimizedPower(arg, pow)
public companion object{
public companion object {
/**
* Raises [arg] to the non-negative integer power [exponent].
*
@ -311,15 +324,6 @@ public interface FieldOps<T> : RingOps<T> {
*/
public fun divide(left: T, right: T): T
/**
* Division of two elements.
*
* @receiver the dividend.
* @param arg the divisor.
* @return the quotient.
*/
public operator fun T.div(arg: T): T = divide(this, arg)
override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) {
DIV_OPERATION -> ::divide
else -> super.binaryOperationFunction(operation)
@ -333,6 +337,16 @@ public interface FieldOps<T> : RingOps<T> {
}
}
/**
* Division of two elements.
*
* @receiver the dividend.
* @param arg the divisor.
* @return the quotient.
*/
context(FieldOps<T>)
public operator fun <T> T.div(arg: T): T = divide(this, arg)
/**
* Represents field i.e., algebraic structure with three operations: associative, commutative addition and
* multiplication, and division. **This interface differs from the eponymous mathematical definition: fields in KMath
@ -345,7 +359,7 @@ public interface Field<T> : Ring<T>, FieldOps<T>, ScaleOperations<T>, NumericAlg
public fun power(arg: T, pow: Int): T = optimizedPower(arg, pow)
public companion object{
public companion object {
/**
* Raises [arg] to the integer power [exponent].
*
@ -358,7 +372,10 @@ public interface Field<T> : Ring<T>, FieldOps<T>, ScaleOperations<T>, NumericAlg
* @author Iaroslav Postovalov, Evgeniy Zhelenskiy
*/
private fun <T> Field<T>.optimizedPower(arg: T, exponent: Int): T = when {
exponent < 0 -> one / (this as Ring<T>).optimizedPower(arg, if (exponent == Int.MIN_VALUE) Int.MAX_VALUE.toUInt().inc() else (-exponent).toUInt())
exponent < 0 -> one / (this as Ring<T>).optimizedPower(
arg,
if (exponent == Int.MIN_VALUE) Int.MAX_VALUE.toUInt().inc() else (-exponent).toUInt()
)
else -> (this as Ring<T>).optimizedPower(arg, exponent.toUInt())
}
}

View File

@ -33,7 +33,7 @@ public object BigIntField : Field<BigInt>, NumbersAddOps<BigInt>, ScaleOperation
override fun number(value: Number): BigInt = value.toLong().toBigInt()
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
override fun BigInt.unaryMinus(): BigInt = -this
override fun negate(arg: BigInt): BigInt = -arg
override fun add(left: BigInt, right: BigInt): BigInt = left.plus(right)
override fun scale(a: BigInt, value: Double): BigInt = a.times(number(value))
override fun multiply(left: BigInt, right: BigInt): BigInt = left.times(right)

View File

@ -137,7 +137,7 @@ public open class BufferRingOps<T, A: Ring<T>>(
override fun add(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l + r }
override fun multiply(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l * r }
override fun Buffer<T>.unaryMinus(): Buffer<T> = map { -it }
override fun negate(arg: Buffer<T>): Buffer<T> = arg.map { negate(it) }
override fun unaryOperationFunction(operation: String): (arg: Buffer<T>) -> Buffer<T> =
super<BufferAlgebra>.unaryOperationFunction(operation)
@ -159,7 +159,7 @@ public open class BufferFieldOps<T, A : Field<T>>(
override fun divide(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l / r }
override fun scale(a: Buffer<T>, value: Double): Buffer<T> = a.map { scale(it, value) }
override fun Buffer<T>.unaryMinus(): Buffer<T> = map { -it }
override fun negate(arg: Buffer<T>): Buffer<T> = arg.map { -it }
override fun binaryOperationFunction(operation: String): (left: Buffer<T>, right: Buffer<T>) -> Buffer<T> =
super<BufferRingOps>.binaryOperationFunction(operation)

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.operations
import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory
import space.kscience.kmath.structures.DoubleBuffer
@ -32,8 +31,6 @@ public abstract class DoubleBufferOps : BufferAlgebra<Double, DoubleField>, Exte
override fun binaryOperationFunction(operation: String): (left: Buffer<Double>, right: Buffer<Double>) -> Buffer<Double> =
super<ExtendedFieldOps>.binaryOperationFunction(operation)
override fun Buffer<Double>.unaryMinus(): DoubleBuffer = mapInline { -it }
override fun add(left: Buffer<Double>, right: Buffer<Double>): DoubleBuffer {
require(right.size == left.size) {
"The size of the first buffer ${left.size} should be the same as for second one: ${right.size} "
@ -46,18 +43,17 @@ public abstract class DoubleBufferOps : BufferAlgebra<Double, DoubleField>, Exte
} else DoubleBuffer(DoubleArray(left.size) { left[it] + right[it] })
}
override fun Buffer<Double>.plus(arg: Buffer<Double>): DoubleBuffer = add(this, arg)
override fun negate(arg: Buffer<Double>): DoubleBuffer = arg.mapInline { -it }
override fun Buffer<Double>.minus(arg: Buffer<Double>): DoubleBuffer {
require(arg.size == this.size) {
"The size of the first buffer ${this.size} should be the same as for second one: ${arg.size} "
override fun subtract(left: Buffer<Double>, right: Buffer<Double>): DoubleBuffer {
require(left.size == right.size) {
"The size of the first buffer ${left.size} should be the same as for second one: ${right.size} "
}
return if (this is DoubleBuffer && arg is DoubleBuffer) {
val aArray = this.array
val bArray = arg.array
DoubleBuffer(DoubleArray(this.size) { aArray[it] - bArray[it] })
} else DoubleBuffer(DoubleArray(this.size) { this[it] - arg[it] })
return if (left is DoubleBuffer && right is DoubleBuffer)
DoubleBuffer(DoubleArray(left.size) { left.array[it] - right.array[it] })
else
DoubleBuffer(DoubleArray(left.size) { left[it] - right[it] })
}
//

View File

@ -116,35 +116,39 @@ public interface ScaleOperations<T> : Algebra<T> {
* @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 arg the multiplicand.
* @return the product.
*/
public operator fun Number.times(arg: T): T = arg * this
}
/**
* Multiplication of this element by a scalar.
*
* @receiver the multiplier.
* @param k the multiplicand.
* @return the product.
*/
context(ScaleOperations<T>)
public operator fun <T> 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.
*/
context(ScaleOperations<T>)
public operator fun <T> T.div(k: Number): T = scale(this, 1.0 / k.toDouble())
/**
* Multiplication of this number by element.
*
* @receiver the multiplier.
* @param arg the multiplicand.
* @return the product.
*/
context(ScaleOperations<T>)
public operator fun <T> Number.times(arg: T): T = arg * this
/**
* A combination of [NumericAlgebra] and [Ring] that adds intrinsic simple operations on numbers like `T+1`
* TODO to be removed and replaced by extensions after multiple receivers are there

View File

@ -68,7 +68,7 @@ public object DoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOp
override inline val zero: Double get() = 0.0
override inline val one: Double get() = 1.0
override inline fun number(value: Number): Double = value.toDouble()
override fun number(value: Number): Double = value.toDouble()
override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
when (operation) {
@ -77,6 +77,8 @@ public object DoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOp
}
override inline fun add(left: Double, right: Double): Double = left + right
override inline fun negate(arg: Double): Double = -arg
override inline fun subtract(left: Double, right: Double): Double = left - right
override inline fun multiply(left: Double, right: Double): Double = left * right
override inline fun divide(left: Double, right: Double): Double = left / right
@ -108,12 +110,6 @@ public object DoubleField : ExtendedField<Double>, Norm<Double, Double>, ScaleOp
override inline fun ln(arg: Double): Double = kotlin.math.ln(arg)
override inline fun norm(arg: Double): Double = abs(arg)
override inline fun Double.unaryMinus(): Double = -this
override inline fun Double.plus(arg: Double): Double = this + arg
override inline fun Double.minus(arg: Double): Double = this - arg
override inline fun Double.times(arg: Double): Double = this * arg
override inline fun Double.div(arg: Double): Double = this / arg
}
public val Double.Companion.algebra: DoubleField get() = DoubleField
@ -135,7 +131,10 @@ public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
}
override inline fun add(left: Float, right: Float): Float = left + right
override fun scale(a: Float, value: Double): Float = a * value.toFloat()
override inline fun negate(arg: Float): Float = -arg
override inline fun subtract(left: Float, right: Float): Float = left - right
override inline fun scale(a: Float, value: Double): Float = a * value.toFloat()
override inline fun multiply(left: Float, right: Float): Float = left * right
@ -162,12 +161,6 @@ public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
override inline fun ln(arg: Float): Float = kotlin.math.ln(arg)
override inline fun norm(arg: Float): Float = abs(arg)
override inline fun Float.unaryMinus(): Float = -this
override inline fun Float.plus(arg: Float): Float = this + arg
override inline fun Float.minus(arg: Float): Float = this - arg
override inline fun Float.times(arg: Float): Float = this * arg
override inline fun Float.div(arg: Float): Float = this / arg
}
public val Float.Companion.algebra: FloatField get() = FloatField
@ -185,13 +178,11 @@ public object IntRing : Ring<Int>, Norm<Int, Int>, NumericAlgebra<Int> {
override fun number(value: Number): Int = value.toInt()
override inline fun add(left: Int, right: Int): Int = left + right
override inline fun negate(arg: Int): Int = -arg
override inline fun subtract(left: Int, right: Int): Int = left - right
override inline fun multiply(left: Int, right: Int): Int = left * right
override inline fun norm(arg: Int): Int = abs(arg)
override inline fun Int.unaryMinus(): Int = -this
override inline fun Int.plus(arg: Int): Int = this + arg
override inline fun Int.minus(arg: Int): Int = this - arg
override inline fun Int.times(arg: Int): Int = this * arg
}
public val Int.Companion.algebra: IntRing get() = IntRing
@ -209,13 +200,11 @@ public object ShortRing : Ring<Short>, Norm<Short, Short>, NumericAlgebra<Short>
override fun number(value: Number): Short = value.toShort()
override inline fun add(left: Short, right: Short): Short = (left + right).toShort()
override inline fun multiply(left: Short, right: Short): Short = (left * right).toShort()
override fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort()
override inline fun negate(arg: Short): Short = (-arg).toShort()
override inline fun subtract(left: Short, right: Short): Short = (left - right).toShort()
override inline fun Short.unaryMinus(): Short = (-this).toShort()
override inline fun Short.plus(arg: Short): Short = (this + arg).toShort()
override inline fun Short.minus(arg: Short): Short = (this - arg).toShort()
override inline fun Short.times(arg: Short): Short = (this * arg).toShort()
override inline fun multiply(left: Short, right: Short): Short = (left * right).toShort()
override inline fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort()
}
public val Short.Companion.algebra: ShortRing get() = ShortRing
@ -233,13 +222,12 @@ public object ByteRing : Ring<Byte>, Norm<Byte, Byte>, NumericAlgebra<Byte> {
override fun number(value: Number): Byte = value.toByte()
override inline fun add(left: Byte, right: Byte): Byte = (left + right).toByte()
override inline fun multiply(left: Byte, right: Byte): Byte = (left * right).toByte()
override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte()
override inline fun negate(arg: Byte): Byte = (-arg).toByte()
override inline fun subtract(left: Byte, right: Byte): Byte = (left - right).toByte()
override inline fun Byte.unaryMinus(): Byte = (-this).toByte()
override inline fun Byte.plus(arg: Byte): Byte = (this + arg).toByte()
override inline fun Byte.minus(arg: Byte): Byte = (this - arg).toByte()
override inline fun Byte.times(arg: Byte): Byte = (this * arg).toByte()
override inline fun multiply(left: Byte, right: Byte): Byte = (left * right).toByte()
override inline fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte()
}
public val Byte.Companion.algebra: ByteRing get() = ByteRing
@ -256,14 +244,13 @@ public object LongRing : Ring<Long>, Norm<Long, Long>, NumericAlgebra<Long> {
get() = 1L
override fun number(value: Number): Long = value.toLong()
override inline fun add(left: Long, right: Long): Long = left + right
override inline fun multiply(left: Long, right: Long): Long = left * right
override fun norm(arg: Long): Long = abs(arg)
override inline fun Long.unaryMinus(): Long = (-this)
override inline fun Long.plus(arg: Long): Long = (this + arg)
override inline fun Long.minus(arg: Long): Long = (this - arg)
override inline fun Long.times(arg: Long): Long = (this * arg)
override inline fun add(left: Long, right: Long): Long = left + right
override inline fun negate(arg: Long): Long = -arg
override inline fun subtract(left: Long, right: Long): Long = left - right
override inline fun multiply(left: Long, right: Long): Long = left * right
override inline fun norm(arg: Long): Long = abs(arg)
}
public val Long.Companion.algebra: LongRing get() = LongRing

View File

@ -6,6 +6,8 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFails

View File

@ -7,13 +7,10 @@ package space.kscience.kmath.expressions
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.BooleanAlgebra
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import kotlin.test.Test
import kotlin.test.assertEquals
internal class InterpretTest {
@Test
fun interpretation() {

View File

@ -5,8 +5,7 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.asBuffer
import kotlin.math.E

View File

@ -10,6 +10,7 @@ import space.kscience.kmath.nd.ndAlgebra
import space.kscience.kmath.nd.structureND
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.times
import space.kscience.kmath.testutils.FieldVerifier
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -8,10 +8,7 @@ package space.kscience.kmath.structures
import space.kscience.kmath.linear.linearSpace
import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Norm
import space.kscience.kmath.operations.algebra
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import kotlin.math.abs
import kotlin.math.pow
import kotlin.test.Test

View File

@ -5,8 +5,7 @@
package space.kscience.kmath.testutils
import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals

View File

@ -5,9 +5,7 @@
package space.kscience.kmath.testutils
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import kotlin.test.assertEquals
internal open class RingVerifier<T, out A>(algebra: A, a: T, b: T, c: T, x: Number) :

View File

@ -5,9 +5,7 @@
package space.kscience.kmath.testutils
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals

View File

@ -19,10 +19,10 @@ public object JBigIntegerField : Ring<BigInteger>, NumericAlgebra<BigInteger> {
override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong())
override fun add(left: BigInteger, right: BigInteger): BigInteger = left.add(right)
override operator fun BigInteger.minus(arg: BigInteger): BigInteger = subtract(arg)
override fun multiply(left: BigInteger, right: BigInteger): BigInteger = left.multiply(right)
override fun negate(arg: BigInteger): BigInteger = arg.negate()
override fun subtract(left: BigInteger, right: BigInteger): BigInteger = left.subtract(right)
override operator fun BigInteger.unaryMinus(): BigInteger = negate()
override fun multiply(left: BigInteger, right: BigInteger): BigInteger = left.multiply(right)
}
/**
@ -40,7 +40,9 @@ public abstract class JBigDecimalFieldBase internal constructor(
get() = BigDecimal.ONE
override fun add(left: BigDecimal, right: BigDecimal): BigDecimal = left.add(right)
override operator fun BigDecimal.minus(arg: BigDecimal): BigDecimal = subtract(arg)
override fun negate(arg: BigDecimal): BigDecimal = arg.negate(mathContext)
override fun subtract(left: BigDecimal, right: BigDecimal): BigDecimal = left.subtract(right)
override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble())
override fun scale(a: BigDecimal, value: Double): BigDecimal =
@ -50,7 +52,6 @@ public abstract class JBigDecimalFieldBase internal constructor(
override fun divide(left: BigDecimal, right: BigDecimal): BigDecimal = left.divide(right, mathContext)
override fun power(arg: BigDecimal, pow: Number): BigDecimal = arg.pow(pow.toInt(), mathContext)
override fun sqrt(arg: BigDecimal): BigDecimal = arg.sqrt(mathContext)
override operator fun BigDecimal.unaryMinus(): BigDecimal = negate(mathContext)
}
/**

View File

@ -1,7 +1,7 @@
plugins {
kotlin("multiplatform")
id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native")
// id("ru.mipt.npm.gradle.native")
}
kotlin.sourceSets {
@ -24,4 +24,9 @@ kotlin.sourceSets {
readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
}
}
// Testing multi-receiver!
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
enabled = false
}

View File

@ -10,10 +10,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.runningReduce
import kotlinx.coroutines.flow.scan
import space.kscience.kmath.operations.GroupOps
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
public fun <T> Flow<T>.cumulativeSum(group: GroupOps<T>): Flow<T> =
group { runningReduce { sum, element -> sum + element } }

View File

@ -39,15 +39,11 @@ public fun <T> StructureND<T>.deferred(index: IntArray): Deferred<T> =
public suspend fun <T> StructureND<T>.await(index: IntArray): T =
if (this is LazyStructureND<T>) await(index) else get(index)
/**
* PENDING would benefit from KEEP-176
*/
context(CoroutineScope)
public inline fun <T, R> StructureND<T>.mapAsyncIndexed(
scope: CoroutineScope,
crossinline function: suspend (T, index: IntArray) -> R,
): LazyStructureND<R> = LazyStructureND(scope, shape) { index -> function(get(index), index) }
): LazyStructureND<R> = LazyStructureND(this@CoroutineScope, shape) { index -> function(get(index), index) }
public inline fun <T, R> StructureND<T>.mapAsync(
scope: CoroutineScope,
crossinline function: suspend (T) -> R,
): LazyStructureND<R> = LazyStructureND(scope, shape) { index -> function(get(index)) }
context(CoroutineScope)
public inline fun <T, R> StructureND<T>.mapAsync(crossinline function: suspend (T) -> R): LazyStructureND<R> =
LazyStructureND(this@CoroutineScope, shape) { index -> function(get(index)) }

View File

@ -1,7 +1,7 @@
plugins {
kotlin("multiplatform")
id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native")
// id("ru.mipt.npm.gradle.native")
}
description = "A proof of concept module for adding type-safe dimensions to structures"
@ -23,3 +23,8 @@ kotlin.sourceSets {
readme {
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
}
// Testing multi-receiver!
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
enabled = false
}

View File

@ -33,10 +33,19 @@ readme {
) { "LinearSpace implementations." }
}
kotlin.sourceSets.main {
val codegen by tasks.creating {
ejmlCodegen(kotlin.srcDirs.first().absolutePath + "/space/kscience/kmath/ejml/_generated.kt")
}
kotlin.sourceSets {
filter { it.name.contains("test", true) }
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
.forEach {
it.optIn("space.kscience.kmath.misc.PerformancePitfall")
it.optIn("space.kscience.kmath.misc.UnstableKMathAPI")
}
kotlin.srcDirs(files().builtBy(codegen))
main {
val codegen by tasks.creating {
ejmlCodegen(kotlin.srcDirs.first().absolutePath + "/space/kscience/kmath/ejml/_generated.kt")
}
kotlin.srcDirs(files().builtBy(codegen))
}
}

View File

@ -208,7 +208,7 @@ public object EjmlLinearSpaceDDRM : EjmlLinearSpace<Double, DoubleField, DMatrix
structure.getFeature(type)?.let { return it }
val origin = structure.toEjml().origin
return when (type) {
return type.cast(when (type) {
InverseMatrixFeature::class -> object : InverseMatrixFeature<Double> {
override val inverse: Matrix<Double> by lazy {
val res = origin.copy()
@ -270,8 +270,8 @@ public object EjmlLinearSpaceDDRM : EjmlLinearSpace<Double, DoubleField, DMatrix
override val p: Matrix<Double> by lazy { lup.getRowPivot(null).wrapMatrix() }
}
else -> null
}?.let(type::cast)
else -> return null
})
}
/**
@ -442,7 +442,7 @@ public object EjmlLinearSpaceFDRM : EjmlLinearSpace<Float, FloatField, FMatrixRM
structure.getFeature(type)?.let { return it }
val origin = structure.toEjml().origin
return when (type) {
return type.cast(when (type) {
InverseMatrixFeature::class -> object : InverseMatrixFeature<Float> {
override val inverse: Matrix<Float> by lazy {
val res = origin.copy()
@ -504,8 +504,8 @@ public object EjmlLinearSpaceFDRM : EjmlLinearSpace<Float, FloatField, FMatrixRM
override val p: Matrix<Float> by lazy { lup.getRowPivot(null).wrapMatrix() }
}
else -> null
}?.let(type::cast)
else -> return null
})
}
/**
@ -684,7 +684,7 @@ public object EjmlLinearSpaceDSCC : EjmlLinearSpace<Double, DoubleField, DMatrix
structure.getFeature(type)?.let { return it }
val origin = structure.toEjml().origin
return when (type) {
return type.cast(when (type) {
QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> {
private val qr by lazy {
DecompositionFactory_DSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) }
@ -733,8 +733,8 @@ public object EjmlLinearSpaceDSCC : EjmlLinearSpace<Double, DoubleField, DMatrix
override val determinant: Double by lazy { elementAlgebra.number(lu.computeDeterminant().real) }
}
else -> null
}?.let(type::cast)
else -> return null
})
}
/**
@ -913,7 +913,7 @@ public object EjmlLinearSpaceFSCC : EjmlLinearSpace<Float, FloatField, FMatrixSp
structure.getFeature(type)?.let { return it }
val origin = structure.toEjml().origin
return when (type) {
return type.cast(when (type) {
QRDecompositionFeature::class -> object : QRDecompositionFeature<Float> {
private val qr by lazy {
DecompositionFactory_FSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) }
@ -962,8 +962,8 @@ public object EjmlLinearSpaceFSCC : EjmlLinearSpace<Float, FloatField, FMatrixSp
override val determinant: Float by lazy { elementAlgebra.number(lu.computeDeterminant().real) }
}
else -> null
}?.let(type::cast)
else -> return null
})
}
/**

View File

@ -1,7 +1,7 @@
plugins {
kotlin("multiplatform")
id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native")
// id("ru.mipt.npm.gradle.native")
}
kotlin.sourceSets.commonMain {
@ -40,3 +40,8 @@ readme {
"Uniform grid generators"
}
}
// Testing multi-receiver!
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
enabled = false
}

View File

@ -1,7 +1,7 @@
plugins {
kotlin("multiplatform")
id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native")
// id("ru.mipt.npm.gradle.native")
}
description = "Functions, integration and interpolation"
@ -32,3 +32,8 @@ readme {
"Univariate and multivariate quadratures"
}
}
// Testing multi-receiver!
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
enabled = false
}

View File

@ -71,7 +71,7 @@ public fun <T, A> Polynomial<T>.integrate(
): Polynomial<T> where A : Field<T>, A : NumericAlgebra<T> = algebra {
val integratedCoefficients = buildList(coefficients.size + 1) {
add(zero)
coefficients.forEachIndexed{ index, t -> add(t / (number(index) + one)) }
coefficients.forEachIndexed { index, t -> add(t / (number(index) + one)) }
}
Polynomial(integratedCoefficients)
}
@ -100,8 +100,8 @@ public class PolynomialSpace<T, C>(
) : Group<Polynomial<T>>, ScaleOperations<Polynomial<T>> where C : Ring<T>, C : ScaleOperations<T> {
override val zero: Polynomial<T> = Polynomial(emptyList())
override fun Polynomial<T>.unaryMinus(): Polynomial<T> = ring {
Polynomial(coefficients.map { -it })
override fun negate(arg: Polynomial<T>): Polynomial<T> = ring {
Polynomial(arg.coefficients.map { -it })
}
override fun add(left: Polynomial<T>, right: Polynomial<T>): Polynomial<T> {

View File

@ -6,6 +6,9 @@ package space.kscience.kmath.integration
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.minus
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.asBuffer
import space.kscience.kmath.structures.indices

View File

@ -6,10 +6,7 @@
package space.kscience.kmath.integration
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.sum
import space.kscience.kmath.operations.*
/**
* Use double pass Simpson rule integration with a fixed number of points.
@ -60,7 +57,8 @@ public class SimpsonIntegrator<T : Any>(
}
@UnstableKMathAPI
public val <T : Any> Field<T>.simpsonIntegrator: SimpsonIntegrator<T> get() = SimpsonIntegrator(this)
public val <T : Any> Field<T>.simpsonIntegrator: SimpsonIntegrator<T>
get() = SimpsonIntegrator(this)
/**
* Use double pass Simpson rule integration with a fixed number of points.

View File

@ -9,8 +9,7 @@ import space.kscience.kmath.data.XYColumnarData
import space.kscience.kmath.functions.PiecewisePolynomial
import space.kscience.kmath.functions.Polynomial
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
@OptIn(UnstableKMathAPI::class)
internal fun <T : Comparable<T>> insureSorted(points: XYColumnarData<*, T, *>) {

View File

@ -9,9 +9,7 @@ import space.kscience.kmath.data.XYColumnarData
import space.kscience.kmath.functions.PiecewisePolynomial
import space.kscience.kmath.functions.Polynomial
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.DoubleBuffer
import space.kscience.kmath.structures.MutableBufferFactory

View File

@ -1,7 +1,7 @@
plugins {
kotlin("multiplatform")
id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native")
// id("ru.mipt.npm.gradle.native")
}
kotlin.sourceSets.commonMain {
@ -13,3 +13,8 @@ kotlin.sourceSets.commonMain {
readme {
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
}
// Testing multi-receiver!
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
enabled = false
}

View File

@ -6,12 +6,11 @@
package space.kscience.kmath.geometry
import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.minus
import kotlin.math.sqrt
@OptIn(UnstableKMathAPI::class)
public interface Vector2D : Point<Double>, Vector {
public val x: Double
public val y: Double
@ -44,7 +43,7 @@ public object Euclidean2DSpace : GeometrySpace<Vector2D>, ScaleOperations<Vector
override val zero: Vector2D by lazy { Vector2D(0.0, 0.0) }
public fun Vector2D.norm(): Double = sqrt(x * x + y * y)
override fun Vector2D.unaryMinus(): Vector2D = Vector2D(-x, -y)
override fun negate(arg: Vector2D): Vector2D = Vector2D(-arg.x, -arg.y)
override fun Vector2D.distanceTo(other: Vector2D): Double = (this - other).norm()
override fun add(left: Vector2D, right: Vector2D): Vector2D = Vector2D(left.x + right.x, left.y + right.y)

View File

@ -6,12 +6,11 @@
package space.kscience.kmath.geometry
import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.minus
import kotlin.math.sqrt
@OptIn(UnstableKMathAPI::class)
public interface Vector3D : Point<Double>, Vector {
public val x: Double
public val y: Double
@ -43,7 +42,7 @@ public object Euclidean3DSpace : GeometrySpace<Vector3D>, ScaleOperations<Vector
override val zero: Vector3D by lazy { Vector3D(0.0, 0.0, 0.0) }
public fun Vector3D.norm(): Double = sqrt(x * x + y * y + z * z)
override fun Vector3D.unaryMinus(): Vector3D = Vector3D(-x, -y, -z)
override fun negate(arg: Vector3D): Vector3D = Vector3D(-arg.x, -arg.y, -arg.z)
override fun Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm()

View File

@ -5,6 +5,11 @@
package space.kscience.kmath.geometry
import space.kscience.kmath.operations.div
import space.kscience.kmath.operations.minus
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
/**
* Project vector onto a line.
* @param vector to project

View File

@ -5,6 +5,8 @@
package space.kscience.kmath.geometry
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import kotlin.math.sqrt
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -5,6 +5,8 @@
package space.kscience.kmath.geometry
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.geometry
import space.kscience.kmath.operations.minus
import kotlin.test.Test
import kotlin.test.assertTrue

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.geometry
import space.kscience.kmath.operations.minus
import kotlin.test.Test
import kotlin.test.assertTrue

View File

@ -1,7 +1,7 @@
plugins {
kotlin("multiplatform")
id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native")
// id("ru.mipt.npm.gradle.native")
}
kscience {
@ -9,6 +9,12 @@ kscience {
}
kotlin.sourceSets {
filter { it.name.contains("test", true) }
.map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings)
.forEach {
it.optIn("space.kscience.kmath.misc.UnstableKMathAPI")
}
commonMain {
dependencies {
api(project(":kmath-core"))
@ -26,3 +32,8 @@ kotlin.sourceSets {
readme {
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
}
// Testing multi-receiver!
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
enabled = false
}

View File

@ -9,6 +9,7 @@ import kotlinx.atomicfu.atomic
import kotlinx.atomicfu.getAndUpdate
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.plus
/**
* Common representation for atomic counters
@ -72,5 +73,3 @@ public class ObjectCounter<T : Any>(private val group: Group<T>) : Counter<T> {
override val value: T get() = innerValue.value
}

View File

@ -11,9 +11,7 @@ import space.kscience.kmath.nd.DefaultStrides
import space.kscience.kmath.nd.FieldOpsND
import space.kscience.kmath.nd.Shape
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
/**
* @param T the type of the argument space

View File

@ -7,10 +7,7 @@ package space.kscience.kmath.histogram
import space.kscience.kmath.domains.DoubleDomain1D
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.Buffer
import kotlin.math.floor
@ -69,8 +66,8 @@ public class UniformHistogram1DGroup<V : Any, A>(
)
}
override fun Histogram1D<Double, V>.unaryMinus(): UniformHistogram1D<V> = valueAlgebra {
UniformHistogram1D(this@UniformHistogram1DGroup, produceFrom(this@unaryMinus).values.mapValues { -it.value })
override fun negate(arg: Histogram1D<Double, V>): UniformHistogram1D<V> = valueAlgebra {
UniformHistogram1D(this@UniformHistogram1DGroup, produceFrom(arg).values.mapValues { -it.value })
}
override fun scale(

View File

@ -14,6 +14,7 @@ import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.unaryMinus
import space.kscience.kmath.structures.*
import kotlin.math.floor
@ -98,8 +99,8 @@ public class UniformHistogramGroupND<V : Any, A : Field<V>>(
return HistogramND(this, values)
}
override fun HistogramND<Double, HyperSquareDomain, V>.unaryMinus(): HistogramND<Double, HyperSquareDomain, V> =
this * (-1)
override fun negate(arg: HistogramND<Double, HyperSquareDomain, V>): HistogramND<Double, HyperSquareDomain, V> =
HistogramND(this, valueAlgebraND { -arg.values })
}
/**

View File

@ -10,6 +10,7 @@ package space.kscience.kmath.histogram
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.DefaultStrides
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.minus
import space.kscience.kmath.real.DoubleVector
import kotlin.random.Random
import kotlin.test.*

View File

@ -10,6 +10,7 @@ import kotlinx.coroutines.test.runTest
import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.plus
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.stat.nextBuffer
import kotlin.native.concurrent.ThreadLocal
@ -36,7 +37,7 @@ internal class UniformHistogram1DTest {
@Test
fun rebinDown() = runTest {
val h1 = Histogram.uniform1D(DoubleField, 0.01).produce(generator.nextDoubleBuffer(10000))
val h2 = Histogram.uniform1D(DoubleField,0.03).produceFrom(h1)
val h2 = Histogram.uniform1D(DoubleField, 0.03).produceFrom(h1)
assertEquals(10000, h2.bins.sumOf { it.binValue }.toInt())
}
@ -44,13 +45,13 @@ internal class UniformHistogram1DTest {
@Test
fun rebinUp() = runTest {
val h1 = Histogram.uniform1D(DoubleField, 0.03).produce(generator.nextDoubleBuffer(10000))
val h2 = Histogram.uniform1D(DoubleField,0.01).produceFrom(h1)
val h2 = Histogram.uniform1D(DoubleField, 0.01).produceFrom(h1)
assertEquals(10000, h2.bins.sumOf { it.binValue }.toInt())
}
@ThreadLocal
companion object{
companion object {
private val generator = RandomGenerator.default(123)
}
}

View File

@ -11,9 +11,7 @@ import space.kscience.kmath.domains.DoubleDomain1D
import space.kscience.kmath.domains.center
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.misc.sorted
import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.first
import space.kscience.kmath.structures.indices
@ -123,7 +121,18 @@ public class TreeHistogramGroup<V : Any, A>(
return TreeHistogram(bins)
}
override fun TreeHistogram<V>.unaryMinus(): TreeHistogram<V> = this * (-1)
override fun negate(arg: TreeHistogram<V>): TreeHistogram<V> {
val bins = TreeMap<Double, Bin1D<Double, V>>().apply {
arg.bins.forEach { bin ->
put(
bin.domain.center,
Bin1D(bin.domain, valueAlgebra { -bin.binValue })
)
}
}
return TreeHistogram(bins)
}
override val zero: TreeHistogram<V> = produce { }
}

View File

@ -29,6 +29,8 @@ public object JafamaDoubleField : ExtendedField<Double>, Norm<Double, Double>, S
}
override inline fun add(left: Double, right: Double): Double = left + right
override inline fun negate(arg: Double): Double = -arg
override inline fun subtract(left: Double, right: Double): Double = left - right
override inline fun multiply(left: Double, right: Double): Double = left * right
override inline fun divide(left: Double, right: Double): Double = left / right
@ -55,12 +57,6 @@ public object JafamaDoubleField : ExtendedField<Double>, Norm<Double, Double>, S
override inline fun ln(arg: Double): Double = FastMath.log(arg)
override inline fun norm(arg: Double): Double = FastMath.abs(arg)
override inline fun Double.unaryMinus(): Double = -this
override inline fun Double.plus(arg: Double): Double = this + arg
override inline fun Double.minus(arg: Double): Double = this - arg
override inline fun Double.times(arg: Double): Double = this * arg
override inline fun Double.div(arg: Double): Double = this / arg
}
/**
@ -80,6 +76,8 @@ public object StrictJafamaDoubleField : ExtendedField<Double>, Norm<Double, Doub
}
override inline fun add(left: Double, right: Double): Double = left + right
override inline fun negate(arg: Double): Double = -arg
override inline fun subtract(left: Double, right: Double): Double = left - right
override inline fun multiply(left: Double, right: Double): Double = left * right
override inline fun divide(left: Double, right: Double): Double = left / right
@ -106,10 +104,4 @@ public object StrictJafamaDoubleField : ExtendedField<Double>, Norm<Double, Doub
override inline fun ln(arg: Double): Double = StrictFastMath.log(arg)
override inline fun norm(arg: Double): Double = StrictFastMath.abs(arg)
override inline fun Double.unaryMinus(): Double = -this
override inline fun Double.plus(arg: Double): Double = this + arg
override inline fun Double.minus(arg: Double): Double = this - arg
override inline fun Double.times(arg: Double): Double = this * arg
override inline fun Double.div(arg: Double): Double = this / arg
}

View File

@ -23,6 +23,8 @@ import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.operations.asSequence
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import space.kscience.kmath.structures.Buffer
/**

View File

@ -8,7 +8,6 @@ package space.kscience.kmath.kotlingrad
import ai.hypergraph.kotlingrad.api.*
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.MstExtendedField
import space.kscience.kmath.expressions.MstExtendedField.unaryMinus
import space.kscience.kmath.expressions.MstNumericAlgebra
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.operations.*

View File

@ -1,7 +1,7 @@
plugins {
kotlin("multiplatform")
id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native")
// id("ru.mipt.npm.gradle.native")
}
readme {

View File

@ -20,8 +20,7 @@ internal class ByteBufferMemory(
val startOffset: Int = 0,
override val size: Int = buffer.limit(),
) : Memory {
@Suppress("NOTHING_TO_INLINE")
private inline fun position(o: Int): Int = startOffset + o
private fun position(o: Int): Int = startOffset + o
override fun view(offset: Int, length: Int): Memory {
require(offset >= 0) { "offset shouldn't be negative: $offset" }

View File

@ -7,28 +7,29 @@ package space.kscience.kmath.multik
import org.jetbrains.kotlinx.multik.ndarray.data.DataType
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.ExponentialOperations
import space.kscience.kmath.operations.TrigonometricOperations
import space.kscience.kmath.operations.*
public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra<Double, DoubleField>(),
TrigonometricOperations<StructureND<Double>>, ExponentialOperations<StructureND<Double>> {
override val elementAlgebra: DoubleField get() = DoubleField
override val type: DataType get() = DataType.DoubleDataType
override fun sin(arg: StructureND<Double>): MultikTensor<Double> = multikMath.mathEx.sin(arg.asMultik().array).wrap()
override fun sin(arg: StructureND<Double>): MultikTensor<Double> =
multikMath.mathEx.sin(arg.asMultik().array).wrap()
override fun cos(arg: StructureND<Double>): MultikTensor<Double> = multikMath.mathEx.cos(arg.asMultik().array).wrap()
override fun cos(arg: StructureND<Double>): MultikTensor<Double> =
multikMath.mathEx.cos(arg.asMultik().array).wrap()
override fun tan(arg: StructureND<Double>): MultikTensor<Double> = sin(arg) / cos(arg)
override fun asin(arg: StructureND<Double>): MultikTensor<Double> = arg.map { asin(it) }
override fun asin(arg: StructureND<Double>): MultikTensor<Double> = arg.map { asin(it) }
override fun acos(arg: StructureND<Double>): MultikTensor<Double> = arg.map { acos(it) }
override fun atan(arg: StructureND<Double>): MultikTensor<Double> = arg.map { atan(it) }
override fun exp(arg: StructureND<Double>): MultikTensor<Double> = multikMath.mathEx.exp(arg.asMultik().array).wrap()
override fun exp(arg: StructureND<Double>): MultikTensor<Double> =
multikMath.mathEx.exp(arg.asMultik().array).wrap()
override fun ln(arg: StructureND<Double>): MultikTensor<Double> = multikMath.mathEx.log(arg.asMultik().array).wrap()
@ -39,7 +40,7 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra<Double, DoubleFi
override fun tanh(arg: StructureND<Double>): MultikTensor<Double> {
val expPlus = exp(arg)
val expMinus = exp(-arg)
return (expPlus - expMinus) / (expPlus + expMinus)
return divide((expPlus - expMinus), (expPlus + expMinus))
}
override fun asinh(arg: StructureND<Double>): MultikTensor<Double> = arg.map { asinh(it) }
@ -51,4 +52,3 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra<Double, DoubleFi
public val Double.Companion.multikAlgebra: MultikTensorAlgebra<Double, DoubleField> get() = MultikDoubleAlgebra
public val DoubleField.multikAlgebra: MultikTensorAlgebra<Double, DoubleField> get() = MultikDoubleAlgebra

View File

@ -50,7 +50,7 @@ private fun <T, D : Dimension> MultiArray<T, D>.asD2Array(): D2Array<T> {
else throw ClassCastException("Cannot cast MultiArray to NDArray.")
}
public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
public abstract class MultikTensorAlgebra<T, out A : Ring<T>> : TensorAlgebra<T, A>
where T : Number, T : Comparable<T> {
public abstract val type: DataType
@ -138,14 +138,8 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
get(intArrayOf(0))
} else null
override fun T.plus(arg: StructureND<T>): MultikTensor<T> =
arg.plus(this)
override fun StructureND<T>.plus(arg: T): MultikTensor<T> =
asMultik().array.deepCopy().apply { plusAssign(arg) }.wrap()
override fun StructureND<T>.plus(arg: StructureND<T>): MultikTensor<T> =
asMultik().array.plus(arg.asMultik().array).wrap()
override fun add(left: StructureND<T>, right: StructureND<T>): MultikTensor<T> =
left.asMultik().array.plus(right.asMultik().array).wrap()
override fun Tensor<T>.plusAssign(value: T) {
if (this is MultikTensor) {
@ -163,13 +157,8 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
}
}
override fun T.minus(arg: StructureND<T>): MultikTensor<T> = (-(arg.asMultik().array - this)).wrap()
override fun StructureND<T>.minus(arg: T): MultikTensor<T> =
asMultik().array.deepCopy().apply { minusAssign(arg) }.wrap()
override fun StructureND<T>.minus(arg: StructureND<T>): MultikTensor<T> =
asMultik().array.minus(arg.asMultik().array).wrap()
override fun subtract(left: StructureND<T>, right: StructureND<T>): MultikTensor<T> =
left.asMultik().array.minus(right.asMultik().array).wrap()
override fun Tensor<T>.minusAssign(value: T) {
if (this is MultikTensor) {
@ -187,14 +176,8 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
}
}
override fun T.times(arg: StructureND<T>): MultikTensor<T> =
arg.asMultik().array.deepCopy().apply { timesAssign(this@times) }.wrap()
override fun StructureND<T>.times(arg: T): Tensor<T> =
asMultik().array.deepCopy().apply { timesAssign(arg) }.wrap()
override fun StructureND<T>.times(arg: StructureND<T>): MultikTensor<T> =
asMultik().array.times(arg.asMultik().array).wrap()
override fun multiply(left: StructureND<T>, right: StructureND<T>): MultikTensor<T> =
left.asMultik().array.times(right.asMultik().array).wrap()
override fun Tensor<T>.timesAssign(value: T) {
if (this is MultikTensor) {
@ -212,12 +195,11 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
}
}
override fun StructureND<T>.unaryMinus(): MultikTensor<T> =
asMultik().array.unaryMinus().wrap()
override fun negate(arg: StructureND<T>): MultikTensor<T> = (-arg.asMultik().array).wrap()
override fun Tensor<T>.get(i: Int): MultikTensor<T> = asMultik().array.mutableView(i).wrap()
override fun Tensor<T>.transpose(i: Int, j: Int): MultikTensor<T> = asMultik().array.transpose(i, j).wrap()
override fun StructureND<T>.transpose(i: Int, j: Int): MultikTensor<T> = asMultik().array.transpose(i, j).wrap()
override fun Tensor<T>.view(shape: IntArray): MultikTensor<T> {
require(shape.all { it > 0 })
@ -282,16 +264,36 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
}
}
public abstract class MultikDivisionTensorAlgebra<T, A : Field<T>>
context(MultikTensorAlgebra<T, A>)
public operator fun <T, A : Ring<T>> T.plus(arg: StructureND<T>): MultikTensor<T> where T : Comparable<T>, T : Number =
arg.plus(this)
context(MultikTensorAlgebra<T, A>)
public operator fun <T, A : Ring<T>> StructureND<T>.plus(arg: T): MultikTensor<T> where T : Comparable<T>, T : Number =
asMultik().array.deepCopy().apply { plusAssign(arg) }.wrap()
context(MultikTensorAlgebra<T, A>)
public operator fun <T, A : Ring<T>> T.minus(arg: StructureND<T>): MultikTensor<T> where T : Comparable<T>, T : Number =
(-(arg.asMultik().array - this)).wrap()
context(MultikTensorAlgebra<T, A>)
public operator fun <T, A : Ring<T>> StructureND<T>.minus(arg: T): MultikTensor<T> where T : Comparable<T>, T : Number =
asMultik().array.deepCopy().apply { minusAssign(arg) }.wrap()
context(MultikTensorAlgebra<T, A>)
public operator fun <T, A : Ring<T>> T.times(arg: StructureND<T>): MultikTensor<T> where T : Comparable<T>, T : Number =
arg.asMultik().array.deepCopy().apply { timesAssign(this@times) }.wrap()
context(MultikTensorAlgebra<T, A>)
public operator fun <T, A : Ring<T>> StructureND<T>.times(arg: T): Tensor<T> where T : Comparable<T>, T : Number =
asMultik().array.deepCopy().apply { timesAssign(arg) }.wrap()
public abstract class MultikDivisionTensorAlgebra<T, out A : Field<T>>
: MultikTensorAlgebra<T, A>(), TensorPartialDivisionAlgebra<T, A> where T : Number, T : Comparable<T> {
override fun T.div(arg: StructureND<T>): MultikTensor<T> = arg.map { elementAlgebra.divide(this@div, it) }
override fun StructureND<T>.div(arg: T): MultikTensor<T> =
asMultik().array.deepCopy().apply { divAssign(arg) }.wrap()
override fun StructureND<T>.div(arg: StructureND<T>): MultikTensor<T> =
asMultik().array.div(arg.asMultik().array).wrap()
override fun divide(left: StructureND<T>, right: StructureND<T>): MultikTensor<T> =
left.asMultik().array.div(right.asMultik().array).wrap()
override fun Tensor<T>.divAssign(value: T) {
if (this is MultikTensor) {
@ -310,6 +312,18 @@ public abstract class MultikDivisionTensorAlgebra<T, A : Field<T>>
}
}
context(MultikDivisionTensorAlgebra<T, A>)
public operator fun <T, A : Field<T>> StructureND<T>.div(arg: StructureND<T>): MultikTensor<T> where T : Number, T : Comparable<T> =
divide(this, arg)
context(MultikDivisionTensorAlgebra<T, A>)
public operator fun <T, A : Field<T>> T.div(arg: StructureND<T>): MultikTensor<T> where T : Number, T : Comparable<T> =
arg.map { elementAlgebra.divide(this@div, it) }
context(MultikDivisionTensorAlgebra<T, A>)
public operator fun <T, A : Field<T>> StructureND<T>.div(arg: T): MultikTensor<T> where T : Number, T : Comparable<T> =
asMultik().array.deepCopy().apply { divAssign(arg) }.wrap()
public object MultikFloatAlgebra : MultikDivisionTensorAlgebra<Float, FloatField>() {
override val elementAlgebra: FloatField get() = FloatField
override val type: DataType get() = DataType.FloatDataType
@ -340,4 +354,4 @@ public object MultikLongAlgebra : MultikTensorAlgebra<Long, LongRing>() {
}
public val Long.Companion.multikAlgebra: MultikTensorAlgebra<Long, LongRing> get() = MultikLongAlgebra
public val LongRing.multikAlgebra: MultikTensorAlgebra<Long, LongRing> get() = MultikLongAlgebra
public val LongRing.multikAlgebra: MultikTensorAlgebra<Long, LongRing> get() = MultikLongAlgebra

View File

@ -45,6 +45,7 @@ public sealed interface Nd4jArrayAlgebra<T, out C : Algebra<T>> : AlgebraND<T, C
return newStruct
}
@OptIn(PerformancePitfall::class)
override fun StructureND<T>.mapIndexed(
transform: C.(index: IntArray, T) -> T,
): Nd4jArrayStructure<T> {
@ -53,6 +54,7 @@ public sealed interface Nd4jArrayAlgebra<T, out C : Algebra<T>> : AlgebraND<T, C
return new
}
@OptIn(PerformancePitfall::class)
override fun zip(
left: StructureND<T>,
right: StructureND<T>,
@ -72,15 +74,14 @@ public sealed interface Nd4jArrayAlgebra<T, out C : Algebra<T>> : AlgebraND<T, C
* @param S the type of space of structure elements.
*/
public sealed interface Nd4jArrayGroupOps<T, out S : Ring<T>> : GroupOpsND<T, S>, Nd4jArrayAlgebra<T, S> {
override fun add(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> =
left.ndArray.add(right.ndArray).wrap()
override operator fun StructureND<T>.minus(arg: StructureND<T>): Nd4jArrayStructure<T> =
ndArray.sub(arg.ndArray).wrap()
override fun subtract(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> =
left.ndArray.sub(right.ndArray).wrap()
override operator fun StructureND<T>.unaryMinus(): Nd4jArrayStructure<T> =
ndArray.neg().wrap()
override fun negate(arg: StructureND<T>): Nd4jArrayStructure<T> =
arg.ndArray.neg().wrap()
public fun multiply(a: StructureND<T>, k: Number): Nd4jArrayStructure<T> =
a.ndArray.mul(k).wrap()
@ -92,7 +93,6 @@ public sealed interface Nd4jArrayGroupOps<T, out S : Ring<T>> : GroupOpsND<T, S>
* @param T the type of the element contained in ND structure.
* @param R the type of ring of structure elements.
*/
@OptIn(UnstableKMathAPI::class)
public sealed interface Nd4jArrayRingOps<T, out R : Ring<T>> : RingOpsND<T, R>, Nd4jArrayGroupOps<T, R> {
override fun multiply(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> =
@ -201,23 +201,29 @@ public open class DoubleNd4jArrayFieldOps : Nd4jArrayExtendedFieldOps<Double, Do
override fun scale(a: StructureND<Double>, value: Double): Nd4jArrayStructure<Double> = a.ndArray.mul(value).wrap()
override operator fun StructureND<Double>.div(arg: Double): Nd4jArrayStructure<Double> = ndArray.div(arg).wrap()
override operator fun StructureND<Double>.plus(arg: Double): Nd4jArrayStructure<Double> = ndArray.add(arg).wrap()
override operator fun StructureND<Double>.minus(arg: Double): Nd4jArrayStructure<Double> = ndArray.sub(arg).wrap()
override operator fun StructureND<Double>.times(arg: Double): Nd4jArrayStructure<Double> = ndArray.mul(arg).wrap()
override operator fun Double.div(arg: StructureND<Double>): Nd4jArrayStructure<Double> =
arg.ndArray.rdiv(this).wrap()
override operator fun Double.minus(arg: StructureND<Double>): Nd4jArrayStructure<Double> =
arg.ndArray.rsub(this).wrap()
public companion object : DoubleNd4jArrayFieldOps()
}
context(DoubleNd4jArrayFieldOps)
public operator fun StructureND<Double>.div(arg: Double): Nd4jArrayStructure<Double> = ndArray.div(arg).wrap()
context(DoubleNd4jArrayFieldOps)
public operator fun StructureND<Double>.plus(arg: Double): Nd4jArrayStructure<Double> = ndArray.add(arg).wrap()
context(DoubleNd4jArrayFieldOps)
public operator fun StructureND<Double>.minus(arg: Double): Nd4jArrayStructure<Double> = ndArray.sub(arg).wrap()
context(DoubleNd4jArrayFieldOps)
public operator fun StructureND<Double>.times(arg: Double): Nd4jArrayStructure<Double> = ndArray.mul(arg).wrap()
context(DoubleNd4jArrayFieldOps)
public operator fun Double.div(arg: StructureND<Double>): Nd4jArrayStructure<Double> =
arg.ndArray.rdiv(this).wrap()
context(DoubleNd4jArrayFieldOps)
public operator fun Double.minus(arg: StructureND<Double>): Nd4jArrayStructure<Double> =
arg.ndArray.rsub(this).wrap()
public val DoubleField.nd4j: DoubleNd4jArrayFieldOps get() = DoubleNd4jArrayFieldOps
public class DoubleNd4jArrayField(override val shape: Shape) : DoubleNd4jArrayFieldOps(), FieldND<Double, DoubleField>
@ -246,27 +252,33 @@ public open class FloatNd4jArrayFieldOps : Nd4jArrayExtendedFieldOps<Float, Floa
override fun scale(a: StructureND<Float>, value: Double): StructureND<Float> =
a.ndArray.mul(value).wrap()
override operator fun StructureND<Float>.div(arg: Float): Nd4jArrayStructure<Float> =
ndArray.div(arg).wrap()
override operator fun StructureND<Float>.plus(arg: Float): Nd4jArrayStructure<Float> =
ndArray.add(arg).wrap()
override operator fun StructureND<Float>.minus(arg: Float): Nd4jArrayStructure<Float> =
ndArray.sub(arg).wrap()
override operator fun StructureND<Float>.times(arg: Float): Nd4jArrayStructure<Float> =
ndArray.mul(arg).wrap()
override operator fun Float.div(arg: StructureND<Float>): Nd4jArrayStructure<Float> =
arg.ndArray.rdiv(this).wrap()
override operator fun Float.minus(arg: StructureND<Float>): Nd4jArrayStructure<Float> =
arg.ndArray.rsub(this).wrap()
public companion object : FloatNd4jArrayFieldOps()
}
context(FloatNd4jArrayFieldOps)
public operator fun StructureND<Float>.div(arg: Float): Nd4jArrayStructure<Float> =
ndArray.div(arg).wrap()
context(FloatNd4jArrayFieldOps)
public operator fun StructureND<Float>.plus(arg: Float): Nd4jArrayStructure<Float> =
ndArray.add(arg).wrap()
context(FloatNd4jArrayFieldOps)
public operator fun StructureND<Float>.minus(arg: Float): Nd4jArrayStructure<Float> =
ndArray.sub(arg).wrap()
context(FloatNd4jArrayFieldOps)
public operator fun StructureND<Float>.times(arg: Float): Nd4jArrayStructure<Float> =
ndArray.mul(arg).wrap()
context(FloatNd4jArrayFieldOps)
public operator fun Float.div(arg: StructureND<Float>): Nd4jArrayStructure<Float> =
arg.ndArray.rdiv(this).wrap()
context(FloatNd4jArrayFieldOps)
public operator fun Float.minus(arg: StructureND<Float>): Nd4jArrayStructure<Float> =
arg.ndArray.rsub(this).wrap()
public class FloatNd4jArrayField(override val shape: Shape) : FloatNd4jArrayFieldOps(), RingND<Float, FloatField>
public val FloatField.nd4j: FloatNd4jArrayFieldOps get() = FloatNd4jArrayFieldOps
@ -291,21 +303,25 @@ public open class IntNd4jArrayRingOps : Nd4jArrayRingOps<Int, IntRing> {
}
}
override operator fun StructureND<Int>.plus(arg: Int): Nd4jArrayStructure<Int> =
ndArray.add(arg).wrap()
override operator fun StructureND<Int>.minus(arg: Int): Nd4jArrayStructure<Int> =
ndArray.sub(arg).wrap()
override operator fun StructureND<Int>.times(arg: Int): Nd4jArrayStructure<Int> =
ndArray.mul(arg).wrap()
override operator fun Int.minus(arg: StructureND<Int>): Nd4jArrayStructure<Int> =
arg.ndArray.rsub(this).wrap()
public companion object : IntNd4jArrayRingOps()
}
context(IntNd4jArrayRingOps)
public operator fun StructureND<Int>.plus(arg: Int): Nd4jArrayStructure<Int> =
ndArray.add(arg).wrap()
context(IntNd4jArrayRingOps)
public operator fun StructureND<Int>.minus(arg: Int): Nd4jArrayStructure<Int> =
ndArray.sub(arg).wrap()
context(IntNd4jArrayRingOps)
public operator fun StructureND<Int>.times(arg: Int): Nd4jArrayStructure<Int> =
ndArray.mul(arg).wrap()
context(IntNd4jArrayRingOps)
public operator fun Int.minus(arg: StructureND<Int>): Nd4jArrayStructure<Int> =
arg.ndArray.rsub(this).wrap()
public val IntRing.nd4j: IntNd4jArrayRingOps get() = IntNd4jArrayRingOps
public class IntNd4jArrayRing(override val shape: Shape) : IntNd4jArrayRingOps(), RingND<Int, IntRing>

View File

@ -16,6 +16,7 @@ import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.nd.DefaultStrides
import space.kscience.kmath.nd.Shape
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Field
import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra
@ -26,7 +27,7 @@ import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
/**
* ND4J based [TensorAlgebra] implementation.
*/
public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTensorAlgebra<T, A> {
public sealed interface Nd4jTensorAlgebra<T : Number, out A : Field<T>> : AnalyticTensorAlgebra<T, A> {
/**
* Wraps [INDArray] to [Nd4jArrayStructure].
@ -51,10 +52,8 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
return structureND(left.shape) { index -> elementAlgebra.transform(left[index], right[index]) }
}
override fun T.plus(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.add(this).wrap()
override fun StructureND<T>.plus(arg: T): Nd4jArrayStructure<T> = ndArray.add(arg).wrap()
override fun StructureND<T>.plus(arg: StructureND<T>): Nd4jArrayStructure<T> = ndArray.add(arg.ndArray).wrap()
override fun add(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> =
left.ndArray.add(right.ndArray).wrap()
override fun Tensor<T>.plusAssign(value: T) {
ndArray.addi(value)
@ -64,9 +63,8 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
ndArray.addi(arg.ndArray)
}
override fun T.minus(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.rsub(this).wrap()
override fun StructureND<T>.minus(arg: T): Nd4jArrayStructure<T> = ndArray.sub(arg).wrap()
override fun StructureND<T>.minus(arg: StructureND<T>): Nd4jArrayStructure<T> = ndArray.sub(arg.ndArray).wrap()
override fun subtract(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> =
left.ndArray.sub(right.ndArray).wrap()
override fun Tensor<T>.minusAssign(value: T) {
ndArray.rsubi(value)
@ -76,12 +74,7 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
ndArray.subi(arg.ndArray)
}
override fun T.times(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.mul(this).wrap()
override fun StructureND<T>.times(arg: T): Nd4jArrayStructure<T> =
ndArray.mul(arg).wrap()
override fun StructureND<T>.times(arg: StructureND<T>): Nd4jArrayStructure<T> = ndArray.mul(arg.ndArray).wrap()
override fun multiply(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> = left.ndArray.mul(right.ndArray).wrap()
override fun Tensor<T>.timesAssign(value: T) {
ndArray.muli(value)
@ -91,9 +84,9 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
ndArray.mmuli(arg.ndArray)
}
override fun StructureND<T>.unaryMinus(): Nd4jArrayStructure<T> = ndArray.neg().wrap()
override fun negate(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.neg().wrap()
override fun Tensor<T>.get(i: Int): Nd4jArrayStructure<T> = ndArray.slice(i.toLong()).wrap()
override fun Tensor<T>.transpose(i: Int, j: Int): Nd4jArrayStructure<T> = ndArray.swapAxes(i, j).wrap()
override fun StructureND<T>.transpose(i: Int, j: Int): Nd4jArrayStructure<T> = ndArray.swapAxes(i, j).wrap()
override fun StructureND<T>.dot(other: StructureND<T>): Nd4jArrayStructure<T> = ndArray.mmul(other.ndArray).wrap()
override fun StructureND<T>.min(dim: Int, keepDim: Boolean): Nd4jArrayStructure<T> =
@ -140,9 +133,7 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
override fun StructureND<T>.std(dim: Int, keepDim: Boolean): Nd4jArrayStructure<T> =
ndArray.std(true, keepDim, dim).wrap()
override fun T.div(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.rdiv(this).wrap()
override fun StructureND<T>.div(arg: T): Nd4jArrayStructure<T> = ndArray.div(arg).wrap()
override fun StructureND<T>.div(arg: StructureND<T>): Nd4jArrayStructure<T> = ndArray.div(arg.ndArray).wrap()
override fun divide(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> = left.ndArray.div(right.ndArray).wrap()
override fun Tensor<T>.divAssign(value: T) {
ndArray.divi(value)
@ -160,6 +151,36 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
}
}
context(Nd4jTensorAlgebra<T, C>)
public fun <T : Number, C : Field<T>> T.plus(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.add(this).wrap()
context(Nd4jTensorAlgebra<T, C>)
public fun <T : Number, C : Field<T>> StructureND<T>.plus(arg: T): Nd4jArrayStructure<T> = ndArray.add(arg).wrap()
context(Nd4jTensorAlgebra<T, C>)
public fun <T : Number, C : Field<T>> T.times(arg: StructureND<T>): Nd4jArrayStructure<T> =
arg.ndArray.mul(this).wrap()
context(Nd4jTensorAlgebra<T, C>)
public fun <T : Number, C : Field<T>> StructureND<T>.times(arg: T): Nd4jArrayStructure<T> =
ndArray.mul(arg).wrap()
context(Nd4jTensorAlgebra<T, C>)
public operator fun <T : Number, C : Field<T>> T.minus(arg: StructureND<T>): Nd4jArrayStructure<T> =
arg.ndArray.rsub(this).wrap()
context(Nd4jTensorAlgebra<T, C>)
public operator fun <T:Number,C : Field<T>> StructureND<T>.minus(arg: T): Nd4jArrayStructure<T> =
ndArray.sub(arg).wrap()
context(Nd4jTensorAlgebra<T, C>)
public operator fun <T : Number, C : Field<T>> T.div(arg: StructureND<T>): Nd4jArrayStructure<T> =
arg.ndArray.rdiv(this).wrap()
context(Nd4jTensorAlgebra<T, C>)
public operator fun <T : Number, C : Field<T>> StructureND<T>.div(arg: T): Nd4jArrayStructure<T> =
ndArray.div(arg).wrap()
/**
* [Double] specialization of [Nd4jTensorAlgebra].
*/

View File

@ -1,6 +1,6 @@
plugins {
id("ru.mipt.npm.gradle.mpp")
id("ru.mipt.npm.gradle.native")
// id("ru.mipt.npm.gradle.native")
}
kscience {
@ -22,3 +22,8 @@ kotlin.sourceSets {
readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
}
// Testing multi-receiver!
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
enabled = false
}

Some files were not shown because too many files have changed in this diff Show More