0.4 WIP
This commit is contained in:
parent
ea887b8c72
commit
46eacbb750
@ -3,10 +3,11 @@
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
- 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
|
||||
- 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.
|
||||
|
||||
### Changed
|
||||
- Default naming for algebra and buffers now uses IntXX/FloatXX notation instead of Java types.
|
||||
|
@ -16,7 +16,7 @@ import kotlin.reflect.typeOf
|
||||
* @param kType raw [KType]
|
||||
*/
|
||||
@JvmInline
|
||||
public value class SafeType<T> @PublishedApi internal constructor(public val kType: KType)
|
||||
public value class SafeType<out T> @PublishedApi internal constructor(public val kType: KType)
|
||||
|
||||
public inline fun <reified T> safeTypeOf(): SafeType<T> = SafeType(typeOf<T>())
|
||||
|
||||
|
@ -52,10 +52,10 @@ public interface XYColumnarData<out T, out X : T, out Y : T> : ColumnarData<T> {
|
||||
* Create two-column data from a list of row-objects (zero-copy)
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <I, T, X : T, Y : T> ofList(
|
||||
public inline fun <I, T, reified X : T, reified Y : T> ofList(
|
||||
list: List<I>,
|
||||
xConverter: (I) -> X,
|
||||
yConverter: (I) -> Y,
|
||||
noinline xConverter: (I) -> X,
|
||||
noinline yConverter: (I) -> Y,
|
||||
): XYColumnarData<T, X, Y> = object : XYColumnarData<T, X, Y> {
|
||||
override val size: Int get() = list.size
|
||||
|
||||
|
@ -13,8 +13,6 @@ 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.
|
||||
@ -84,6 +82,8 @@ 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.
|
||||
*
|
||||
|
@ -6,6 +6,7 @@
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
@ -17,6 +18,8 @@ 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.
|
||||
*/
|
||||
@ -49,6 +52,7 @@ 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> =
|
||||
|
@ -7,11 +7,14 @@ 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)
|
||||
@ -27,6 +30,9 @@ 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)
|
||||
@ -57,7 +63,11 @@ 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)
|
||||
@ -87,7 +97,11 @@ 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)
|
||||
@ -117,7 +131,11 @@ 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)
|
||||
@ -164,6 +182,9 @@ 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) {
|
||||
@ -176,7 +197,7 @@ public object MstLogicAlgebra : LogicAlgebra<MST> {
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -5,9 +5,11 @@
|
||||
|
||||
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
|
||||
@ -30,9 +32,10 @@ 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].
|
||||
*/
|
||||
@ -49,19 +52,23 @@ 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()
|
||||
return variables.map(::derivative).asBuffer(type)
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents field in context of which functions can be derived.
|
||||
* Represents field. Function derivatives could be computed in this field
|
||||
*/
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
public open class SimpleAutoDiffField<T : Any, F : Field<T>>(
|
||||
public val context: F,
|
||||
public val algebra: F,
|
||||
bindings: Map<Symbol, T>,
|
||||
) : Field<AutoDiffValue<T>>, ExpressionAlgebra<T, AutoDiffValue<T>>, NumbersAddOps<AutoDiffValue<T>> {
|
||||
override val zero: AutoDiffValue<T> get() = const(context.zero)
|
||||
override val one: AutoDiffValue<T> get() = const(context.one)
|
||||
|
||||
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)
|
||||
|
||||
// this stack contains pairs of blocks and values to apply them to
|
||||
private var stack: Array<Any?> = arrayOfNulls<Any?>(8)
|
||||
@ -69,7 +76,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, context.zero)
|
||||
it.key.identity to AutoDiffVariableWithDerivative(it.key.identity, it.value, algebra.zero)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,7 +99,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] ?: context.zero
|
||||
(variable as? AutoDiffVariableWithDerivative)?.d ?: derivatives[variable] ?: algebra.zero
|
||||
|
||||
private fun setDerivative(variable: AutoDiffValue<T>, value: T) {
|
||||
if (variable is AutoDiffVariableWithDerivative) variable.d = value else derivatives[variable] = value
|
||||
@ -103,7 +110,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
|
||||
context.block(value)
|
||||
algebra.block(value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +137,6 @@ 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)
|
||||
@ -142,9 +148,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 = context.one // computing derivative w.r.t result
|
||||
result.d = algebra.one // computing derivative w.r.t result
|
||||
runBackwardPass()
|
||||
return DerivationResult(result.value, bindings.mapValues { it.value.d }, context)
|
||||
return DerivationResult(result.value, algebra.type, bindings.mapValues { it.value.d }, algebra)
|
||||
}
|
||||
|
||||
// // Overloads for Double constants
|
||||
@ -194,7 +200,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(context.block())
|
||||
return const(algebra.block())
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,10 +10,9 @@ 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.
|
||||
@ -34,7 +33,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>
|
||||
public interface MatrixOperations<T> : WithType<T>
|
||||
|
||||
/**
|
||||
* Basic operations on matrices and vectors.
|
||||
@ -45,6 +44,8 @@ public interface MatrixOperations<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.
|
||||
*/
|
||||
@ -212,4 +213,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(size, 1) { i, _ -> get(i) }
|
||||
public fun <T : Any> Point<T>.asMatrix(): VirtualMatrix<T> = VirtualMatrix(type, size, 1) { i, _ -> get(i) }
|
@ -22,11 +22,27 @@ 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 data class LupDecomposition<T>(
|
||||
public class LupDecomposition<T>(
|
||||
public val linearSpace: LinearSpace<T, Ring<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>>) :
|
||||
@ -168,7 +184,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(rowNum, colNum) { i, j ->
|
||||
val l: MatrixWrapper<T> = VirtualMatrix(type, rowNum, colNum) { i, j ->
|
||||
when {
|
||||
j < i -> lu[i, j]
|
||||
j == i -> one
|
||||
@ -176,7 +192,7 @@ public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
|
||||
}
|
||||
}.withAttribute(LowerTriangular)
|
||||
|
||||
val u = VirtualMatrix(rowNum, colNum) { i, j ->
|
||||
val u = VirtualMatrix(type, rowNum, colNum) { i, j ->
|
||||
if (j >= i) lu[i, j] else zero
|
||||
}.withAttribute(UpperTriangular)
|
||||
//
|
||||
@ -184,7 +200,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(l, u, pivot.asBuffer())
|
||||
return LupDecomposition(this@lup, l, u, pivot.asBuffer())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,16 +6,21 @@
|
||||
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.MutableBuffer
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
|
||||
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] }
|
||||
@ -61,7 +66,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, MutableBuffer.Companion::boxing)) {
|
||||
return with(BufferAccessor2D<T?>(rows, rows, MutableBufferFactory(type))) {
|
||||
val cache = factory(rows * rows) { null }
|
||||
linearSpace.buildMatrix(rows, rows) { i, j ->
|
||||
val cached = cache[i, j]
|
||||
|
@ -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(rows, columns) { i, j ->
|
||||
): MatrixWrapper<T> = VirtualMatrix(type, 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(rows, columns) { _, _ ->
|
||||
): MatrixWrapper<T> = VirtualMatrix(type, rows, columns) { _, _ ->
|
||||
elementAlgebra.zero
|
||||
}.withAttribute(IsZero)
|
||||
|
@ -6,10 +6,14 @@
|
||||
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]
|
||||
|
@ -6,6 +6,7 @@
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.attributes.Attributes
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.kmath.nd.ShapeND
|
||||
|
||||
|
||||
@ -14,7 +15,8 @@ import space.kscience.kmath.nd.ShapeND
|
||||
*
|
||||
* @property generator the function that provides elements.
|
||||
*/
|
||||
public class VirtualMatrix<out T : Any>(
|
||||
public class VirtualMatrix<out T>(
|
||||
override val type: SafeType<T>,
|
||||
override val rowNum: Int,
|
||||
override val colNum: Int,
|
||||
override val attributes: Attributes = Attributes.EMPTY,
|
||||
@ -29,4 +31,4 @@ public class VirtualMatrix<out T : Any>(
|
||||
public fun <T : Any> MatrixBuilder<T, *>.virtual(
|
||||
attributes: Attributes = Attributes.EMPTY,
|
||||
generator: (i: Int, j: Int) -> T,
|
||||
): VirtualMatrix<T> = VirtualMatrix(rows, columns, attributes, generator)
|
||||
): VirtualMatrix<T> = VirtualMatrix(type, rows, columns, attributes, generator)
|
||||
|
@ -3,13 +3,11 @@
|
||||
* 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
|
||||
|
||||
/**
|
||||
@ -51,9 +49,11 @@ public val <T> MatrixOperations<T>.Inverted: Inverted<T> get() = Inverted(safeTy
|
||||
*
|
||||
* @param T the type of matrices' items.
|
||||
*/
|
||||
public class Determinant<T> : MatrixAttribute<T>
|
||||
public class Determinant<T>(type: SafeType<T>) :
|
||||
PolymorphicAttribute<T>(type),
|
||||
MatrixAttribute<T>
|
||||
|
||||
public val <T> MatrixOperations<T>.Determinant: Determinant<T> get() = Determinant()
|
||||
public val <T> MatrixOperations<T>.Determinant: Determinant<T> get() = Determinant(type)
|
||||
|
||||
/**
|
||||
* Matrices with this feature are lower triangular ones.
|
||||
|
@ -4,6 +4,8 @@
|
||||
*/
|
||||
|
||||
|
||||
@file:OptIn(UnstableKMathAPI::class)
|
||||
|
||||
package space.kscience.kmath.misc
|
||||
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
@ -22,10 +24,9 @@ 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(size) { this[permutations[it]] }
|
||||
return VirtualBuffer(type, size) { this[permutations[it]] }
|
||||
}
|
||||
|
||||
@UnstableKMathAPI
|
||||
@ -35,30 +36,27 @@ 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(size) { this[permutations[it]] }
|
||||
return VirtualBuffer(type, 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(size) { this[permutations[it]] }
|
||||
return VirtualBuffer(type, 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(size) { this[permutations[it]] }
|
||||
return VirtualBuffer(type, size) { this[permutations[it]] }
|
||||
}
|
||||
|
||||
@UnstableKMathAPI
|
||||
@ -68,10 +66,9 @@ 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(size) { this[permutations[it]] }
|
||||
return VirtualBuffer(type,size) { this[permutations[it]] }
|
||||
}
|
||||
|
||||
private fun <V> Buffer<V>.permSortIndicesWith(comparator: Comparator<Int>): IntArray {
|
||||
|
@ -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 kotlin.reflect.KClass
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
|
||||
/**
|
||||
* The base interface for all ND-algebra implementations.
|
||||
@ -91,6 +91,8 @@ 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.
|
||||
*
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
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.*
|
||||
@ -105,6 +107,9 @@ 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 }
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
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
|
||||
@ -23,6 +24,8 @@ 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)]
|
||||
|
||||
@ -36,7 +39,7 @@ public open class BufferND<out T>(
|
||||
*/
|
||||
public inline fun <reified T> BufferND(
|
||||
shape: ShapeND,
|
||||
bufferFactory: BufferFactory<T> = BufferFactory.auto<T>(),
|
||||
bufferFactory: BufferFactory<T> = BufferFactory<T>(),
|
||||
crossinline initializer: (IntArray) -> T,
|
||||
): BufferND<T> {
|
||||
val strides = Strides(shape)
|
||||
@ -84,10 +87,10 @@ public open class MutableBufferND<T>(
|
||||
/**
|
||||
* Create a generic [BufferND] using provided [initializer]
|
||||
*/
|
||||
public fun <T> MutableBufferND(
|
||||
public inline fun <reified T> MutableBufferND(
|
||||
shape: ShapeND,
|
||||
bufferFactory: MutableBufferFactory<T> = MutableBufferFactory.boxing(),
|
||||
initializer: (IntArray) -> T,
|
||||
bufferFactory: MutableBufferFactory<T> = MutableBufferFactory(),
|
||||
crossinline initializer: (IntArray) -> T,
|
||||
): MutableBufferND<T> {
|
||||
val strides = Strides(shape)
|
||||
return MutableBufferND(strides, bufferFactory(strides.linearSize) { initializer(strides.index(it)) })
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package space.kscience.kmath.nd
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.kmath.PerformancePitfall
|
||||
|
||||
|
||||
@ -13,6 +14,8 @@ 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
|
||||
|
||||
@ -32,6 +35,7 @@ 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) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
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
|
||||
@ -46,6 +47,9 @@ 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]
|
||||
|
||||
@ -60,6 +64,9 @@ 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]
|
||||
|
||||
@ -79,7 +86,7 @@ private class MutableStructure1DWrapper<T>(val structure: MutableStructureND<T>)
|
||||
.elements()
|
||||
.map(Pair<IntArray, T>::second)
|
||||
.toMutableList()
|
||||
.asMutableBuffer()
|
||||
.asMutableBuffer(type)
|
||||
|
||||
override fun toString(): String = Buffer.toString(this)
|
||||
}
|
||||
@ -90,6 +97,9 @@ 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
|
||||
|
||||
@ -102,6 +112,9 @@ 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
|
||||
|
||||
|
@ -6,13 +6,12 @@
|
||||
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.
|
||||
@ -33,18 +32,18 @@ public interface Structure2D<out T> : StructureND<T> {
|
||||
override val shape: ShapeND get() = ShapeND(rowNum, colNum)
|
||||
|
||||
/**
|
||||
* The buffer of rows of this structure. It gets elements from the structure dynamically.
|
||||
* The buffer of rows for this structure. It gets elements from the structure dynamically.
|
||||
*/
|
||||
@PerformancePitfall
|
||||
public val rows: List<Buffer<T>>
|
||||
get() = List(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } }
|
||||
get() = List(rowNum) { i -> VirtualBuffer(type, colNum) { j -> get(i, j) } }
|
||||
|
||||
/**
|
||||
* The buffer of columns of this structure. It gets elements from the structure dynamically.
|
||||
* The buffer of columns for this structure. It gets elements from the structure dynamically.
|
||||
*/
|
||||
@PerformancePitfall
|
||||
public val columns: List<Buffer<T>>
|
||||
get() = List(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } }
|
||||
get() = List(colNum) { j -> VirtualBuffer(type, rowNum) { i -> get(i, j) } }
|
||||
|
||||
/**
|
||||
* Retrieves an element from the structure by two indices.
|
||||
@ -88,14 +87,14 @@ public interface MutableStructure2D<T> : Structure2D<T>, MutableStructureND<T> {
|
||||
*/
|
||||
@PerformancePitfall
|
||||
override val rows: List<MutableBuffer<T>>
|
||||
get() = List(rowNum) { i -> MutableListBuffer(colNum) { j -> get(i, j) } }
|
||||
get() = List(rowNum) { i -> MutableBuffer(type, colNum) { j -> get(i, j) } }
|
||||
|
||||
/**
|
||||
* The buffer of columns of this structure. It gets elements from the structure dynamically.
|
||||
* The buffer of columns for this structure. It gets elements from the structure dynamically.
|
||||
*/
|
||||
@PerformancePitfall
|
||||
override val columns: List<MutableBuffer<T>>
|
||||
get() = List(colNum) { j -> MutableListBuffer(rowNum) { i -> get(i, j) } }
|
||||
get() = List(colNum) { j -> MutableBuffer(type, rowNum) { i -> get(i, j) } }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,6 +102,9 @@ 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]
|
||||
@ -122,6 +124,9 @@ 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]
|
||||
|
@ -12,6 +12,7 @@ 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
|
||||
@ -28,9 +29,9 @@ public interface StructureAttribute<T> : Attribute<T>
|
||||
*
|
||||
* @param T the type of items.
|
||||
*/
|
||||
public interface StructureND<out T> : AttributeContainer, WithShape {
|
||||
public interface StructureND<out T> : AttributeContainer, WithShape, WithType<T> {
|
||||
/**
|
||||
* The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions of
|
||||
* The shape of structure i.e., non-empty sequence of non-negative integers that specify sizes of dimensions for
|
||||
* this structure.
|
||||
*/
|
||||
override val shape: ShapeND
|
||||
@ -117,57 +118,61 @@ public interface StructureND<out T> : AttributeContainer, WithShape {
|
||||
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.
|
||||
*/
|
||||
|
@ -5,10 +5,13 @@
|
||||
|
||||
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> {
|
||||
@ -24,10 +27,10 @@ public open class VirtualStructureND<T>(
|
||||
public class VirtualDoubleStructureND(
|
||||
shape: ShapeND,
|
||||
producer: (IntArray) -> Double,
|
||||
) : VirtualStructureND<Double>(shape, producer)
|
||||
) : VirtualStructureND<Double>(safeTypeOf(), shape, producer)
|
||||
|
||||
@UnstableKMathAPI
|
||||
public class VirtualIntStructureND(
|
||||
shape: ShapeND,
|
||||
producer: (IntArray) -> Int,
|
||||
) : VirtualStructureND<Int>(shape, producer)
|
||||
) : VirtualStructureND<Int>(safeTypeOf(), shape, producer)
|
@ -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(shape) { index ->
|
||||
return VirtualStructureND(type, 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(shape) { index ->
|
||||
return VirtualStructureND(type, shape) { index ->
|
||||
val newIndex: IntArray = IntArray(index.size) { indexAxis ->
|
||||
val offset = axisMap[indexAxis] ?: 0
|
||||
(index[indexAxis] + offset).mod(shape[indexAxis])
|
||||
|
@ -5,22 +5,32 @@
|
||||
|
||||
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
|
||||
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.
|
||||
*
|
||||
* @param T the type of element which Algebra operates on.
|
||||
*/
|
||||
public interface Algebra<T> {
|
||||
public interface Algebra<T> : WithType<T> {
|
||||
/**
|
||||
* Provide a factory for buffers, associated with this [Algebra]
|
||||
*/
|
||||
public val bufferFactory: MutableBufferFactory<T> get() = MutableBufferFactory.boxing()
|
||||
public val bufferFactory: MutableBufferFactory<T>
|
||||
|
||||
override val type: SafeType<T> get() = bufferFactory.type
|
||||
|
||||
/**
|
||||
* Wraps a raw string to [T] object. This method is designed for three purposes:
|
||||
@ -265,7 +275,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].
|
||||
*
|
||||
@ -348,7 +358,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].
|
||||
*
|
||||
@ -361,7 +371,11 @@ 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())
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
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
|
||||
@ -26,6 +28,9 @@ 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
|
||||
|
||||
@ -528,10 +533,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.boxing(size, initializer)
|
||||
Buffer(size, initializer)
|
||||
|
||||
public inline fun BigInt.Companion.mutableBuffer(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> =
|
||||
Buffer.boxing(size, initializer)
|
||||
Buffer(size, initializer)
|
||||
|
||||
public val BigIntField.nd: BufferedRingOpsND<BigInt, BigIntField>
|
||||
get() = BufferedRingOpsND(BufferRingOps(BigIntField))
|
||||
|
@ -5,10 +5,11 @@
|
||||
|
||||
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
|
||||
@ -20,6 +21,8 @@ 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> {
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
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
|
||||
|
||||
@ -72,6 +74,8 @@ 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
|
||||
|
@ -8,7 +8,10 @@ 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.*
|
||||
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 kotlin.math.roundToInt
|
||||
import kotlin.math.roundToLong
|
||||
|
||||
@ -22,7 +25,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(::Int16Buffer)
|
||||
override val bufferFactory: MutableBufferFactory<Int16> = MutableBufferFactory<Int16>()
|
||||
override val zero: Int16 get() = 0
|
||||
override val one: Int16 get() = 1
|
||||
|
||||
@ -45,7 +48,8 @@ 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(::Int32Buffer)
|
||||
override val bufferFactory: MutableBufferFactory<Int> = MutableBufferFactory()
|
||||
|
||||
override val zero: Int get() = 0
|
||||
override val one: Int get() = 1
|
||||
|
||||
@ -68,7 +72,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(::Int64Buffer)
|
||||
override val bufferFactory: MutableBufferFactory<Int64> = MutableBufferFactory()
|
||||
override val zero: Int64 get() = 0L
|
||||
override val one: Int64 get() = 1L
|
||||
|
||||
|
@ -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(::Float64Buffer)
|
||||
override val bufferFactory: MutableBufferFactory<Double> = MutableBufferFactory()
|
||||
|
||||
override val zero: Double get() = 0.0
|
||||
override val one: Double get() = 1.0
|
||||
|
@ -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,35 +17,46 @@ import kotlin.reflect.typeOf
|
||||
*
|
||||
* @param T the type of buffer.
|
||||
*/
|
||||
public fun interface BufferFactory<T> {
|
||||
public interface BufferFactory<T> : WithType<T> {
|
||||
|
||||
public operator fun invoke(size: Int, builder: (Int) -> T): Buffer<T>
|
||||
|
||||
public companion object{
|
||||
public inline fun <reified T> auto(): BufferFactory<T> =
|
||||
BufferFactory(Buffer.Companion::auto)
|
||||
|
||||
public fun <T> boxing(): BufferFactory<T> =
|
||||
BufferFactory(Buffer.Companion::boxing)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create [BufferFactory] using the reified type
|
||||
*/
|
||||
public inline fun <reified T> BufferFactory(): BufferFactory<T> = BufferFactory(safeTypeOf())
|
||||
|
||||
/**
|
||||
* Function that produces [MutableBuffer] from its size and function that supplies values.
|
||||
*
|
||||
* @param T the type of buffer.
|
||||
*/
|
||||
public fun interface MutableBufferFactory<T> : BufferFactory<T> {
|
||||
public interface MutableBufferFactory<T> : BufferFactory<T> {
|
||||
override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer<T>
|
||||
|
||||
public companion object {
|
||||
public inline fun <reified T : Any> auto(): MutableBufferFactory<T> =
|
||||
MutableBufferFactory(MutableBuffer.Companion::auto)
|
||||
|
||||
public fun <T> boxing(): MutableBufferFactory<T> =
|
||||
MutableBufferFactory(MutableBuffer.Companion::boxing)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create [BufferFactory] using the reified type
|
||||
*/
|
||||
public inline fun <reified T> MutableBufferFactory(): MutableBufferFactory<T> = MutableBufferFactory(safeTypeOf())
|
||||
|
||||
/**
|
||||
* A generic read-only random-access structure for both primitives and objects.
|
||||
*
|
||||
@ -53,14 +64,14 @@ public fun interface MutableBufferFactory<T> : BufferFactory<T> {
|
||||
*
|
||||
* @param T the type of elements contained in the buffer.
|
||||
*/
|
||||
public interface Buffer<out T> : WithSize {
|
||||
public interface Buffer<out T> : WithSize, WithType<T> {
|
||||
/**
|
||||
* The size of this buffer.
|
||||
*/
|
||||
override val size: Int
|
||||
|
||||
/**
|
||||
* Gets element at given index.
|
||||
* Gets an element at given index.
|
||||
*/
|
||||
public operator fun get(index: Int): T
|
||||
|
||||
@ -87,41 +98,48 @@ public interface Buffer<out T> : WithSize {
|
||||
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]. 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): 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 -> 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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an [IntRange] of the valid indices for this [Buffer].
|
||||
*/
|
||||
@ -144,28 +162,17 @@ 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 single element from the buffer.
|
||||
* Useful when one needs a single element from the buffer.
|
||||
*
|
||||
* @param T the type of elements provided by the buffer.
|
||||
*/
|
||||
public class VirtualBuffer<out T>(override val size: Int, private val generator: (Int) -> T) : Buffer<T> {
|
||||
public class VirtualBuffer<out T>(
|
||||
override val type: SafeType<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)
|
||||
@ -177,6 +184,9 @@ public class VirtualBuffer<out T>(override val size: Int, private val generator:
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this buffer to read-only buffer.
|
||||
* Inline builder for [VirtualBuffer]
|
||||
*/
|
||||
public fun <T> Buffer<T>.asReadOnly(): Buffer<T> = if (this is MutableBuffer) ReadOnlyBuffer(this) else this
|
||||
public inline fun <reified T> VirtualBuffer(
|
||||
size: Int,
|
||||
noinline generator: (Int) -> T,
|
||||
): VirtualBuffer<T> = VirtualBuffer(safeTypeOf(), size, generator)
|
||||
|
@ -5,7 +5,13 @@
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.kmath.nd.*
|
||||
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
|
||||
|
||||
/**
|
||||
* A context that allows to operate on a [MutableBuffer] as on 2d array
|
||||
@ -27,11 +33,13 @@ 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> = StructureND.buffered(
|
||||
ColumnStrides(ShapeND(rowNum, colNum))
|
||||
fun MutableBuffer<T>.toStructure2D(): Structure2D<T> = BufferND(
|
||||
type, 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]
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
import kotlin.experimental.and
|
||||
|
||||
/**
|
||||
@ -57,6 +59,9 @@ 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" }
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
/**
|
||||
@ -15,6 +17,9 @@ 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]
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
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
|
||||
|
||||
@ -15,6 +17,9 @@ 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]
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
/**
|
||||
@ -14,6 +16,8 @@ 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]
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
/**
|
||||
@ -14,6 +16,9 @@ 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]
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
/**
|
||||
@ -14,6 +16,9 @@ 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]
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
/**
|
||||
@ -14,6 +16,9 @@ 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]
|
||||
|
@ -5,7 +5,8 @@
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import kotlin.jvm.JvmInline
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
|
||||
/**
|
||||
* [Buffer] implementation over [List].
|
||||
@ -13,9 +14,7 @@ import kotlin.jvm.JvmInline
|
||||
* @param T the type of elements contained in the buffer.
|
||||
* @property list The underlying list.
|
||||
*/
|
||||
public class ListBuffer<T>(public val list: List<T>) : Buffer<T> {
|
||||
|
||||
public constructor(size: Int, initializer: (Int) -> T) : this(List(size, initializer))
|
||||
public class ListBuffer<T>(override val type: SafeType<T>, public val list: List<T>) : Buffer<T> {
|
||||
|
||||
override val size: Int get() = list.size
|
||||
|
||||
@ -29,7 +28,12 @@ public class ListBuffer<T>(public val list: List<T>) : Buffer<T> {
|
||||
/**
|
||||
* Returns an [ListBuffer] that wraps the original list.
|
||||
*/
|
||||
public fun <T> List<T>.asBuffer(): ListBuffer<T> = ListBuffer(this)
|
||||
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())
|
||||
|
||||
/**
|
||||
* [MutableBuffer] implementation over [MutableList].
|
||||
@ -37,10 +41,7 @@ public fun <T> List<T>.asBuffer(): ListBuffer<T> = ListBuffer(this)
|
||||
* @param T the type of elements contained in the buffer.
|
||||
* @property list The underlying list.
|
||||
*/
|
||||
@JvmInline
|
||||
public value class MutableListBuffer<T>(public val list: MutableList<T>) : MutableBuffer<T> {
|
||||
|
||||
public constructor(size: Int, initializer: (Int) -> T) : this(MutableList(size, initializer))
|
||||
public class MutableListBuffer<T>(override val type: SafeType<T>, public val list: MutableList<T>) : MutableBuffer<T> {
|
||||
|
||||
override val size: Int get() = list.size
|
||||
|
||||
@ -51,10 +52,24 @@ public value class MutableListBuffer<T>(public val list: MutableList<T>) : Mutab
|
||||
}
|
||||
|
||||
override operator fun iterator(): Iterator<T> = list.iterator()
|
||||
override fun copy(): MutableBuffer<T> = MutableListBuffer(ArrayList(list))
|
||||
override fun copy(): MutableBuffer<T> = MutableListBuffer(type, ArrayList(list))
|
||||
|
||||
override fun toString(): String = Buffer.toString(this)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an [MutableListBuffer] that wraps the original list.
|
||||
*/
|
||||
public fun <T> MutableList<T>.asMutableBuffer(): MutableListBuffer<T> = MutableListBuffer(this)
|
||||
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
|
||||
)
|
||||
|
@ -61,41 +61,35 @@ 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> 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>
|
@ -40,7 +40,7 @@ class DoubleLUSolverTest {
|
||||
//Check determinant
|
||||
assertEquals(7.0, lup.determinant)
|
||||
|
||||
assertMatrixEquals(lup.p dot matrix, lup.l dot lup.u)
|
||||
assertMatrixEquals(lup.pivotMatrix dot matrix, lup.l dot lup.u)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -19,19 +19,13 @@ import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC
|
||||
import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC
|
||||
import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC
|
||||
import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.linear.*
|
||||
import space.kscience.kmath.linear.Matrix
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.StructureFeature
|
||||
import space.kscience.kmath.structures.Float64
|
||||
import space.kscience.kmath.structures.Float32
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.Float32Field
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.FloatField
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.structures.Float64Buffer
|
||||
import space.kscience.kmath.structures.Float32Buffer
|
||||
import space.kscience.kmath.structures.DoubleBuffer
|
||||
import space.kscience.kmath.structures.FloatBuffer
|
||||
import kotlin.reflect.KClass
|
||||
|
@ -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,
|
||||
ListBuffer(
|
||||
DoubleBuffer(
|
||||
ranges
|
||||
.map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
|
||||
.map(ClosedFloatingPointRange<Double>::start)
|
||||
),
|
||||
ListBuffer(
|
||||
DoubleBuffer(
|
||||
ranges
|
||||
.map(Pair<ClosedFloatingPointRange<Double>, Int>::first)
|
||||
.map(ClosedFloatingPointRange<Double>::endInclusive)
|
||||
|
Loading…
Reference in New Issue
Block a user