Compare commits

..

No commits in common. "46eacbb7506d40962fa91f70cc0a047d63ed5a17" and "9da14089e03939d940000df5a9628101be5dc01a" have entirely different histories.

84 changed files with 386 additions and 662 deletions

View File

@ -3,11 +3,10 @@
## Unreleased ## Unreleased
### Added ### Added
- Explicit `SafeType` for algebras and buffers. - Integer division algebras
- Integer division algebras. - Float32 geometries
- Float32 geometries. - New Attributes-kt module that could be used as stand-alone. It declares type-safe attributes containers.
- New Attributes-kt module that could be used as stand-alone. It declares. type-safe attributes containers. - Explicit `mutableStructureND` builders for mutable structures
- Explicit `mutableStructureND` builders for mutable structures.
### Changed ### Changed
- Default naming for algebra and buffers now uses IntXX/FloatXX notation instead of Java types. - Default naming for algebra and buffers now uses IntXX/FloatXX notation instead of Java types.
@ -20,7 +19,6 @@
### Deprecated ### Deprecated
### Removed ### Removed
- `asPolynomial` function due to scope pollution
### Fixed ### Fixed
- Median statistics - Median statistics

View File

@ -7,10 +7,8 @@ package space.kscience.attributes
/** /**
* A safe builder for [Attributes] * A safe builder for [Attributes]
*
* @param O type marker of an owner object, for which these attributes are made
*/ */
public class TypedAttributesBuilder<in O> internal constructor(private val map: MutableMap<Attribute<*>, Any>) { public class AttributesBuilder internal constructor(private val map: MutableMap<Attribute<*>, Any>) {
public constructor() : this(mutableMapOf()) public constructor() : this(mutableMapOf())
@ -49,8 +47,6 @@ public class TypedAttributesBuilder<in O> internal constructor(private val map:
public fun build(): Attributes = Attributes(map) public fun build(): Attributes = Attributes(map)
} }
public typealias AttributesBuilder = TypedAttributesBuilder<Any?>
public fun AttributesBuilder( public fun AttributesBuilder(
attributes: Attributes, attributes: Attributes,
): AttributesBuilder = AttributesBuilder(attributes.content.toMutableMap()) ): AttributesBuilder = AttributesBuilder(attributes.content.toMutableMap())

View File

@ -16,7 +16,7 @@ import kotlin.reflect.typeOf
* @param kType raw [KType] * @param kType raw [KType]
*/ */
@JvmInline @JvmInline
public value class SafeType<out T> @PublishedApi internal constructor(public val kType: KType) public value class SafeType<T> @PublishedApi internal constructor(public val kType: KType)
public inline fun <reified T> safeTypeOf(): SafeType<T> = SafeType(typeOf<T>()) public inline fun <reified T> safeTypeOf(): SafeType<T> = SafeType(typeOf<T>())

View File

@ -1,3 +1,4 @@
import space.kscience.gradle.isInDevelopment
import space.kscience.gradle.useApache2Licence import space.kscience.gradle.useApache2Licence
import space.kscience.gradle.useSPCTeam import space.kscience.gradle.useSPCTeam
@ -63,10 +64,17 @@ ksciencePublish {
useApache2Licence() useApache2Licence()
useSPCTeam() useSPCTeam()
} }
repository("spc","https://maven.sciprog.center/kscience") github("kmath", "SciProgCentre")
space(
if (isInDevelopment) {
"https://maven.pkg.jetbrains.space/spc/p/sci/dev"
} else {
"https://maven.pkg.jetbrains.space/spc/p/sci/maven"
}
)
sonatype("https://oss.sonatype.org") sonatype("https://oss.sonatype.org")
} }
apiValidation.nonPublicMarkers.add("space.kscience.kmath.UnstableKMathAPI") apiValidation.nonPublicMarkers.add("space.kscience.kmath.UnstableKMathAPI")
val multikVersion by extra("0.2.2") val multikVersion by extra("0.2.0")

View File

