Numeric operations are decoupled from Ring
This commit is contained in:
parent
4635080317
commit
ab32cd9561
@ -32,6 +32,7 @@
|
|||||||
- Optimized dot product for buffer matrices moved to `kmath-for-real`
|
- Optimized dot product for buffer matrices moved to `kmath-for-real`
|
||||||
- EjmlMatrix context is an object
|
- EjmlMatrix context is an object
|
||||||
- Matrix LUP `inverse` renamed to `inverseWithLUP`
|
- Matrix LUP `inverse` renamed to `inverseWithLUP`
|
||||||
|
- `NumericAlgebra` moved outside of regular algebra chain (`Ring` no longer implements it).
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ plugins {
|
|||||||
id("ru.mipt.npm.project")
|
id("ru.mipt.npm.project")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val kmathVersion: String by extra("0.2.0-dev-4")
|
internal val kmathVersion: String by extra("0.2.0-dev-5")
|
||||||
internal val bintrayRepo: String by extra("kscience")
|
internal val bintrayRepo: String by extra("kscience")
|
||||||
internal val githubProject: String by extra("kmath")
|
internal val githubProject: String by extra("kmath")
|
||||||
|
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package kscience.kmath.benchmarks
|
||||||
|
|
||||||
|
import kscience.kmath.structures.NDField
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark
|
||||||
|
import org.openjdk.jmh.annotations.Scope
|
||||||
|
import org.openjdk.jmh.annotations.State
|
||||||
|
import org.openjdk.jmh.infra.Blackhole
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
class LargeNDBenchmark {
|
||||||
|
val arraySize = 10000
|
||||||
|
val RANDOM = Random(222)
|
||||||
|
val src1 = DoubleArray(arraySize) { RANDOM.nextDouble() }
|
||||||
|
val src2 = DoubleArray(arraySize) { RANDOM.nextDouble() }
|
||||||
|
val field = NDField.real(arraySize)
|
||||||
|
val kmathArray1 = field.produce { (a) -> src1[a] }
|
||||||
|
val kmathArray2 = field.produce { (a) -> src2[a] }
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun test10000(bh: Blackhole) {
|
||||||
|
bh.consume(field.add(kmathArray1, kmathArray2))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,7 +3,6 @@ package kscience.kmath.commons.prob
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kscience.kmath.chains.BlockingRealChain
|
|
||||||
import kscience.kmath.stat.*
|
import kscience.kmath.stat.*
|
||||||
import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler
|
import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler
|
||||||
import org.apache.commons.rng.simple.RandomSource
|
import org.apache.commons.rng.simple.RandomSource
|
||||||
@ -13,7 +12,7 @@ import java.time.Instant
|
|||||||
private fun runChain(): Duration {
|
private fun runChain(): Duration {
|
||||||
val generator = RandomGenerator.fromSource(RandomSource.MT, 123L)
|
val generator = RandomGenerator.fromSource(RandomSource.MT, 123L)
|
||||||
val normal = Distribution.normal(NormalSamplerMethod.Ziggurat)
|
val normal = Distribution.normal(NormalSamplerMethod.Ziggurat)
|
||||||
val chain = normal.sample(generator) as BlockingRealChain
|
val chain = normal.sample(generator)
|
||||||
val startTime = Instant.now()
|
val startTime = Instant.now()
|
||||||
var sum = 0.0
|
var sum = 0.0
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ fun main() {
|
|||||||
val n = 1000
|
val n = 1000
|
||||||
|
|
||||||
val realField = NDField.real(dim, dim)
|
val realField = NDField.real(dim, dim)
|
||||||
val complexField = NDField.complex(dim, dim)
|
val complexField: ComplexNDField = NDField.complex(dim, dim)
|
||||||
|
|
||||||
val realTime = measureTimeMillis {
|
val realTime = measureTimeMillis {
|
||||||
realField {
|
realField {
|
||||||
|
@ -33,7 +33,7 @@ fun main() {
|
|||||||
measureAndPrint("Automatic field addition") {
|
measureAndPrint("Automatic field addition") {
|
||||||
autoField {
|
autoField {
|
||||||
var res: NDBuffer<Double> = one
|
var res: NDBuffer<Double> = one
|
||||||
repeat(n) { res += number(1.0) }
|
repeat(n) { res += 1.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,14 +45,14 @@ fun main() {
|
|||||||
measureAndPrint("Specialized addition") {
|
measureAndPrint("Specialized addition") {
|
||||||
specializedField {
|
specializedField {
|
||||||
var res: NDBuffer<Double> = one
|
var res: NDBuffer<Double> = one
|
||||||
repeat(n) { res += one }
|
repeat(n) { res += 1.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
measureAndPrint("Nd4j specialized addition") {
|
measureAndPrint("Nd4j specialized addition") {
|
||||||
nd4jField {
|
nd4jField {
|
||||||
var res = one
|
var res = one
|
||||||
repeat(n) { res += one }
|
repeat(n) { res += 1.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ fun main() {
|
|||||||
genericField {
|
genericField {
|
||||||
var res: NDBuffer<Double> = one
|
var res: NDBuffer<Double> = one
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
res += one // couldn't avoid using `one` due to resolution ambiguity }
|
res += 1.0 // couldn't avoid using `one` due to resolution ambiguity }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package kscience.kmath.ast
|
package kscience.kmath.ast
|
||||||
|
|
||||||
|
import kscience.kmath.misc.UnstableKMathAPI
|
||||||
import kscience.kmath.operations.*
|
import kscience.kmath.operations.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,8 +26,11 @@ public object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
|||||||
public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value)
|
public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value)
|
||||||
public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value)
|
public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value)
|
||||||
public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b)
|
public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b)
|
||||||
public override operator fun MST.unaryPlus(): MST.Unary = unaryOperationFunction(SpaceOperations.PLUS_OPERATION)(this)
|
public override operator fun MST.unaryPlus(): MST.Unary =
|
||||||
public override operator fun MST.unaryMinus(): MST.Unary = unaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this)
|
unaryOperationFunction(SpaceOperations.PLUS_OPERATION)(this)
|
||||||
|
|
||||||
|
public override operator fun MST.unaryMinus(): MST.Unary =
|
||||||
|
unaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this)
|
||||||
|
|
||||||
public override operator fun MST.minus(b: MST): MST.Binary =
|
public override operator fun MST.minus(b: MST): MST.Binary =
|
||||||
binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b)
|
binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b)
|
||||||
@ -44,7 +48,8 @@ public object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
|||||||
/**
|
/**
|
||||||
* [Ring] over [MST] nodes.
|
* [Ring] over [MST] nodes.
|
||||||
*/
|
*/
|
||||||
public object MstRing : Ring<MST>, NumericAlgebra<MST> {
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
public object MstRing : Ring<MST>, RingWithNumbers<MST> {
|
||||||
public override val zero: MST.Numeric
|
public override val zero: MST.Numeric
|
||||||
get() = MstSpace.zero
|
get() = MstSpace.zero
|
||||||
|
|
||||||
@ -54,7 +59,9 @@ public object MstRing : Ring<MST>, NumericAlgebra<MST> {
|
|||||||
public override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value)
|
public override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value)
|
||||||
public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b)
|
public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b)
|
||||||
public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k)
|
public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k)
|
||||||
public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b)
|
public override fun multiply(a: MST, b: MST): MST.Binary =
|
||||||
|
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b)
|
||||||
|
|
||||||
public override operator fun MST.unaryPlus(): MST.Unary = MstSpace { +this@unaryPlus }
|
public override operator fun MST.unaryPlus(): MST.Unary = MstSpace { +this@unaryPlus }
|
||||||
public override operator fun MST.unaryMinus(): MST.Unary = MstSpace { -this@unaryMinus }
|
public override operator fun MST.unaryMinus(): MST.Unary = MstSpace { -this@unaryMinus }
|
||||||
public override operator fun MST.minus(b: MST): MST.Binary = MstSpace { this@minus - b }
|
public override operator fun MST.minus(b: MST): MST.Binary = MstSpace { this@minus - b }
|
||||||
@ -69,7 +76,8 @@ public object MstRing : Ring<MST>, NumericAlgebra<MST> {
|
|||||||
/**
|
/**
|
||||||
* [Field] over [MST] nodes.
|
* [Field] over [MST] nodes.
|
||||||
*/
|
*/
|
||||||
public object MstField : Field<MST> {
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
public object MstField : Field<MST>, RingWithNumbers<MST> {
|
||||||
public override val zero: MST.Numeric
|
public override val zero: MST.Numeric
|
||||||
get() = MstRing.zero
|
get() = MstRing.zero
|
||||||
|
|
||||||
@ -81,7 +89,9 @@ public object MstField : Field<MST> {
|
|||||||
public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b)
|
public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b)
|
||||||
public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k)
|
public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k)
|
||||||
public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b)
|
public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b)
|
||||||
public override fun divide(a: MST, b: MST): MST.Binary = binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b)
|
public override fun divide(a: MST, b: MST): MST.Binary =
|
||||||
|
binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b)
|
||||||
|
|
||||||
public override operator fun MST.unaryPlus(): MST.Unary = MstRing { +this@unaryPlus }
|
public override operator fun MST.unaryPlus(): MST.Unary = MstRing { +this@unaryPlus }
|
||||||
public override operator fun MST.unaryMinus(): MST.Unary = MstRing { -this@unaryMinus }
|
public override operator fun MST.unaryMinus(): MST.Unary = MstRing { -this@unaryMinus }
|
||||||
public override operator fun MST.minus(b: MST): MST.Binary = MstRing { this@minus - b }
|
public override operator fun MST.minus(b: MST): MST.Binary = MstRing { this@minus - b }
|
||||||
@ -89,13 +99,14 @@ public object MstField : Field<MST> {
|
|||||||
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
||||||
MstRing.binaryOperationFunction(operation)
|
MstRing.binaryOperationFunction(operation)
|
||||||
|
|
||||||
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = MstRing.unaryOperationFunction(operation)
|
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
|
||||||
|
MstRing.unaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [ExtendedField] over [MST] nodes.
|
* [ExtendedField] over [MST] nodes.
|
||||||
*/
|
*/
|
||||||
public object MstExtendedField : ExtendedField<MST> {
|
public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
|
||||||
public override val zero: MST.Numeric
|
public override val zero: MST.Numeric
|
||||||
get() = MstField.zero
|
get() = MstField.zero
|
||||||
|
|
||||||
@ -103,6 +114,7 @@ public object MstExtendedField : ExtendedField<MST> {
|
|||||||
get() = MstField.one
|
get() = MstField.one
|
||||||
|
|
||||||
public override fun symbol(value: String): MST.Symbolic = MstField.symbol(value)
|
public override fun symbol(value: String): MST.Symbolic = MstField.symbol(value)
|
||||||
|
public override fun number(value: Number): MST.Numeric = MstRing.number(value)
|
||||||
public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg)
|
public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg)
|
||||||
public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg)
|
public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg)
|
||||||
public override fun tan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.TAN_OPERATION)(arg)
|
public override fun tan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.TAN_OPERATION)(arg)
|
||||||
@ -132,5 +144,6 @@ public object MstExtendedField : ExtendedField<MST> {
|
|||||||
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
|
||||||
MstField.binaryOperationFunction(operation)
|
MstField.binaryOperationFunction(operation)
|
||||||
|
|
||||||
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = MstField.unaryOperationFunction(operation)
|
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
|
||||||
|
MstField.unaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package kscience.kmath.commons.expressions
|
package kscience.kmath.commons.expressions
|
||||||
|
|
||||||
import kscience.kmath.expressions.*
|
import kscience.kmath.expressions.*
|
||||||
|
import kscience.kmath.misc.UnstableKMathAPI
|
||||||
import kscience.kmath.operations.ExtendedField
|
import kscience.kmath.operations.ExtendedField
|
||||||
|
import kscience.kmath.operations.RingWithNumbers
|
||||||
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
|
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,15 +12,18 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
|
|||||||
* @property order The derivation order.
|
* @property order The derivation order.
|
||||||
* @property bindings The map of bindings values. All bindings are considered free parameters
|
* @property bindings The map of bindings values. All bindings are considered free parameters
|
||||||
*/
|
*/
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public class DerivativeStructureField(
|
public class DerivativeStructureField(
|
||||||
public val order: Int,
|
public val order: Int,
|
||||||
bindings: Map<Symbol, Double>,
|
bindings: Map<Symbol, Double>,
|
||||||
) : ExtendedField<DerivativeStructure>, ExpressionAlgebra<Double, DerivativeStructure> {
|
) : ExtendedField<DerivativeStructure>, ExpressionAlgebra<Double, DerivativeStructure>, RingWithNumbers<DerivativeStructure> {
|
||||||
public val numberOfVariables: Int = bindings.size
|
public val numberOfVariables: Int = bindings.size
|
||||||
|
|
||||||
public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) }
|
public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) }
|
||||||
public override val one: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order, 1.0) }
|
public override val one: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order, 1.0) }
|
||||||
|
|
||||||
|
override fun number(value: Number): DerivativeStructure = const(value.toDouble())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that implements both [DerivativeStructure] and a [Symbol]
|
* A class that implements both [DerivativeStructure] and a [Symbol]
|
||||||
*/
|
*/
|
||||||
|
@ -7,8 +7,9 @@ import kscience.kmath.operations.*
|
|||||||
*
|
*
|
||||||
* @param algebra The algebra to provide for Expressions built.
|
* @param algebra The algebra to provide for Expressions built.
|
||||||
*/
|
*/
|
||||||
public abstract class FunctionalExpressionAlgebra<T, A : Algebra<T>>(public val algebra: A) :
|
public abstract class FunctionalExpressionAlgebra<T, A : Algebra<T>>(
|
||||||
ExpressionAlgebra<T, Expression<T>> {
|
public val algebra: A,
|
||||||
|
) : ExpressionAlgebra<T, Expression<T>> {
|
||||||
/**
|
/**
|
||||||
* Builds an Expression of constant expression which does not depend on arguments.
|
* Builds an Expression of constant expression which does not depend on arguments.
|
||||||
*/
|
*/
|
||||||
@ -42,8 +43,9 @@ public abstract class FunctionalExpressionAlgebra<T, A : Algebra<T>>(public val
|
|||||||
/**
|
/**
|
||||||
* A context class for [Expression] construction for [Space] algebras.
|
* A context class for [Expression] construction for [Space] algebras.
|
||||||
*/
|
*/
|
||||||
public open class FunctionalExpressionSpace<T, A : Space<T>>(algebra: A) :
|
public open class FunctionalExpressionSpace<T, A : Space<T>>(
|
||||||
FunctionalExpressionAlgebra<T, A>(algebra), Space<Expression<T>> {
|
algebra: A,
|
||||||
|
) : FunctionalExpressionAlgebra<T, A>(algebra), Space<Expression<T>> {
|
||||||
public override val zero: Expression<T> get() = const(algebra.zero)
|
public override val zero: Expression<T> get() = const(algebra.zero)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,8 +73,9 @@ public open class FunctionalExpressionSpace<T, A : Space<T>>(algebra: A) :
|
|||||||
super<FunctionalExpressionAlgebra>.binaryOperationFunction(operation)
|
super<FunctionalExpressionAlgebra>.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class FunctionalExpressionRing<T, A>(algebra: A) : FunctionalExpressionSpace<T, A>(algebra),
|
public open class FunctionalExpressionRing<T, A : Ring<T>>(
|
||||||
Ring<Expression<T>> where A : Ring<T>, A : NumericAlgebra<T> {
|
algebra: A,
|
||||||
|
) : FunctionalExpressionSpace<T, A>(algebra), Ring<Expression<T>> {
|
||||||
public override val one: Expression<T>
|
public override val one: Expression<T>
|
||||||
get() = const(algebra.one)
|
get() = const(algebra.one)
|
||||||
|
|
||||||
@ -92,9 +95,8 @@ public open class FunctionalExpressionRing<T, A>(algebra: A) : FunctionalExpress
|
|||||||
super<FunctionalExpressionSpace>.binaryOperationFunction(operation)
|
super<FunctionalExpressionSpace>.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class FunctionalExpressionField<T, A>(algebra: A) :
|
public open class FunctionalExpressionField<T, A : Field<T>>(algebra: A) :
|
||||||
FunctionalExpressionRing<T, A>(algebra), Field<Expression<T>>
|
FunctionalExpressionRing<T, A>(algebra), Field<Expression<T>> {
|
||||||
where A : Field<T>, A : NumericAlgebra<T> {
|
|
||||||
/**
|
/**
|
||||||
* Builds an Expression of division an expression by another one.
|
* Builds an Expression of division an expression by another one.
|
||||||
*/
|
*/
|
||||||
@ -111,9 +113,12 @@ public open class FunctionalExpressionField<T, A>(algebra: A) :
|
|||||||
super<FunctionalExpressionRing>.binaryOperationFunction(operation)
|
super<FunctionalExpressionRing>.binaryOperationFunction(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class FunctionalExpressionExtendedField<T, A>(algebra: A) :
|
public open class FunctionalExpressionExtendedField<T, A : ExtendedField<T>>(
|
||||||
FunctionalExpressionField<T, A>(algebra),
|
algebra: A,
|
||||||
ExtendedField<Expression<T>> where A : ExtendedField<T>, A : NumericAlgebra<T> {
|
) : FunctionalExpressionField<T, A>(algebra), ExtendedField<Expression<T>> {
|
||||||
|
|
||||||
|
override fun number(value: Number): Expression<T> = const(algebra.number(value))
|
||||||
|
|
||||||
public override fun sin(arg: Expression<T>): Expression<T> =
|
public override fun sin(arg: Expression<T>): Expression<T> =
|
||||||
unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg)
|
unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg)
|
||||||
|
|
||||||
@ -135,7 +140,8 @@ public open class FunctionalExpressionExtendedField<T, A>(algebra: A) :
|
|||||||
public override fun exp(arg: Expression<T>): Expression<T> =
|
public override fun exp(arg: Expression<T>): Expression<T> =
|
||||||
unaryOperationFunction(ExponentialOperations.EXP_OPERATION)(arg)
|
unaryOperationFunction(ExponentialOperations.EXP_OPERATION)(arg)
|
||||||
|
|
||||||
public override fun ln(arg: Expression<T>): Expression<T> = unaryOperationFunction(ExponentialOperations.LN_OPERATION)(arg)
|
public override fun ln(arg: Expression<T>): Expression<T> =
|
||||||
|
unaryOperationFunction(ExponentialOperations.LN_OPERATION)(arg)
|
||||||
|
|
||||||
public override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
|
public override fun unaryOperationFunction(operation: String): (arg: Expression<T>) -> Expression<T> =
|
||||||
super<FunctionalExpressionField>.unaryOperationFunction(operation)
|
super<FunctionalExpressionField>.unaryOperationFunction(operation)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package kscience.kmath.expressions
|
package kscience.kmath.expressions
|
||||||
|
|
||||||
import kscience.kmath.linear.Point
|
import kscience.kmath.linear.Point
|
||||||
|
import kscience.kmath.misc.UnstableKMathAPI
|
||||||
import kscience.kmath.operations.*
|
import kscience.kmath.operations.*
|
||||||
import kscience.kmath.structures.asBuffer
|
import kscience.kmath.structures.asBuffer
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
@ -79,10 +80,11 @@ public fun <T : Any, F : Field<T>> F.simpleAutoDiff(
|
|||||||
/**
|
/**
|
||||||
* Represents field in context of which functions can be derived.
|
* Represents field in context of which functions can be derived.
|
||||||
*/
|
*/
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
|
public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
|
||||||
public val context: F,
|
public val context: F,
|
||||||
bindings: Map<Symbol, T>,
|
bindings: Map<Symbol, T>,
|
||||||
) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>> {
|
) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, RingWithNumbers<AutoDiffValue<T>> {
|
||||||
public override val zero: AutoDiffValue<T>
|
public override val zero: AutoDiffValue<T>
|
||||||
get() = const(context.zero)
|
get() = const(context.zero)
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package kscience.kmath.linear
|
package kscience.kmath.linear
|
||||||
|
|
||||||
|
import kscience.kmath.structures.Matrix
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A marker interface representing some properties of matrices or additional transformations of them. Features are used
|
* A marker interface representing some properties of matrices or additional transformations of them. Features are used
|
||||||
* to optimize matrix operations performance in some cases or retrieve the APIs.
|
* to optimize matrix operations performance in some cases or retrieve the APIs.
|
||||||
@ -30,7 +32,7 @@ public interface InverseMatrixFeature<T : Any> : MatrixFeature {
|
|||||||
/**
|
/**
|
||||||
* The inverse matrix of the matrix that owns this feature.
|
* The inverse matrix of the matrix that owns this feature.
|
||||||
*/
|
*/
|
||||||
public val inverse: FeaturedMatrix<T>
|
public val inverse: Matrix<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,85 +88,6 @@ public interface Algebra<T> {
|
|||||||
public fun binaryOperation(operation: String, left: T, right: T): T = binaryOperationFunction(operation)(left, right)
|
public fun binaryOperation(operation: String, left: T, right: T): T = binaryOperationFunction(operation)(left, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An algebraic structure where elements can have numeric representation.
|
|
||||||
*
|
|
||||||
* @param T the type of element of this structure.
|
|
||||||
*/
|
|
||||||
public interface NumericAlgebra<T> : Algebra<T> {
|
|
||||||
/**
|
|
||||||
* Wraps a number to [T] object.
|
|
||||||
*
|
|
||||||
* @param value the number to wrap.
|
|
||||||
* @return an object.
|
|
||||||
*/
|
|
||||||
public fun number(value: Number): T
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dynamically dispatches a binary operation with the certain name with numeric first argument.
|
|
||||||
*
|
|
||||||
* This function must follow two properties:
|
|
||||||
*
|
|
||||||
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
|
||||||
* 2. This function is symmetric with the other [leftSideNumberOperation] overload:
|
|
||||||
* i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b)`.
|
|
||||||
*
|
|
||||||
* @param operation the name of operation.
|
|
||||||
* @return an operation.
|
|
||||||
*/
|
|
||||||
public fun leftSideNumberOperationFunction(operation: String): (left: Number, right: T) -> T =
|
|
||||||
{ l, r -> binaryOperationFunction(operation)(number(l), r) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dynamically invokes a binary operation with the certain name with numeric first argument.
|
|
||||||
*
|
|
||||||
* This function must follow two properties:
|
|
||||||
*
|
|
||||||
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
|
||||||
* 2. This function is symmetric with second [leftSideNumberOperation] overload:
|
|
||||||
* i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`.
|
|
||||||
*
|
|
||||||
* @param operation the name of operation.
|
|
||||||
* @param left the first argument of operation.
|
|
||||||
* @param right the second argument of operation.
|
|
||||||
* @return a result of operation.
|
|
||||||
*/
|
|
||||||
public fun leftSideNumberOperation(operation: String, left: Number, right: T): T =
|
|
||||||
leftSideNumberOperationFunction(operation)(left, right)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dynamically dispatches a binary operation with the certain name with numeric first argument.
|
|
||||||
*
|
|
||||||
* This function must follow two properties:
|
|
||||||
*
|
|
||||||
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
|
||||||
* 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload:
|
|
||||||
* i.e. `rightSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`.
|
|
||||||
*
|
|
||||||
* @param operation the name of operation.
|
|
||||||
* @return an operation.
|
|
||||||
*/
|
|
||||||
public fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T =
|
|
||||||
{ l, r -> binaryOperationFunction(operation)(l, number(r)) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dynamically invokes a binary operation with the certain name with numeric second argument.
|
|
||||||
*
|
|
||||||
* This function must follow two properties:
|
|
||||||
*
|
|
||||||
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
|
||||||
* 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload:
|
|
||||||
* i.e. `rightSideNumberOperationFunction(a)(b, c) == rightSideNumberOperation(a, b, c)`.
|
|
||||||
*
|
|
||||||
* @param operation the name of operation.
|
|
||||||
* @param left the first argument of operation.
|
|
||||||
* @param right the second argument of operation.
|
|
||||||
* @return a result of operation.
|
|
||||||
*/
|
|
||||||
public fun rightSideNumberOperation(operation: String, left: T, right: Number): T =
|
|
||||||
rightSideNumberOperationFunction(operation)(left, right)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call a block with an [Algebra] as receiver.
|
* Call a block with an [Algebra] as receiver.
|
||||||
*/
|
*/
|
||||||
@ -341,47 +262,11 @@ public interface RingOperations<T> : SpaceOperations<T> {
|
|||||||
*
|
*
|
||||||
* @param T the type of element of this ring.
|
* @param T the type of element of this ring.
|
||||||
*/
|
*/
|
||||||
public interface Ring<T> : Space<T>, RingOperations<T>, NumericAlgebra<T> {
|
public interface Ring<T> : Space<T>, RingOperations<T> {
|
||||||
/**
|
/**
|
||||||
* neutral operation for multiplication
|
* neutral operation for multiplication
|
||||||
*/
|
*/
|
||||||
public val one: T
|
public val one: T
|
||||||
|
|
||||||
public override fun number(value: Number): T = one * value.toDouble()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Addition of element and scalar.
|
|
||||||
*
|
|
||||||
* @receiver the addend.
|
|
||||||
* @param b the augend.
|
|
||||||
*/
|
|
||||||
public operator fun T.plus(b: Number): T = this + number(b)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Addition of scalar and element.
|
|
||||||
*
|
|
||||||
* @receiver the addend.
|
|
||||||
* @param b the augend.
|
|
||||||
*/
|
|
||||||
public operator fun Number.plus(b: T): T = b + this
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subtraction of element from number.
|
|
||||||
*
|
|
||||||
* @receiver the minuend.
|
|
||||||
* @param b the subtrahend.
|
|
||||||
* @receiver the difference.
|
|
||||||
*/
|
|
||||||
public operator fun T.minus(b: Number): T = this - number(b)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subtraction of number from element.
|
|
||||||
*
|
|
||||||
* @receiver the minuend.
|
|
||||||
* @param b the subtrahend.
|
|
||||||
* @receiver the difference.
|
|
||||||
*/
|
|
||||||
public operator fun Number.minus(b: T): T = -b + this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package kscience.kmath.operations
|
package kscience.kmath.operations
|
||||||
|
|
||||||
|
import kscience.kmath.misc.UnstableKMathAPI
|
||||||
import kscience.kmath.operations.BigInt.Companion.BASE
|
import kscience.kmath.operations.BigInt.Companion.BASE
|
||||||
import kscience.kmath.operations.BigInt.Companion.BASE_SIZE
|
import kscience.kmath.operations.BigInt.Companion.BASE_SIZE
|
||||||
import kscience.kmath.structures.*
|
import kscience.kmath.structures.*
|
||||||
@ -16,7 +17,8 @@ public typealias TBase = ULong
|
|||||||
*
|
*
|
||||||
* @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai)
|
* @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai)
|
||||||
*/
|
*/
|
||||||
public object BigIntField : Field<BigInt> {
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
public object BigIntField : Field<BigInt>, RingWithNumbers<BigInt> {
|
||||||
override val zero: BigInt = BigInt.ZERO
|
override val zero: BigInt = BigInt.ZERO
|
||||||
override val one: BigInt = BigInt.ONE
|
override val one: BigInt = BigInt.ONE
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ private val PI_DIV_2 = Complex(PI / 2, 0)
|
|||||||
/**
|
/**
|
||||||
* A field of [Complex].
|
* A field of [Complex].
|
||||||
*/
|
*/
|
||||||
public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
|
public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex>, RingWithNumbers<Complex> {
|
||||||
override val zero: Complex = 0.0.toComplex()
|
override val zero: Complex = 0.0.toComplex()
|
||||||
override val one: Complex = 1.0.toComplex()
|
override val one: Complex = 1.0.toComplex()
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
|
|||||||
|
|
||||||
override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg)
|
override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg)
|
||||||
|
|
||||||
override fun symbol(value: String): Complex = if (value == "i") i else super.symbol(value)
|
override fun symbol(value: String): Complex = if (value == "i") i else super<ExtendedField>.symbol(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,125 @@
|
|||||||
|
package kscience.kmath.operations
|
||||||
|
|
||||||
|
import kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An algebraic structure where elements can have numeric representation.
|
||||||
|
*
|
||||||
|
* @param T the type of element of this structure.
|
||||||
|
*/
|
||||||
|
public interface NumericAlgebra<T> : Algebra<T> {
|
||||||
|
/**
|
||||||
|
* Wraps a number to [T] object.
|
||||||
|
*
|
||||||
|
* @param value the number to wrap.
|
||||||
|
* @return an object.
|
||||||
|
*/
|
||||||
|
public fun number(value: Number): T
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamically dispatches a binary operation with the certain name with numeric first argument.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with the other [leftSideNumberOperation] overload:
|
||||||
|
* i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @return an operation.
|
||||||
|
*/
|
||||||
|
public fun leftSideNumberOperationFunction(operation: String): (left: Number, right: T) -> T =
|
||||||
|
{ l, r -> binaryOperationFunction(operation)(number(l), r) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamically invokes a binary operation with the certain name with numeric first argument.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with second [leftSideNumberOperation] overload:
|
||||||
|
* i.e. `leftSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @param left the first argument of operation.
|
||||||
|
* @param right the second argument of operation.
|
||||||
|
* @return a result of operation.
|
||||||
|
*/
|
||||||
|
public fun leftSideNumberOperation(operation: String, left: Number, right: T): T =
|
||||||
|
leftSideNumberOperationFunction(operation)(left, right)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamically dispatches a binary operation with the certain name with numeric first argument.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload:
|
||||||
|
* i.e. `rightSideNumberOperationFunction(a)(b, c) == leftSideNumberOperation(a, b, c)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @return an operation.
|
||||||
|
*/
|
||||||
|
public fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T =
|
||||||
|
{ l, r -> binaryOperationFunction(operation)(l, number(r)) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamically invokes a binary operation with the certain name with numeric second argument.
|
||||||
|
*
|
||||||
|
* This function must follow two properties:
|
||||||
|
*
|
||||||
|
* 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException].
|
||||||
|
* 2. This function is symmetric with the other [rightSideNumberOperationFunction] overload:
|
||||||
|
* i.e. `rightSideNumberOperationFunction(a)(b, c) == rightSideNumberOperation(a, b, c)`.
|
||||||
|
*
|
||||||
|
* @param operation the name of operation.
|
||||||
|
* @param left the first argument of operation.
|
||||||
|
* @param right the second argument of operation.
|
||||||
|
* @return a result of operation.
|
||||||
|
*/
|
||||||
|
public fun rightSideNumberOperation(operation: String, left: T, right: Number): T =
|
||||||
|
rightSideNumberOperationFunction(operation)(left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A combination of [NumericAlgebra] and [Ring] that adds intrinsic simple operations on numbers like `T+1`
|
||||||
|
* TODO to be removed and replaced by extensions after multiple receivers are there
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public interface RingWithNumbers<T>: Ring<T>, NumericAlgebra<T>{
|
||||||
|
public override fun number(value: Number): T = one * value
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addition of element and scalar.
|
||||||
|
*
|
||||||
|
* @receiver the addend.
|
||||||
|
* @param b the augend.
|
||||||
|
*/
|
||||||
|
public operator fun T.plus(b: Number): T = this + number(b)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addition of scalar and element.
|
||||||
|
*
|
||||||
|
* @receiver the addend.
|
||||||
|
* @param b the augend.
|
||||||
|
*/
|
||||||
|
public operator fun Number.plus(b: T): T = b + this
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtraction of element from number.
|
||||||
|
*
|
||||||
|
* @receiver the minuend.
|
||||||
|
* @param b the subtrahend.
|
||||||
|
* @receiver the difference.
|
||||||
|
*/
|
||||||
|
public operator fun T.minus(b: Number): T = this - number(b)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtraction of number from element.
|
||||||
|
*
|
||||||
|
* @receiver the minuend.
|
||||||
|
* @param b the subtrahend.
|
||||||
|
* @receiver the difference.
|
||||||
|
*/
|
||||||
|
public operator fun Number.minus(b: T): T = -b + this
|
||||||
|
}
|
@ -37,7 +37,7 @@ public interface ExtendedFieldOperations<T> :
|
|||||||
/**
|
/**
|
||||||
* Advanced Number-like field that implements basic operations.
|
* Advanced Number-like field that implements basic operations.
|
||||||
*/
|
*/
|
||||||
public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T> {
|
public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T>, NumericAlgebra<T> {
|
||||||
public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2
|
public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2
|
||||||
public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2
|
public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2
|
||||||
public override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
|
public override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
|
||||||
@ -80,6 +80,8 @@ public object RealField : ExtendedField<Double>, Norm<Double, Double> {
|
|||||||
public override val one: Double
|
public override val one: Double
|
||||||
get() = 1.0
|
get() = 1.0
|
||||||
|
|
||||||
|
override fun number(value: Number): Double = value.toDouble()
|
||||||
|
|
||||||
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
|
public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double =
|
||||||
when (operation) {
|
when (operation) {
|
||||||
PowerOperations.POW_OPERATION -> ::power
|
PowerOperations.POW_OPERATION -> ::power
|
||||||
@ -131,10 +133,13 @@ public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
|
|||||||
public override val one: Float
|
public override val one: Float
|
||||||
get() = 1.0f
|
get() = 1.0f
|
||||||
|
|
||||||
public override fun binaryOperationFunction(operation: String): (left: Float, right: Float) -> Float = when (operation) {
|
override fun number(value: Number): Float = value.toFloat()
|
||||||
PowerOperations.POW_OPERATION -> ::power
|
|
||||||
else -> super.binaryOperationFunction(operation)
|
public override fun binaryOperationFunction(operation: String): (left: Float, right: Float) -> Float =
|
||||||
}
|
when (operation) {
|
||||||
|
PowerOperations.POW_OPERATION -> ::power
|
||||||
|
else -> super.binaryOperationFunction(operation)
|
||||||
|
}
|
||||||
|
|
||||||
public override inline fun add(a: Float, b: Float): Float = a + b
|
public override inline fun add(a: Float, b: Float): Float = a + b
|
||||||
public override inline fun multiply(a: Float, k: Number): Float = a * k.toFloat()
|
public override inline fun multiply(a: Float, k: Number): Float = a * k.toFloat()
|
@ -1,9 +1,7 @@
|
|||||||
package kscience.kmath.structures
|
package kscience.kmath.structures
|
||||||
|
|
||||||
import kscience.kmath.operations.Complex
|
import kscience.kmath.misc.UnstableKMathAPI
|
||||||
import kscience.kmath.operations.ComplexField
|
import kscience.kmath.operations.*
|
||||||
import kscience.kmath.operations.FieldElement
|
|
||||||
import kscience.kmath.operations.complex
|
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
@ -12,15 +10,22 @@ public typealias ComplexNDElement = BufferedNDFieldElement<Complex, ComplexField
|
|||||||
/**
|
/**
|
||||||
* An optimized nd-field for complex numbers
|
* An optimized nd-field for complex numbers
|
||||||
*/
|
*/
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public class ComplexNDField(override val shape: IntArray) :
|
public class ComplexNDField(override val shape: IntArray) :
|
||||||
BufferedNDField<Complex, ComplexField>,
|
BufferedNDField<Complex, ComplexField>,
|
||||||
ExtendedNDField<Complex, ComplexField, NDBuffer<Complex>> {
|
ExtendedNDField<Complex, ComplexField, NDBuffer<Complex>>,
|
||||||
|
RingWithNumbers<NDBuffer<Complex>>{
|
||||||
|
|
||||||
override val strides: Strides = DefaultStrides(shape)
|
override val strides: Strides = DefaultStrides(shape)
|
||||||
override val elementContext: ComplexField get() = ComplexField
|
override val elementContext: ComplexField get() = ComplexField
|
||||||
override val zero: ComplexNDElement by lazy { produce { zero } }
|
override val zero: ComplexNDElement by lazy { produce { zero } }
|
||||||
override val one: ComplexNDElement by lazy { produce { one } }
|
override val one: ComplexNDElement by lazy { produce { one } }
|
||||||
|
|
||||||
|
override fun number(value: Number): NDBuffer<Complex> {
|
||||||
|
val c = value.toComplex()
|
||||||
|
return produce { c }
|
||||||
|
}
|
||||||
|
|
||||||
public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Complex): Buffer<Complex> =
|
public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Complex): Buffer<Complex> =
|
||||||
Buffer.complex(size) { initializer(it) }
|
Buffer.complex(size) { initializer(it) }
|
||||||
|
|
||||||
@ -29,7 +34,7 @@ public class ComplexNDField(override val shape: IntArray) :
|
|||||||
*/
|
*/
|
||||||
override fun map(
|
override fun map(
|
||||||
arg: NDBuffer<Complex>,
|
arg: NDBuffer<Complex>,
|
||||||
transform: ComplexField.(Complex) -> Complex
|
transform: ComplexField.(Complex) -> Complex,
|
||||||
): ComplexNDElement {
|
): ComplexNDElement {
|
||||||
check(arg)
|
check(arg)
|
||||||
val array = buildBuffer(arg.strides.linearSize) { offset -> ComplexField.transform(arg.buffer[offset]) }
|
val array = buildBuffer(arg.strides.linearSize) { offset -> ComplexField.transform(arg.buffer[offset]) }
|
||||||
@ -43,7 +48,7 @@ public class ComplexNDField(override val shape: IntArray) :
|
|||||||
|
|
||||||
override fun mapIndexed(
|
override fun mapIndexed(
|
||||||
arg: NDBuffer<Complex>,
|
arg: NDBuffer<Complex>,
|
||||||
transform: ComplexField.(index: IntArray, Complex) -> Complex
|
transform: ComplexField.(index: IntArray, Complex) -> Complex,
|
||||||
): ComplexNDElement {
|
): ComplexNDElement {
|
||||||
check(arg)
|
check(arg)
|
||||||
|
|
||||||
@ -60,7 +65,7 @@ public class ComplexNDField(override val shape: IntArray) :
|
|||||||
override fun combine(
|
override fun combine(
|
||||||
a: NDBuffer<Complex>,
|
a: NDBuffer<Complex>,
|
||||||
b: NDBuffer<Complex>,
|
b: NDBuffer<Complex>,
|
||||||
transform: ComplexField.(Complex, Complex) -> Complex
|
transform: ComplexField.(Complex, Complex) -> Complex,
|
||||||
): ComplexNDElement {
|
): ComplexNDElement {
|
||||||
check(a, b)
|
check(a, b)
|
||||||
|
|
||||||
@ -141,7 +146,7 @@ public fun NDField.Companion.complex(vararg shape: Int): ComplexNDField = Comple
|
|||||||
|
|
||||||
public fun NDElement.Companion.complex(
|
public fun NDElement.Companion.complex(
|
||||||
vararg shape: Int,
|
vararg shape: Int,
|
||||||
initializer: ComplexField.(IntArray) -> Complex
|
initializer: ComplexField.(IntArray) -> Complex,
|
||||||
): ComplexNDElement = NDField.complex(*shape).produce(initializer)
|
): ComplexNDElement = NDField.complex(*shape).produce(initializer)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,6 +150,8 @@ public class RealBufferField(public val size: Int) : ExtendedField<Buffer<Double
|
|||||||
public override val zero: Buffer<Double> by lazy { RealBuffer(size) { 0.0 } }
|
public override val zero: Buffer<Double> by lazy { RealBuffer(size) { 0.0 } }
|
||||||
public override val one: Buffer<Double> by lazy { RealBuffer(size) { 1.0 } }
|
public override val one: Buffer<Double> by lazy { RealBuffer(size) { 1.0 } }
|
||||||
|
|
||||||
|
override fun number(value: Number): Buffer<Double> = RealBuffer(size) { value.toDouble() }
|
||||||
|
|
||||||
public override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
public override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||||
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
|
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
|
||||||
return RealBufferFieldOperations.add(a, b)
|
return RealBufferFieldOperations.add(a, b)
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
package kscience.kmath.structures
|
package kscience.kmath.structures
|
||||||
|
|
||||||
|
import kscience.kmath.misc.UnstableKMathAPI
|
||||||
import kscience.kmath.operations.FieldElement
|
import kscience.kmath.operations.FieldElement
|
||||||
import kscience.kmath.operations.RealField
|
import kscience.kmath.operations.RealField
|
||||||
|
import kscience.kmath.operations.RingWithNumbers
|
||||||
|
|
||||||
public typealias RealNDElement = BufferedNDFieldElement<Double, RealField>
|
public typealias RealNDElement = BufferedNDFieldElement<Double, RealField>
|
||||||
|
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public class RealNDField(override val shape: IntArray) :
|
public class RealNDField(override val shape: IntArray) :
|
||||||
BufferedNDField<Double, RealField>,
|
BufferedNDField<Double, RealField>,
|
||||||
ExtendedNDField<Double, RealField, NDBuffer<Double>> {
|
ExtendedNDField<Double, RealField, NDBuffer<Double>>,
|
||||||
|
RingWithNumbers<NDBuffer<Double>>{
|
||||||
|
|
||||||
override val strides: Strides = DefaultStrides(shape)
|
override val strides: Strides = DefaultStrides(shape)
|
||||||
|
|
||||||
@ -15,7 +19,12 @@ public class RealNDField(override val shape: IntArray) :
|
|||||||
override val zero: RealNDElement by lazy { produce { zero } }
|
override val zero: RealNDElement by lazy { produce { zero } }
|
||||||
override val one: RealNDElement by lazy { produce { one } }
|
override val one: RealNDElement by lazy { produce { one } }
|
||||||
|
|
||||||
public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer<Double> =
|
override fun number(value: Number): NDBuffer<Double> {
|
||||||
|
val d = value.toDouble()
|
||||||
|
return produce { d }
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer<Double> =
|
||||||
RealBuffer(DoubleArray(size) { initializer(it) })
|
RealBuffer(DoubleArray(size) { initializer(it) })
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,7 +68,8 @@ public class RealNDField(override val shape: IntArray) :
|
|||||||
check(a, b)
|
check(a, b)
|
||||||
return BufferedNDFieldElement(
|
return BufferedNDFieldElement(
|
||||||
this,
|
this,
|
||||||
buildBuffer(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) })
|
buildBuffer(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun NDBuffer<Double>.toElement(): FieldElement<NDBuffer<Double>, *, out BufferedNDField<Double, RealField>> =
|
override fun NDBuffer<Double>.toElement(): FieldElement<NDBuffer<Double>, *, out BufferedNDField<Double, RealField>> =
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
package kscience.kmath.structures
|
package kscience.kmath.structures
|
||||||
|
|
||||||
import kscience.kmath.operations.internal.FieldVerifier
|
import kscience.kmath.operations.internal.FieldVerifier
|
||||||
import kscience.kmath.operations.invoke
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class NDFieldTest {
|
internal class NDFieldTest {
|
||||||
@Test
|
@Test
|
||||||
fun verify() {
|
fun verify() {
|
||||||
(NDField.real(12, 32)) { FieldVerifier(this, one + 3, one - 23, one * 12, 6.66) }
|
NDField.real(12, 32).run { FieldVerifier(this, one + 3, one - 23, one * 12, 6.66) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -7,7 +7,7 @@ import java.math.MathContext
|
|||||||
/**
|
/**
|
||||||
* A field over [BigInteger].
|
* A field over [BigInteger].
|
||||||
*/
|
*/
|
||||||
public object JBigIntegerField : Field<BigInteger> {
|
public object JBigIntegerField : Field<BigInteger>, NumericAlgebra<BigInteger> {
|
||||||
public override val zero: BigInteger
|
public override val zero: BigInteger
|
||||||
get() = BigInteger.ZERO
|
get() = BigInteger.ZERO
|
||||||
|
|
||||||
@ -28,9 +28,9 @@ public object JBigIntegerField : Field<BigInteger> {
|
|||||||
*
|
*
|
||||||
* @property mathContext the [MathContext] to use.
|
* @property mathContext the [MathContext] to use.
|
||||||
*/
|
*/
|
||||||
public abstract class JBigDecimalFieldBase internal constructor(public val mathContext: MathContext = MathContext.DECIMAL64) :
|
public abstract class JBigDecimalFieldBase internal constructor(
|
||||||
Field<BigDecimal>,
|
private val mathContext: MathContext = MathContext.DECIMAL64,
|
||||||
PowerOperations<BigDecimal> {
|
) : Field<BigDecimal>, PowerOperations<BigDecimal>, NumericAlgebra<BigDecimal> {
|
||||||
public override val zero: BigDecimal
|
public override val zero: BigDecimal
|
||||||
get() = BigDecimal.ZERO
|
get() = BigDecimal.ZERO
|
||||||
|
|
||||||
|
@ -12,8 +12,10 @@ import org.ejml.simple.SimpleMatrix
|
|||||||
* @property origin the underlying [SimpleMatrix].
|
* @property origin the underlying [SimpleMatrix].
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public class EjmlMatrix(public val origin: SimpleMatrix, features: Set<MatrixFeature> = emptySet()) :
|
public class EjmlMatrix(
|
||||||
FeaturedMatrix<Double> {
|
public val origin: SimpleMatrix,
|
||||||
|
features: Set<MatrixFeature> = emptySet()
|
||||||
|
) : FeaturedMatrix<Double> {
|
||||||
public override val rowNum: Int
|
public override val rowNum: Int
|
||||||
get() = origin.numRows()
|
get() = origin.numRows()
|
||||||
|
|
||||||
@ -88,11 +90,7 @@ public class EjmlMatrix(public val origin: SimpleMatrix, features: Set<MatrixFea
|
|||||||
return NDStructure.equals(this, other as? NDStructure<*> ?: return false)
|
return NDStructure.equals(this, other as? NDStructure<*> ?: return false)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun hashCode(): Int {
|
public override fun hashCode(): Int = origin.hashCode()
|
||||||
var result = origin.hashCode()
|
|
||||||
result = 31 * result + features.hashCode()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun toString(): String = "EjmlMatrix(origin=$origin, features=$features)"
|
public override fun toString(): String = "EjmlMatrix($origin)"
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package kscience.kmath.ejml
|
package kscience.kmath.ejml
|
||||||
|
|
||||||
|
import kscience.kmath.linear.InverseMatrixFeature
|
||||||
import kscience.kmath.linear.MatrixContext
|
import kscience.kmath.linear.MatrixContext
|
||||||
import kscience.kmath.linear.Point
|
import kscience.kmath.linear.Point
|
||||||
|
import kscience.kmath.linear.getFeature
|
||||||
import kscience.kmath.structures.Matrix
|
import kscience.kmath.structures.Matrix
|
||||||
import org.ejml.simple.SimpleMatrix
|
import org.ejml.simple.SimpleMatrix
|
||||||
|
|
||||||
@ -77,3 +79,7 @@ public fun EjmlMatrixContext.solve(a: Matrix<Double>, b: Matrix<Double>): EjmlMa
|
|||||||
*/
|
*/
|
||||||
public fun EjmlMatrixContext.solve(a: Matrix<Double>, b: Point<Double>): EjmlVector =
|
public fun EjmlMatrixContext.solve(a: Matrix<Double>, b: Point<Double>): EjmlVector =
|
||||||
EjmlVector(a.toEjml().origin.solve(b.toEjml().origin))
|
EjmlVector(a.toEjml().origin.solve(b.toEjml().origin))
|
||||||
|
|
||||||
|
public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature<InverseMatrixFeature<Double>>()!!.inverse as EjmlMatrix
|
||||||
|
|
||||||
|
public fun EjmlMatrixContext.inverse(matrix: Matrix<Double>): Matrix<Double> = matrix.toEjml().inverted()
|
@ -1,5 +1,6 @@
|
|||||||
package kscience.kmath.nd4j
|
package kscience.kmath.nd4j
|
||||||
|
|
||||||
|
import kscience.kmath.misc.UnstableKMathAPI
|
||||||
import kscience.kmath.operations.*
|
import kscience.kmath.operations.*
|
||||||
import kscience.kmath.structures.NDAlgebra
|
import kscience.kmath.structures.NDAlgebra
|
||||||
import kscience.kmath.structures.NDField
|
import kscience.kmath.structures.NDField
|
||||||
@ -35,7 +36,7 @@ public interface Nd4jArrayAlgebra<T, C> : NDAlgebra<T, C, Nd4jArrayStructure<T>>
|
|||||||
|
|
||||||
public override fun mapIndexed(
|
public override fun mapIndexed(
|
||||||
arg: Nd4jArrayStructure<T>,
|
arg: Nd4jArrayStructure<T>,
|
||||||
transform: C.(index: IntArray, T) -> T
|
transform: C.(index: IntArray, T) -> T,
|
||||||
): Nd4jArrayStructure<T> {
|
): Nd4jArrayStructure<T> {
|
||||||
check(arg)
|
check(arg)
|
||||||
val new = Nd4j.create(*shape).wrap()
|
val new = Nd4j.create(*shape).wrap()
|
||||||
@ -46,7 +47,7 @@ public interface Nd4jArrayAlgebra<T, C> : NDAlgebra<T, C, Nd4jArrayStructure<T>>
|
|||||||
public override fun combine(
|
public override fun combine(
|
||||||
a: Nd4jArrayStructure<T>,
|
a: Nd4jArrayStructure<T>,
|
||||||
b: Nd4jArrayStructure<T>,
|
b: Nd4jArrayStructure<T>,
|
||||||
transform: C.(T, T) -> T
|
transform: C.(T, T) -> T,
|
||||||
): Nd4jArrayStructure<T> {
|
): Nd4jArrayStructure<T> {
|
||||||
check(a, b)
|
check(a, b)
|
||||||
val new = Nd4j.create(*shape).wrap()
|
val new = Nd4j.create(*shape).wrap()
|
||||||
@ -61,8 +62,8 @@ public interface Nd4jArrayAlgebra<T, C> : NDAlgebra<T, C, Nd4jArrayStructure<T>>
|
|||||||
* @param T the type of the element contained in ND structure.
|
* @param T the type of the element contained in ND structure.
|
||||||
* @param S the type of space of structure elements.
|
* @param S the type of space of structure elements.
|
||||||
*/
|
*/
|
||||||
public interface Nd4jArraySpace<T, S> : NDSpace<T, S, Nd4jArrayStructure<T>>,
|
public interface Nd4jArraySpace<T, S : Space<T>> : NDSpace<T, S, Nd4jArrayStructure<T>>, Nd4jArrayAlgebra<T, S> {
|
||||||
Nd4jArrayAlgebra<T, S> where S : Space<T> {
|
|
||||||
public override val zero: Nd4jArrayStructure<T>
|
public override val zero: Nd4jArrayStructure<T>
|
||||||
get() = Nd4j.zeros(*shape).wrap()
|
get() = Nd4j.zeros(*shape).wrap()
|
||||||
|
|
||||||
@ -103,7 +104,9 @@ public interface Nd4jArraySpace<T, S> : NDSpace<T, S, Nd4jArrayStructure<T>>,
|
|||||||
* @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.
|
||||||
*/
|
*/
|
||||||
public interface Nd4jArrayRing<T, R> : NDRing<T, R, Nd4jArrayStructure<T>>, Nd4jArraySpace<T, R> where R : Ring<T> {
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
public interface Nd4jArrayRing<T, R : Ring<T>> : NDRing<T, R, Nd4jArrayStructure<T>>, Nd4jArraySpace<T, R> {
|
||||||
|
|
||||||
public override val one: Nd4jArrayStructure<T>
|
public override val one: Nd4jArrayStructure<T>
|
||||||
get() = Nd4j.ones(*shape).wrap()
|
get() = Nd4j.ones(*shape).wrap()
|
||||||
|
|
||||||
@ -111,21 +114,21 @@ public interface Nd4jArrayRing<T, R> : NDRing<T, R, Nd4jArrayStructure<T>>, Nd4j
|
|||||||
check(a, b)
|
check(a, b)
|
||||||
return a.ndArray.mul(b.ndArray).wrap()
|
return a.ndArray.mul(b.ndArray).wrap()
|
||||||
}
|
}
|
||||||
|
//
|
||||||
public override operator fun Nd4jArrayStructure<T>.minus(b: Number): Nd4jArrayStructure<T> {
|
// public override operator fun Nd4jArrayStructure<T>.minus(b: Number): Nd4jArrayStructure<T> {
|
||||||
check(this)
|
// check(this)
|
||||||
return ndArray.sub(b).wrap()
|
// return ndArray.sub(b).wrap()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public override operator fun Nd4jArrayStructure<T>.plus(b: Number): Nd4jArrayStructure<T> {
|
// public override operator fun Nd4jArrayStructure<T>.plus(b: Number): Nd4jArrayStructure<T> {
|
||||||
check(this)
|
// check(this)
|
||||||
return ndArray.add(b).wrap()
|
// return ndArray.add(b).wrap()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public override operator fun Number.minus(b: Nd4jArrayStructure<T>): Nd4jArrayStructure<T> {
|
// public override operator fun Number.minus(b: Nd4jArrayStructure<T>): Nd4jArrayStructure<T> {
|
||||||
check(b)
|
// check(b)
|
||||||
return b.ndArray.rsub(this).wrap()
|
// return b.ndArray.rsub(this).wrap()
|
||||||
}
|
// }
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
private val intNd4jArrayRingCache: ThreadLocal<MutableMap<IntArray, IntNd4jArrayRing>> =
|
private val intNd4jArrayRingCache: ThreadLocal<MutableMap<IntArray, IntNd4jArrayRing>> =
|
||||||
@ -165,7 +168,8 @@ public interface Nd4jArrayRing<T, R> : NDRing<T, R, Nd4jArrayStructure<T>>, Nd4j
|
|||||||
* @param N the type of ND structure.
|
* @param N the type of ND structure.
|
||||||
* @param F the type field of structure elements.
|
* @param F the type field of structure elements.
|
||||||
*/
|
*/
|
||||||
public interface Nd4jArrayField<T, F> : NDField<T, F, Nd4jArrayStructure<T>>, Nd4jArrayRing<T, F> where F : Field<T> {
|
public interface Nd4jArrayField<T, F : Field<T>> : NDField<T, F, Nd4jArrayStructure<T>>, Nd4jArrayRing<T, F> {
|
||||||
|
|
||||||
public override fun divide(a: Nd4jArrayStructure<T>, b: Nd4jArrayStructure<T>): Nd4jArrayStructure<T> {
|
public override fun divide(a: Nd4jArrayStructure<T>, b: Nd4jArrayStructure<T>): Nd4jArrayStructure<T> {
|
||||||
check(a, b)
|
check(a, b)
|
||||||
return a.ndArray.div(b.ndArray).wrap()
|
return a.ndArray.div(b.ndArray).wrap()
|
||||||
|
@ -8,8 +8,8 @@ pluginManagement {
|
|||||||
maven("https://dl.bintray.com/kotlin/kotlinx")
|
maven("https://dl.bintray.com/kotlin/kotlinx")
|
||||||
}
|
}
|
||||||
|
|
||||||
val toolsVersion = "0.7.2-dev-2"
|
val toolsVersion = "0.7.3-1.4.30-RC"
|
||||||
val kotlinVersion = "1.4.21"
|
val kotlinVersion = "1.4.30-RC"
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("kotlinx.benchmark") version "0.2.0-dev-20"
|
id("kotlinx.benchmark") version "0.2.0-dev-20"
|
||||||
|
Loading…
Reference in New Issue
Block a user