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

View File

@ -7,10 +7,8 @@ package space.kscience.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())
@ -49,8 +47,6 @@ public class TypedAttributesBuilder<in O> internal constructor(private val map:
public fun build(): Attributes = Attributes(map)
}
public typealias AttributesBuilder = TypedAttributesBuilder<Any?>
public fun AttributesBuilder(
attributes: Attributes,
): AttributesBuilder = AttributesBuilder(attributes.content.toMutableMap())

View File

@ -16,7 +16,7 @@ import kotlin.reflect.typeOf
* @param kType raw [KType]
*/
@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>())

View File

@ -1,3 +1,4 @@
import space.kscience.gradle.isInDevelopment
import space.kscience.gradle.useApache2Licence
import space.kscience.gradle.useSPCTeam
@ -63,10 +64,17 @@ ksciencePublish {
useApache2Licence()
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")
}
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 {
api("space.kscience:gradle-tools:$toolsVersion")
//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")
//to be used inside build-script only
//implementation(spclibs.kotlinx.serialization.json)

View File

@ -1,13 +1,4 @@
/*
* 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"
}
rootProject.name = "buildSrc"
dependencyResolutionManagement {
val projectProperties = java.util.Properties()

View File

@ -54,9 +54,9 @@ fun Project.addBenchmarkProperties() {
p.extensions.findByType(KScienceReadmeExtension::class.java)?.run {
benchmarksProject.extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg ->
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()
}

View File

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

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
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
zipStorePath=wrapper/dists

View File

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

View File

@ -17,7 +17,7 @@ internal class TestFeatures {
fun printNumeric() {
val num = object : Number() {
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 toFloat(): Float = throw UnsupportedOperationException()
override fun toInt(): Int = throw UnsupportedOperationException()

View File

@ -8,8 +8,9 @@
"OVERRIDING_FINAL_MEMBER",
"RETURN_TYPE_MISMATCH_ON_OVERRIDE",
"CONFLICTING_OVERLOADS",
"NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING",
"PropertyName",
"ClassName", "ENUM_CLASS_IN_EXTERNAL_DECLARATION_WARNING",
"ClassName",
)
@file:JsModule("binaryen")

View File

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

View File

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

View File

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

View File

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

View File

@ -10,7 +10,6 @@ import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.VirtualBuffer
import kotlin.math.max
/**
@ -34,10 +33,7 @@ public interface XYColumnarData<out T, out X : T, out Y : T> : ColumnarData<T> {
else -> null
}
public companion object {
/**
* Create data form two buffers (zero-copy)
*/
public companion object{
@UnstableKMathAPI
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}" }
@ -47,26 +43,6 @@ public interface XYColumnarData<out T, out X : T, out Y : T> : ColumnarData<T> {
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,
): XYColumnarData<T, T, T> = object : XYColumnarData<T, T, T> {
init {
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[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"}
}
override val size: Int get() = this@asXYData.size
override val x: Buffer<T> get() = this@asXYData[xSymbol]!!
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 kotlin.math.max
import kotlin.math.min
import kotlin.reflect.KType
import kotlin.reflect.typeOf
/**
* 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>,
) : ExpressionAlgebra<T, DS<T, A>>, SymbolIndexer {
override val bufferFactory: MutableBufferFactory<DS<T, A>> = MutableBufferFactory()
/**
* Get the compiler for number of free parameters and order.
*

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.MutableBufferFactory
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
@ -18,8 +17,6 @@ import kotlin.contracts.contract
public abstract class FunctionalExpressionAlgebra<T, out A : Algebra<T>>(
public val algebra: A,
) : 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.
*/
@ -52,7 +49,6 @@ public abstract class FunctionalExpressionAlgebra<T, out A : Algebra<T>>(
public open class FunctionalExpressionGroup<T, out A : Group<T>>(
algebra: A,
) : FunctionalExpressionAlgebra<T, A>(algebra), Group<Expression<T>> {
override val zero: Expression<T> get() = const(algebra.zero)
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.operations.*
import space.kscience.kmath.structures.MutableBufferFactory
/**
* [Algebra] over [MST] nodes.
*/
public object MstNumericAlgebra : NumericAlgebra<MST> {
override val bufferFactory: MutableBufferFactory<MST> = MutableBufferFactory()
override fun number(value: Number): MST.Numeric = MST.Numeric(value)
override fun bindSymbolOrNull(value: String): Symbol = StringSymbol(value)
override fun bindSymbol(value: String): Symbol = bindSymbolOrNull(value)
@ -30,9 +27,6 @@ public object MstNumericAlgebra : NumericAlgebra<MST> {
* [Group] over [MST] nodes.
*/
public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
override val bufferFactory: MutableBufferFactory<MST> = MutableBufferFactory()
override val zero: MST.Numeric = number(0.0)
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")
@OptIn(UnstableKMathAPI::class)
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 val one: MST.Numeric = number(1.0)
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")
@OptIn(UnstableKMathAPI::class)
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 one: MST.Numeric get() = MstRing.one
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")
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 one: MST.Numeric get() = MstField.one
override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
@ -182,9 +164,6 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
*/
@UnstableKMathAPI
public object MstLogicAlgebra : LogicAlgebra<MST> {
override val bufferFactory: MutableBufferFactory<MST> = MutableBufferFactory()
override fun bindSymbolOrNull(value: String): MST = super.bindSymbolOrNull(value) ?: StringSymbol(value)
override fun const(boolean: Boolean): Symbol = if (boolean) {

View File

@ -5,11 +5,9 @@
package space.kscience.kmath.expressions
import space.kscience.attributes.SafeType
import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.linear.Point
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.MutableBufferFactory
import space.kscience.kmath.structures.asBuffer
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
@ -32,10 +30,9 @@ public open class AutoDiffValue<out T>(public val value: T)
*/
public class DerivationResult<T : Any>(
public val value: T,
override val type: SafeType<T>,
private val derivativeValues: Map<String, T>,
public val context: Field<T>,
) : WithType<T> {
) {
/**
* 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> {
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)
public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
public val algebra: F,
public val context: F,
bindings: Map<Symbol, T>,
) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, NumbersAddOps<AutoDiffValue<T>> {
override val bufferFactory: MutableBufferFactory<AutoDiffValue<T>> = MutableBufferFactory<AutoDiffValue<T>>()
override val zero: AutoDiffValue<T> get() = const(algebra.zero)
override val one: AutoDiffValue<T> get() = const(algebra.one)
override val zero: AutoDiffValue<T> get() = const(context.zero)
override val one: AutoDiffValue<T> get() = const(context.one)
// this stack contains pairs of blocks and values to apply them to
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 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]
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) {
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) {
val value = stack[--sp]
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 {
// save block to stack for backward pass
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> {
val result = function()
result.d = algebra.one // computing derivative w.r.t result
result.d = context.one // computing derivative w.r.t result
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
@ -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> {
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.operations.BufferRingOps
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.WithType
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer
import kotlin.reflect.KType
import kotlin.reflect.typeOf
/**
* 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
* @param T type of matrix element
*/
public interface MatrixOperations<T> : WithType<T>
public interface MatrixOperations<T>
/**
* 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 val elementAlgebra: A
override val type: SafeType<T> get() = elementAlgebra.type
/**
* 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.
* @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 u The upper triangular matrix in this decomposition. It may have [UpperTriangular].
*/
public class LupDecomposition<T>(
public val linearSpace: LinearSpace<T, Ring<T>>,
public data class LupDecomposition<T>(
public val l: Matrix<T>,
public val u: Matrix<T>,
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>>) :
@ -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
}
val l: MatrixWrapper<T> = VirtualMatrix(type, rowNum, colNum) { i, j ->
val l: MatrixWrapper<T> = VirtualMatrix(rowNum, colNum) { i, j ->
when {
j < i -> lu[i, j]
j == i -> one
@ -192,7 +176,7 @@ public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
}
}.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
}.withAttribute(UpperTriangular)
//
@ -200,7 +184,7 @@ public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
// if (j == pivot[i]) one else zero
// }.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
import space.kscience.attributes.FlagAttribute
import space.kscience.attributes.SafeType
import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.WithType
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 val linearSpace: LinearSpace<T, A>,
public val rows: Int,
public val columns: Int,
) : WithType<T> {
override val type: SafeType<T> get() = linearSpace.type
) {
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" }
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,
): Matrix<T> {
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 }
linearSpace.buildMatrix(rows, rows) { 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,
attrValue: T,
): MatrixWrapper<T> = if (this is MatrixWrapper) {
MatrixWrapper(origin, attributes.withAttribute(attribute, attrValue))
MatrixWrapper(origin, attributes.withAttribute(attribute,attrValue))
} else {
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(
rows: 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
}.withAttribute(IsUnit)
@ -79,6 +79,6 @@ public fun <T : Any> LinearSpace<T, Ring<T>>.one(
public fun <T : Any> LinearSpace<T, Ring<T>>.zero(
rows: Int,
columns: Int,
): MatrixWrapper<T> = VirtualMatrix(type, rows, columns) { _, _ ->
): MatrixWrapper<T> = VirtualMatrix(rows, columns) { _, _ ->
elementAlgebra.zero
}.withAttribute(IsZero)

View File

@ -6,14 +6,10 @@
package space.kscience.kmath.linear
import space.kscience.attributes.Attributes
import space.kscience.attributes.SafeType
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 colNum: Int get() = origin.rowNum
override fun get(i: Int, j: Int): T = origin[j, i]

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.linear
import space.kscience.attributes.Attributes
import space.kscience.attributes.SafeType
import space.kscience.kmath.nd.ShapeND
@ -15,8 +14,7 @@ import space.kscience.kmath.nd.ShapeND
*
* @property generator the function that provides elements.
*/
public class VirtualMatrix<out T>(
override val type: SafeType<T>,
public class VirtualMatrix<out T : Any>(
override val rowNum: Int,
override val colNum: Int,
override val attributes: Attributes = Attributes.EMPTY,
@ -31,4 +29,4 @@ public class VirtualMatrix<out T>(
public fun <T : Any> MatrixBuilder<T, *>.virtual(
attributes: Attributes = Attributes.EMPTY,
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.
*/
@file:OptIn(UnstableKMathAPI::class)
@file:Suppress("UnusedReceiverParameter")
package space.kscience.kmath.linear
import space.kscience.attributes.*
import space.kscience.kmath.UnstableKMathAPI
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.
*/
public class Determinant<T>(type: SafeType<T>) :
PolymorphicAttribute<T>(type),
MatrixAttribute<T>
public class Determinant<T> : 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.

View File

@ -4,8 +4,6 @@
*/
@file:OptIn(UnstableKMathAPI::class)
package space.kscience.kmath.misc
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
*/
@OptIn(UnstableKMathAPI::class)
public fun <V : Comparable<V>> Buffer<V>.sorted(): Buffer<V> {
val permutations = indicesSorted()
return VirtualBuffer(type, size) { this[permutations[it]] }
return VirtualBuffer(size) { this[permutations[it]] }
}
@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
*/
@OptIn(UnstableKMathAPI::class)
public fun <V : Comparable<V>> Buffer<V>.sortedDescending(): Buffer<V> {
val permutations = indicesSortedDescending()
return VirtualBuffer(type, size) { this[permutations[it]] }
return VirtualBuffer(size) { this[permutations[it]] }
}
@UnstableKMathAPI
public fun <V, C : Comparable<C>> Buffer<V>.indicesSortedBy(selector: (V) -> C): IntArray =
permSortIndicesWith(compareBy { selector(get(it)) })
@OptIn(UnstableKMathAPI::class)
public fun <V, C : Comparable<C>> Buffer<V>.sortedBy(selector: (V) -> C): Buffer<V> {
val permutations = indicesSortedBy(selector)
return VirtualBuffer(type, size) { this[permutations[it]] }
return VirtualBuffer(size) { this[permutations[it]] }
}
@UnstableKMathAPI
public fun <V, C : Comparable<C>> Buffer<V>.indicesSortedByDescending(selector: (V) -> C): IntArray =
permSortIndicesWith(compareByDescending { selector(get(it)) })
@OptIn(UnstableKMathAPI::class)
public fun <V, C : Comparable<C>> Buffer<V>.sortedByDescending(selector: (V) -> C): Buffer<V> {
val permutations = indicesSortedByDescending(selector)
return VirtualBuffer(type, size) { this[permutations[it]] }
return VirtualBuffer(size) { this[permutations[it]] }
}
@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]
*/
@OptIn(UnstableKMathAPI::class)
public fun <V> Buffer<V>.sortedWith(comparator: Comparator<V>): Buffer<V> {
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 {

View File

@ -8,7 +8,7 @@ package space.kscience.kmath.nd
import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.MutableBufferFactory
import kotlin.reflect.KClass
/**
* 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.
*/
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.
*

View File

@ -7,8 +7,6 @@
package space.kscience.kmath.nd
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.UnstableKMathAPI
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 indexerBuilder: (ShapeND) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder,
) : 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 }
}

View File

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

View File

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

View File

@ -5,7 +5,6 @@
package space.kscience.kmath.nd
import space.kscience.attributes.SafeType
import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.operations.asSequence
import space.kscience.kmath.structures.Buffer
@ -47,9 +46,6 @@ public interface MutableStructure1D<T> : Structure1D<T>, MutableStructureND<T>,
*/
@JvmInline
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 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
*/
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 size: Int get() = structure.shape[0]
@ -86,7 +79,7 @@ private class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>)
.elements()
.map(Pair<IntArray, T>::second)
.toMutableList()
.asMutableBuffer(type)
.asMutableBuffer()
override fun toString(): String = Buffer.toString(this)
}
@ -97,9 +90,6 @@ private class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>)
*/
@JvmInline
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 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> {
override val type: SafeType<T> get() = buffer.type
override val shape: ShapeND get() = ShapeND(buffer.size)
override val size: Int get() = buffer.size

View File

@ -6,12 +6,13 @@
package space.kscience.kmath.nd
import space.kscience.attributes.Attributes
import space.kscience.attributes.SafeType
import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.MutableBuffer
import space.kscience.kmath.structures.MutableListBuffer
import space.kscience.kmath.structures.VirtualBuffer
import kotlin.jvm.JvmInline
import kotlin.reflect.KClass
/**
* 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)
/**
* 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
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
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.
@ -87,14 +88,14 @@ public interface MutableStructure2D<T> : Structure2D<T>, MutableStructureND<T> {
*/
@PerformancePitfall
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
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
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 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
*/
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 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.linear.LinearSpace
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.WithType
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer
import kotlin.jvm.JvmName
@ -29,9 +28,9 @@ public interface StructureAttribute<T> : Attribute<T>
*
* @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.
*/
override val shape: ShapeND
@ -118,60 +117,56 @@ public interface StructureND<out T> : AttributeContainer, WithShape, WithType<T>
return "$className(shape=${structure.shape}, buffer=$bufferRepr)"
}
}
}
/**
/**
* Creates a NDStructure with explicit buffer factory.
*
* Strides should be reused if possible.
*/
public fun <T> BufferND(
type: SafeType<T>,
public fun <T> buffered(
strides: Strides,
initializer: (IntArray) -> T,
): BufferND<T> = BufferND(strides, Buffer(type, strides.linearSize) { i -> initializer(strides.index(i)) })
): BufferND<T> = BufferND(strides, Buffer.boxing(strides.linearSize) { i -> initializer(strides.index(i)) })
public fun <T> BufferND(
type: SafeType<T>,
public fun <T> buffered(
shape: ShapeND,
initializer: (IntArray) -> T,
): BufferND<T> = BufferND(type, ColumnStrides(shape), initializer)
): BufferND<T> = buffered(ColumnStrides(shape), initializer)
/**
/**
* Inline create NDStructure with non-boxing buffer implementation if it is possible
*/
public inline fun <reified T : Any> BufferND(
public inline fun <reified T : Any> auto(
strides: Strides,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(strides, Buffer(strides.linearSize) { i -> initializer(strides.index(i)) })
): BufferND<T> = BufferND(strides, Buffer.auto(strides.linearSize) { i -> initializer(strides.index(i)) })
public inline fun <T : Any> BufferND(
public inline fun <T : Any> auto(
type: SafeType<T>,
strides: Strides,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(strides, Buffer(type, strides.linearSize) { i -> initializer(strides.index(i)) })
): BufferND<T> = BufferND(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) })
public inline fun <reified T : Any> BufferND(
public inline fun <reified T : Any> auto(
shape: ShapeND,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(ColumnStrides(shape), initializer)
): BufferND<T> = auto(ColumnStrides(shape), initializer)
@JvmName("autoVarArg")
public inline fun <reified T : Any> BufferND(
@JvmName("autoVarArg")
public inline fun <reified T : Any> auto(
vararg shape: Int,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(ColumnStrides(ShapeND(shape)), initializer)
): BufferND<T> =
auto(ColumnStrides(ShapeND(shape)), initializer)
public inline fun <T : Any> BufferND(
public inline fun <T : Any> auto(
type: SafeType<T>,
vararg shape: Int,
crossinline initializer: (IntArray) -> T,
): BufferND<T> = BufferND(type, ColumnStrides(ShapeND(shape)), initializer)
): BufferND<T> = auto(type, ColumnStrides(ShapeND(shape)), initializer)
}
}
/**
* Indicates whether some [StructureND] is equal to another one.

View File

@ -5,13 +5,10 @@
package space.kscience.kmath.nd
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.PerformancePitfall
import space.kscience.kmath.UnstableKMathAPI
public open class VirtualStructureND<T>(
override val type: SafeType<T>,
override val shape: ShapeND,
public val producer: (IntArray) -> T,
) : StructureND<T> {
@ -27,10 +24,10 @@ public open class VirtualStructureND<T>(
public class VirtualDoubleStructureND(
shape: ShapeND,
producer: (IntArray) -> Double,
) : VirtualStructureND<Double>(safeTypeOf(), shape, producer)
) : VirtualStructureND<Double>(shape, producer)
@UnstableKMathAPI
public class VirtualIntStructureND(
shape: ShapeND,
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)
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})" }
return VirtualStructureND(type, shape) { index ->
return VirtualStructureND(shape) { index ->
val newIndex: IntArray = IntArray(index.size) { indexAxis ->
if (indexAxis == axis) {
(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> {
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})" }
return VirtualStructureND(type, shape) { index ->
return VirtualStructureND(shape) { index ->
val newIndex: IntArray = IntArray(index.size) { indexAxis ->
val offset = axisMap[indexAxis] ?: 0
(index[indexAxis] + offset).mod(shape[indexAxis])

View File

@ -5,32 +5,22 @@
package space.kscience.kmath.operations
import space.kscience.attributes.SafeType
import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.operations.Ring.Companion.optimizedPower
import space.kscience.kmath.structures.MutableBufferFactory
/**
* An interface containing [type] for dynamic type checking.
*/
public interface WithType<out T> {
public val type: SafeType<T>
}
import kotlin.reflect.KType
/**
* Represents an algebraic structure.
*
* @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]
*/
public val bufferFactory: MutableBufferFactory<T>
override val type: SafeType<T> get() = bufferFactory.type
public val bufferFactory: MutableBufferFactory<T> get() = MutableBufferFactory.boxing()
/**
* 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 companion object {
public companion object{
/**
* 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 companion object {
public companion object{
/**
* 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
*/
private fun <T> Field<T>.optimizedPower(arg: T, exponent: Int): T = when {
exponent < 0 -> one / (this as Ring<T>).optimizedPower(
arg,
if (exponent == Int.MIN_VALUE) Int.MAX_VALUE.toUInt().inc() else (-exponent).toUInt()
)
exponent < 0 -> one / (this as Ring<T>).optimizedPower(arg, if (exponent == Int.MIN_VALUE) Int.MAX_VALUE.toUInt().inc() else (-exponent).toUInt())
else -> (this as Ring<T>).optimizedPower(arg, exponent.toUInt())
}
}

View File

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

View File

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

View File

@ -5,10 +5,9 @@
package space.kscience.kmath.operations
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.expressions.symbol
/**
* An algebra for generic boolean logic
@ -62,8 +61,8 @@ public interface LogicAlgebra<T : Any> : Algebra<T> {
public companion object {
public val TRUE: Symbol = Symbol("TRUE")//by symbol
public val FALSE: Symbol = Symbol("FALSE")// by symbol
public val TRUE: Symbol by symbol
public val FALSE: Symbol by symbol
}
}
@ -74,8 +73,6 @@ public interface LogicAlgebra<T : Any> : Algebra<T> {
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public object BooleanAlgebra : LogicAlgebra<Boolean> {
override val type: SafeType<Boolean> get() = safeTypeOf()
override fun const(boolean: Boolean): Boolean = boolean
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.Int32Field.div
import space.kscience.kmath.operations.Int64Field.div
import space.kscience.kmath.structures.Int16
import space.kscience.kmath.structures.Int32
import space.kscience.kmath.structures.Int64
import space.kscience.kmath.structures.MutableBufferFactory
import space.kscience.kmath.structures.*
import kotlin.math.roundToInt
import kotlin.math.roundToLong
@ -25,7 +22,7 @@ import kotlin.math.roundToLong
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
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 one: Int16 get() = 1
@ -48,8 +45,7 @@ public object Int16Field : Field<Int16>, Norm<Int16, Int16>, NumericAlgebra<Int1
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
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 one: Int get() = 1
@ -72,7 +68,7 @@ public object Int32Field : Field<Int32>, Norm<Int32, Int32>, NumericAlgebra<Int3
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
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 one: Int64 get() = 1L

View File

@ -67,7 +67,7 @@ public interface ExtendedField<T> : ExtendedFieldOps<T>, Field<T>, NumericAlgebr
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
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 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.safeTypeOf
import space.kscience.kmath.operations.WithSize
import space.kscience.kmath.operations.WithType
import space.kscience.kmath.operations.asSequence
import kotlin.jvm.JvmInline
import kotlin.reflect.typeOf
/**
@ -17,45 +17,34 @@ import kotlin.reflect.typeOf
*
* @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>
}
/**
* Create a [BufferFactory] for given [type], using primitive storage if possible
*/
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 companion object{
public inline fun <reified T> auto(): BufferFactory<T> =
BufferFactory(Buffer.Companion::auto)
/**
* Create [BufferFactory] using the reified type
*/
public inline fun <reified T> BufferFactory(): BufferFactory<T> = BufferFactory(safeTypeOf())
public fun <T> boxing(): BufferFactory<T> =
BufferFactory(Buffer.Companion::boxing)
}
}
/**
* Function that produces [MutableBuffer] from its size and function that supplies values.
*
* @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>
}
/**
* Create a [MutableBufferFactory] for given [type], using primitive storage if possible
*/
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 companion object {
public inline fun <reified T : Any> auto(): MutableBufferFactory<T> =
MutableBufferFactory(MutableBuffer.Companion::auto)
/**
* Create [BufferFactory] using the reified type
*/
public inline fun <reified T> MutableBufferFactory(): MutableBufferFactory<T> = MutableBufferFactory(safeTypeOf())
public fun <T> boxing(): MutableBufferFactory<T> =
MutableBufferFactory(MutableBuffer.Companion::boxing)
}
}
/**
* 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.
*/
public interface Buffer<out T> : WithSize, WithType<T> {
public interface Buffer<out T> : WithSize {
/**
* The size of this buffer.
*/
override val size: Int
/**
* Gets an element at given index.
* Gets element at given index.
*/
public operator fun get(index: Int): T
@ -98,46 +87,39 @@ public interface Buffer<out T> : WithSize, WithType<T> {
return true
}
}
}
/**
* Creates a [Buffer] 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.
/**
* Creates a [ListBuffer] of given type [T] with given [size]. Each element is calculated by calling the
* specified [initializer] function.
*/
@Suppress("UNCHECKED_CAST")
public inline fun <reified T> Buffer(size: Int, initializer: (Int) -> T): Buffer<T> {
val type = safeTypeOf<T>()
return 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)
}
}
public inline fun <T> boxing(size: Int, initializer: (Int) -> T): Buffer<T> =
List(size, initializer).asBuffer()
/**
/**
* Creates a [Buffer] 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 fun <T> Buffer(
type: SafeType<T>,
size: Int,
initializer: (Int) -> T,
): Buffer<T> = when (type.kType) {
@Suppress("UNCHECKED_CAST")
public inline fun <T> auto(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)
else -> boxing(size, initializer)
}
/**
* Creates a [Buffer] 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): Buffer<T> =
auto(safeTypeOf<T>(), size, initializer)
}
}
/**
@ -162,17 +144,28 @@ public fun <T> Buffer<T>.last(): T {
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.
* 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.
*/
public class VirtualBuffer<out T>(
override val type: SafeType<T>,
override val size: Int,
private val generator: (Int) -> T,
) : Buffer<T> {
public class VirtualBuffer<out T>(override val size: Int, private val generator: (Int) -> T) : Buffer<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")
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(
size: Int,
noinline generator: (Int) -> T,
): VirtualBuffer<T> = VirtualBuffer(safeTypeOf(), size, generator)
public fun <T> Buffer<T>.asReadOnly(): Buffer<T> = if (this is MutableBuffer) ReadOnlyBuffer(this) else this

View File

@ -5,13 +5,7 @@
package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
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
import space.kscience.kmath.nd.*
/**
* 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] }
//TODO optimize wrapper
fun MutableBuffer<T>.toStructure2D(): Structure2D<T> = BufferND(
type, ShapeND(rowNum, colNum)
fun MutableBuffer<T>.toStructure2D(): Structure2D<T> = StructureND.buffered(
ColumnStrides(ShapeND(rowNum, colNum))
) { (i, j) -> get(i, j) }.as2D()
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 operator fun get(index: Int): T = buffer[rowIndex, index]

View File

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

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline
/**
@ -17,9 +15,6 @@ import kotlin.jvm.JvmInline
*/
@JvmInline
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 operator fun get(index: Int): Float = array[index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import space.kscience.kmath.operations.BufferTransform
import kotlin.jvm.JvmInline
@ -17,9 +15,6 @@ import kotlin.jvm.JvmInline
*/
@JvmInline
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 operator fun get(index: Int): Double = array[index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline
/**
@ -16,8 +14,6 @@ import kotlin.jvm.JvmInline
*/
@JvmInline
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 operator fun get(index: Int): Short = array[index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline
/**
@ -16,9 +14,6 @@ import kotlin.jvm.JvmInline
*/
@JvmInline
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 operator fun get(index: Int): Int = array[index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline
/**
@ -16,9 +14,6 @@ import kotlin.jvm.JvmInline
*/
@JvmInline
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 operator fun get(index: Int): Long = array[index]

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline
/**
@ -16,9 +14,6 @@ import kotlin.jvm.JvmInline
*/
@JvmInline
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 operator fun get(index: Int): Byte = array[index]

View File

@ -5,8 +5,7 @@
package space.kscience.kmath.structures
import space.kscience.attributes.SafeType
import space.kscience.attributes.safeTypeOf
import kotlin.jvm.JvmInline
/**
* [Buffer] implementation over [List].
@ -14,7 +13,9 @@ import space.kscience.attributes.safeTypeOf
* @param T the type of elements contained in the buffer.
* @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
@ -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.
*/
public fun <T> List<T>.asBuffer(type: SafeType<T>): ListBuffer<T> = ListBuffer(type, this)
/**
* Returns an [ListBuffer] that wraps the original list.
*/
public inline fun <reified T> List<T>.asBuffer(): ListBuffer<T> = asBuffer(safeTypeOf())
public fun <T> List<T>.asBuffer(): ListBuffer<T> = ListBuffer(this)
/**
* [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.
* @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
@ -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 fun copy(): MutableBuffer<T> = MutableListBuffer(type, ArrayList(list))
override fun toString(): String = Buffer.toString(this)
override fun copy(): MutableBuffer<T> = MutableListBuffer(ArrayList(list))
}
/**
* Returns an [MutableListBuffer] that wraps the original list.
*/
public fun <T> MutableList<T>.asMutableBuffer(type: SafeType<T>): MutableListBuffer<T> = MutableListBuffer(
type,
this
)
/**
* Returns an [MutableListBuffer] that wraps the original list.
*/
public inline fun <reified T> MutableList<T>.asMutableBuffer(): MutableListBuffer<T> = MutableListBuffer(
safeTypeOf(),
this
)
public fun <T> MutableList<T>.asMutableBuffer(): MutableListBuffer<T> = MutableListBuffer(this)

View File

@ -61,35 +61,41 @@ public interface MutableBuffer<T> : Buffer<T> {
*/
public inline fun float(size: Int, initializer: (Int) -> Float): Float32Buffer =
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> MutableBuffer(type: SafeType<T>, size: Int, initializer: (Int) -> T): MutableBuffer<T> =
@Suppress("UNCHECKED_CAST")
public inline fun <T> auto(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))
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> MutableBuffer(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
MutableBuffer(safeTypeOf<T>(), size, initializer)
public inline fun <reified T> auto(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
auto(safeTypeOf<T>(), size, initializer)
}
}
public sealed interface PrimitiveBuffer<T> : MutableBuffer<T>

View File

@ -40,7 +40,7 @@ class DoubleLUSolverTest {
//Check 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

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)

View File

@ -4,7 +4,7 @@
*/
package space.kscience.kmath.integration
import space.kscience.attributes.TypedAttributesBuilder
import space.kscience.attributes.AttributesBuilder
import space.kscience.kmath.UnstableKMathAPI
import space.kscience.kmath.operations.Field
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 (points, weights) = buildRule(integrand)
var res: T = zero
var res = zero
var c = zero
for (i in points.indices) {
val x = points[i]
@ -67,8 +67,8 @@ public class GaussIntegrator<T : Any>(
c = t - res - y
res = t
}
return integrand.withAttributes {
IntegrandValue(res)
return integrand.modify {
value(res)
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.
*/
@UnstableKMathAPI
public inline fun <reified T : Any> GaussIntegrator<T>.integrate(
public fun <T : Any> GaussIntegrator<T>.integrate(
range: ClosedRange<Double>,
order: Int = 10,
intervals: Int = 10,
attributesBuilder: TypedAttributesBuilder<UnivariateIntegrand<T>>.() -> Unit,
noinline function: (Double) -> T,
attributesBuilder: AttributesBuilder.() -> Unit,
function: (Double) -> T,
): UnivariateIntegrand<T> {
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" }
@ -102,8 +102,8 @@ public inline fun <reified T : Any> GaussIntegrator<T>.integrate(
val ranges = UnivariateIntegrandRanges(
(0 until intervals).map { i -> (range.start + rangeSize * i)..(range.start + rangeSize * (i + 1)) to order }
)
return integrate(
UnivariateIntegrand<T>(
return process(
UnivariateIntegrand(
attributeBuilder = {
IntegrationRange(range)
GaussIntegratorRuleFactory(GaussLegendreRuleFactory)

View File

@ -5,7 +5,10 @@
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>
@ -13,10 +16,9 @@ public interface Integrand<T> : AttributeContainer {
public val type: SafeType<T>
/**
* Create a copy of this integrand with a new set of attributes
*/
public fun withAttributes(attributes: Attributes): Integrand<T>
public fun modify(block: AttributesBuilder.() -> Unit): Integrand<T>
public fun <A : Any> withAttribute(attribute: Attribute<A>, value: A): Integrand<T>
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)
}

View File

@ -8,9 +8,9 @@ package space.kscience.kmath.integration
/**
* 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.
*/
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,
) : Integrand<T> {
override fun withAttributes(attributes: Attributes): MultivariateIntegrand<T> =
MultivariateIntegrand(type, attributes, function)
override fun modify(block: AttributesBuilder.() -> Unit): MultivariateIntegrand<T> =
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(
attributeBuilder: TypedAttributesBuilder<MultivariateIntegrand<T>>.() -> Unit,
attributeBuilder: AttributesBuilder.() -> Unit,
noinline function: (Point<T>) -> T,
): MultivariateIntegrand<T> = MultivariateIntegrand(safeTypeOf<T>(), Attributes(attributeBuilder), function)

View File

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

View File

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

View File

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

View File

@ -6,26 +6,16 @@
package space.kscience.kmath.geometry.euclidean2d
import kotlinx.serialization.Serializable
import space.kscience.kmath.geometry.Vector2D
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
*/
@Serializable
public data class Float64Circle2D(
@Serializable(Float64Space2D.VectorSerializer::class) override val center: Float64Vector2D,
override val radius: Double
): Circle2D<Double>
public fun Circle2D(center: Float64Vector2D, radius: Double): Circle2D<Double> = Float64Circle2D(center, radius)
public data class Circle2D(
@Serializable(Float64Space2D.VectorSerializer::class) public val center: DoubleVector2D,
public val radius: Double,
)
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.linear.Float64LinearSpace
import space.kscience.kmath.operations.Float64Field
import space.kscience.kmath.operations.ScaleOperations
import kotlin.math.pow
import kotlin.math.sqrt
@ -29,7 +28,9 @@ public val Vector2D<Double>.r: Double get() = Float64Space2D.norm(this)
/**
* 2D Euclidean space
*/
public object Float64Space2D : GeometrySpace<DoubleVector2D>, ScaleOperations<DoubleVector2D> {
public object Float64Space2D : GeometrySpace<DoubleVector2D, Double> {
public val linearSpace: Float64LinearSpace = Float64LinearSpace
@Serializable
@SerialName("Float64Vector2D")
@ -71,6 +72,4 @@ public object Float64Space2D : GeometrySpace<DoubleVector2D>, ScaleOperations<Do
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

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,
): UniformHistogramGroupND<V, A> = UniformHistogramGroupND(
valueAlgebraND,
DoubleBuffer(
ListBuffer(
ranges
.map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
.map(ClosedFloatingPointRange<Double>::start)
),
DoubleBuffer(
ListBuffer(
ranges
.map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
.map(ClosedFloatingPointRange<Double>::endInclusive)

View File

@ -15,6 +15,3 @@ readme {
An API and basic implementation for arranging objects in a continuous memory block.
""".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
import kotlin.experimental.ExperimentalNativeApi
@PublishedApi
internal class NativeMemory(
val array: ByteArray,
@ -28,7 +26,6 @@ internal class NativeMemory(
return NativeMemory(copy)
}
@OptIn(ExperimentalNativeApi::class)
private val reader: MemoryReader = object : MemoryReader {
override val memory: Memory get() = this@NativeMemory
@ -51,7 +48,6 @@ internal class NativeMemory(
override fun reader(): MemoryReader = reader
@OptIn(ExperimentalNativeApi::class)
private val writer: MemoryWriter = object : MemoryWriter {
override val memory: Memory get() = this@NativeMemory

View File

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

View File

@ -310,11 +310,7 @@ internal fun DoubleTensorAlgebra.svdHelper(
}
}
internal fun MutableStructure2D<Double>.svdGolubKahanHelper(
u: MutableStructure2D<Double>, w: BufferedTensor<Double>,
v: MutableStructure2D<Double>, iterations: Int, epsilon: Double,
) {
fun pythag(a: Double, b: Double): Double {
private fun pythag(a: Double, b: Double): Double {
val at: Double = abs(a)
val bt: Double = abs(b)
val ct: Double
@ -327,9 +323,19 @@ internal fun MutableStructure2D<Double>.svdGolubKahanHelper(
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(
u: MutableStructure2D<Double>, w: BufferedTensor<Double>,
v: MutableStructure2D<Double>, iterations: Int, epsilon: Double,
) {
val shape = this.shape
val m = shape.component1()
val n = shape.component2()
@ -547,7 +553,7 @@ internal fun MutableStructure2D<Double>.svdGolubKahanHelper(
h = rv1[k]
f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y)
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
s = 1.0
@ -557,7 +563,7 @@ internal fun MutableStructure2D<Double>.svdGolubKahanHelper(
g = rv1[i]
y = wBuffer[wStart + i]
h = s * g
g *= c
g = c * g
z = pythag(f, h)
rv1[j] = z
c = f / z