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 { kotlin {
jvm() jvm()
js(IR) { // Testing multi-receiver!
nodejs() // js(IR) {
} // nodejs()
// }
sourceSets { sourceSets {
all { all {
@ -74,7 +75,8 @@ benchmark {
// Setup configurations // Setup configurations
targets { targets {
register("jvm") register("jvm")
register("js") // Testing multi-receiver!
// register("js")
} }
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() { fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
@ -158,7 +160,7 @@ kotlin.sourceSets.all {
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> { tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
kotlinOptions { kotlinOptions {
jvmTarget = "11" 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 kotlinx.benchmark.State
import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.asm.compileToExpression
import space.kscience.kmath.expressions.* import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import kotlin.math.sin import kotlin.math.sin
import kotlin.random.Random import kotlin.random.Random

View File

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

View File

@ -4,4 +4,4 @@
# #
kotlin.code.style=official 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 } structure.getFeature(type)?.let { return it }
val origin = structure.toEjml().origin val origin = structure.toEjml().origin
return when (type) { return type.cast(when (type) {
${ ${
if (isDense) if (isDense)
""" InverseMatrixFeature::class -> object : InverseMatrixFeature<${type}> { """ InverseMatrixFeature::class -> object : InverseMatrixFeature<${type}> {
@ -318,8 +318,8 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
}""" }"""
} }
else -> null else -> return null
}?.let(type::cast) })
} }
/** /**

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 } 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 ## Nested fields
Contexts allow one to build more complex structures. For example, it is possible to create a `Matrix` from complex 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> { tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
kotlinOptions { kotlinOptions {
jvmTarget = "11" 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.asm.compileToExpression
import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.MstExtendedField
import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.invoke
fun main() { fun main() {
val expr = MstExtendedField { 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.chiSquaredExpression
import space.kscience.kmath.expressions.symbol import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.asIterable 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.operations.toList
import space.kscience.kmath.optimization.FunctionOptimizationTarget import space.kscience.kmath.optimization.FunctionOptimizationTarget
import space.kscience.kmath.optimization.optimizeWith 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.binding
import space.kscience.kmath.expressions.symbol import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.asIterable 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.operations.toList
import space.kscience.kmath.optimization.QowOptimizer import space.kscience.kmath.optimization.QowOptimizer
import space.kscience.kmath.optimization.chiSquaredOrNull 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.nd.withNdAlgebra
import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.algebra
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.times
fun main(): Unit = Double.algebra { fun main(): Unit = Double.algebra {
withNdAlgebra(2, 2) { withNdAlgebra(2, 2) {

View File

@ -7,7 +7,6 @@ package space.kscience.kmath.operations
import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.commons.linear.CMLinearSpace
import space.kscience.kmath.linear.matrix import space.kscience.kmath.linear.matrix
import space.kscience.kmath.nd.DoubleBufferND
import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.Shape
import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.nd.ndAlgebra 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 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 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.nd.structureND
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
fun main() { fun main() {

View File

@ -80,7 +80,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND<Double, Double
return BufferND(strides, array.asBuffer()) 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 } 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 package space.kscience.kmath.structures
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.buffer
import space.kscience.kmath.operations.bufferAlgebra
import space.kscience.kmath.operations.withSize
inline fun <reified R : Any> MutableBuffer.Companion.same( inline fun <reified R : Any> MutableBuffer.Companion.same(
n: Int, n: Int,

View File

@ -5,12 +5,13 @@
package space.kscience.kmath.tensors 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.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 space.kscience.kmath.tensors.core.DoubleTensorAlgebra
import kotlin.math.abs
// OLS estimator using SVD // OLS estimator using SVD
fun main() { fun main() {
@ -48,14 +49,16 @@ fun main() {
// inverse Sigma matrix can be restored from singular values with diagonalEmbedding function // 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 val alphaOLS = v dot sigma dot u.transpose() dot y
println("Estimated alpha:\n" + println(
"$alphaOLS") "Estimated alpha:\n" +
"$alphaOLS"
)
// figure out MSE of approximation // 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.size == 1)
require(yTrue.shape contentEquals yPred.shape) require(yTrue.shape contentEquals yPred.shape)

View File

@ -5,10 +5,11 @@
package space.kscience.kmath.tensors 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.tensorAlgebra
import space.kscience.kmath.tensors.core.withBroadcast import space.kscience.kmath.tensors.core.withBroadcast
// simple PCA // simple PCA
fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods

View File

@ -5,10 +5,11 @@
package space.kscience.kmath.tensors 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.tensorAlgebra
import space.kscience.kmath.tensors.core.withBroadcast import space.kscience.kmath.tensors.core.withBroadcast
// Dataset normalization // Dataset normalization
fun main() = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods 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.multik.multikAlgebra
import space.kscience.kmath.nd.one import space.kscience.kmath.nd.one
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.minus
import space.kscience.kmath.operations.plus
fun main(): Unit = with(DoubleField.multikAlgebra) { fun main(): Unit = with(DoubleField.multikAlgebra) {
val a = Multik.ndarray(intArrayOf(1, 2, 3)).asType<Double>().wrap() val a = Multik.ndarray(intArrayOf(1, 2, 3)).asType<Double>().wrap()

View File

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

View File

@ -84,3 +84,8 @@ readme {
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt" ref = "src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt"
) { "Extendable MST rendering" } ) { "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.MstRing
import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.interpret import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.operations.invoke
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals 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.MstExtendedField
import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.invoke
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

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

View File

@ -6,6 +6,9 @@
package space.kscience.kmath.commons.expressions package space.kscience.kmath.commons.expressions
import space.kscience.kmath.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.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.test.Test 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.Symbol.Companion.y
import space.kscience.kmath.expressions.chiSquaredExpression import space.kscience.kmath.expressions.chiSquaredExpression
import space.kscience.kmath.expressions.symbol 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.optimization.*
import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.DoubleBuffer

View File

@ -1,7 +1,7 @@
plugins { plugins {
kotlin("multiplatform") kotlin("multiplatform")
id("ru.mipt.npm.gradle.common") id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native") // id("ru.mipt.npm.gradle.native")
} }
kotlin.sourceSets { kotlin.sourceSets {
@ -29,3 +29,8 @@ readme {
ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt" 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 package space.kscience.kmath.complex
import space.kscience.kmath.complex.ComplexField.plus
import space.kscience.kmath.memory.MemoryReader import space.kscience.kmath.memory.MemoryReader
import space.kscience.kmath.memory.MemorySpec import space.kscience.kmath.memory.MemorySpec
import space.kscience.kmath.memory.MemoryWriter import space.kscience.kmath.memory.MemoryWriter
@ -71,14 +72,13 @@ public object ComplexField :
*/ */
public val i: Complex by lazy { Complex(0.0, 1.0) } public val i: Complex by lazy { Complex(0.0, 1.0) }
override fun Complex.unaryMinus(): Complex = Complex(-re, -im)
override fun number(value: Number): Complex = Complex(value.toDouble(), 0.0) override fun 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 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 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 = 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) 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 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 override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2.0
@ -139,53 +137,58 @@ public object ComplexField :
override fun ln(arg: Complex): Complex = ln(arg.r) + i * atan2(arg.im, arg.re) override fun ln(arg: Complex): Complex = ln(arg.r) + i * atan2(arg.im, arg.re)
/** override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg)
}
/**
* Adds complex number to real one. * Adds complex number to real one.
* *
* @receiver the augend. * @receiver the augend.
* @param c the addend. * @param c the addend.
* @return the sum. * @return the sum.
*/ */
public operator fun Double.plus(c: Complex): Complex = add(this.toComplex(), c) context(ComplexField)
public operator fun Double.plus(c: Complex): Complex = add(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. * Adds real number to complex one.
* *
* @receiver the augend. * @receiver the augend.
* @param d the addend. * @param d the addend.
* @return the sum. * @return the sum.
*/ */
public operator fun Complex.plus(d: Double): Complex = d + this 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. * Subtracts real number from complex one.
* *
* @receiver the minuend. * @receiver the minuend.
* @param d the subtrahend. * @param d the subtrahend.
* @return the difference. * @return the difference.
*/ */
public operator fun Complex.minus(d: Double): Complex = add(this, -d.toComplex()) context(ComplexField)
public operator fun Complex.minus(d: Double): Complex = add(this, -d.toComplex())
/** /**
* Multiplies real number by complex one. * Multiplies real number by complex one.
* *
* @receiver the multiplier. * @receiver the multiplier.
* @param c the multiplicand. * @param c the multiplicand.
* @receiver the product. * @receiver the product.
*/ */
public operator fun Double.times(c: Complex): Complex = Complex(c.re * this, c.im * this) context(ComplexField)
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)
}
/** /**
* Represents `double`-based complex number. * Represents `double`-based complex number.
@ -193,7 +196,6 @@ public object ComplexField :
* @property re The real part. * @property re The real part.
* @property im The imaginary part. * @property im The imaginary part.
*/ */
@OptIn(UnstableKMathAPI::class)
public data class Complex(val re: Double, val im: Double) { 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, im: Number) : this(re.toDouble(), im.toDouble())
public constructor(re: Number) : this(re.toDouble(), 0.0) 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.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 Quaternion.minus(other: Number): Quaternion = Quaternion(w - other.toDouble(), x, y, z)
override operator fun Number.times(arg: Quaternion): Quaternion = override fun negate(arg: Quaternion): Quaternion = Quaternion(-arg.w, -arg.x, -arg.y, -arg.z)
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 norm(arg: Quaternion): Quaternion = sqrt(arg.conjugate * arg) override fun norm(arg: Quaternion): Quaternion = sqrt(arg.conjugate * arg)
override fun bindSymbolOrNull(value: String): Quaternion? = when (value) { override fun bindSymbolOrNull(value: String): Quaternion? = when (value) {

View File

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

View File

@ -6,6 +6,8 @@
package space.kscience.kmath.complex package space.kscience.kmath.complex
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.minus
import space.kscience.kmath.operations.plus
import kotlin.math.sqrt import kotlin.math.sqrt
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals 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.invoke
import space.kscience.kmath.expressions.symbol import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.bindSymbol 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.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -6,6 +6,8 @@
package space.kscience.kmath.complex package space.kscience.kmath.complex
import space.kscience.kmath.operations.invoke 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.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -1,7 +1,7 @@
plugins { plugins {
kotlin("multiplatform") kotlin("multiplatform")
id("ru.mipt.npm.gradle.common") 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" // id("com.xcporter.metaview") version "0.0.5"
} }
@ -72,3 +72,8 @@ readme {
ref = "src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt" ref = "src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt"
) { "Automatic differentiation" } ) { "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>> { ) : FunctionalExpressionAlgebra<T, A>(algebra), Group<Expression<T>> {
override val zero: Expression<T> get() = const(algebra.zero) override val zero: Expression<T> get() = const(algebra.zero)
override fun Expression<T>.unaryMinus(): Expression<T> = override fun negate(arg: Expression<T>): Expression<T> =
unaryOperation(GroupOps.MINUS_OPERATION, this) unaryOperation(GroupOps.MINUS_OPERATION, arg)
/** /**
* Builds an Expression of addition of two another expressions. * 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> = override fun add(left: Expression<T>, right: Expression<T>): Expression<T> =
binaryOperation(GroupOps.PLUS_OPERATION, left, right) 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> = override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
super<FunctionalExpressionAlgebra>.unaryOperationFunction(operation) super<FunctionalExpressionAlgebra>.unaryOperationFunction(operation)
override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> = override fun binaryOperationFunction(operation: String): (left: Expression<T>, right: Expression<T>) -> Expression<T> =
super<FunctionalExpressionAlgebra>.binaryOperationFunction(operation) 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>>( public open class FunctionalExpressionRing<T, out A : Ring<T>>(
algebra: A, algebra: A,
) : FunctionalExpressionGroup<T, A>(algebra), Ring<Expression<T>> { ) : 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> = override fun multiply(left: Expression<T>, right: Expression<T>): Expression<T> =
binaryOperationFunction(RingOps.TIMES_OPERATION)(left, right) 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> = override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
super<FunctionalExpressionGroup>.unaryOperationFunction(operation) super<FunctionalExpressionGroup>.unaryOperationFunction(operation)
@ -101,6 +97,12 @@ public open class FunctionalExpressionRing<T, out A : Ring<T>>(
super<FunctionalExpressionGroup>.binaryOperationFunction(operation) 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>>( public open class FunctionalExpressionField<T, out A : Field<T>>(
algebra: A, algebra: A,
) : FunctionalExpressionRing<T, A>(algebra), Field<Expression<T>>, ScaleOperations<Expression<T>> { ) : 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> = override fun divide(left: Expression<T>, right: Expression<T>): Expression<T> =
binaryOperationFunction(FieldOps.DIV_OPERATION)(left, right) 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> = override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
super<FunctionalExpressionRing>.unaryOperationFunction(operation) super<FunctionalExpressionRing>.unaryOperationFunction(operation)
@ -127,6 +126,12 @@ public open class FunctionalExpressionField<T, out A : Field<T>>(
super<FunctionalExpressionRing>.bindSymbolOrNull(value) 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>>( public open class FunctionalExpressionExtendedField<T, out A : ExtendedField<T>>(
algebra: A, algebra: A,
) : FunctionalExpressionField<T, A>(algebra), ExtendedField<Expression<T>> { ) : 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 number(value: Number): MST.Numeric = MstNumericAlgebra.number(value)
override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(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 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 = override fun negate(arg: MST): MST.Unary =
unaryOperationFunction(GroupOps.MINUS_OPERATION)(this) unaryOperationFunction(GroupOps.MINUS_OPERATION)(arg)
override operator fun MST.minus(arg: MST): MST.Binary = override fun subtract(left: MST, right: MST): MST.Binary =
binaryOperationFunction(GroupOps.MINUS_OPERATION)(this, arg) binaryOperationFunction(GroupOps.MINUS_OPERATION)(left, right)
override fun scale(a: MST, value: Double): MST.Binary = override fun scale(a: MST, value: Double): MST.Binary =
binaryOperationFunction(RingOps.TIMES_OPERATION)(a, number(value)) 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 = override fun multiply(left: MST, right: MST): MST.Binary =
binaryOperationFunction(RingOps.TIMES_OPERATION)(left, right) binaryOperationFunction(RingOps.TIMES_OPERATION)(left, right)
override operator fun MST.unaryPlus(): MST.Unary = MstGroup { +this@unaryPlus } override fun negate(arg: MST): MST.Unary = MstGroup.negate(arg)
override operator fun MST.unaryMinus(): MST.Unary = MstGroup { -this@unaryMinus } override fun subtract(left: MST, right: MST): MST.Binary = MstGroup.subtract(left, right)
override operator fun MST.minus(arg: MST): MST.Binary = MstGroup { this@minus - arg }
override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstGroup.binaryOperationFunction(operation) 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 = override fun divide(left: MST, right: MST): MST.Binary =
binaryOperationFunction(FieldOps.DIV_OPERATION)(left, right) binaryOperationFunction(FieldOps.DIV_OPERATION)(left, right)
override operator fun MST.unaryPlus(): MST.Unary = MstRing { +this@unaryPlus } override fun negate(arg: MST): MST.Unary = MstRing.negate(arg)
override operator fun MST.unaryMinus(): MST.Unary = MstRing { -this@unaryMinus } override fun subtract(left: MST, right: MST): MST.Binary = MstRing.subtract(left, right)
override operator fun MST.minus(arg: MST): MST.Binary = MstRing { this@minus - arg }
override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstRing.binaryOperationFunction(operation) 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 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 fun divide(left: MST, right: MST): MST.Binary = MstField.divide(left, right)
override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus } override fun negate(arg: MST): MST.Unary = MstField.negate(arg)
override operator fun MST.unaryMinus(): MST.Unary = MstField { -this@unaryMinus } override fun subtract(left: MST, right: MST): MST.Binary = MstField.subtract(left, right)
override operator fun MST.minus(arg: MST): MST.Binary = MstField { this@minus - arg }
override fun power(arg: MST, pow: Number): MST.Binary = override fun power(arg: MST, pow: Number): MST.Binary =
binaryOperationFunction(PowerOperations.POW_OPERATION)(arg, number(pow)) 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 } // derive(const { this@minus.value - one * b.toDouble() }) { z -> d += z.d }
override fun AutoDiffValue<T>.unaryMinus(): AutoDiffValue<T> = override fun negate(arg: AutoDiffValue<T>): AutoDiffValue<T> =
derive(const { -value }) { z -> d -= z.d } derive(const { -arg.value }) { z -> arg.d -= z.d }
// Basic math (+, -, *, /) // Basic math (+, -, *, /)

View File

@ -5,8 +5,7 @@
package space.kscience.kmath.expressions package space.kscience.kmath.expressions
import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.asIterable
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.indices import space.kscience.kmath.structures.indices
import kotlin.jvm.JvmName 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.DoubleFieldOpsND
import space.kscience.kmath.nd.as2D import space.kscience.kmath.nd.as2D
import space.kscience.kmath.nd.asND import space.kscience.kmath.nd.asND
import space.kscience.kmath.operations.DoubleBufferOps import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.DoubleBuffer 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.Structure2D
import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.nd.StructureFeature
import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as1D
import space.kscience.kmath.operations.BufferRingOps import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory
import space.kscience.kmath.structures.DoubleBuffer 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` * Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A`
*/ */
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@OptIn(UnstableKMathAPI::class)
public fun <T : Any> Matrix<T>.transpose(): Matrix<T> = getFeature(TransposedFeature::class)?.original as? Matrix<T> 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)) ?: 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.Ring
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.plus
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
/** /**

View File

@ -127,50 +127,53 @@ public interface GroupOpsND<T, out A : GroupOps<T>> : GroupOps<StructureND<T>>,
override fun add(left: StructureND<T>, right: StructureND<T>): StructureND<T> = override fun add(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
zip(left, right) { aValue, bValue -> add(aValue, bValue) } zip(left, right) { aValue, bValue -> add(aValue, bValue) }
// TODO move to extensions after KEEP-176 public companion object
}
/** /**
* Adds an ND structure to an element of it. * Adds an ND structure to an element of it.
* *
* @receiver the augend. * @receiver the augend.
* @param arg the addend. * @param arg the addend.
* @return the sum. * @return the sum.
*/ */
@OptIn(PerformancePitfall::class) context(GroupOpsND<T, A>)
public operator fun StructureND<T>.plus(arg: T): StructureND<T> = this.map { value -> add(arg, value) } @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. * Subtracts an element from ND structure of it.
* *
* @receiver the dividend. * @receiver the dividend.
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
@OptIn(PerformancePitfall::class) context(GroupOpsND<T, A>)
public operator fun StructureND<T>.minus(arg: T): StructureND<T> = this.map { value -> add(arg, -value) } @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. * Adds an element to ND structure of it.
* *
* @receiver the augend. * @receiver the augend.
* @param arg the addend. * @param arg the addend.
* @return the sum. * @return the sum.
*/ */
@OptIn(PerformancePitfall::class) context(GroupOpsND<T, A>)
public operator fun T.plus(arg: StructureND<T>): StructureND<T> = arg.map { value -> add(this@plus, value) } @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. * Subtracts an ND structure from an element of it.
* *
* @receiver the dividend. * @receiver the dividend.
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
@OptIn(PerformancePitfall::class) context(GroupOpsND<T, A>)
public operator fun T.minus(arg: StructureND<T>): StructureND<T> = arg.map { value -> add(-this@minus, value) } @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 companion object
}
public interface GroupND<T, out A : Group<T>> : Group<StructureND<T>>, GroupOpsND<T, A>, WithShape { 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 } override val zero: StructureND<T> get() = structureND(shape) { elementAlgebra.zero }
@ -194,30 +197,33 @@ public interface RingOpsND<T, out A : RingOps<T>> : RingOps<StructureND<T>>, Gro
override fun multiply(left: StructureND<T>, right: StructureND<T>): StructureND<T> = override fun multiply(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
zip(left, right) { aValue, bValue -> multiply(aValue, bValue) } zip(left, right) { aValue, bValue -> multiply(aValue, bValue) }
//TODO move to extensions with context receivers
/** public companion object
}
/**
* Multiplies an ND structure by an element of it. * Multiplies an ND structure by an element of it.
* *
* @receiver the multiplicand. * @receiver the multiplicand.
* @param arg the multiplier. * @param arg the multiplier.
* @return the product. * @return the product.
*/ */
@OptIn(PerformancePitfall::class) context(RingOpsND<T, A>)
public operator fun StructureND<T>.times(arg: T): StructureND<T> = this.map { value -> multiply(arg, value) } @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. * Multiplies an element by a ND structure of it.
* *
* @receiver the multiplicand. * @receiver the multiplicand.
* @param arg the multiplier. * @param arg the multiplier.
* @return the product. * @return the product.
*/ */
@OptIn(PerformancePitfall::class) context(RingOpsND<T, A>)
public operator fun T.times(arg: StructureND<T>): StructureND<T> = arg.map { value -> multiply(this@times, value) } @OptIn(PerformancePitfall::class)
public operator fun <T, A : RingOps<T>> T.times(arg: StructureND<T>): StructureND<T> =
public companion object 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 { 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 } override val one: StructureND<T> get() = structureND(shape) { elementAlgebra.one }
@ -245,30 +251,32 @@ public interface FieldOpsND<T, out A : Field<T>> :
override fun divide(left: StructureND<T>, right: StructureND<T>): StructureND<T> = override fun divide(left: StructureND<T>, right: StructureND<T>): StructureND<T> =
zip(left, right) { aValue, bValue -> divide(aValue, bValue) } zip(left, right) { aValue, bValue -> divide(aValue, bValue) }
//TODO move to extensions after https://github.com/Kotlin/KEEP/blob/master/proposals/context-receivers.md @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. * Divides an ND structure by an element of it.
* *
* @receiver the dividend. * @receiver the dividend.
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
@OptIn(PerformancePitfall::class) context(FieldOpsND<T, A>)
public operator fun StructureND<T>.div(arg: T): StructureND<T> = this.map { value -> divide(arg, value) } @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. * Divides an element by an ND structure of it.
* *
* @receiver the dividend. * @receiver the dividend.
* @param arg the divisor. * @param arg the divisor.
* @return the quotient. * @return the quotient.
*/ */
@OptIn(PerformancePitfall::class) context(FieldOpsND<T, A>)
public operator fun T.div(arg: StructureND<T>): StructureND<T> = arg.map { divide(it, this@div) } @OptIn(PerformancePitfall::class)
public operator fun <T, A : Field<T>> 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) }
}
public interface FieldND<T, out A : Field<T>> : Field<StructureND<T>>, FieldOpsND<T, A>, RingND<T, A>, WithShape { 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 } 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 bufferAlgebra: BufferAlgebra<T, A>,
override val indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, override val indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
) : GroupOpsND<T, A>, BufferAlgebraND<T, A> { ) : 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>>( 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 = override fun add(left: StructureND<Double>, right: StructureND<Double>): DoubleBufferND =
zipInline(left.toBufferND(), right.toBufferND()) { l, r -> l + r } 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 = override fun multiply(left: StructureND<Double>, right: StructureND<Double>): DoubleBufferND =
zipInline(left.toBufferND(), right.toBufferND()) { l, r -> l * r } 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 = override fun divide(left: StructureND<Double>, right: StructureND<Double>): DoubleBufferND =
zipInline(left.toBufferND(), right.toBufferND()) { l: Double, r: Double -> l / r } 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 = override fun scale(a: StructureND<Double>, value: Double): DoubleBufferND =
mapInline(a.toBufferND()) { it * value } mapInline(a.toBufferND()) { it * value }
@ -181,7 +148,7 @@ public class DoubleFieldND(override val shape: Shape) :
it.kpow(pow) 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()) power(arg, pow.toInt())
} else { } else {
val dpow = pow.toDouble() 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.misc.PerformancePitfall
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.minus
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory
import kotlin.jvm.JvmName 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.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Ring.Companion.optimizedPower import space.kscience.kmath.operations.Ring.Companion.optimizedPower
/**
* Stub for DSL the [Algebra] is.
*/
@DslMarker
public annotation class KMathContext
/** /**
* Represents an algebraic structure. * Represents an algebraic structure.
* *
@ -137,46 +131,26 @@ public interface GroupOps<T> : Algebra<T> {
*/ */
public fun add(left: T, right: T): 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. * The negation of this element.
* *
* @receiver this value. * @param arg the element.
* @return the additive inverse of this value. * @return the additive inverse of this value.
*/ */
public operator fun T.unaryMinus(): T public fun negate(arg: T): 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)
/** /**
* Subtraction of two elements. * Subtraction of two elements.
* *
* @receiver the minuend. * @parm left the minuend.
* @param arg the subtrahend. * @param right the subtrahend.
* @return the difference. * @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) { override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) {
PLUS_OPERATION -> { arg -> +arg } PLUS_OPERATION -> { arg -> arg }
MINUS_OPERATION -> { arg -> -arg } MINUS_OPERATION -> ::negate
else -> super.unaryOperationFunction(operation) 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]. * 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 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) { override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) {
TIMES_OPERATION -> ::multiply TIMES_OPERATION -> ::multiply
else -> super.binaryOperationFunction(operation) 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 * Represents ring i.e., algebraic structure with two associative binary operations called "addition" and
* "multiplication" and their neutral elements. * "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 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]. * 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 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) { override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = when (operation) {
DIV_OPERATION -> ::divide DIV_OPERATION -> ::divide
else -> super.binaryOperationFunction(operation) 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 * 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 * 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 fun power(arg: T, pow: Int): T = optimizedPower(arg, pow)
public companion object{ public companion object {
/** /**
* Raises [arg] to the integer power [exponent]. * 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 * @author Iaroslav Postovalov, Evgeniy Zhelenskiy
*/ */
private fun <T> Field<T>.optimizedPower(arg: T, exponent: Int): T = when { 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()) 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() override fun number(value: Number): BigInt = value.toLong().toBigInt()
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") @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 add(left: BigInt, right: BigInt): BigInt = left.plus(right)
override fun scale(a: BigInt, value: Double): BigInt = a.times(number(value)) override fun scale(a: BigInt, value: Double): BigInt = a.times(number(value))
override fun multiply(left: BigInt, right: BigInt): BigInt = left.times(right) 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 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 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> = override fun unaryOperationFunction(operation: String): (arg: Buffer<T>) -> Buffer<T> =
super<BufferAlgebra>.unaryOperationFunction(operation) 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 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 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> = override fun binaryOperationFunction(operation: String): (left: Buffer<T>, right: Buffer<T>) -> Buffer<T> =
super<BufferRingOps>.binaryOperationFunction(operation) super<BufferRingOps>.binaryOperationFunction(operation)

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.operations package space.kscience.kmath.operations
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory
import space.kscience.kmath.structures.DoubleBuffer 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> = override fun binaryOperationFunction(operation: String): (left: Buffer<Double>, right: Buffer<Double>) -> Buffer<Double> =
super<ExtendedFieldOps>.binaryOperationFunction(operation) super<ExtendedFieldOps>.binaryOperationFunction(operation)
override fun Buffer<Double>.unaryMinus(): DoubleBuffer = mapInline { -it }
override fun add(left: Buffer<Double>, right: Buffer<Double>): DoubleBuffer { override fun add(left: Buffer<Double>, right: Buffer<Double>): DoubleBuffer {
require(right.size == left.size) { require(right.size == left.size) {
"The size of the first buffer ${left.size} should be the same as for second one: ${right.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] }) } 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 { override fun subtract(left: Buffer<Double>, right: Buffer<Double>): DoubleBuffer {
require(arg.size == this.size) { require(left.size == right.size) {
"The size of the first buffer ${this.size} should be the same as for second one: ${arg.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) { return if (left is DoubleBuffer && right is DoubleBuffer)
val aArray = this.array DoubleBuffer(DoubleArray(left.size) { left.array[it] - right.array[it] })
val bArray = arg.array else
DoubleBuffer(DoubleArray(this.size) { aArray[it] - bArray[it] }) DoubleBuffer(DoubleArray(left.size) { left[it] - right[it] })
} else DoubleBuffer(DoubleArray(this.size) { this[it] - arg[it] })
} }
// //

View File

@ -116,34 +116,38 @@ public interface ScaleOperations<T> : Algebra<T> {
* @return the produce. * @return the produce.
*/ */
public fun scale(a: T, value: Double): T public fun scale(a: T, value: Double): T
}
/**
/**
* Multiplication of this element by a scalar. * Multiplication of this element by a scalar.
* *
* @receiver the multiplier. * @receiver the multiplier.
* @param k the multiplicand. * @param k the multiplicand.
* @return the product. * @return the product.
*/ */
public operator fun T.times(k: Number): T = scale(this, k.toDouble()) context(ScaleOperations<T>)
public operator fun <T> T.times(k: Number): T = scale(this, k.toDouble())
/** /**
* Division of this element by scalar. * Division of this element by scalar.
* *
* @receiver the dividend. * @receiver the dividend.
* @param k the divisor. * @param k the divisor.
* @return the quotient. * @return the quotient.
*/ */
public operator fun T.div(k: Number): T = scale(this, 1.0 / k.toDouble()) context(ScaleOperations<T>)
public operator fun <T> T.div(k: Number): T = scale(this, 1.0 / k.toDouble())
/** /**
* Multiplication of this number by element. * Multiplication of this number by element.
* *
* @receiver the multiplier. * @receiver the multiplier.
* @param arg the multiplicand. * @param arg the multiplicand.
* @return the product. * @return the product.
*/ */
public operator fun Number.times(arg: T): T = arg * this 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` * A combination of [NumericAlgebra] and [Ring] that adds intrinsic simple operations on numbers like `T+1`

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 zero: Double get() = 0.0
override inline val one: Double get() = 1.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 = override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
when (operation) { 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 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 multiply(left: Double, right: Double): Double = left * right
override inline fun divide(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 ln(arg: Double): Double = kotlin.math.ln(arg)
override inline fun norm(arg: Double): Double = abs(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 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 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 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 ln(arg: Float): Float = kotlin.math.ln(arg)
override inline fun norm(arg: Float): Float = abs(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 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 fun number(value: Number): Int = value.toInt()
override inline fun add(left: Int, right: Int): Int = left + right 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 multiply(left: Int, right: Int): Int = left * right
override inline fun norm(arg: Int): Int = abs(arg) 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 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 fun number(value: Number): Short = value.toShort()
override inline fun add(left: Short, right: Short): Short = (left + right).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 inline fun negate(arg: Short): Short = (-arg).toShort()
override fun norm(arg: Short): Short = if (arg > 0) arg else (-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 multiply(left: Short, right: Short): Short = (left * right).toShort()
override inline fun Short.plus(arg: Short): Short = (this + arg).toShort() override inline fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort()
override inline fun Short.minus(arg: Short): Short = (this - arg).toShort()
override inline fun Short.times(arg: Short): Short = (this * arg).toShort()
} }
public val Short.Companion.algebra: ShortRing get() = ShortRing 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 fun number(value: Number): Byte = value.toByte()
override inline fun add(left: Byte, right: Byte): Byte = (left + right).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 inline fun negate(arg: Byte): Byte = (-arg).toByte()
override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-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 multiply(left: Byte, right: Byte): Byte = (left * right).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 norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte()
override inline fun Byte.times(arg: Byte): Byte = (this * arg).toByte()
} }
public val Byte.Companion.algebra: ByteRing get() = ByteRing public val Byte.Companion.algebra: ByteRing get() = ByteRing
@ -256,14 +244,13 @@ public object LongRing : Ring<Long>, Norm<Long, Long>, NumericAlgebra<Long> {
get() = 1L get() = 1L
override fun number(value: Number): Long = value.toLong() override fun number(value: Number): Long = value.toLong()
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 add(left: Long, right: Long): Long = left + right
override inline fun Long.plus(arg: Long): Long = (this + arg) override inline fun negate(arg: Long): Long = -arg
override inline fun Long.minus(arg: Long): Long = (this - arg) override inline fun subtract(left: Long, right: Long): Long = left - right
override inline fun Long.times(arg: Long): Long = (this * arg)
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 public val Long.Companion.algebra: LongRing get() = LongRing

View File

@ -6,6 +6,8 @@
package space.kscience.kmath.expressions package space.kscience.kmath.expressions
import space.kscience.kmath.operations.DoubleField 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.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFails 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.expressions.Symbol.Companion.x
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.BooleanAlgebra import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class InterpretTest { internal class InterpretTest {
@Test @Test
fun interpretation() { fun interpretation() {

View File

@ -5,8 +5,7 @@
package space.kscience.kmath.expressions package space.kscience.kmath.expressions
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.asBuffer
import kotlin.math.E 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.nd.structureND
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.times
import space.kscience.kmath.testutils.FieldVerifier import space.kscience.kmath.testutils.FieldVerifier
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals 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.linear.linearSpace
import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.Norm
import space.kscience.kmath.operations.algebra
import space.kscience.kmath.operations.invoke
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.pow import kotlin.math.pow
import kotlin.test.Test import kotlin.test.Test

View File

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

View File

@ -5,9 +5,7 @@
package space.kscience.kmath.testutils package space.kscience.kmath.testutils
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal open class RingVerifier<T, out A>(algebra: A, a: T, b: T, c: T, x: Number) : 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 package space.kscience.kmath.testutils
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotEquals 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 number(value: Number): BigInteger = BigInteger.valueOf(value.toLong())
override fun add(left: BigInteger, right: BigInteger): BigInteger = left.add(right) override fun add(left: BigInteger, right: BigInteger): BigInteger = left.add(right)
override operator fun BigInteger.minus(arg: BigInteger): BigInteger = subtract(arg) override fun negate(arg: BigInteger): BigInteger = arg.negate()
override fun multiply(left: BigInteger, right: BigInteger): BigInteger = left.multiply(right) 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 get() = BigDecimal.ONE
override fun add(left: BigDecimal, right: BigDecimal): BigDecimal = left.add(right) 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 number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble())
override fun scale(a: BigDecimal, value: Double): BigDecimal = 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 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 power(arg: BigDecimal, pow: Number): BigDecimal = arg.pow(pow.toInt(), mathContext)
override fun sqrt(arg: BigDecimal): BigDecimal = arg.sqrt(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 { plugins {
kotlin("multiplatform") kotlin("multiplatform")
id("ru.mipt.npm.gradle.common") id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native") // id("ru.mipt.npm.gradle.native")
} }
kotlin.sourceSets { kotlin.sourceSets {
@ -25,3 +25,8 @@ kotlin.sourceSets {
readme { readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL 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.map
import kotlinx.coroutines.flow.runningReduce import kotlinx.coroutines.flow.runningReduce
import kotlinx.coroutines.flow.scan import kotlinx.coroutines.flow.scan
import space.kscience.kmath.operations.GroupOps import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
public fun <T> Flow<T>.cumulativeSum(group: GroupOps<T>): Flow<T> = public fun <T> Flow<T>.cumulativeSum(group: GroupOps<T>): Flow<T> =
group { runningReduce { sum, element -> sum + element } } 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 = public suspend fun <T> StructureND<T>.await(index: IntArray): T =
if (this is LazyStructureND<T>) await(index) else get(index) if (this is LazyStructureND<T>) await(index) else get(index)
/** context(CoroutineScope)
* PENDING would benefit from KEEP-176
*/
public inline fun <T, R> StructureND<T>.mapAsyncIndexed( public inline fun <T, R> StructureND<T>.mapAsyncIndexed(
scope: CoroutineScope,
crossinline function: suspend (T, index: IntArray) -> R, 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( context(CoroutineScope)
scope: CoroutineScope, public inline fun <T, R> StructureND<T>.mapAsync(crossinline function: suspend (T) -> R): LazyStructureND<R> =
crossinline function: suspend (T) -> R, LazyStructureND(this@CoroutineScope, shape) { index -> function(get(index)) }
): LazyStructureND<R> = LazyStructureND(scope, shape) { index -> function(get(index)) }

View File

@ -1,7 +1,7 @@
plugins { plugins {
kotlin("multiplatform") kotlin("multiplatform")
id("ru.mipt.npm.gradle.common") 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" description = "A proof of concept module for adding type-safe dimensions to structures"
@ -23,3 +23,8 @@ kotlin.sourceSets {
readme { readme {
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE 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." } ) { "LinearSpace implementations." }
} }
kotlin.sourceSets.main { 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")
}
main {
val codegen by tasks.creating { val codegen by tasks.creating {
ejmlCodegen(kotlin.srcDirs.first().absolutePath + "/space/kscience/kmath/ejml/_generated.kt") ejmlCodegen(kotlin.srcDirs.first().absolutePath + "/space/kscience/kmath/ejml/_generated.kt")
} }
kotlin.srcDirs(files().builtBy(codegen)) kotlin.srcDirs(files().builtBy(codegen))
}
} }

View File

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

View File

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

View File

@ -1,7 +1,7 @@
plugins { plugins {
kotlin("multiplatform") kotlin("multiplatform")
id("ru.mipt.npm.gradle.common") id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native") // id("ru.mipt.npm.gradle.native")
} }
description = "Functions, integration and interpolation" description = "Functions, integration and interpolation"
@ -32,3 +32,8 @@ readme {
"Univariate and multivariate quadratures" "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 { ): Polynomial<T> where A : Field<T>, A : NumericAlgebra<T> = algebra {
val integratedCoefficients = buildList(coefficients.size + 1) { val integratedCoefficients = buildList(coefficients.size + 1) {
add(zero) add(zero)
coefficients.forEachIndexed{ index, t -> add(t / (number(index) + one)) } coefficients.forEachIndexed { index, t -> add(t / (number(index) + one)) }
} }
Polynomial(integratedCoefficients) Polynomial(integratedCoefficients)
} }
@ -100,8 +100,8 @@ public class PolynomialSpace<T, C>(
) : Group<Polynomial<T>>, ScaleOperations<Polynomial<T>> where C : Ring<T>, C : ScaleOperations<T> { ) : Group<Polynomial<T>>, ScaleOperations<Polynomial<T>> where C : Ring<T>, C : ScaleOperations<T> {
override val zero: Polynomial<T> = Polynomial(emptyList()) override val zero: Polynomial<T> = Polynomial(emptyList())
override fun Polynomial<T>.unaryMinus(): Polynomial<T> = ring { override fun negate(arg: Polynomial<T>): Polynomial<T> = ring {
Polynomial(coefficients.map { -it }) Polynomial(arg.coefficients.map { -it })
} }
override fun add(left: Polynomial<T>, right: Polynomial<T>): Polynomial<T> { 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.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Field 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.Buffer
import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.asBuffer
import space.kscience.kmath.structures.indices import space.kscience.kmath.structures.indices

View File

@ -6,10 +6,7 @@
package space.kscience.kmath.integration package space.kscience.kmath.integration
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.sum
/** /**
* Use double pass Simpson rule integration with a fixed number of points. * Use double pass Simpson rule integration with a fixed number of points.
@ -60,7 +57,8 @@ public class SimpsonIntegrator<T : Any>(
} }
@UnstableKMathAPI @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. * 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.PiecewisePolynomial
import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.functions.Polynomial
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.invoke
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
internal fun <T : Comparable<T>> insureSorted(points: XYColumnarData<*, T, *>) { 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.PiecewisePolynomial
import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.functions.Polynomial
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.DoubleBuffer
import space.kscience.kmath.structures.MutableBufferFactory import space.kscience.kmath.structures.MutableBufferFactory

View File

@ -1,7 +1,7 @@
plugins { plugins {
kotlin("multiplatform") kotlin("multiplatform")
id("ru.mipt.npm.gradle.common") id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native") // id("ru.mipt.npm.gradle.native")
} }
kotlin.sourceSets.commonMain { kotlin.sourceSets.commonMain {
@ -13,3 +13,8 @@ kotlin.sourceSets.commonMain {
readme { readme {
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE 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 package space.kscience.kmath.geometry
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.minus
import kotlin.math.sqrt import kotlin.math.sqrt
@OptIn(UnstableKMathAPI::class)
public interface Vector2D : Point<Double>, Vector { public interface Vector2D : Point<Double>, Vector {
public val x: Double public val x: Double
public val y: 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) } override val zero: Vector2D by lazy { Vector2D(0.0, 0.0) }
public fun Vector2D.norm(): Double = sqrt(x * x + y * y) public fun Vector2D.norm(): Double = sqrt(x * x + y * y)
override fun Vector2D.unaryMinus(): Vector2D = Vector2D(-x, -y) override fun negate(arg: Vector2D): Vector2D = Vector2D(-arg.x, -arg.y)
override fun Vector2D.distanceTo(other: Vector2D): Double = (this - other).norm() 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) 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 package space.kscience.kmath.geometry
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.minus
import kotlin.math.sqrt import kotlin.math.sqrt
@OptIn(UnstableKMathAPI::class)
public interface Vector3D : Point<Double>, Vector { public interface Vector3D : Point<Double>, Vector {
public val x: Double public val x: Double
public val y: 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) } override val zero: Vector3D by lazy { Vector3D(0.0, 0.0, 0.0) }
public fun Vector3D.norm(): Double = sqrt(x * x + y * y + z * z) public fun Vector3D.norm(): Double = sqrt(x * x + y * y + z * z)
override fun Vector3D.unaryMinus(): Vector3D = Vector3D(-x, -y, -z) override fun negate(arg: Vector3D): Vector3D = Vector3D(-arg.x, -arg.y, -arg.z)
override fun Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm() override fun Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm()

View File

@ -5,6 +5,11 @@
package space.kscience.kmath.geometry 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. * Project vector onto a line.
* @param vector to project * @param vector to project

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
plugins { plugins {
kotlin("multiplatform") kotlin("multiplatform")
id("ru.mipt.npm.gradle.common") id("ru.mipt.npm.gradle.common")
id("ru.mipt.npm.gradle.native") // id("ru.mipt.npm.gradle.native")
} }
kscience { kscience {
@ -9,6 +9,12 @@ kscience {
} }
kotlin.sourceSets { 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 { commonMain {
dependencies { dependencies {
api(project(":kmath-core")) api(project(":kmath-core"))
@ -26,3 +32,8 @@ kotlin.sourceSets {
readme { readme {
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE 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 kotlinx.atomicfu.getAndUpdate
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.plus
/** /**
* Common representation for atomic counters * 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 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.FieldOpsND
import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.Shape
import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
/** /**
* @param T the type of the argument space * @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.domains.DoubleDomain1D
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import kotlin.math.floor import kotlin.math.floor
@ -69,8 +66,8 @@ public class UniformHistogram1DGroup<V : Any, A>(
) )
} }
override fun Histogram1D<Double, V>.unaryMinus(): UniformHistogram1D<V> = valueAlgebra { override fun negate(arg: Histogram1D<Double, V>): UniformHistogram1D<V> = valueAlgebra {
UniformHistogram1D(this@UniformHistogram1DGroup, produceFrom(this@unaryMinus).values.mapValues { -it.value }) UniformHistogram1D(this@UniformHistogram1DGroup, produceFrom(arg).values.mapValues { -it.value })
} }
override fun scale( 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.DoubleField
import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.unaryMinus
import space.kscience.kmath.structures.* import space.kscience.kmath.structures.*
import kotlin.math.floor import kotlin.math.floor
@ -98,8 +99,8 @@ public class UniformHistogramGroupND<V : Any, A : Field<V>>(
return HistogramND(this, values) return HistogramND(this, values)
} }
override fun HistogramND<Double, HyperSquareDomain, V>.unaryMinus(): HistogramND<Double, HyperSquareDomain, V> = override fun negate(arg: HistogramND<Double, HyperSquareDomain, V>): HistogramND<Double, HyperSquareDomain, V> =
this * (-1) 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.misc.UnstableKMathAPI
import space.kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.DefaultStrides
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.minus
import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.DoubleVector
import kotlin.random.Random import kotlin.random.Random
import kotlin.test.* import kotlin.test.*

View File

@ -10,6 +10,7 @@ import kotlinx.coroutines.test.runTest
import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.plus
import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.stat.nextBuffer import space.kscience.kmath.stat.nextBuffer
import kotlin.native.concurrent.ThreadLocal import kotlin.native.concurrent.ThreadLocal
@ -36,7 +37,7 @@ internal class UniformHistogram1DTest {
@Test @Test
fun rebinDown() = runTest { fun rebinDown() = runTest {
val h1 = Histogram.uniform1D(DoubleField, 0.01).produce(generator.nextDoubleBuffer(10000)) 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()) assertEquals(10000, h2.bins.sumOf { it.binValue }.toInt())
} }
@ -44,13 +45,13 @@ internal class UniformHistogram1DTest {
@Test @Test
fun rebinUp() = runTest { fun rebinUp() = runTest {
val h1 = Histogram.uniform1D(DoubleField, 0.03).produce(generator.nextDoubleBuffer(10000)) 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()) assertEquals(10000, h2.bins.sumOf { it.binValue }.toInt())
} }
@ThreadLocal @ThreadLocal
companion object{ companion object {
private val generator = RandomGenerator.default(123) 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.domains.center
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.misc.sorted import space.kscience.kmath.misc.sorted
import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.first import space.kscience.kmath.structures.first
import space.kscience.kmath.structures.indices import space.kscience.kmath.structures.indices
@ -123,7 +121,18 @@ public class TreeHistogramGroup<V : Any, A>(
return TreeHistogram(bins) 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 { } 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 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 multiply(left: Double, right: Double): Double = left * right
override inline fun divide(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 ln(arg: Double): Double = FastMath.log(arg)
override inline fun norm(arg: Double): Double = FastMath.abs(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 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 multiply(left: Double, right: Double): Double = left * right
override inline fun divide(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 ln(arg: Double): Double = StrictFastMath.log(arg)
override inline fun norm(arg: Double): Double = StrictFastMath.abs(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.nd.Structure2D
import space.kscience.kmath.operations.asSequence import space.kscience.kmath.operations.asSequence
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.plus
import space.kscience.kmath.operations.times
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
/** /**

View File

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

View File

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

View File

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

View File

@ -7,18 +7,18 @@ package space.kscience.kmath.multik
import org.jetbrains.kotlinx.multik.ndarray.data.DataType import org.jetbrains.kotlinx.multik.ndarray.data.DataType
import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.ExponentialOperations
import space.kscience.kmath.operations.TrigonometricOperations
public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra<Double, DoubleField>(), public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra<Double, DoubleField>(),
TrigonometricOperations<StructureND<Double>>, ExponentialOperations<StructureND<Double>> { TrigonometricOperations<StructureND<Double>>, ExponentialOperations<StructureND<Double>> {
override val elementAlgebra: DoubleField get() = DoubleField override val elementAlgebra: DoubleField get() = DoubleField
override val type: DataType get() = DataType.DoubleDataType 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 tan(arg: StructureND<Double>): MultikTensor<Double> = sin(arg) / cos(arg)
@ -28,7 +28,8 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra<Double, DoubleFi
override fun atan(arg: StructureND<Double>): MultikTensor<Double> = arg.map { atan(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() 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> { override fun tanh(arg: StructureND<Double>): MultikTensor<Double> {
val expPlus = exp(arg) val expPlus = exp(arg)
val expMinus = 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) } 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 Double.Companion.multikAlgebra: MultikTensorAlgebra<Double, DoubleField> get() = MultikDoubleAlgebra
public val DoubleField.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.") 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> { where T : Number, T : Comparable<T> {
public abstract val type: DataType public abstract val type: DataType
@ -138,14 +138,8 @@ public abstract class MultikTensorAlgebra<T, A : Ring<T>> : TensorAlgebra<T, A>
get(intArrayOf(0)) get(intArrayOf(0))
} else null } else null
override fun T.plus(arg: StructureND<T>): MultikTensor<T> = override fun add(left: StructureND<T>, right: StructureND<T>): MultikTensor<T> =
arg.plus(this) left.asMultik().array.plus(right.asMultik().array).wrap()
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 Tensor<T>.plusAssign(value: T) { override fun Tensor<T>.plusAssign(value: T) {
if (this is MultikTensor) { 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 subtract(left: StructureND<T>, right: StructureND<T>): MultikTensor<T> =
left.asMultik().array.minus(right.asMultik().array).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 Tensor<T>.minusAssign(value: T) { override fun Tensor<T>.minusAssign(value: T) {
if (this is MultikTensor) { 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> = override fun multiply(left: StructureND<T>, right: StructureND<T>): MultikTensor<T> =
arg.asMultik().array.deepCopy().apply { timesAssign(this@times) }.wrap() left.asMultik().array.times(right.asMultik().array).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 Tensor<T>.timesAssign(value: T) { override fun Tensor<T>.timesAssign(value: T) {
if (this is MultikTensor) { 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> = override fun negate(arg: StructureND<T>): MultikTensor<T> = (-arg.asMultik().array).wrap()
asMultik().array.unaryMinus().wrap()
override fun Tensor<T>.get(i: Int): MultikTensor<T> = asMultik().array.mutableView(i).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> { override fun Tensor<T>.view(shape: IntArray): MultikTensor<T> {
require(shape.all { it > 0 }) 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> { : 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 divide(left: StructureND<T>, right: StructureND<T>): MultikTensor<T> =
left.asMultik().array.div(right.asMultik().array).wrap()
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 Tensor<T>.divAssign(value: T) { override fun Tensor<T>.divAssign(value: T) {
if (this is MultikTensor) { 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>() { public object MultikFloatAlgebra : MultikDivisionTensorAlgebra<Float, FloatField>() {
override val elementAlgebra: FloatField get() = FloatField override val elementAlgebra: FloatField get() = FloatField
override val type: DataType get() = DataType.FloatDataType override val type: DataType get() = DataType.FloatDataType

View File

@ -45,6 +45,7 @@ public sealed interface Nd4jArrayAlgebra<T, out C : Algebra<T>> : AlgebraND<T, C
return newStruct return newStruct
} }
@OptIn(PerformancePitfall::class)
override fun StructureND<T>.mapIndexed( override fun StructureND<T>.mapIndexed(
transform: C.(index: IntArray, T) -> T, transform: C.(index: IntArray, T) -> T,
): Nd4jArrayStructure<T> { ): Nd4jArrayStructure<T> {
@ -53,6 +54,7 @@ public sealed interface Nd4jArrayAlgebra<T, out C : Algebra<T>> : AlgebraND<T, C
return new return new
} }
@OptIn(PerformancePitfall::class)
override fun zip( override fun zip(
left: StructureND<T>, left: StructureND<T>,
right: 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. * @param S the type of space of structure elements.
*/ */
public sealed interface Nd4jArrayGroupOps<T, out S : Ring<T>> : GroupOpsND<T, S>, Nd4jArrayAlgebra<T, S> { 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> = override fun add(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> =
left.ndArray.add(right.ndArray).wrap() left.ndArray.add(right.ndArray).wrap()
override operator fun StructureND<T>.minus(arg: StructureND<T>): Nd4jArrayStructure<T> = override fun subtract(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> =
ndArray.sub(arg.ndArray).wrap() left.ndArray.sub(right.ndArray).wrap()
override operator fun StructureND<T>.unaryMinus(): Nd4jArrayStructure<T> = override fun negate(arg: StructureND<T>): Nd4jArrayStructure<T> =
ndArray.neg().wrap() arg.ndArray.neg().wrap()
public fun multiply(a: StructureND<T>, k: Number): Nd4jArrayStructure<T> = public fun multiply(a: StructureND<T>, k: Number): Nd4jArrayStructure<T> =
a.ndArray.mul(k).wrap() 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 T the type of the element contained in ND structure.
* @param R the type of ring of structure elements. * @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> { 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> = 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 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() 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 val DoubleField.nd4j: DoubleNd4jArrayFieldOps get() = DoubleNd4jArrayFieldOps
public class DoubleNd4jArrayField(override val shape: Shape) : DoubleNd4jArrayFieldOps(), FieldND<Double, DoubleField> 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> = override fun scale(a: StructureND<Float>, value: Double): StructureND<Float> =
a.ndArray.mul(value).wrap() 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() 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 class FloatNd4jArrayField(override val shape: Shape) : FloatNd4jArrayFieldOps(), RingND<Float, FloatField>
public val FloatField.nd4j: FloatNd4jArrayFieldOps get() = FloatNd4jArrayFieldOps 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() 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 val IntRing.nd4j: IntNd4jArrayRingOps get() = IntNd4jArrayRingOps
public class IntNd4jArrayRing(override val shape: Shape) : IntNd4jArrayRingOps(), RingND<Int, IntRing> 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.DefaultStrides
import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.Shape
import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.Field
import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra
@ -26,7 +27,7 @@ import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
/** /**
* ND4J based [TensorAlgebra] implementation. * 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]. * 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]) } 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 add(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> =
override fun StructureND<T>.plus(arg: T): Nd4jArrayStructure<T> = ndArray.add(arg).wrap() left.ndArray.add(right.ndArray).wrap()
override fun StructureND<T>.plus(arg: StructureND<T>): Nd4jArrayStructure<T> = ndArray.add(arg.ndArray).wrap()
override fun Tensor<T>.plusAssign(value: T) { override fun Tensor<T>.plusAssign(value: T) {
ndArray.addi(value) ndArray.addi(value)
@ -64,9 +63,8 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
ndArray.addi(arg.ndArray) ndArray.addi(arg.ndArray)
} }
override fun T.minus(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.rsub(this).wrap() override fun subtract(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> =
override fun StructureND<T>.minus(arg: T): Nd4jArrayStructure<T> = ndArray.sub(arg).wrap() left.ndArray.sub(right.ndArray).wrap()
override fun StructureND<T>.minus(arg: StructureND<T>): Nd4jArrayStructure<T> = ndArray.sub(arg.ndArray).wrap()
override fun Tensor<T>.minusAssign(value: T) { override fun Tensor<T>.minusAssign(value: T) {
ndArray.rsubi(value) ndArray.rsubi(value)
@ -76,12 +74,7 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
ndArray.subi(arg.ndArray) ndArray.subi(arg.ndArray)
} }
override fun T.times(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.mul(this).wrap() override fun multiply(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> = left.ndArray.mul(right.ndArray).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 Tensor<T>.timesAssign(value: T) { override fun Tensor<T>.timesAssign(value: T) {
ndArray.muli(value) ndArray.muli(value)
@ -91,9 +84,9 @@ public sealed interface Nd4jTensorAlgebra<T : Number, A : Field<T>> : AnalyticTe
ndArray.mmuli(arg.ndArray) 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>.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>.dot(other: StructureND<T>): Nd4jArrayStructure<T> = ndArray.mmul(other.ndArray).wrap()
override fun StructureND<T>.min(dim: Int, keepDim: Boolean): Nd4jArrayStructure<T> = 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> = override fun StructureND<T>.std(dim: Int, keepDim: Boolean): Nd4jArrayStructure<T> =
ndArray.std(true, keepDim, dim).wrap() ndArray.std(true, keepDim, dim).wrap()
override fun T.div(arg: StructureND<T>): Nd4jArrayStructure<T> = arg.ndArray.rdiv(this).wrap() override fun divide(left: StructureND<T>, right: StructureND<T>): Nd4jArrayStructure<T> = left.ndArray.div(right.ndArray).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 Tensor<T>.divAssign(value: T) { override fun Tensor<T>.divAssign(value: T) {
ndArray.divi(value) 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]. * [Double] specialization of [Nd4jTensorAlgebra].
*/ */

View File

@ -1,6 +1,6 @@
plugins { plugins {
id("ru.mipt.npm.gradle.mpp") id("ru.mipt.npm.gradle.mpp")
id("ru.mipt.npm.gradle.native") // id("ru.mipt.npm.gradle.native")
} }
kscience { kscience {
@ -22,3 +22,8 @@ kotlin.sourceSets {
readme { readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL 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