@ -17,7 +17,7 @@ val benchmarksVersion = spclibs.versions.kotlinx.benchmark.get()
dependencies { dependencies {
api("space.kscience:gradle-tools:$toolsVersion") api("space.kscience:gradle-tools:$toolsVersion")
//plugins form benchmarks //plugins form benchmarks
api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.4.9") api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.4.7")
//api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion") //api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
//to be used inside build-script only //to be used inside build-script only
//implementation(spclibs.kotlinx.serialization.json) //implementation(spclibs.kotlinx.serialization.json)

View File

@ -1,13 +1,4 @@
/* rootProject.name = "buildSrc"
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
}
dependencyResolutionManagement { dependencyResolutionManagement {
val projectProperties = java.util.Properties() val projectProperties = java.util.Properties()

View File

@ -54,9 +54,9 @@ fun Project.addBenchmarkProperties() {
p.extensions.findByType(KScienceReadmeExtension::class.java)?.run { p.extensions.findByType(KScienceReadmeExtension::class.java)?.run {
benchmarksProject.extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg -> benchmarksProject.extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg ->
property("benchmark${cfg.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}") { property("benchmark${cfg.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}") {
val launches = benchmarksProject.layout.buildDirectory.dir("reports/benchmarks/${cfg.name}").get() val launches = benchmarksProject.buildDir.resolve("reports/benchmarks/${cfg.name}")
val resDirectory = launches.files().maxByOrNull { val resDirectory = launches.listFiles()?.maxByOrNull {
LocalDateTime.parse(it.name, ISO_DATE_TIME).atZone(ZoneId.systemDefault()).toInstant() LocalDateTime.parse(it.name, ISO_DATE_TIME).atZone(ZoneId.systemDefault()).toInstant()
} }

View File

@ -6,12 +6,9 @@ kotlin.code.style=official
kotlin.mpp.stability.nowarn=true kotlin.mpp.stability.nowarn=true
kotlin.native.ignoreDisabledTargets=true kotlin.native.ignoreDisabledTargets=true
org.gradle.configureondemand=true toolsVersion=0.14.9-kotlin-1.8.20
org.gradle.jvmargs=-Xmx4096m
org.gradle.parallel=true org.gradle.parallel=true
org.gradle.workers.max=4 org.gradle.workers.max=4
org.gradle.configureondemand=true
toolsVersion=0.15.0-kotlin-1.9.20 org.gradle.jvmargs=-Xmx4096m
#kotlin.experimental.tryK2=true
#kscience.wasm.disabled=true

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -31,7 +31,7 @@ kscience{
kotlin { kotlin {
js { js {
nodejs { nodejs {
testTask{ testTask {
useMocha().timeout = "0" useMocha().timeout = "0"
} }
} }

View File

@ -17,7 +17,7 @@ internal class TestFeatures {
fun printNumeric() { fun printNumeric() {
val num = object : Number() { val num = object : Number() {
override fun toByte(): Byte = throw UnsupportedOperationException() override fun toByte(): Byte = throw UnsupportedOperationException()
// override fun toChar(): Char = throw UnsupportedOperationException() override fun toChar(): Char = throw UnsupportedOperationException()
override fun toDouble(): Double = throw UnsupportedOperationException() override fun toDouble(): Double = throw UnsupportedOperationException()
override fun toFloat(): Float = throw UnsupportedOperationException() override fun toFloat(): Float = throw UnsupportedOperationException()
override fun toInt(): Int = throw UnsupportedOperationException() override fun toInt(): Int = throw UnsupportedOperationException()

View File

@ -8,8 +8,9 @@
"OVERRIDING_FINAL_MEMBER", "OVERRIDING_FINAL_MEMBER",
"RETURN_TYPE_MISMATCH_ON_OVERRIDE", "RETURN_TYPE_MISMATCH_ON_OVERRIDE",
"CONFLICTING_OVERLOADS", "CONFLICTING_OVERLOADS",
"NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING",
"PropertyName", "PropertyName",
"ClassName", "ENUM_CLASS_IN_EXTERNAL_DECLARATION_WARNING", "ClassName",
) )
@file:JsModule("binaryen") @file:JsModule("binaryen")
@ -52,7 +53,7 @@ internal external fun createType(types: Array<Type>): Type
internal external fun expandType(type: Type): Array<Type> internal external fun expandType(type: Type): Array<Type>
internal external enum class ExpressionIds { internal external enum class ExpressionIds {
Invalid, Invalid,
Block, Block,
If, If,

View File

@ -1,20 +1,17 @@
plugins { plugins {
id("space.kscience.gradle.mpp") id("space.kscience.gradle.jvm")
} }
description = "Commons math binding for kmath" description = "Commons math binding for kmath"
kscience { dependencies {
jvm() api(project(":kmath-core"))
jvmMain { api(project(":kmath-complex"))
api(projects.kmathCore) api(project(":kmath-coroutines"))
api(projects.kmathComplex) api(project(":kmath-optimization"))
api(projects.kmathCoroutines) api(project(":kmath-stat"))
api(projects.kmathOptimization) api(project(":kmath-functions"))
api(projects.kmathStat) api("org.apache.commons:commons-math3:3.6.1")
api(projects.kmathFunctions)
api("org.apache.commons:commons-math3:3.6.1")
}
} }
readme { readme {

View File

@ -22,7 +22,7 @@ public class CMGaussRuleIntegrator(
val integrator: GaussIntegrator = getIntegrator(range) val integrator: GaussIntegrator = getIntegrator(range)
//TODO check performance //TODO check performance
val res: Double = integrator.integrate(integrand.function) val res: Double = integrator.integrate(integrand.function)
return integrand.withAttributes { return integrand.modify {
IntegrandValue(res) IntegrandValue(res)
IntegrandCallsPerformed(integrand.calls + numpoints) IntegrandCallsPerformed(integrand.calls + numpoints)
} }

View File

@ -26,7 +26,7 @@ public class CMIntegrator(
val range = integrand[IntegrationRange] ?: error("Integration range is not provided") val range = integrand[IntegrationRange] ?: error("Integration range is not provided")
val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive) val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive)
return integrand.withAttributes { return integrand.modify {
value(res) value(res)
IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy) IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy)
IntegrandRelativeAccuracy(integrator.relativeAccuracy) IntegrandRelativeAccuracy(integrator.relativeAccuracy)

View File

@ -6,6 +6,7 @@ kscience {
jvm() jvm()
js() js()
native() native()
wasm() wasm()
dependencies { dependencies {

View File

@ -10,7 +10,6 @@ import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.VirtualBuffer
import kotlin.math.max import kotlin.math.max
/** /**
@ -34,10 +33,7 @@ public interface XYColumnarData<out T, out X : T, out Y : T> : ColumnarData<T> {
else -> null else -> null
} }
public companion object { public companion object{
/**
* Create data form two buffers (zero-copy)
*/
@UnstableKMathAPI @UnstableKMathAPI
public fun <T, X : T, Y : T> of(x: Buffer<X>, y: Buffer<Y>): XYColumnarData<T, X, Y> { public fun <T, X : T, Y : T> of(x: Buffer<X>, y: Buffer<Y>): XYColumnarData<T, X, Y> {
require(x.size == y.size) { "Buffer size mismatch. x buffer size is ${x.size}, y buffer size is ${y.size}" } require(x.size == y.size) { "Buffer size mismatch. x buffer size is ${x.size}, y buffer size is ${y.size}" }
@ -47,26 +43,6 @@ public interface XYColumnarData<out T, out X : T, out Y : T> : ColumnarData<T> {
override val y: Buffer<Y> = y override val y: Buffer<Y> = y
} }
} }
/**
* Create two-column data from a list of row-objects (zero-copy)
*/
@UnstableKMathAPI
public inline fun <I, T, reified X : T, reified Y : T> ofList(
list: List<I>,
noinline xConverter: (I) -> X,
noinline yConverter: (I) -> Y,
): XYColumnarData<T, X, Y> = object : XYColumnarData<T, X, Y> {
override val size: Int get() = list.size
override val x: Buffer<X> = VirtualBuffer(list.size) {
xConverter(list[it])
}
override val y: Buffer<Y> = VirtualBuffer(list.size) {
yConverter(list[it])
}
}
} }
} }
@ -80,10 +56,9 @@ public fun <T> ColumnarData<T>.asXYData(
ySymbol: Symbol, ySymbol: Symbol,
): XYColumnarData<T, T, T> = object : XYColumnarData<T, T, T> { ): XYColumnarData<T, T, T> = object : XYColumnarData<T, T, T> {
init { init {
requireNotNull(this@asXYData[xSymbol]) { "The column with name $xSymbol is not present in $this" } requireNotNull(this@asXYData[xSymbol]){"The column with name $xSymbol is not present in $this"}
requireNotNull(this@asXYData[ySymbol]) { "The column with name $ySymbol is not present in $this" } requireNotNull(this@asXYData[ySymbol]){"The column with name $ySymbol is not present in $this"}
} }
override val size: Int get() = this@asXYData.size override val size: Int get() = this@asXYData.size
override val x: Buffer<T> get() = this@asXYData[xSymbol]!! override val x: Buffer<T> get() = this@asXYData[xSymbol]!!
override val y: Buffer<T> get() = this@asXYData[ySymbol]!! override val y: Buffer<T> get() = this@asXYData[ySymbol]!!

View File

@ -13,6 +13,8 @@ import space.kscience.kmath.structures.MutableBufferFactory
import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.asBuffer
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlin.reflect.KType
import kotlin.reflect.typeOf
/** /**
* Class representing both the value and the differentials of a function. * Class representing both the value and the differentials of a function.
@ -82,8 +84,6 @@ public abstract class DSAlgebra<T, A : Ring<T>>(
bindings: Map<Symbol, T>, bindings: Map<Symbol, T>,
) : ExpressionAlgebra<T, DS<T, A>>, SymbolIndexer { ) : ExpressionAlgebra<T, DS<T, A>>, SymbolIndexer {
override val bufferFactory: MutableBufferFactory<DS<T, A>> = MutableBufferFactory()
/** /**
* Get the compiler for number of free parameters and order. * Get the compiler for number of free parameters and order.
* *

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.expressions package space.kscience.kmath.expressions
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.MutableBufferFactory
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
@ -18,8 +17,6 @@ import kotlin.contracts.contract
public abstract class FunctionalExpressionAlgebra<T, out A : Algebra<T>>( public abstract class FunctionalExpressionAlgebra<T, out A : Algebra<T>>(
public val algebra: A, public val algebra: A,
) : ExpressionAlgebra<T, Expression<T>> { ) : ExpressionAlgebra<T, Expression<T>> {
override val bufferFactory: MutableBufferFactory<Expression<T>> = MutableBufferFactory<Expression<T>>()
/** /**
* Builds an Expression of constant expression that does not depend on arguments. * Builds an Expression of constant expression that does not depend on arguments.
*/ */
@ -52,7 +49,6 @@ public abstract class FunctionalExpressionAlgebra<T, out A : Algebra<T>>(
public open class FunctionalExpressionGroup<T, out A : Group<T>>( public open class FunctionalExpressionGroup<T, out A : Group<T>>(
algebra: A, algebra: A,
) : 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 Expression<T>.unaryMinus(): Expression<T> =

View File

@ -7,14 +7,11 @@ package space.kscience.kmath.expressions
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.MutableBufferFactory
/** /**
* [Algebra] over [MST] nodes. * [Algebra] over [MST] nodes.
*/ */
public object MstNumericAlgebra : NumericAlgebra<MST> { public object MstNumericAlgebra : NumericAlgebra<MST> {
override val bufferFactory: MutableBufferFactory<MST> = MutableBufferFactory()
override fun number(value: Number): MST.Numeric = MST.Numeric(value) override fun number(value: Number): MST.Numeric = MST.Numeric(value)
override fun bindSymbolOrNull(value: String): Symbol = StringSymbol(value) override fun bindSymbolOrNull(value: String): Symbol = StringSymbol(value)
override fun bindSymbol(value: String): Symbol = bindSymbolOrNull(value) override fun bindSymbol(value: String): Symbol = bindSymbolOrNull(value)
@ -30,9 +27,6 @@ public object MstNumericAlgebra : NumericAlgebra<MST> {
* [Group] over [MST] nodes. * [Group] over [MST] nodes.
*/ */
public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> { public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
override val bufferFactory: MutableBufferFactory<MST> = MutableBufferFactory()
override val zero: MST.Numeric = number(0.0) override val zero: MST.Numeric = number(0.0)
override fun number(value: Number): MST.Numeric = MstNumericAlgebra.number(value) override fun number(value: Number): MST.Numeric = MstNumericAlgebra.number(value)
@ -63,11 +57,7 @@ public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
@Suppress("OVERRIDE_BY_INLINE") @Suppress("OVERRIDE_BY_INLINE")
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public object MstRing : Ring<MST>, NumbersAddOps<MST>, ScaleOperations<MST> { public object MstRing : Ring<MST>, NumbersAddOps<MST>, ScaleOperations<MST> {
override val bufferFactory: MutableBufferFactory<MST> = MutableBufferFactory()
override inline val zero: MST.Numeric get() = MstGroup.zero override inline val zero: MST.Numeric get() = MstGroup.zero
override val one: MST.Numeric = number(1.0) override val one: MST.Numeric = number(1.0)
override fun number(value: Number): MST.Numeric = MstGroup.number(value) override fun number(value: Number): MST.Numeric = MstGroup.number(value)
@ -97,11 +87,7 @@ public object MstRing : Ring<MST>, NumbersAddOps<MST>, ScaleOperations<MST> {
@Suppress("OVERRIDE_BY_INLINE") @Suppress("OVERRIDE_BY_INLINE")
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public object MstField : Field<MST>, NumbersAddOps<MST>, ScaleOperations<MST> { public object MstField : Field<MST>, NumbersAddOps<MST>, ScaleOperations<MST> {
override val bufferFactory: MutableBufferFactory<MST> = MutableBufferFactory()
override inline val zero: MST.Numeric get() = MstRing.zero override inline val zero: MST.Numeric get() = MstRing.zero
override inline val one: MST.Numeric get() = MstRing.one override inline val one: MST.Numeric get() = MstRing.one
override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value) override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
@ -131,11 +117,7 @@ public object MstField : Field<MST>, NumbersAddOps<MST>, ScaleOperations<MST> {
*/ */
@Suppress("OVERRIDE_BY_INLINE") @Suppress("OVERRIDE_BY_INLINE")
public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> { public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
override val bufferFactory: MutableBufferFactory<MST> = MutableBufferFactory()
override inline val zero: MST.Numeric get() = MstField.zero override inline val zero: MST.Numeric get() = MstField.zero
override inline val one: MST.Numeric get() = MstField.one override inline val one: MST.Numeric get() = MstField.one
override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value) override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
@ -182,9 +164,6 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public object MstLogicAlgebra : LogicAlgebra<MST> { public object MstLogicAlgebra : LogicAlgebra<MST> {
override val bufferFactory: MutableBufferFactory<MST> = MutableBufferFactory()
override fun bindSymbolOrNull(value: String): MST = super.bindSymbolOrNull(value) ?: StringSymbol(value) override fun bindSymbolOrNull(value: String): MST = super.bindSymbolOrNull(value) ?: StringSymbol(value)
override fun const(boolean: Boolean): Symbol = if (boolean) { override fun const(boolean: Boolean): Symbol = if (boolean) {
@ -197,7 +176,7 @@ public object MstLogicAlgebra : LogicAlgebra<MST> {
override fun MST.and(other: MST): MST = MST.Binary(Boolean::and.name, this, other) override fun MST.and(other: MST): MST = MST.Binary(Boolean::and.name, this, other)
override fun MST.or(other: MST): MST = MST.Binary(Boolean::or.name, this, other) override fun MST.or(other: MST): MST = MST.Binary(Boolean::or.name, this, other)
override fun MST.xor(other: MST): MST = MST.Binary(Boolean::xor.name, this, other) override fun MST.xor(other: MST): MST = MST.Binary(Boolean::xor.name, this, other)
} }

View File

@ -5,11 +5,9 @@
package space.kscience.kmath.expressions package space.kscience.kmath.expressions
import space.kscience.attributes.SafeType
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.Point
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.MutableBufferFactory
import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.asBuffer
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
@ -32,10 +30,9 @@ public open class AutoDiffValue<out T>(public val value: T)
*/ */
public class DerivationResult<T : Any>( public class DerivationResult<T : Any>(
public val value: T, public val value: T,
override val type: SafeType<T>,
private val derivativeValues: Map<String, T>, private val derivativeValues: Map<String, T>,
public val context: Field<T>, public val context: Field<T>,
) : WithType<T> { ) {
/** /**
* Returns derivative of [variable] or returns [Ring.zero] in [context]. * Returns derivative of [variable] or returns [Ring.zero] in [context].
*/ */
@ -52,23 +49,19 @@ public class DerivationResult<T : Any>(
*/ */
public fun <T : Any> DerivationResult<T>.grad(vararg variables: Symbol): Point<T> { public fun <T : Any> DerivationResult<T>.grad(vararg variables: Symbol): Point<T> {
check(variables.isNotEmpty()) { "Variable order is not provided for gradient construction" } check(variables.isNotEmpty()) { "Variable order is not provided for gradient construction" }
return variables.map(::derivative).asBuffer(type) return variables.map(::derivative).asBuffer()
} }
/** /**
* Represents field. Function derivatives could be computed in this field * Represents field in context of which functions can be derived.
*/ */
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public open class SimpleAutoDiffField<T : Any, F : Field<T>>( public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
public val algebra: F, public val context: F,
bindings: Map<Symbol, T>, bindings: Map<Symbol, T>,
) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, NumbersAddOps<AutoDiffValue<T>> { ) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, NumbersAddOps<AutoDiffValue<T>> {
override val zero: AutoDiffValue<T> get() = const(context.zero)
override val bufferFactory: MutableBufferFactory<AutoDiffValue<T>> = MutableBufferFactory<AutoDiffValue<T>>() override val one: AutoDiffValue<T> get() = const(context.one)
override val zero: AutoDiffValue<T> get() = const(algebra.zero)
override val one: AutoDiffValue<T> get() = const(algebra.one)
// this stack contains pairs of blocks and values to apply them to // this stack contains pairs of blocks and values to apply them to
private var stack: Array<Any?> = arrayOfNulls<Any?>(8) private var stack: Array<Any?> = arrayOfNulls<Any?>(8)
@ -76,7 +69,7 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
private val derivatives: MutableMap<AutoDiffValue<T>, T> = hashMapOf() private val derivatives: MutableMap<AutoDiffValue<T>, T> = hashMapOf()
private val bindings: Map<String, AutoDiffVariableWithDerivative<T>> = bindings.entries.associate { private val bindings: Map<String, AutoDiffVariableWithDerivative<T>> = bindings.entries.associate {
it.key.identity to AutoDiffVariableWithDerivative(it.key.identity, it.value, algebra.zero) it.key.identity to AutoDiffVariableWithDerivative(it.key.identity, it.value, context.zero)
} }
/** /**
@ -99,7 +92,7 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
override fun bindSymbolOrNull(value: String): AutoDiffValue<T>? = bindings[value] override fun bindSymbolOrNull(value: String): AutoDiffValue<T>? = bindings[value]
private fun getDerivative(variable: AutoDiffValue<T>): T = private fun getDerivative(variable: AutoDiffValue<T>): T =
(variable as? AutoDiffVariableWithDerivative)?.d ?: derivatives[variable] ?: algebra.zero (variable as? AutoDiffVariableWithDerivative)?.d ?: derivatives[variable] ?: context.zero
private fun setDerivative(variable: AutoDiffValue<T>, value: T) { private fun setDerivative(variable: AutoDiffValue<T>, value: T) {
if (variable is AutoDiffVariableWithDerivative) variable.d = value else derivatives[variable] = value if (variable is AutoDiffVariableWithDerivative) variable.d = value else derivatives[variable] = value
@ -110,7 +103,7 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
while (sp > 0) { while (sp > 0) {
val value = stack[--sp] val value = stack[--sp]
val block = stack[--sp] as F.(Any?) -> Unit val block = stack[--sp] as F.(Any?) -> Unit
algebra.block(value) context.block(value)
} }
} }
@ -137,6 +130,7 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
* } * }
* ``` * ```
*/ */
@Suppress("UNCHECKED_CAST")
public fun <R> derive(value: R, block: F.(R) -> Unit): R { public fun <R> derive(value: R, block: F.(R) -> Unit): R {
// save block to stack for backward pass // save block to stack for backward pass
if (sp >= stack.size) stack = stack.copyOf(stack.size * 2) if (sp >= stack.size) stack = stack.copyOf(stack.size * 2)
@ -148,9 +142,9 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
internal fun differentiate(function: SimpleAutoDiffField<T, F>.() -> AutoDiffValue<T>): DerivationResult<T> { internal fun differentiate(function: SimpleAutoDiffField<T, F>.() -> AutoDiffValue<T>): DerivationResult<T> {
val result = function() val result = function()
result.d = algebra.one // computing derivative w.r.t result result.d = context.one // computing derivative w.r.t result
runBackwardPass() runBackwardPass()
return DerivationResult(result.value, algebra.type, bindings.mapValues { it.value.d }, algebra) return DerivationResult(result.value, bindings.mapValues { it.value.d }, context)
} }
// // Overloads for Double constants // // Overloads for Double constants
@ -200,7 +194,7 @@ public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
public inline fun <T : Any, F : Field<T>> SimpleAutoDiffField<T, F>.const(block: F.() -> T): AutoDiffValue<T> { public inline fun <T : Any, F : Field<T>> SimpleAutoDiffField<T, F>.const(block: F.() -> T): AutoDiffValue<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return const(algebra.block()) return const(context.block())
} }

View File

@ -10,9 +10,10 @@ import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.BufferRingOps import space.kscience.kmath.operations.BufferRingOps
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.WithType
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import kotlin.reflect.KType
import kotlin.reflect.typeOf
/** /**
* Alias for [Structure2D] with more familiar name. * Alias for [Structure2D] with more familiar name.
@ -33,7 +34,7 @@ public typealias Point<T> = Buffer<T>
* A marker interface for algebras that operate on matrices * A marker interface for algebras that operate on matrices
* @param T type of matrix element * @param T type of matrix element
*/ */
public interface MatrixOperations<T> : WithType<T> public interface MatrixOperations<T>
/** /**
* Basic operations on matrices and vectors. * Basic operations on matrices and vectors.
@ -44,8 +45,6 @@ public interface MatrixOperations<T> : WithType<T>
public interface LinearSpace<T, out A : Ring<T>> : MatrixOperations<T> { public interface LinearSpace<T, out A : Ring<T>> : MatrixOperations<T> {
public val elementAlgebra: A public val elementAlgebra: A
override val type: SafeType<T> get() = elementAlgebra.type
/** /**
* Produces a matrix with this context and given dimensions. * Produces a matrix with this context and given dimensions.
*/ */
@ -213,4 +212,4 @@ public fun <T : Any> Matrix<T>.asVector(): Point<T> =
* @receiver a buffer. * @receiver a buffer.
* @return the new matrix. * @return the new matrix.
*/ */
public fun <T : Any> Point<T>.asMatrix(): VirtualMatrix<T> = VirtualMatrix(type, size, 1) { i, _ -> get(i) } public fun <T : Any> Point<T>.asMatrix(): VirtualMatrix<T> = VirtualMatrix(size, 1) { i, _ -> get(i) }

View File

@ -22,27 +22,11 @@ import space.kscience.kmath.structures.*
* @param l The lower triangular matrix in this decomposition. It may have [LowerTriangular]. * @param l The lower triangular matrix in this decomposition. It may have [LowerTriangular].
* @param u The upper triangular matrix in this decomposition. It may have [UpperTriangular]. * @param u The upper triangular matrix in this decomposition. It may have [UpperTriangular].
*/ */
public class LupDecomposition<T>( public data class LupDecomposition<T>(
public val linearSpace: LinearSpace<T, Ring<T>>,
public val l: Matrix<T>, public val l: Matrix<T>,
public val u: Matrix<T>, public val u: Matrix<T>,
public val pivot: IntBuffer, public val pivot: IntBuffer,
) { )
public val elementAlgebra: Ring<T> get() = linearSpace.elementAlgebra
public val pivotMatrix: VirtualMatrix<T>
get() = VirtualMatrix(linearSpace.type, l.rowNum, l.colNum) { row, column ->
if (column == pivot[row]) elementAlgebra.one else elementAlgebra.zero
}
public val <T> LupDecomposition<T>.determinant by lazy {
elementAlgebra { (0 until l.shape[0]).fold(if (even) one else -one) { value, i -> value * lu[i, i] } }
}
}
public class LupDecompositionAttribute<T>(type: SafeType<LupDecomposition<T>>) : public class LupDecompositionAttribute<T>(type: SafeType<LupDecomposition<T>>) :
@ -184,7 +168,7 @@ public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
for (row in col + 1 until m) lu[row, col] /= luDiag for (row in col + 1 until m) lu[row, col] /= luDiag
} }
val l: MatrixWrapper<T> = VirtualMatrix(type, rowNum, colNum) { i, j -> val l: MatrixWrapper<T> = VirtualMatrix(rowNum, colNum) { i, j ->
when { when {
j < i -> lu[i, j] j < i -> lu[i, j]
j == i -> one j == i -> one
@ -192,7 +176,7 @@ public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
} }
}.withAttribute(LowerTriangular) }.withAttribute(LowerTriangular)
val u = VirtualMatrix(type, rowNum, colNum) { i, j -> val u = VirtualMatrix(rowNum, colNum) { i, j ->
if (j >= i) lu[i, j] else zero if (j >= i) lu[i, j] else zero
}.withAttribute(UpperTriangular) }.withAttribute(UpperTriangular)
// //
@ -200,7 +184,7 @@ public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
// if (j == pivot[i]) one else zero // if (j == pivot[i]) one else zero
// }.withAttribute(Determinant, if (even) one else -one) // }.withAttribute(Determinant, if (even) one else -one)
return LupDecomposition(this@lup, l, u, pivot.asBuffer()) return LupDecomposition(l, u, pivot.asBuffer())
} }
} }
} }

View File

@ -6,21 +6,16 @@
package space.kscience.kmath.linear package space.kscience.kmath.linear
import space.kscience.attributes.FlagAttribute import space.kscience.attributes.FlagAttribute
import space.kscience.attributes.SafeType
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.WithType
import space.kscience.kmath.structures.BufferAccessor2D import space.kscience.kmath.structures.BufferAccessor2D
import space.kscience.kmath.structures.MutableBufferFactory import space.kscience.kmath.structures.MutableBuffer
public class MatrixBuilder<T : Any, out A : Ring<T>>( public class MatrixBuilder<T : Any, out A : Ring<T>>(
public val linearSpace: LinearSpace<T, A>, public val linearSpace: LinearSpace<T, A>,
public val rows: Int, public val rows: Int,
public val columns: Int, public val columns: Int,
) : WithType<T> { ) {
override val type: SafeType<T> get() = linearSpace.type
public operator fun invoke(vararg elements: T): Matrix<T> { public operator fun invoke(vararg elements: T): Matrix<T> {
require(rows * columns == elements.size) { "The number of elements ${elements.size} is not equal $rows * $columns" } require(rows * columns == elements.size) { "The number of elements ${elements.size} is not equal $rows * $columns" }
return linearSpace.buildMatrix(rows, columns) { i, j -> elements[i * columns + j] } return linearSpace.buildMatrix(rows, columns) { i, j -> elements[i * columns + j] }
@ -66,7 +61,7 @@ public fun <T : Any, A : Ring<T>> MatrixBuilder<T, A>.symmetric(
builder: (i: Int, j: Int) -> T, builder: (i: Int, j: Int) -> T,
): Matrix<T> { ): Matrix<T> {
require(columns == rows) { "In order to build symmetric matrix, number of rows $rows should be equal to number of columns $columns" } require(columns == rows) { "In order to build symmetric matrix, number of rows $rows should be equal to number of columns $columns" }
return with(BufferAccessor2D<T?>(rows, rows, MutableBufferFactory(type))) { return with(BufferAccessor2D<T?>(rows, rows, MutableBuffer.Companion::boxing)) {
val cache = factory(rows * rows) { null } val cache = factory(rows * rows) { null }
linearSpace.buildMatrix(rows, rows) { i, j -> linearSpace.buildMatrix(rows, rows) { i, j ->
val cached = cache[i, j] val cached = cache[i, j]

View File

@ -39,7 +39,7 @@ public fun <T : Any, A : Attribute<T>> Matrix<T>.withAttribute(
attribute: A, attribute: A,
attrValue: T, attrValue: T,
): MatrixWrapper<T> = if (this is MatrixWrapper) { ): MatrixWrapper<T> = if (this is MatrixWrapper) {
MatrixWrapper(origin, attributes.withAttribute(attribute, attrValue)) MatrixWrapper(origin, attributes.withAttribute(attribute,attrValue))
} else { } else {
MatrixWrapper(this, Attributes(attribute, attrValue)) MatrixWrapper(this, Attributes(attribute, attrValue))
} }
@ -68,7 +68,7 @@ public fun <T : Any> Matrix<T>.modifyAttributes(modifier: (Attributes) -> Attrib
public fun <T : Any> LinearSpace<T, Ring<T>>.one( public fun <T : Any> LinearSpace<T, Ring<T>>.one(
rows: Int, rows: Int,
columns: Int, columns: Int,
): MatrixWrapper<T> = VirtualMatrix(type, rows, columns) { i, j -> ): MatrixWrapper<T> = VirtualMatrix(rows, columns) { i, j ->
if (i == j) elementAlgebra.one else elementAlgebra.zero if (i == j) elementAlgebra.one else elementAlgebra.zero
}.withAttribute(IsUnit) }.withAttribute(IsUnit)
@ -79,6 +79,6 @@ public fun <T : Any> LinearSpace<T, Ring<T>>.one(
public fun <T : Any> LinearSpace<T, Ring<T>>.zero( public fun <T : Any> LinearSpace<T, Ring<T>>.zero(
rows: Int, rows: Int,
columns: Int, columns: Int,
): MatrixWrapper<T> = VirtualMatrix(type, rows, columns) { _, _ -> ): MatrixWrapper<T> = VirtualMatrix(rows, columns) { _, _ ->
elementAlgebra.zero elementAlgebra.zero
}.withAttribute(IsZero) }.withAttribute(IsZero)

View File

@ -6,14 +6,10 @@
package space.kscience.kmath.linear package space.kscience.kmath.linear
import space.kscience.attributes.Attributes import space.kscience.attributes.Attributes
import space.kscience.attributes.SafeType
public class TransposedMatrix<T>(public val origin: Matrix<T>) : Matrix<T> { public class TransposedMatrix<T>(public val origin: Matrix<T>) : Matrix<T> {
override val type: SafeType<T> get() = origin.type
override val rowNum: Int get() = origin.colNum override val rowNum: Int get() = origin.colNum
override val colNum: Int get() = origin.rowNum override val colNum: Int get() = origin.rowNum
override fun get(i: Int, j: Int): T = origin[j, i] override fun get(i: Int, j: Int): T = origin[j, i]

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.linear package space.kscience.kmath.linear
import space.kscience.attributes.Attributes import space.kscience.attributes.Attributes
import space.kscience.attributes.SafeType
import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.ShapeND
@ -15,8 +14,7 @@ import space.kscience.kmath.nd.ShapeND
* *
* @property generator the function that provides elements. * @property generator the function that provides elements.
*/ */
public class VirtualMatrix<out T>( public class VirtualMatrix<out T : Any>(
override val type: SafeType<T>,
override val rowNum: Int, override val rowNum: Int,
override val colNum: Int, override val colNum: Int,
override val attributes: Attributes = Attributes.EMPTY, override val attributes: Attributes = Attributes.EMPTY,
@ -31,4 +29,4 @@ public class VirtualMatrix<out T>(
public fun <T : Any> MatrixBuilder<T, *>.virtual( public fun <T : Any> MatrixBuilder<T, *>.virtual(
attributes: Attributes = Attributes.EMPTY, attributes: Attributes = Attributes.EMPTY,
generator: (i: Int, j: Int) -> T, generator: (i: Int, j: Int) -> T,
): VirtualMatrix<T> = VirtualMatrix(type, rows, columns, attributes, generator) ): VirtualMatrix<T> = VirtualMatrix(rows, columns, attributes, generator)

View File

@ -3,11 +3,13 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@file:OptIn(UnstableKMathAPI::class)
@file:Suppress("UnusedReceiverParameter") @file:Suppress("UnusedReceiverParameter")
package space.kscience.kmath.linear package space.kscience.kmath.linear
import space.kscience.attributes.* import space.kscience.attributes.*
import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.nd.StructureAttribute import space.kscience.kmath.nd.StructureAttribute
/** /**
@ -49,11 +51,9 @@ public val <T> MatrixOperations<T>.Inverted: Inverted<T> get() = Inverted(safeTy
* *
* @param T the type of matrices' items. * @param T the type of matrices' items.
*/ */
public class Determinant<T>(type: SafeType<T>) : public class Determinant<T> : MatrixAttribute<T>
PolymorphicAttribute<T>(type),
MatrixAttribute<T>
public val <T> MatrixOperations<T>.Determinant: Determinant<T> get() = Determinant(type) public val <T> MatrixOperations<T>.Determinant: Determinant<T> get() = Determinant()
/** /**
* Matrices with this feature are lower triangular ones. * Matrices with this feature are lower triangular ones.

View File

@ -4,8 +4,6 @@
*/ */
@file:OptIn(UnstableKMathAPI::class)
package space.kscience.kmath.misc package space.kscience.kmath.misc
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
@ -24,9 +22,10 @@ public fun <V : Comparable<V>> Buffer<V>.indicesSorted(): IntArray = permSortInd
/** /**
* Create a zero-copy virtual buffer that contains the same elements but in ascending order * Create a zero-copy virtual buffer that contains the same elements but in ascending order
*/ */
@OptIn(UnstableKMathAPI::class)
public fun <V : Comparable<V>> Buffer<V>.sorted(): Buffer<V> { public fun <V : Comparable<V>> Buffer<V>.sorted(): Buffer<V> {
val permutations = indicesSorted() val permutations = indicesSorted()
return VirtualBuffer(type, size) { this[permutations[it]] } return VirtualBuffer(size) { this[permutations[it]] }
} }
@UnstableKMathAPI @UnstableKMathAPI
@ -36,27 +35,30 @@ public fun <V : Comparable<V>> Buffer<V>.indicesSortedDescending(): IntArray =
/** /**
* Create a zero-copy virtual buffer that contains the same elements but in descending order * Create a zero-copy virtual buffer that contains the same elements but in descending order
*/ */
@OptIn(UnstableKMathAPI::class)
public fun <V : Comparable<V>> Buffer<V>.sortedDescending(): Buffer<V> { public fun <V : Comparable<V>> Buffer<V>.sortedDescending(): Buffer<V> {
val permutations = indicesSortedDescending() val permutations = indicesSortedDescending()
return VirtualBuffer(type, size) { this[permutations[it]] } return VirtualBuffer(size) { this[permutations[it]] }
} }
@UnstableKMathAPI @UnstableKMathAPI
public fun <V, C : Comparable<C>> Buffer<V>.indicesSortedBy(selector: (V) -> C): IntArray = public fun <V, C : Comparable<C>> Buffer<V>.indicesSortedBy(selector: (V) -> C): IntArray =
permSortIndicesWith(compareBy { selector(get(it)) }) permSortIndicesWith(compareBy { selector(get(it)) })
@OptIn(UnstableKMathAPI::class)
public fun <V, C : Comparable<C>> Buffer<V>.sortedBy(selector: (V) -> C): Buffer<V> { public fun <V, C : Comparable<C>> Buffer<V>.sortedBy(selector: (V) -> C): Buffer<V> {
val permutations = indicesSortedBy(selector) val permutations = indicesSortedBy(selector)
return VirtualBuffer(type, size) { this[permutations[it]] } return VirtualBuffer(size) { this[permutations[it]] }
} }
@UnstableKMathAPI @UnstableKMathAPI
public fun <V, C : Comparable<C>> Buffer<V>.indicesSortedByDescending(selector: (V) -> C): IntArray = public fun <V, C : Comparable<C>> Buffer<V>.indicesSortedByDescending(selector: (V) -> C): IntArray =
permSortIndicesWith(compareByDescending { selector(get(it)) }) permSortIndicesWith(compareByDescending { selector(get(it)) })
@OptIn(UnstableKMathAPI::class)
public fun <V, C : Comparable<C>> Buffer<V>.sortedByDescending(selector: (V) -> C): Buffer<V> { public fun <V, C : Comparable<C>> Buffer<V>.sortedByDescending(selector: (V) -> C): Buffer<V> {
val permutations = indicesSortedByDescending(selector) val permutations = indicesSortedByDescending(selector)
return VirtualBuffer(type, size) { this[permutations[it]] } return VirtualBuffer(size) { this[permutations[it]] }
} }
@UnstableKMathAPI @UnstableKMathAPI
@ -66,9 +68,10 @@ public fun <V> Buffer<V>.indicesSortedWith(comparator: Comparator<V>): IntArray
/** /**
* Create virtual zero-copy buffer with elements sorted by [comparator] * Create virtual zero-copy buffer with elements sorted by [comparator]
*/ */
@OptIn(UnstableKMathAPI::class)
public fun <V> Buffer<V>.sortedWith(comparator: Comparator<V>): Buffer<V> { public fun <V> Buffer<V>.sortedWith(comparator: Comparator<V>): Buffer<V> {
val permutations = indicesSortedWith(comparator) val permutations = indicesSortedWith(comparator)
return VirtualBuffer(type,size) { this[permutations[it]] } return VirtualBuffer(size) { this[permutations[it]] }
} }
private fun <V> Buffer<V>.permSortIndicesWith(comparator: Comparator<Int>): IntArray { private fun <V> Buffer<V>.permSortIndicesWith(comparator: Comparator<Int>): IntArray {

View File

@ -8,7 +8,7 @@ package space.kscience.kmath.nd
import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.MutableBufferFactory import kotlin.reflect.KClass
/** /**
* The base interface for all ND-algebra implementations. * The base interface for all ND-algebra implementations.
@ -91,8 +91,6 @@ public interface AlgebraND<T, out C : Algebra<T>> : Algebra<StructureND<T>> {
* @param A the type of group over structure elements. * @param A the type of group over structure elements.
*/ */
public interface GroupOpsND<T, out A : GroupOps<T>> : GroupOps<StructureND<T>>, AlgebraND<T, A> { public interface GroupOpsND<T, out A : GroupOps<T>> : GroupOps<StructureND<T>>, AlgebraND<T, A> {
override val bufferFactory: MutableBufferFactory<StructureND<T>> get() = MutableBufferFactory<StructureND<T>>()
/** /**
* Element-wise addition. * Element-wise addition.
* *

View File

@ -7,8 +7,6 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
@ -107,9 +105,6 @@ public open class BufferedGroupNDOps<T, out A : Group<T>>(
override val bufferAlgebra: BufferAlgebra<T, A>, override val bufferAlgebra: BufferAlgebra<T, A>,
override val indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, override val indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
) : GroupOpsND<T, A>, BufferAlgebraND<T, A> { ) : GroupOpsND<T, A>, BufferAlgebraND<T, A> {
override val type: SafeType<StructureND<T>> get() = safeTypeOf<StructureND<T>>()
override fun StructureND<T>.unaryMinus(): StructureND<T> = map { -it } override fun StructureND<T>.unaryMinus(): StructureND<T> = map { -it }
} }

View File

@ -5,7 +5,6 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.attributes.SafeType
import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferFactory
@ -24,8 +23,6 @@ public open class BufferND<out T>(
public open val buffer: Buffer<T>, public open val buffer: Buffer<T>,
) : StructureND<T> { ) : StructureND<T> {
override val type: SafeType<T> get() = buffer.type
@PerformancePitfall @PerformancePitfall
override operator fun get(index: IntArray): T = buffer[indices.offset(index)] override operator fun get(index: IntArray): T = buffer[indices.offset(index)]
@ -39,7 +36,7 @@ public open class BufferND<out T>(
*/ */
public inline fun <reified T> BufferND( public inline fun <reified T> BufferND(
shape: ShapeND, shape: ShapeND,
bufferFactory: BufferFactory<T> = BufferFactory<T>(), bufferFactory: BufferFactory<T> = BufferFactory.auto<T>(),
crossinline initializer: (IntArray) -> T, crossinline initializer: (IntArray) -> T,
): BufferND<T> { ): BufferND<T> {
val strides = Strides(shape) val strides = Strides(shape)
@ -87,10 +84,10 @@ public open class MutableBufferND<T>(
/** /**
* Create a generic [BufferND] using provided [initializer] * Create a generic [BufferND] using provided [initializer]
*/ */
public inline fun <reified T> MutableBufferND( public fun <T> MutableBufferND(
shape: ShapeND, shape: ShapeND,
bufferFactory: MutableBufferFactory<T> = MutableBufferFactory(), bufferFactory: MutableBufferFactory<T> = MutableBufferFactory.boxing(),
crossinline initializer: (IntArray) -> T, initializer: (IntArray) -> T,
): MutableBufferND<T> { ): MutableBufferND<T> {
val strides = Strides(shape) val strides = Strides(shape)
return MutableBufferND(strides, bufferFactory(strides.linearSize) { initializer(strides.index(it)) }) return MutableBufferND(strides, bufferFactory(strides.linearSize) { initializer(strides.index(it)) })

View File

@ -5,7 +5,6 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.attributes.SafeType
import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.PerformancePitfall
@ -14,8 +13,6 @@ public class PermutedStructureND<T>(
public val permutation: (IntArray) -> IntArray, public val permutation: (IntArray) -> IntArray,
) : StructureND<T> { ) : StructureND<T> {
override val type: SafeType<T> get() = origin.type
override val shape: ShapeND override val shape: ShapeND
get() = origin.shape get() = origin.shape
@ -35,7 +32,6 @@ public class PermutedMutableStructureND<T>(
public val permutation: (IntArray) -> IntArray, public val permutation: (IntArray) -> IntArray,
) : MutableStructureND<T> { ) : MutableStructureND<T> {
override val type: SafeType<T> get() = origin.type
@OptIn(PerformancePitfall::class) @OptIn(PerformancePitfall::class)
override fun set(index: IntArray, value: T) { override fun set(index: IntArray, value: T) {

View File

@ -5,7 +5,6 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.attributes.SafeType
import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.operations.asSequence import space.kscience.kmath.operations.asSequence
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
@ -47,9 +46,6 @@ public interface MutableStructure1D<T> : Structure1D<T>, MutableStructureND<T>,
*/ */
@JvmInline @JvmInline
private value class Structure1DWrapper<out T>(val structure: StructureND<T>) : Structure1D<T> { private value class Structure1DWrapper<out T>(val structure: StructureND<T>) : Structure1D<T> {
override val type: SafeType<T> get() = structure.type
override val shape: ShapeND get() = structure.shape override val shape: ShapeND get() = structure.shape
override val size: Int get() = structure.shape[0] override val size: Int get() = structure.shape[0]
@ -64,9 +60,6 @@ private value class Structure1DWrapper<out T>(val structure: StructureND<T>) : S
* A 1D wrapper for a mutable nd-structure * A 1D wrapper for a mutable nd-structure
*/ */
private class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>) : MutableStructure1D<T> { private class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>) : MutableStructure1D<T> {
override val type: SafeType<T> get() = structure.type
override val shape: ShapeND get() = structure.shape override val shape: ShapeND get() = structure.shape
override val size: Int get() = structure.shape[0] override val size: Int get() = structure.shape[0]
@ -86,7 +79,7 @@ private class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>)
.elements() .elements()
.map(Pair<IntArray, T>::second) .map(Pair<IntArray, T>::second)
.toMutableList() .toMutableList()
.asMutableBuffer(type) .asMutableBuffer()
override fun toString(): String = Buffer.toString(this) override fun toString(): String = Buffer.toString(this)
} }
@ -97,9 +90,6 @@ private class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>)
*/ */
@JvmInline @JvmInline
private value class Buffer1DWrapper<out T>(val buffer: Buffer<T>) : Structure1D<T> { private value class Buffer1DWrapper<out T>(val buffer: Buffer<T>) : Structure1D<T> {
override val type: SafeType<T> get() = buffer.type
override val shape: ShapeND get() = ShapeND(buffer.size) override val shape: ShapeND get() = ShapeND(buffer.size)
override val size: Int get() = buffer.size override val size: Int get() = buffer.size
@ -112,9 +102,6 @@ private value class Buffer1DWrapper<out T>(val buffer: Buffer<T>) : Structure1D<
} }
internal class MutableBuffer1DWrapper<T>(val buffer: MutableBuffer<T>) : MutableStructure1D<T> { internal class MutableBuffer1DWrapper<T>(val buffer: MutableBuffer<T>) : MutableStructure1D<T> {
override val type: SafeType<T> get() = buffer.type
override val shape: ShapeND get() = ShapeND(buffer.size) override val shape: ShapeND get() = ShapeND(buffer.size)
override val size: Int get() = buffer.size override val size: Int get() = buffer.size

View File

@ -6,12 +6,13 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.attributes.Attributes import space.kscience.attributes.Attributes
import space.kscience.attributes.SafeType
import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableBuffer
import space.kscience.kmath.structures.MutableListBuffer
import space.kscience.kmath.structures.VirtualBuffer import space.kscience.kmath.structures.VirtualBuffer
import kotlin.jvm.JvmInline import kotlin.jvm.JvmInline
import kotlin.reflect.KClass
/** /**
* A structure that is guaranteed to be two-dimensional. * A structure that is guaranteed to be two-dimensional.
@ -32,18 +33,18 @@ public interface Structure2D<out T> : StructureND<T> {
override val shape: ShapeND get() = ShapeND(rowNum, colNum) override val shape: ShapeND get() = ShapeND(rowNum, colNum)
/** /**
* The buffer of rows for this structure. It gets elements from the structure dynamically. * The buffer of rows of this structure. It gets elements from the structure dynamically.
*/ */
@PerformancePitfall @PerformancePitfall
public val rows: List<Buffer<T>> public val rows: List<Buffer<T>>
get() = List(rowNum) { i -> VirtualBuffer(type, colNum) { j -> get(i, j) } } get() = List(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } }
/** /**
* The buffer of columns for this structure. It gets elements from the structure dynamically. * The buffer of columns of this structure. It gets elements from the structure dynamically.
*/ */
@PerformancePitfall @PerformancePitfall
public val columns: List<Buffer<T>> public val columns: List<Buffer<T>>
get() = List(colNum) { j -> VirtualBuffer(type, rowNum) { i -> get(i, j) } } get() = List(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } }
/** /**
* Retrieves an element from the structure by two indices. * Retrieves an element from the structure by two indices.
@ -87,14 +88,14 @@ public interface MutableStructure2D<T> : Structure2D<T>, MutableStructureND<T> {
*/ */
@PerformancePitfall @PerformancePitfall
override val rows: List<MutableBuffer<T>> override val rows: List<MutableBuffer<T>>
get() = List(rowNum) { i -> MutableBuffer(type, colNum) { j -> get(i, j) } } get() = List(rowNum) { i -> MutableListBuffer(colNum) { j -> get(i, j) } }
/** /**
* The buffer of columns for this structure. It gets elements from the structure dynamically. * The buffer of columns of this structure. It gets elements from the structure dynamically.
*/ */
@PerformancePitfall @PerformancePitfall
override val columns: List<MutableBuffer<T>> override val columns: List<MutableBuffer<T>>
get() = List(colNum) { j -> MutableBuffer(type, rowNum) { i -> get(i, j) } } get() = List(colNum) { j -> MutableListBuffer(rowNum) { i -> get(i, j) } }
} }
/** /**
@ -102,9 +103,6 @@ public interface MutableStructure2D<T> : Structure2D<T>, MutableStructureND<T> {
*/ */
@JvmInline @JvmInline
private value class Structure2DWrapper<out T>(val structure: StructureND<T>) : Structure2D<T> { private value class Structure2DWrapper<out T>(val structure: StructureND<T>) : Structure2D<T> {
override val type: SafeType<T> get() = structure.type
override val shape: ShapeND get() = structure.shape override val shape: ShapeND get() = structure.shape
override val rowNum: Int get() = shape[0] override val rowNum: Int get() = shape[0]
@ -124,9 +122,6 @@ private value class Structure2DWrapper<out T>(val structure: StructureND<T>) : S
* A 2D wrapper for a mutable nd-structure * A 2D wrapper for a mutable nd-structure
*/ */
private class MutableStructure2DWrapper<T>(val structure: MutableStructureND<T>) : MutableStructure2D<T> { private class MutableStructure2DWrapper<T>(val structure: MutableStructureND<T>) : MutableStructure2D<T> {
override val type: SafeType<T> get() = structure.type
override val shape: ShapeND get() = structure.shape override val shape: ShapeND get() = structure.shape
override val rowNum: Int get() = shape[0] override val rowNum: Int get() = shape[0]

View File

@ -12,7 +12,6 @@ import space.kscience.attributes.SafeType
import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.LinearSpace
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.WithType
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
@ -29,9 +28,9 @@ public interface StructureAttribute<T> : Attribute<T>
* *
* @param T the type of items. * @param T the type of items.
*/ */
public interface StructureND<out T> : AttributeContainer, WithShape, WithType<T> { public interface StructureND<out T> : AttributeContainer, WithShape {
/** /**
* The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions for * The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions of
* this structure. * this structure.
*/ */
override val shape: ShapeND override val shape: ShapeND
@ -118,61 +117,57 @@ public interface StructureND<out T> : AttributeContainer, WithShape, WithType<T>
return "$className(shape=${structure.shape}, buffer=$bufferRepr)" return "$className(shape=${structure.shape}, buffer=$bufferRepr)"
} }
/**
* Creates a NDStructure with explicit buffer factory.
*
* Strides should be reused if possible.
*/
public fun <T> buffered(
strides: Strides,
initializer: (IntArray) -> T,
): BufferND<T> = BufferND(strides, Buffer.boxing(strides.linearSize) { i -> initializer(strides.index(i)) })
public fun <T> buffered(
shape: ShapeND,
initializer: (IntArray) -> T,
): BufferND<T> = buffered(ColumnStrides(shape), initializer)
/**
* Inline create NDStructure with non-boxing buffer implementation if it is possible
*/
public inline fun <reified T : Any> auto(
strides: Strides,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(strides, Buffer.auto(strides.linearSize) { i -> initializer(strides.index(i)) })
public inline fun <T : Any> auto(
type: SafeType<T>,
strides: Strides,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) })
public inline fun <reified T : Any> auto(
shape: ShapeND,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = auto(ColumnStrides(shape), initializer)
@JvmName("autoVarArg")
public inline fun <reified T : Any> auto(
vararg shape: Int,
crossinline initializer: (IntArray) -> T,
): BufferND<T> =
auto(ColumnStrides(ShapeND(shape)), initializer)
public inline fun <T : Any> auto(
type: SafeType<T>,
vararg shape: Int,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = auto(type, ColumnStrides(ShapeND(shape)), initializer)
} }
} }
/**
* Creates a NDStructure with explicit buffer factory.
*
* Strides should be reused if possible.
*/
public fun <T> BufferND(
type: SafeType<T>,
strides: Strides,
initializer: (IntArray) -> T,
): BufferND<T> = BufferND(strides, Buffer(type, strides.linearSize) { i -> initializer(strides.index(i)) })
public fun <T> BufferND(
type: SafeType<T>,
shape: ShapeND,
initializer: (IntArray) -> T,
): BufferND<T> = BufferND(type, ColumnStrides(shape), initializer)
/**
* Inline create NDStructure with non-boxing buffer implementation if it is possible
*/
public inline fun <reified T : Any> BufferND(
strides: Strides,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(strides, Buffer(strides.linearSize) { i -> initializer(strides.index(i)) })
public inline fun <T : Any> BufferND(
type: SafeType<T>,
strides: Strides,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(strides, Buffer(type, strides.linearSize) { i -> initializer(strides.index(i)) })
public inline fun <reified T : Any> BufferND(
shape: ShapeND,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(ColumnStrides(shape), initializer)
@JvmName("autoVarArg")
public inline fun <reified T : Any> BufferND(
vararg shape: Int,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(ColumnStrides(ShapeND(shape)), initializer)
public inline fun <T : Any> BufferND(
type: SafeType<T>,
vararg shape: Int,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(type, ColumnStrides(ShapeND(shape)), initializer)
/** /**
* Indicates whether some [StructureND] is equal to another one. * Indicates whether some [StructureND] is equal to another one.
*/ */

View File

@ -5,13 +5,10 @@
package space.kscience.kmath.nd package space.kscience.kmath.nd
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
public open class VirtualStructureND<T>( public open class VirtualStructureND<T>(
override val type: SafeType<T>,
override val shape: ShapeND, override val shape: ShapeND,
public val producer: (IntArray) -> T, public val producer: (IntArray) -> T,
) : StructureND<T> { ) : StructureND<T> {
@ -27,10 +24,10 @@ public open class VirtualStructureND<T>(
public class VirtualDoubleStructureND( public class VirtualDoubleStructureND(
shape: ShapeND, shape: ShapeND,
producer: (IntArray) -> Double, producer: (IntArray) -> Double,
) : VirtualStructureND<Double>(safeTypeOf(), shape, producer) ) : VirtualStructureND<Double>(shape, producer)
@UnstableKMathAPI @UnstableKMathAPI
public class VirtualIntStructureND( public class VirtualIntStructureND(
shape: ShapeND, shape: ShapeND,
producer: (IntArray) -> Int, producer: (IntArray) -> Int,
) : VirtualStructureND<Int>(safeTypeOf(), shape, producer) ) : VirtualStructureND<Int>(shape, producer)

View File

@ -10,7 +10,7 @@ import space.kscience.kmath.PerformancePitfall
@OptIn(PerformancePitfall::class) @OptIn(PerformancePitfall::class)
public fun <T> StructureND<T>.roll(axis: Int, step: Int = 1): StructureND<T> { public fun <T> StructureND<T>.roll(axis: Int, step: Int = 1): StructureND<T> {
require(axis in shape.indices) { "Axis $axis is outside of shape dimensions: [0, ${shape.size})" } require(axis in shape.indices) { "Axis $axis is outside of shape dimensions: [0, ${shape.size})" }
return VirtualStructureND(type, shape) { index -> return VirtualStructureND(shape) { index ->
val newIndex: IntArray = IntArray(index.size) { indexAxis -> val newIndex: IntArray = IntArray(index.size) { indexAxis ->
if (indexAxis == axis) { if (indexAxis == axis) {
(index[indexAxis] + step).mod(shape[indexAxis]) (index[indexAxis] + step).mod(shape[indexAxis])
@ -26,7 +26,7 @@ public fun <T> StructureND<T>.roll(axis: Int, step: Int = 1): StructureND<T> {
public fun <T> StructureND<T>.roll(pair: Pair<Int, Int>, vararg others: Pair<Int, Int>): StructureND<T> { public fun <T> StructureND<T>.roll(pair: Pair<Int, Int>, vararg others: Pair<Int, Int>): StructureND<T> {
val axisMap: Map<Int, Int> = mapOf(pair, *others) val axisMap: Map<Int, Int> = mapOf(pair, *others)
require(axisMap.keys.all { it in shape.indices }) { "Some of axes ${axisMap.keys} is outside of shape dimensions: [0, ${shape.size})" } require(axisMap.keys.all { it in shape.indices }) { "Some of axes ${axisMap.keys} is outside of shape dimensions: [0, ${shape.size})" }
return VirtualStructureND(type, shape) { index -> return VirtualStructureND(shape) { index ->
val newIndex: IntArray = IntArray(index.size) { indexAxis -> val newIndex: IntArray = IntArray(index.size) { indexAxis ->
val offset = axisMap[indexAxis] ?: 0 val offset = axisMap[indexAxis] ?: 0
(index[indexAxis] + offset).mod(shape[indexAxis]) (index[indexAxis] + offset).mod(shape[indexAxis])

View File

@ -5,32 +5,22 @@
package space.kscience.kmath.operations package space.kscience.kmath.operations
import space.kscience.attributes.SafeType
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.operations.Ring.Companion.optimizedPower import space.kscience.kmath.operations.Ring.Companion.optimizedPower
import space.kscience.kmath.structures.MutableBufferFactory import space.kscience.kmath.structures.MutableBufferFactory
import kotlin.reflect.KType
/**
* An interface containing [type] for dynamic type checking.
*/
public interface WithType<out T> {
public val type: SafeType<T>
}
/** /**
* Represents an algebraic structure. * Represents an algebraic structure.
* *
* @param T the type of element which Algebra operates on. * @param T the type of element which Algebra operates on.
*/ */
public interface Algebra<T> : WithType<T> { public interface Algebra<T> {
/** /**
* Provide a factory for buffers, associated with this [Algebra] * Provide a factory for buffers, associated with this [Algebra]
*/ */
public val bufferFactory: MutableBufferFactory<T> public val bufferFactory: MutableBufferFactory<T> get() = MutableBufferFactory.boxing()
override val type: SafeType<T> get() = bufferFactory.type
/** /**
* Wraps a raw string to [T] object. This method is designed for three purposes: * Wraps a raw string to [T] object. This method is designed for three purposes:
@ -275,7 +265,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].
* *
@ -358,7 +348,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].
* *
@ -371,11 +361,7 @@ 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( exponent < 0 -> one / (this as Ring<T>).optimizedPower(arg, if (exponent == Int.MIN_VALUE) Int.MAX_VALUE.toUInt().inc() else (-exponent).toUInt())
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

@ -5,8 +5,6 @@
package space.kscience.kmath.operations package space.kscience.kmath.operations
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.nd.BufferedRingOpsND import space.kscience.kmath.nd.BufferedRingOpsND
import space.kscience.kmath.operations.BigInt.Companion.BASE import space.kscience.kmath.operations.BigInt.Companion.BASE
@ -28,9 +26,6 @@ private typealias TBase = ULong
*/ */
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public object BigIntField : Field<BigInt>, NumbersAddOps<BigInt>, ScaleOperations<BigInt> { public object BigIntField : Field<BigInt>, NumbersAddOps<BigInt>, ScaleOperations<BigInt> {
override val type: SafeType<BigInt> = safeTypeOf()
override val zero: BigInt = BigInt.ZERO override val zero: BigInt = BigInt.ZERO
override val one: BigInt = BigInt.ONE override val one: BigInt = BigInt.ONE
@ -533,10 +528,10 @@ public fun String.parseBigInteger(): BigInt? {
public val BigInt.algebra: BigIntField get() = BigIntField public val BigInt.algebra: BigIntField get() = BigIntField
public inline fun BigInt.Companion.buffer(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> = public inline fun BigInt.Companion.buffer(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> =
Buffer(size, initializer) Buffer.boxing(size, initializer)
public inline fun BigInt.Companion.mutableBuffer(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> = public inline fun BigInt.Companion.mutableBuffer(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> =
Buffer(size, initializer) Buffer.boxing(size, initializer)
public val BigIntField.nd: BufferedRingOpsND<BigInt, BigIntField> public val BigIntField.nd: BufferedRingOpsND<BigInt, BigIntField>
get() = BufferedRingOpsND(BufferRingOps(BigIntField)) get() = BufferedRingOpsND(BufferRingOps(BigIntField))

View File

@ -5,11 +5,10 @@
package space.kscience.kmath.operations package space.kscience.kmath.operations
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableBuffer
import space.kscience.kmath.structures.MutableBufferFactory import space.kscience.kmath.structures.MutableBufferFactory
import kotlin.reflect.KType
public interface WithSize { public interface WithSize {
public val size: Int public val size: Int
@ -21,8 +20,6 @@ public interface WithSize {
public interface BufferAlgebra<T, out A : Algebra<T>> : Algebra<Buffer<T>> { public interface BufferAlgebra<T, out A : Algebra<T>> : Algebra<Buffer<T>> {
public val elementAlgebra: A public val elementAlgebra: A
override val type: SafeType<Buffer<T>> get() = safeTypeOf<Buffer<T>>()
public val elementBufferFactory: MutableBufferFactory<T> get() = elementAlgebra.bufferFactory public val elementBufferFactory: MutableBufferFactory<T> get() = elementAlgebra.bufferFactory
public fun buffer(size: Int, vararg elements: T): Buffer<T> { public fun buffer(size: Int, vararg elements: T): Buffer<T> {

View File

@ -5,10 +5,9 @@
package space.kscience.kmath.operations package space.kscience.kmath.operations
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.expressions.symbol
/** /**
* An algebra for generic boolean logic * An algebra for generic boolean logic
@ -62,8 +61,8 @@ public interface LogicAlgebra<T : Any> : Algebra<T> {
public companion object { public companion object {
public val TRUE: Symbol = Symbol("TRUE")//by symbol public val TRUE: Symbol by symbol
public val FALSE: Symbol = Symbol("FALSE")// by symbol public val FALSE: Symbol by symbol
} }
} }
@ -74,8 +73,6 @@ public interface LogicAlgebra<T : Any> : Algebra<T> {
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") @Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public object BooleanAlgebra : LogicAlgebra<Boolean> { public object BooleanAlgebra : LogicAlgebra<Boolean> {
override val type: SafeType<Boolean> get() = safeTypeOf()
override fun const(boolean: Boolean): Boolean = boolean override fun const(boolean: Boolean): Boolean = boolean
override fun Boolean.not(): Boolean = !this override fun Boolean.not(): Boolean = !this

View File

@ -8,10 +8,7 @@ package space.kscience.kmath.operations
import space.kscience.kmath.operations.Int16Field.div import space.kscience.kmath.operations.Int16Field.div
import space.kscience.kmath.operations.Int32Field.div import space.kscience.kmath.operations.Int32Field.div
import space.kscience.kmath.operations.Int64Field.div import space.kscience.kmath.operations.Int64Field.div
import space.kscience.kmath.structures.Int16 import space.kscience.kmath.structures.*
import space.kscience.kmath.structures.Int32
import space.kscience.kmath.structures.Int64
import space.kscience.kmath.structures.MutableBufferFactory
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.math.roundToLong import kotlin.math.roundToLong
@ -25,7 +22,7 @@ import kotlin.math.roundToLong
*/ */
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") @Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public object Int16Field : Field<Int16>, Norm<Int16, Int16>, NumericAlgebra<Int16> { public object Int16Field : Field<Int16>, Norm<Int16, Int16>, NumericAlgebra<Int16> {
override val bufferFactory: MutableBufferFactory<Int16> = MutableBufferFactory<Int16>() override val bufferFactory: MutableBufferFactory<Int16> = MutableBufferFactory(::Int16Buffer)
override val zero: Int16 get() = 0 override val zero: Int16 get() = 0
override val one: Int16 get() = 1 override val one: Int16 get() = 1
@ -48,8 +45,7 @@ public object Int16Field : Field<Int16>, Norm<Int16, Int16>, NumericAlgebra<Int1
*/ */
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") @Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public object Int32Field : Field<Int32>, Norm<Int32, Int32>, NumericAlgebra<Int32> { public object Int32Field : Field<Int32>, Norm<Int32, Int32>, NumericAlgebra<Int32> {
override val bufferFactory: MutableBufferFactory<Int> = MutableBufferFactory() override val bufferFactory: MutableBufferFactory<Int> = MutableBufferFactory(::Int32Buffer)
override val zero: Int get() = 0 override val zero: Int get() = 0
override val one: Int get() = 1 override val one: Int get() = 1
@ -72,7 +68,7 @@ public object Int32Field : Field<Int32>, Norm<Int32, Int32>, NumericAlgebra<Int3
*/ */
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") @Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public object Int64Field : Field<Int64>, Norm<Int64, Int64>, NumericAlgebra<Int64> { public object Int64Field : Field<Int64>, Norm<Int64, Int64>, NumericAlgebra<Int64> {
override val bufferFactory: MutableBufferFactory<Int64> = MutableBufferFactory() override val bufferFactory: MutableBufferFactory<Int64> = MutableBufferFactory(::Int64Buffer)
override val zero: Int64 get() = 0L override val zero: Int64 get() = 0L
override val one: Int64 get() = 1L override val one: Int64 get() = 1L

View File

@ -67,7 +67,7 @@ public interface ExtendedField<T> : ExtendedFieldOps<T>, Field<T>, NumericAlgebr
*/ */
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") @Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public object Float64Field : ExtendedField<Double>, Norm<Double, Double>, ScaleOperations<Double> { public object Float64Field : ExtendedField<Double>, Norm<Double, Double>, ScaleOperations<Double> {
override val bufferFactory: MutableBufferFactory<Double> = MutableBufferFactory() override val bufferFactory: MutableBufferFactory<Double> = MutableBufferFactory(::Float64Buffer)
override val zero: Double get() = 0.0 override val zero: Double get() = 0.0
override val one: Double get() = 1.0 override val one: Double get() = 1.0

View File

@ -8,8 +8,8 @@ package space.kscience.kmath.structures
import space.kscience.attributes.SafeType import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.operations.WithSize import space.kscience.kmath.operations.WithSize
import space.kscience.kmath.operations.WithType
import space.kscience.kmath.operations.asSequence import space.kscience.kmath.operations.asSequence
import kotlin.jvm.JvmInline
import kotlin.reflect.typeOf import kotlin.reflect.typeOf
/** /**
@ -17,45 +17,34 @@ import kotlin.reflect.typeOf
* *
* @param T the type of buffer. * @param T the type of buffer.
*/ */
public interface BufferFactory<T> : WithType<T> { public fun interface BufferFactory<T> {
public operator fun invoke(size: Int, builder: (Int) -> T): Buffer<T> public operator fun invoke(size: Int, builder: (Int) -> T): Buffer<T>
}
/** public companion object{
* Create a [BufferFactory] for given [type], using primitive storage if possible public inline fun <reified T> auto(): BufferFactory<T> =
*/ BufferFactory(Buffer.Companion::auto)
public fun <T> BufferFactory(type: SafeType<T>): BufferFactory<T> = object : BufferFactory<T> {
override val type: SafeType<T> = type
override fun invoke(size: Int, builder: (Int) -> T): Buffer<T> = Buffer(type, size, builder)
}
/** public fun <T> boxing(): BufferFactory<T> =
* Create [BufferFactory] using the reified type BufferFactory(Buffer.Companion::boxing)
*/ }
public inline fun <reified T> BufferFactory(): BufferFactory<T> = BufferFactory(safeTypeOf()) }
/** /**
* Function that produces [MutableBuffer] from its size and function that supplies values. * Function that produces [MutableBuffer] from its size and function that supplies values.
* *
* @param T the type of buffer. * @param T the type of buffer.
*/ */
public interface MutableBufferFactory<T> : BufferFactory<T> { public fun interface MutableBufferFactory<T> : BufferFactory<T> {
override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer<T> override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer<T>
}
/** public companion object {
* Create a [MutableBufferFactory] for given [type], using primitive storage if possible public inline fun <reified T : Any> auto(): MutableBufferFactory<T> =
*/ MutableBufferFactory(MutableBuffer.Companion::auto)
public fun <T> MutableBufferFactory(type: SafeType<T>): MutableBufferFactory<T> = object : MutableBufferFactory<T> {
override val type: SafeType<T> = type
override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer<T> = MutableBuffer(type, size, builder)
}
/** public fun <T> boxing(): MutableBufferFactory<T> =
* Create [BufferFactory] using the reified type MutableBufferFactory(MutableBuffer.Companion::boxing)
*/ }
public inline fun <reified T> MutableBufferFactory(): MutableBufferFactory<T> = MutableBufferFactory(safeTypeOf()) }
/** /**
* A generic read-only random-access structure for both primitives and objects. * A generic read-only random-access structure for both primitives and objects.
@ -64,14 +53,14 @@ public inline fun <reified T> MutableBufferFactory(): MutableBufferFactory<T> =
* *
* @param T the type of elements contained in the buffer. * @param T the type of elements contained in the buffer.
*/ */
public interface Buffer<out T> : WithSize, WithType<T> { public interface Buffer<out T> : WithSize {
/** /**
* The size of this buffer. * The size of this buffer.
*/ */
override val size: Int override val size: Int
/** /**
* Gets an element at given index. * Gets element at given index.
*/ */
public operator fun get(index: Int): T public operator fun get(index: Int): T
@ -98,46 +87,39 @@ public interface Buffer<out T> : WithSize, WithType<T> {
return true return true
} }
} /**
} * Creates a [ListBuffer] of given type [T] with given [size]. Each element is calculated by calling the
* specified [initializer] function.
*/
public inline fun <T> boxing(size: Int, initializer: (Int) -> T): Buffer<T> =
List(size, initializer).asBuffer()
/** /**
* Creates a [Buffer] of given type [T]. If the type is primitive, specialized buffers are used ([Int32Buffer], * Creates a [Buffer] of given [type]. If the type is primitive, specialized buffers are used ([Int32Buffer],
* [Float64Buffer], etc.), [ListBuffer] is returned otherwise. * [Float64Buffer], etc.), [ListBuffer] is returned otherwise.
* *
* The [size] is specified, and each element is calculated by calling the specified [initializer] function. * The [size] is specified, and each element is calculated by calling the specified [initializer] function.
*/ */
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
public inline fun <reified T> Buffer(size: Int, initializer: (Int) -> T): Buffer<T> { public inline fun <T> auto(type: SafeType<T>, size: Int, initializer: (Int) -> T): Buffer<T> =
val type = safeTypeOf<T>() when (type.kType) {
return when (type.kType) { typeOf<Double>() -> MutableBuffer.double(size) { initializer(it) as Double } as Buffer<T>
typeOf<Double>() -> MutableBuffer.double(size) { initializer(it) as Double } as Buffer<T> typeOf<Short>() -> MutableBuffer.short(size) { initializer(it) as Short } as Buffer<T>
typeOf<Short>() -> MutableBuffer.short(size) { initializer(it) as Short } as Buffer<T> typeOf<Int>() -> MutableBuffer.int(size) { initializer(it) as Int } as Buffer<T>
typeOf<Int>() -> MutableBuffer.int(size) { initializer(it) as Int } as Buffer<T> typeOf<Long>() -> MutableBuffer.long(size) { initializer(it) as Long } as Buffer<T>
typeOf<Long>() -> MutableBuffer.long(size) { initializer(it) as Long } as Buffer<T> typeOf<Float>() -> MutableBuffer.float(size) { initializer(it) as Float } as Buffer<T>
typeOf<Float>() -> MutableBuffer.float(size) { initializer(it) as Float } as Buffer<T> else -> boxing(size, initializer)
else -> List(size, initializer).asBuffer(type) }
}
}
/** /**
* Creates a [Buffer] of given [type]. If the type is primitive, specialized buffers are used ([Int32Buffer], * Creates a [Buffer] of given type [T]. If the type is primitive, specialized buffers are used ([Int32Buffer],
* [Float64Buffer], etc.), [ListBuffer] is returned otherwise. * [Float64Buffer], etc.), [ListBuffer] is returned otherwise.
* *
* The [size] is specified, and each element is calculated by calling the specified [initializer] function. * The [size] is specified, and each element is calculated by calling the specified [initializer] function.
*/ */
@Suppress("UNCHECKED_CAST") public inline fun <reified T> auto(size: Int, initializer: (Int) -> T): Buffer<T> =
public fun <T> Buffer( auto(safeTypeOf<T>(), size, initializer)
type: SafeType<T>, }
size: Int,
initializer: (Int) -> T,
): Buffer<T> = when (type.kType) {
typeOf<Double>() -> MutableBuffer.double(size) { initializer(it) as Double } as Buffer<T>
typeOf<Short>() -> MutableBuffer.short(size) { initializer(it) as Short } as Buffer<T>
typeOf<Int>() -> MutableBuffer.int(size) { initializer(it) as Int } as Buffer<T>
typeOf<Long>() -> MutableBuffer.long(size) { initializer(it) as Long } as Buffer<T>
typeOf<Float>() -> MutableBuffer.float(size) { initializer(it) as Float } as Buffer<T>
else -> List(size, initializer).asBuffer(type)
} }
/** /**
@ -162,17 +144,28 @@ public fun <T> Buffer<T>.last(): T {
return get(size - 1) return get(size - 1)
} }
/**
* Immutable wrapper for [MutableBuffer].
*
* @param T the type of elements contained in the buffer.
* @property buffer The underlying buffer.
*/
@JvmInline
public value class ReadOnlyBuffer<T>(public val buffer: MutableBuffer<T>) : Buffer<T> {
override val size: Int get() = buffer.size
override operator fun get(index: Int): T = buffer[index]
override operator fun iterator(): Iterator<T> = buffer.iterator()
}
/** /**
* A buffer with content calculated on-demand. The calculated content is not stored, so it is recalculated on each call. * A buffer with content calculated on-demand. The calculated content is not stored, so it is recalculated on each call.
* Useful when one needs a single element from the buffer. * Useful when one needs single element from the buffer.
* *
* @param T the type of elements provided by the buffer. * @param T the type of elements provided by the buffer.
*/ */
public class VirtualBuffer<out T>( public class VirtualBuffer<out T>(override val size: Int, private val generator: (Int) -> T) : Buffer<T> {
override val type: SafeType<T>,
override val size: Int,
private val generator: (Int) -> T,
) : Buffer<T> {
override operator fun get(index: Int): T { override operator fun get(index: Int): T {
if (index < 0 || index >= size) throw IndexOutOfBoundsException("Expected index from 0 to ${size - 1}, but found $index") if (index < 0 || index >= size) throw IndexOutOfBoundsException("Expected index from 0 to ${size - 1}, but found $index")
return generator(index) return generator(index)
@ -184,9 +177,6 @@ public class VirtualBuffer<out T>(
} }
/** /**
* Inline builder for [VirtualBuffer] * Convert this buffer to read-only buffer.
*/ */
public inline fun <reified T> VirtualBuffer( public fun <T> Buffer<T>.asReadOnly(): Buffer<T> = if (this is MutableBuffer) ReadOnlyBuffer(this) else this
size: Int,
noinline generator: (Int) -> T,
): VirtualBuffer<T> = VirtualBuffer(safeTypeOf(), size, generator)

View File

@ -5,13 +5,7 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.attributes.SafeType import space.kscience.kmath.nd.*
import space.kscience.kmath.nd.BufferND
import space.kscience.kmath.nd.ShapeND
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.nd.as2D
import kotlin.collections.component1
import kotlin.collections.component2
/** /**
* A context that allows to operate on a [MutableBuffer] as on 2d array * A context that allows to operate on a [MutableBuffer] as on 2d array
@ -33,13 +27,11 @@ internal class BufferAccessor2D<T>(
fun create(mat: Structure2D<T>): MutableBuffer<T> = create { i, j -> mat[i, j] } fun create(mat: Structure2D<T>): MutableBuffer<T> = create { i, j -> mat[i, j] }
//TODO optimize wrapper //TODO optimize wrapper
fun MutableBuffer<T>.toStructure2D(): Structure2D<T> = BufferND( fun MutableBuffer<T>.toStructure2D(): Structure2D<T> = StructureND.buffered(
type, ShapeND(rowNum, colNum) ColumnStrides(ShapeND(rowNum, colNum))
) { (i, j) -> get(i, j) }.as2D() ) { (i, j) -> get(i, j) }.as2D()
inner class Row(val buffer: MutableBuffer<T>, val rowIndex: Int) : MutableBuffer<T> { inner class Row(val buffer: MutableBuffer<T>, val rowIndex: Int) : MutableBuffer<T> {
override val type: SafeType<T> get() = buffer.type
override val size: Int get() = colNum override val size: Int get() = colNum
override operator fun get(index: Int): T = buffer[rowIndex, index] override operator fun get(index: Int): T = buffer[rowIndex, index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.experimental.and import kotlin.experimental.and
/** /**
@ -59,9 +57,6 @@ public class FlaggedDoubleBuffer(
public val values: DoubleArray, public val values: DoubleArray,
public val flags: ByteArray public val flags: ByteArray
) : FlaggedBuffer<Double?>, Buffer<Double?> { ) : FlaggedBuffer<Double?>, Buffer<Double?> {
override val type: SafeType<Double?> = safeTypeOf()
init { init {
require(values.size == flags.size) { "Values and flags must have the same dimensions" } require(values.size == flags.size) { "Values and flags must have the same dimensions" }
} }

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline import kotlin.jvm.JvmInline
/** /**
@ -17,9 +15,6 @@ import kotlin.jvm.JvmInline
*/ */
@JvmInline @JvmInline
public value class Float32Buffer(public val array: FloatArray) : PrimitiveBuffer<Float> { public value class Float32Buffer(public val array: FloatArray) : PrimitiveBuffer<Float> {
override val type: SafeType<Float32> get() = safeTypeOf<Float32>()
override val size: Int get() = array.size override val size: Int get() = array.size
override operator fun get(index: Int): Float = array[index] override operator fun get(index: Int): Float = array[index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.operations.BufferTransform import space.kscience.kmath.operations.BufferTransform
import kotlin.jvm.JvmInline import kotlin.jvm.JvmInline
@ -17,9 +15,6 @@ import kotlin.jvm.JvmInline
*/ */
@JvmInline @JvmInline
public value class Float64Buffer(public val array: DoubleArray) : PrimitiveBuffer<Double> { public value class Float64Buffer(public val array: DoubleArray) : PrimitiveBuffer<Double> {
override val type: SafeType<Double> get() = safeTypeOf()
override val size: Int get() = array.size override val size: Int get() = array.size
override operator fun get(index: Int): Double = array[index] override operator fun get(index: Int): Double = array[index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline import kotlin.jvm.JvmInline
/** /**
@ -16,8 +14,6 @@ import kotlin.jvm.JvmInline
*/ */
@JvmInline @JvmInline
public value class Int16Buffer(public val array: ShortArray) : MutableBuffer<Short> { public value class Int16Buffer(public val array: ShortArray) : MutableBuffer<Short> {
override val type: SafeType<Short> get() = safeTypeOf()
override val size: Int get() = array.size override val size: Int get() = array.size
override operator fun get(index: Int): Short = array[index] override operator fun get(index: Int): Short = array[index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline import kotlin.jvm.JvmInline
/** /**
@ -16,9 +14,6 @@ import kotlin.jvm.JvmInline
*/ */
@JvmInline @JvmInline
public value class Int32Buffer(public val array: IntArray) : PrimitiveBuffer<Int> { public value class Int32Buffer(public val array: IntArray) : PrimitiveBuffer<Int> {
override val type: SafeType<Int> get() = safeTypeOf()
override val size: Int get() = array.size override val size: Int get() = array.size
override operator fun get(index: Int): Int = array[index] override operator fun get(index: Int): Int = array[index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline import kotlin.jvm.JvmInline
/** /**
@ -16,9 +14,6 @@ import kotlin.jvm.JvmInline
*/ */
@JvmInline @JvmInline
public value class Int64Buffer(public val array: LongArray) : PrimitiveBuffer<Long> { public value class Int64Buffer(public val array: LongArray) : PrimitiveBuffer<Long> {
override val type: SafeType<Long> get() = safeTypeOf()
override val size: Int get() = array.size override val size: Int get() = array.size
override operator fun get(index: Int): Long = array[index] override operator fun get(index: Int): Long = array[index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline import kotlin.jvm.JvmInline
/** /**
@ -16,9 +14,6 @@ import kotlin.jvm.JvmInline
*/ */
@JvmInline @JvmInline
public value class Int8Buffer(public val array: ByteArray) : MutableBuffer<Byte> { public value class Int8Buffer(public val array: ByteArray) : MutableBuffer<Byte> {
override val type: SafeType<Byte> get() = safeTypeOf()
override val size: Int get() = array.size override val size: Int get() = array.size
override operator fun get(index: Int): Byte = array[index] override operator fun get(index: Int): Byte = array[index]

View File

@ -5,8 +5,7 @@
package space.kscience.kmath.structures package space.kscience.kmath.structures
import space.kscience.attributes.SafeType import kotlin.jvm.JvmInline
import space.kscience.attributes.safeTypeOf
/** /**
* [Buffer] implementation over [List]. * [Buffer] implementation over [List].
@ -14,7 +13,9 @@ import space.kscience.attributes.safeTypeOf
* @param T the type of elements contained in the buffer. * @param T the type of elements contained in the buffer.
* @property list The underlying list. * @property list The underlying list.
*/ */
public class ListBuffer<T>(override val type: SafeType<T>, public val list: List<T>) : Buffer<T> { public class ListBuffer<T>(public val list: List<T>) : Buffer<T> {
public constructor(size: Int, initializer: (Int) -> T) : this(List(size, initializer))
override val size: Int get() = list.size override val size: Int get() = list.size
@ -28,12 +29,7 @@ public class ListBuffer<T>(override val type: SafeType<T>, public val list: List
/** /**
* Returns an [ListBuffer] that wraps the original list. * Returns an [ListBuffer] that wraps the original list.
*/ */
public fun <T> List<T>.asBuffer(type: SafeType<T>): ListBuffer<T> = ListBuffer(type, this) public fun <T> List<T>.asBuffer(): ListBuffer<T> = ListBuffer(this)
/**
* Returns an [ListBuffer] that wraps the original list.
*/
public inline fun <reified T> List<T>.asBuffer(): ListBuffer<T> = asBuffer(safeTypeOf())
/** /**
* [MutableBuffer] implementation over [MutableList]. * [MutableBuffer] implementation over [MutableList].
@ -41,7 +37,10 @@ public inline fun <reified T> List<T>.asBuffer(): ListBuffer<T> = asBuffer(safeT
* @param T the type of elements contained in the buffer. * @param T the type of elements contained in the buffer.
* @property list The underlying list. * @property list The underlying list.
*/ */
public class MutableListBuffer<T>(override val type: SafeType<T>, public val list: MutableList<T>) : MutableBuffer<T> { @JvmInline
public value class MutableListBuffer<T>(public val list: MutableList<T>) : MutableBuffer<T> {
public constructor(size: Int, initializer: (Int) -> T) : this(MutableList(size, initializer))
override val size: Int get() = list.size override val size: Int get() = list.size
@ -52,24 +51,10 @@ public class MutableListBuffer<T>(override val type: SafeType<T>, public val lis
} }
override operator fun iterator(): Iterator<T> = list.iterator() override operator fun iterator(): Iterator<T> = list.iterator()
override fun copy(): MutableBuffer<T> = MutableListBuffer(type, ArrayList(list)) override fun copy(): MutableBuffer<T> = MutableListBuffer(ArrayList(list))
override fun toString(): String = Buffer.toString(this)
} }
/** /**
* Returns an [MutableListBuffer] that wraps the original list. * Returns an [MutableListBuffer] that wraps the original list.
*/ */
public fun <T> MutableList<T>.asMutableBuffer(type: SafeType<T>): MutableListBuffer<T> = MutableListBuffer( public fun <T> MutableList<T>.asMutableBuffer(): MutableListBuffer<T> = MutableListBuffer(this)
type,
this
)
/**
* Returns an [MutableListBuffer] that wraps the original list.
*/
public inline fun <reified T> MutableList<T>.asMutableBuffer(): MutableListBuffer<T> = MutableListBuffer(
safeTypeOf(),
this
)

View File

@ -61,35 +61,41 @@ public interface MutableBuffer<T> : Buffer<T> {
*/ */
public inline fun float(size: Int, initializer: (Int) -> Float): Float32Buffer = public inline fun float(size: Int, initializer: (Int) -> Float): Float32Buffer =
Float32Buffer(size, initializer) Float32Buffer(size, initializer)
/**
* Create a boxing mutable buffer of given type
*/
public inline fun <T> boxing(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
MutableListBuffer(MutableList(size, initializer))
/**
* Creates a [MutableBuffer] of given [type]. If the type is primitive, specialized buffers are used
* ([Int32Buffer], [Float64Buffer], etc.), [ListBuffer] is returned otherwise.
*
* The [size] is specified, and each element is calculated by calling the specified [initializer] function.
*/
@Suppress("UNCHECKED_CAST")
public inline fun <T> auto(type: SafeType<T>, size: Int, initializer: (Int) -> T): MutableBuffer<T> =
when (type.kType) {
typeOf<Double>() -> double(size) { initializer(it) as Double } as MutableBuffer<T>
typeOf<Short>() -> short(size) { initializer(it) as Short } as MutableBuffer<T>
typeOf<Int>() -> int(size) { initializer(it) as Int } as MutableBuffer<T>
typeOf<Float>() -> float(size) { initializer(it) as Float } as MutableBuffer<T>
typeOf<Long>() -> long(size) { initializer(it) as Long } as MutableBuffer<T>
else -> boxing(size, initializer)
}
/**
* Creates a [MutableBuffer] of given type [T]. If the type is primitive, specialized buffers are used
* ([Int32Buffer], [Float64Buffer], etc.), [ListBuffer] is returned otherwise.
*
* The [size] is specified, and each element is calculated by calling the specified [initializer] function.
*/
public inline fun <reified T> auto(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
auto(safeTypeOf<T>(), size, initializer)
} }
} }
/**
* Creates a [MutableBuffer] of given [type]. If the type is primitive, specialized buffers are used
* ([Int32Buffer], [Float64Buffer], etc.), [ListBuffer] is returned otherwise.
*
* The [size] is specified, and each element is calculated by calling the specified [initializer] function.
*/
@Suppress("UNCHECKED_CAST")
public inline fun <T> MutableBuffer(type: SafeType<T>, size: Int, initializer: (Int) -> T): MutableBuffer<T> =
when (type.kType) {
typeOf<Double>() -> MutableBuffer.double(size) { initializer(it) as Double } as MutableBuffer<T>
typeOf<Short>() -> MutableBuffer.short(size) { initializer(it) as Short } as MutableBuffer<T>
typeOf<Int>() -> MutableBuffer.int(size) { initializer(it) as Int } as MutableBuffer<T>
typeOf<Float>() -> MutableBuffer.float(size) { initializer(it) as Float } as MutableBuffer<T>
typeOf<Long>() -> MutableBuffer.long(size) { initializer(it) as Long } as MutableBuffer<T>
else -> MutableListBuffer(type, MutableList(size, initializer))
}
/**
* Creates a [MutableBuffer] of given type [T]. If the type is primitive, specialized buffers are used
* ([Int32Buffer], [Float64Buffer], etc.), [ListBuffer] is returned otherwise.
*
* The [size] is specified, and each element is calculated by calling the specified [initializer] function.
*/
public inline fun <reified T> MutableBuffer(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
MutableBuffer(safeTypeOf<T>(), size, initializer)
public sealed interface PrimitiveBuffer<T> : MutableBuffer<T> public sealed interface PrimitiveBuffer<T> : MutableBuffer<T>

View File

@ -40,7 +40,7 @@ class DoubleLUSolverTest {
//Check determinant //Check determinant
assertEquals(7.0, lup.determinant) assertEquals(7.0, lup.determinant)
assertMatrixEquals(lup.pivotMatrix dot matrix, lup.l dot lup.u) assertMatrixEquals(lup.p dot matrix, lup.l dot lup.u)
} }
@Test @Test

View File

@ -65,7 +65,9 @@ public class RingBuffer<T>(
} }
} }
private fun Int.forward(n: Int): Int = (this + n) % (buffer.size)
@Suppress("NOTHING_TO_INLINE")
private inline fun Int.forward(n: Int): Int = (this + n) % (buffer.size)
override fun toString(): String = Buffer.toString(this) override fun toString(): String = Buffer.toString(this)

View File

@ -4,7 +4,7 @@
*/ */
package space.kscience.kmath.integration package space.kscience.kmath.integration
import space.kscience.attributes.TypedAttributesBuilder import space.kscience.attributes.AttributesBuilder
import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.Field
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
@ -54,10 +54,10 @@ public class GaussIntegrator<T : Any>(
} }
} }
override fun integrate(integrand: UnivariateIntegrand<T>): UnivariateIntegrand<T> = with(algebra) { override fun process(integrand: UnivariateIntegrand<T>): UnivariateIntegrand<T> = with(algebra) {
val f = integrand.function val f = integrand.function
val (points, weights) = buildRule(integrand) val (points, weights) = buildRule(integrand)
var res: T = zero var res = zero
var c = zero var c = zero
for (i in points.indices) { for (i in points.indices) {
val x = points[i] val x = points[i]
@ -67,8 +67,8 @@ public class GaussIntegrator<T : Any>(
c = t - res - y c = t - res - y
res = t res = t
} }
return integrand.withAttributes { return integrand.modify {
IntegrandValue(res) value(res)
IntegrandCallsPerformed(integrand.calls + points.size) IntegrandCallsPerformed(integrand.calls + points.size)
} }
} }
@ -88,12 +88,12 @@ public val <T : Any> Field<T>.gaussIntegrator: GaussIntegrator<T> get() = GaussI
* Integrate using [intervals] segments with Gauss-Legendre rule of [order] order. * Integrate using [intervals] segments with Gauss-Legendre rule of [order] order.
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public inline fun <reified T : Any> GaussIntegrator<T>.integrate( public fun <T : Any> GaussIntegrator<T>.integrate(
range: ClosedRange<Double>, range: ClosedRange<Double>,
order: Int = 10, order: Int = 10,
intervals: Int = 10, intervals: Int = 10,
attributesBuilder: TypedAttributesBuilder<UnivariateIntegrand<T>>.() -> Unit, attributesBuilder: AttributesBuilder.() -> Unit,
noinline function: (Double) -> T, function: (Double) -> T,
): UnivariateIntegrand<T> { ): UnivariateIntegrand<T> {
require(range.endInclusive > range.start) { "The range upper bound should be higher than lower bound" } require(range.endInclusive > range.start) { "The range upper bound should be higher than lower bound" }
require(order > 1) { "The order of polynomial must be more than 1" } require(order > 1) { "The order of polynomial must be more than 1" }
@ -102,8 +102,8 @@ public inline fun <reified T : Any> GaussIntegrator<T>.integrate(
val ranges = UnivariateIntegrandRanges( val ranges = UnivariateIntegrandRanges(
(0 until intervals).map { i -> (range.start + rangeSize * i)..(range.start + rangeSize * (i + 1)) to order } (0 until intervals).map { i -> (range.start + rangeSize * i)..(range.start + rangeSize * (i + 1)) to order }
) )
return integrate( return process(
UnivariateIntegrand<T>( UnivariateIntegrand(
attributeBuilder = { attributeBuilder = {
IntegrationRange(range) IntegrationRange(range)
GaussIntegratorRuleFactory(GaussLegendreRuleFactory) GaussIntegratorRuleFactory(GaussLegendreRuleFactory)

View File

@ -5,7 +5,10 @@
package space.kscience.kmath.integration package space.kscience.kmath.integration
import space.kscience.attributes.* import space.kscience.attributes.Attribute
import space.kscience.attributes.AttributeContainer
import space.kscience.attributes.AttributesBuilder
import space.kscience.attributes.SafeType
public interface IntegrandAttribute<T> : Attribute<T> public interface IntegrandAttribute<T> : Attribute<T>
@ -13,10 +16,9 @@ public interface Integrand<T> : AttributeContainer {
public val type: SafeType<T> public val type: SafeType<T>
/** public fun modify(block: AttributesBuilder.() -> Unit): Integrand<T>
* Create a copy of this integrand with a new set of attributes
*/ public fun <A : Any> withAttribute(attribute: Attribute<A>, value: A): Integrand<T>
public fun withAttributes(attributes: Attributes): Integrand<T>
public companion object public companion object
} }
@ -30,7 +32,7 @@ public sealed class IntegrandValue<T> private constructor(): IntegrandAttribute<
} }
} }
public fun <T> TypedAttributesBuilder<Integrand<T>>.value(value: T) { public fun <T> AttributesBuilder.value(value: T) {
IntegrandValue.forType<T>().invoke(value) IntegrandValue.forType<T>().invoke(value)
} }

View File

@ -8,9 +8,9 @@ package space.kscience.kmath.integration
/** /**
* A general interface for all integrators. * A general interface for all integrators.
*/ */
public interface Integrator<T, I : Integrand<T>> { public interface Integrator<I : Integrand> {
/** /**
* Runs one integration pass and return a new [Integrand] with a new set of features. * Runs one integration pass and return a new [Integrand] with a new set of features.
*/ */
public fun integrate(integrand: I): I public fun process(integrand: I): I
} }

View File

@ -14,21 +14,14 @@ public class MultivariateIntegrand<T>(
public val function: (Point<T>) -> T, public val function: (Point<T>) -> T,
) : Integrand<T> { ) : Integrand<T> {
override fun withAttributes(attributes: Attributes): MultivariateIntegrand<T> = override fun modify(block: AttributesBuilder.() -> Unit): MultivariateIntegrand<T> =
MultivariateIntegrand(type, attributes, function) MultivariateIntegrand(type, attributes.modify(block), function)
override fun <A : Any> withAttribute(attribute: Attribute<A>, value: A): MultivariateIntegrand<T> =
MultivariateIntegrand(type, attributes.withAttribute(attribute, value), function)
} }
public fun <T, A : Any> MultivariateIntegrand<T>.withAttribute(
attribute: Attribute<A>,
value: A,
): MultivariateIntegrand<T> = withAttributes(attributes.withAttribute(attribute, value))
public fun <T> MultivariateIntegrand<T>.withAttributes(
block: TypedAttributesBuilder<MultivariateIntegrand<T>>.() -> Unit,
): MultivariateIntegrand<T> = withAttributes(attributes.modify(block))
public inline fun <reified T : Any> MultivariateIntegrand( public inline fun <reified T : Any> MultivariateIntegrand(
attributeBuilder: TypedAttributesBuilder<MultivariateIntegrand<T>>.() -> Unit, attributeBuilder: AttributesBuilder.() -> Unit,
noinline function: (Point<T>) -> T, noinline function: (Point<T>) -> T,
): MultivariateIntegrand<T> = MultivariateIntegrand(safeTypeOf<T>(), Attributes(attributeBuilder), function) ): MultivariateIntegrand<T> = MultivariateIntegrand(safeTypeOf<T>(), Attributes(attributeBuilder), function)

View File

@ -44,12 +44,12 @@ public class SimpsonIntegrator<T : Any>(
return res return res
} }
override fun integrate(integrand: UnivariateIntegrand<T>): UnivariateIntegrand<T> { override fun process(integrand: UnivariateIntegrand<T>): UnivariateIntegrand<T> {
val ranges = integrand[UnivariateIntegrandRanges] val ranges = integrand[UnivariateIntegrandRanges]
return if (ranges != null) { return if (ranges != null) {
val res = algebra.sum(ranges.ranges.map { integrateRange(integrand, it.first, it.second) }) val res = algebra.sum(ranges.ranges.map { integrateRange(integrand, it.first, it.second) })
integrand.withAttributes { integrand.modify {
IntegrandValue(res) value(res)
IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second }) IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second })
} }
} else { } else {
@ -57,8 +57,8 @@ public class SimpsonIntegrator<T : Any>(
require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" } require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" }
val range = integrand[IntegrationRange] ?: 0.0..1.0 val range = integrand[IntegrationRange] ?: 0.0..1.0
val res = integrateRange(integrand, range, numPoints) val res = integrateRange(integrand, range, numPoints)
integrand.withAttributes { integrand.modify {
IntegrandValue(res) value(res)
IntegrandCallsPerformed(integrand.calls + numPoints) IntegrandCallsPerformed(integrand.calls + numPoints)
} }
} }
@ -96,12 +96,12 @@ public object DoubleSimpsonIntegrator : UnivariateIntegrator<Double> {
return res return res
} }
override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> { override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
val ranges = integrand[UnivariateIntegrandRanges] val ranges = integrand[UnivariateIntegrandRanges]
return if (ranges != null) { return if (ranges != null) {
val res = ranges.ranges.sumOf { integrateRange(integrand, it.first, it.second) } val res = ranges.ranges.sumOf { integrateRange(integrand, it.first, it.second) }
integrand.withAttributes { integrand.modify {
IntegrandValue(res) value(res)
IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second }) IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second })
} }
} else { } else {
@ -109,8 +109,8 @@ public object DoubleSimpsonIntegrator : UnivariateIntegrator<Double> {
require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" } require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" }
val range = integrand[IntegrationRange] ?: 0.0..1.0 val range = integrand[IntegrationRange] ?: 0.0..1.0
val res = integrateRange(integrand, range, numPoints) val res = integrateRange(integrand, range, numPoints)
integrand.withAttributes { integrand.modify {
IntegrandValue(res) value(res)
IntegrandCallsPerformed(integrand.calls + numPoints) IntegrandCallsPerformed(integrand.calls + numPoints)
} }
} }

View File

@ -54,7 +54,7 @@ public class SplineIntegrator<T : Comparable<T>>(
public val algebra: Field<T>, public val algebra: Field<T>,
public val bufferFactory: MutableBufferFactory<T>, public val bufferFactory: MutableBufferFactory<T>,
) : UnivariateIntegrator<T> { ) : UnivariateIntegrator<T> {
override fun integrate(integrand: UnivariateIntegrand<T>): UnivariateIntegrand<T> = algebra { override fun process(integrand: UnivariateIntegrand<T>): UnivariateIntegrand<T> = algebra {
val range = integrand[IntegrationRange] ?: 0.0..1.0 val range = integrand[IntegrationRange] ?: 0.0..1.0
val interpolator: PolynomialInterpolator<T> = SplineInterpolator(algebra, bufferFactory) val interpolator: PolynomialInterpolator<T> = SplineInterpolator(algebra, bufferFactory)
@ -71,8 +71,8 @@ public class SplineIntegrator<T : Comparable<T>>(
values values
) )
val res = polynomials.integrate(algebra, number(range.start)..number(range.endInclusive)) val res = polynomials.integrate(algebra, number(range.start)..number(range.endInclusive))
integrand.withAttributes { integrand.modify {
IntegrandValue(res) value(res)
IntegrandCallsPerformed(integrand.calls + nodes.size) IntegrandCallsPerformed(integrand.calls + nodes.size)
} }
} }
@ -86,7 +86,7 @@ public class SplineIntegrator<T : Comparable<T>>(
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public object DoubleSplineIntegrator : UnivariateIntegrator<Double> { public object DoubleSplineIntegrator : UnivariateIntegrator<Double> {
override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> { override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
val range = integrand[IntegrationRange] ?: 0.0..1.0 val range = integrand[IntegrationRange] ?: 0.0..1.0
val interpolator: PolynomialInterpolator<Double> = SplineInterpolator(Float64Field, ::Float64Buffer) val interpolator: PolynomialInterpolator<Double> = SplineInterpolator(Float64Field, ::Float64Buffer)
@ -99,8 +99,8 @@ public object DoubleSplineIntegrator : UnivariateIntegrator<Double> {
val values = nodes.mapToBuffer(::Float64Buffer) { integrand.function(it) } val values = nodes.mapToBuffer(::Float64Buffer) { integrand.function(it) }
val polynomials = interpolator.interpolatePolynomials(nodes, values) val polynomials = interpolator.interpolatePolynomials(nodes, values)
val res = polynomials.integrate(Float64Field, range) val res = polynomials.integrate(Float64Field, range)
return integrand.withAttributes { return integrand.modify {
IntegrandValue(res) value(res)
IntegrandCallsPerformed(integrand.calls + nodes.size) IntegrandCallsPerformed(integrand.calls + nodes.size)
} }
} }

View File

@ -16,25 +16,19 @@ public class UnivariateIntegrand<T>(
public val function: (Double) -> T, public val function: (Double) -> T,
) : Integrand<T> { ) : Integrand<T> {
override fun withAttributes(attributes: Attributes): UnivariateIntegrand<T> = override fun <A : Any> withAttribute(attribute: Attribute<A>, value: A): UnivariateIntegrand<T> =
UnivariateIntegrand(type, attributes, function) UnivariateIntegrand(type, attributes.withAttribute(attribute, value), function)
override fun modify(block: AttributesBuilder.() -> Unit): UnivariateIntegrand<T> =
UnivariateIntegrand(type, attributes.modify(block), function)
} }
public fun <T, A : Any> UnivariateIntegrand<T>.withAttribute(
attribute: Attribute<A>,
value: A,
): UnivariateIntegrand<T> = withAttributes(attributes.withAttribute(attribute, value))
public fun <T> UnivariateIntegrand<T>.withAttributes(
block: TypedAttributesBuilder<UnivariateIntegrand<T>>.() -> Unit,
): UnivariateIntegrand<T> = withAttributes(attributes.modify(block))
public inline fun <reified T : Any> UnivariateIntegrand( public inline fun <reified T : Any> UnivariateIntegrand(
attributeBuilder: TypedAttributesBuilder<UnivariateIntegrand<T>>.() -> Unit, attributeBuilder: AttributesBuilder.() -> Unit,
noinline function: (Double) -> T, noinline function: (Double) -> T,
): UnivariateIntegrand<T> = UnivariateIntegrand(safeTypeOf(), Attributes(attributeBuilder), function) ): UnivariateIntegrand<T> = UnivariateIntegrand(safeTypeOf(), Attributes(attributeBuilder), function)
public typealias UnivariateIntegrator<T> = Integrator<T, UnivariateIntegrand<T>> public typealias UnivariateIntegrator<T> = Integrator<UnivariateIntegrand<T>>
public object IntegrationRange : IntegrandAttribute<ClosedRange<Double>> public object IntegrationRange : IntegrandAttribute<ClosedRange<Double>>
@ -58,7 +52,7 @@ public class UnivariateIntegrandRanges(public val ranges: List<Pair<ClosedRange<
public object UnivariateIntegrationNodes : IntegrandAttribute<Buffer<Double>> public object UnivariateIntegrationNodes : IntegrandAttribute<Buffer<Double>>
public fun TypedAttributesBuilder<UnivariateIntegrand<*>>.integrationNodes(vararg nodes: Double) { public fun AttributesBuilder.integrationNodes(vararg nodes: Double) {
UnivariateIntegrationNodes(Float64Buffer(nodes)) UnivariateIntegrationNodes(Float64Buffer(nodes))
} }
@ -68,9 +62,9 @@ public fun TypedAttributesBuilder<UnivariateIntegrand<*>>.integrationNodes(varar
*/ */
@UnstableKMathAPI @UnstableKMathAPI
public inline fun <reified T : Any> UnivariateIntegrator<T>.integrate( public inline fun <reified T : Any> UnivariateIntegrator<T>.integrate(
attributesBuilder: TypedAttributesBuilder<UnivariateIntegrand<T>>.() -> Unit, attributesBuilder: AttributesBuilder.() -> Unit,
noinline function: (Double) -> T, noinline function: (Double) -> T,
): UnivariateIntegrand<T> = integrate(UnivariateIntegrand(attributesBuilder, function)) ): UnivariateIntegrand<T> = process(UnivariateIntegrand(attributesBuilder, function))
/** /**
* A shortcut method to integrate a [function] in [range] with additional features. * A shortcut method to integrate a [function] in [range] with additional features.
@ -79,11 +73,11 @@ public inline fun <reified T : Any> UnivariateIntegrator<T>.integrate(
@UnstableKMathAPI @UnstableKMathAPI
public inline fun <reified T : Any> UnivariateIntegrator<T>.integrate( public inline fun <reified T : Any> UnivariateIntegrator<T>.integrate(
range: ClosedRange<Double>, range: ClosedRange<Double>,
attributeBuilder: TypedAttributesBuilder<UnivariateIntegrand<T>>.() -> Unit = {}, attributeBuilder: AttributesBuilder.() -> Unit = {},
noinline function: (Double) -> T, noinline function: (Double) -> T,
): UnivariateIntegrand<T> { ): UnivariateIntegrand<T> {
return integrate( return process(
UnivariateIntegrand( UnivariateIntegrand(
attributeBuilder = { attributeBuilder = {
IntegrationRange(range) IntegrationRange(range)

View File

@ -6,26 +6,16 @@
package space.kscience.kmath.geometry.euclidean2d package space.kscience.kmath.geometry.euclidean2d
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import space.kscience.kmath.geometry.Vector2D
import kotlin.math.PI import kotlin.math.PI
public interface Circle2D<T>{
public val center: Vector2D<T>
public val radius: Double
}
public val Circle2D<*>.circumference: Double get() = radius * 2 * PI
/** /**
* A circle in 2D space * A circle in 2D space
*/ */
@Serializable @Serializable
public data class Float64Circle2D( public data class Circle2D(
@Serializable(Float64Space2D.VectorSerializer::class) override val center: Float64Vector2D, @Serializable(Float64Space2D.VectorSerializer::class) public val center: DoubleVector2D,
override val radius: Double public val radius: Double,
): Circle2D<Double> )
public fun Circle2D(center: Float64Vector2D, radius: Double): Circle2D<Double> = Float64Circle2D(center, radius)
public val Circle2D.circumference: Double get() = radius * 2 * PI

View File

@ -15,7 +15,6 @@ import space.kscience.kmath.geometry.GeometrySpace
import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.geometry.Vector2D
import space.kscience.kmath.linear.Float64LinearSpace import space.kscience.kmath.linear.Float64LinearSpace
import space.kscience.kmath.operations.Float64Field import space.kscience.kmath.operations.Float64Field
import space.kscience.kmath.operations.ScaleOperations
import kotlin.math.pow import kotlin.math.pow
import kotlin.math.sqrt import kotlin.math.sqrt
@ -29,7 +28,9 @@ public val Vector2D<Double>.r: Double get() = Float64Space2D.norm(this)
/** /**
* 2D Euclidean space * 2D Euclidean space
*/ */
public object Float64Space2D : GeometrySpace<DoubleVector2D>, ScaleOperations<DoubleVector2D> { public object Float64Space2D : GeometrySpace<DoubleVector2D, Double> {
public val linearSpace: Float64LinearSpace = Float64LinearSpace
@Serializable @Serializable
@SerialName("Float64Vector2D") @SerialName("Float64Vector2D")
@ -71,6 +72,4 @@ public object Float64Space2D : GeometrySpace<DoubleVector2D>, ScaleOperations<Do
override val defaultPrecision: Double = 1e-6 override val defaultPrecision: Double = 1e-6
} }
public fun Float64Vector2D(x: Number, y: Number): Float64Vector2D = Float64Space2D.vector(x, y)
public val Float64Field.euclidean2D: Float64Space2D get() = Float64Space2D public val Float64Field.euclidean2D: Float64Space2D get() = Float64Space2D

View File

@ -1,33 +0,0 @@
/*
* Copyright 2018-2023 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.geometry
import space.kscience.kmath.complex.Quaternion
import space.kscience.kmath.complex.QuaternionAlgebra
import space.kscience.kmath.complex.conjugate
import space.kscience.kmath.geometry.euclidean3d.theta
public operator fun Quaternion.times(other: Quaternion): Quaternion = QuaternionAlgebra.multiply(this, other)
public operator fun Quaternion.div(other: Quaternion): Quaternion = QuaternionAlgebra.divide(this, other)
public fun Quaternion.power(number: Number): Quaternion = QuaternionAlgebra.power(this, number)
/**
* Linear interpolation between [from] and [to] in spherical space
*/
public fun QuaternionAlgebra.slerp(from: Quaternion, to: Quaternion, fraction: Double): Quaternion =
(to / from).pow(fraction) * from
/**
* Scalar angle between two quaternions
*/
public fun QuaternionAlgebra.angleBetween(q1: Quaternion, q2: Quaternion): Angle = (q1.conjugate * q2).theta
/**
* Euclidean product of two quaternions
*/
public infix fun Quaternion.dot(other: Quaternion): Double = w * other.w + x * other.x + y * other.y + z * other.z

View File

@ -147,12 +147,12 @@ public fun <V : Any, A : Field<V>> Histogram.Companion.uniformNDFromRanges(
bufferFactory: BufferFactory<V> = valueAlgebraND.elementAlgebra.bufferFactory, bufferFactory: BufferFactory<V> = valueAlgebraND.elementAlgebra.bufferFactory,
): UniformHistogramGroupND<V, A> = UniformHistogramGroupND( ): UniformHistogramGroupND<V, A> = UniformHistogramGroupND(
valueAlgebraND, valueAlgebraND,
DoubleBuffer( ListBuffer(
ranges ranges
.map(Pair<ClosedFloatingPointRange<Double>, Int>::first) .map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
.map(ClosedFloatingPointRange<Double>::start) .map(ClosedFloatingPointRange<Double>::start)
), ),
DoubleBuffer( ListBuffer(
ranges ranges
.map(Pair<ClosedFloatingPointRange<Double>, Int>::first) .map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
.map(ClosedFloatingPointRange<Double>::endInclusive) .map(ClosedFloatingPointRange<Double>::endInclusive)

View File

@ -15,6 +15,3 @@ readme {
An API and basic implementation for arranging objects in a continuous memory block. An API and basic implementation for arranging objects in a continuous memory block.
""".trimIndent() """.trimIndent()
} }
//rootProject.the<NodeJsRootExtension>().versions.webpack.version = "5.76.2"
//rootProject.the<NodeJsRootExtension>().nodeVersion = "20.8.0"

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.memory package space.kscience.kmath.memory
import kotlin.experimental.ExperimentalNativeApi
@PublishedApi @PublishedApi
internal class NativeMemory( internal class NativeMemory(
val array: ByteArray, val array: ByteArray,
@ -28,7 +26,6 @@ internal class NativeMemory(
return NativeMemory(copy) return NativeMemory(copy)
} }
@OptIn(ExperimentalNativeApi::class)
private val reader: MemoryReader = object : MemoryReader { private val reader: MemoryReader = object : MemoryReader {
override val memory: Memory get() = this@NativeMemory override val memory: Memory get() = this@NativeMemory
@ -51,7 +48,6 @@ internal class NativeMemory(
override fun reader(): MemoryReader = reader override fun reader(): MemoryReader = reader
@OptIn(ExperimentalNativeApi::class)
private val writer: MemoryWriter = object : MemoryWriter { private val writer: MemoryWriter = object : MemoryWriter {
override val memory: Memory get() = this@NativeMemory override val memory: Memory get() = this@NativeMemory

View File

@ -6,7 +6,7 @@ kscience{
jvm() jvm()
js { js {
browser { browser {
testTask{ testTask {
useMocha().timeout = "0" useMocha().timeout = "0"
} }
} }

View File

@ -310,26 +310,32 @@ internal fun DoubleTensorAlgebra.svdHelper(
} }
} }
private fun pythag(a: Double, b: Double): Double {
val at: Double = abs(a)
val bt: Double = abs(b)
val ct: Double
val result: Double
if (at > bt) {
ct = bt / at
result = at * sqrt(1.0 + ct * ct)
} else if (bt > 0.0) {
ct = at / bt
result = bt * sqrt(1.0 + ct * ct)
} else result = 0.0
return result
}
private fun SIGN(a: Double, b: Double): Double {
if (b >= 0.0)
return abs(a)
else
return -abs(a)
}
internal fun MutableStructure2D<Double>.svdGolubKahanHelper( internal fun MutableStructure2D<Double>.svdGolubKahanHelper(
u: MutableStructure2D<Double>, w: BufferedTensor<Double>, u: MutableStructure2D<Double>, w: BufferedTensor<Double>,
v: MutableStructure2D<Double>, iterations: Int, epsilon: Double, v: MutableStructure2D<Double>, iterations: Int, epsilon: Double,
) { ) {
fun pythag(a: Double, b: Double): Double {
val at: Double = abs(a)
val bt: Double = abs(b)
val ct: Double
val result: Double
if (at > bt) {
ct = bt / at
result = at * sqrt(1.0 + ct * ct)
} else if (bt > 0.0) {
ct = at / bt
result = bt * sqrt(1.0 + ct * ct)
} else result = 0.0
return result
}
val shape = this.shape val shape = this.shape
val m = shape.component1() val m = shape.component1()
val n = shape.component2() val n = shape.component2()
@ -547,7 +553,7 @@ internal fun MutableStructure2D<Double>.svdGolubKahanHelper(
h = rv1[k] h = rv1[k]
f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y) f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y)
g = pythag(f, 1.0) g = pythag(f, 1.0)
f = ((x - z) * (x + z) + h * ((y / (f + if (f >= 0.0) abs(g) else -abs(g) )) - h)) / x f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x
c = 1.0 c = 1.0
s = 1.0 s = 1.0
@ -557,7 +563,7 @@ internal fun MutableStructure2D<Double>.svdGolubKahanHelper(
g = rv1[i] g = rv1[i]
y = wBuffer[wStart + i] y = wBuffer[wStart + i]
h = s * g h = s * g
g *= c g = c * g
z = pythag(f, h) z = pythag(f, h)
rv1[j] = z rv1[j] = z
c = f / z c = f / z