0.4 WIP
This commit is contained in:
parent
46eacbb750
commit
2386ecba41
@ -106,4 +106,11 @@ public fun <T : Any, A : Attribute<T>> Attributes(
|
||||
attrValue: T,
|
||||
): Attributes = Attributes(mapOf(attribute to attrValue))
|
||||
|
||||
/**
|
||||
* Create Attributes with a single [Unit] valued attribute
|
||||
*/
|
||||
public fun <A : Attribute<Unit>> Attributes(
|
||||
attribute: A
|
||||
): Attributes = Attributes(mapOf(attribute to Unit))
|
||||
|
||||
public operator fun Attributes.plus(other: Attributes): Attributes = Attributes(content + other.content)
|
@ -26,3 +26,10 @@ public inline fun <reified T> safeTypeOf(): SafeType<T> = SafeType(typeOf<T>())
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@UnstableAttributesAPI
|
||||
public val <T> SafeType<T>.kClass: KClass<T & Any> get() = kType.classifier as KClass<T & Any>
|
||||
|
||||
/**
|
||||
* An interface containing [type] for dynamic type checking.
|
||||
*/
|
||||
public interface WithType<out T> {
|
||||
public val type: SafeType<T>
|
||||
}
|
@ -47,7 +47,7 @@ internal class MatrixInverseBenchmark {
|
||||
@Benchmark
|
||||
fun ejmlInverse(blackhole: Blackhole) {
|
||||
EjmlLinearSpaceDDRM {
|
||||
blackhole.consume(matrix.toEjml().inverse())
|
||||
blackhole.consume(matrix.toEjml().inverted())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import space.kscience.kmath.complex.ComplexField
|
||||
import space.kscience.kmath.expressions.interpret
|
||||
import space.kscience.kmath.operations.Algebra
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@ -39,6 +40,8 @@ internal class TestParser {
|
||||
@Test
|
||||
fun evaluateMstBinary() {
|
||||
val magicalAlgebra = object : Algebra<String> {
|
||||
override val bufferFactory: MutableBufferFactory<String> get() = MutableBufferFactory()
|
||||
|
||||
override fun bindSymbolOrNull(value: String): String = value
|
||||
|
||||
override fun unaryOperationFunction(operation: String): (arg: String) -> String {
|
||||
|
@ -10,6 +10,7 @@ kscience {
|
||||
|
||||
dependencies {
|
||||
api(projects.kmathCore)
|
||||
api(projects.kmathMemory)
|
||||
}
|
||||
|
||||
testDependencies {
|
||||
|
@ -5,12 +5,14 @@
|
||||
|
||||
package space.kscience.kmath.complex
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.memory.MemoryReader
|
||||
import space.kscience.kmath.memory.MemorySpec
|
||||
import space.kscience.kmath.memory.MemoryWriter
|
||||
import space.kscience.kmath.memory.*
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.*
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.MutableBuffer
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
import kotlin.math.*
|
||||
|
||||
/**
|
||||
@ -51,8 +53,11 @@ public object ComplexField :
|
||||
Norm<Complex, Complex>,
|
||||
NumbersAddOps<Complex>,
|
||||
ScaleOperations<Complex> {
|
||||
override val bufferFactory: MutableBufferFactory<Complex> = MutableBufferFactory { size, init ->
|
||||
MutableMemoryBuffer.create(Complex, size, init)
|
||||
override val bufferFactory: MutableBufferFactory<Complex> = object : MutableBufferFactory<Complex> {
|
||||
override fun invoke(size: Int, builder: (Int) -> Complex): MutableBuffer<Complex> =
|
||||
MutableMemoryBuffer.create(Complex, size, builder)
|
||||
|
||||
override val type: SafeType<Complex> = safeTypeOf()
|
||||
}
|
||||
|
||||
override val zero: Complex = 0.0.toComplex()
|
||||
@ -202,8 +207,10 @@ public data class Complex(val re: Double, val im: Double) {
|
||||
override fun toString(): String = "($re + i * $im)"
|
||||
|
||||
public companion object : MemorySpec<Complex> {
|
||||
override val objectSize: Int
|
||||
get() = 16
|
||||
|
||||
override val type: SafeType<Complex> get() = safeTypeOf()
|
||||
|
||||
override val objectSize: Int get() = 16
|
||||
|
||||
override fun MemoryReader.read(offset: Int): Complex =
|
||||
Complex(readDouble(offset), readDouble(offset + 8))
|
||||
|
@ -5,15 +5,14 @@
|
||||
|
||||
package space.kscience.kmath.complex
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.memory.MemoryReader
|
||||
import space.kscience.kmath.memory.MemorySpec
|
||||
import space.kscience.kmath.memory.MemoryWriter
|
||||
import space.kscience.kmath.memory.*
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.MemoryBuffer
|
||||
import space.kscience.kmath.structures.MutableBuffer
|
||||
import space.kscience.kmath.structures.MutableMemoryBuffer
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
import kotlin.math.*
|
||||
|
||||
/**
|
||||
@ -37,6 +36,8 @@ public class Quaternion(
|
||||
require(!z.isNaN()) { "z-component of quaternion is not-a-number" }
|
||||
}
|
||||
|
||||
override val type: SafeType<Double> get() = safeTypeOf()
|
||||
|
||||
/**
|
||||
* Returns a string representation of this quaternion.
|
||||
*/
|
||||
@ -78,6 +79,7 @@ public class Quaternion(
|
||||
|
||||
public companion object : MemorySpec<Quaternion> {
|
||||
override val objectSize: Int get() = 32
|
||||
override val type: SafeType<Quaternion> get() = safeTypeOf()
|
||||
|
||||
override fun MemoryReader.read(offset: Int): Quaternion = Quaternion(
|
||||
readDouble(offset),
|
||||
@ -122,7 +124,7 @@ public val Quaternion.reciprocal: Quaternion
|
||||
/**
|
||||
* Produce a normalized version of this quaternion
|
||||
*/
|
||||
public fun Quaternion.normalized(): Quaternion = with(QuaternionAlgebra){ this@normalized / norm(this@normalized) }
|
||||
public fun Quaternion.normalized(): Quaternion = with(QuaternionAlgebra) { this@normalized / norm(this@normalized) }
|
||||
|
||||
/**
|
||||
* A field of [Quaternion].
|
||||
@ -131,6 +133,8 @@ public fun Quaternion.normalized(): Quaternion = with(QuaternionAlgebra){ this@n
|
||||
public object QuaternionAlgebra : Group<Quaternion>, Norm<Quaternion, Double>, PowerOperations<Quaternion>,
|
||||
ExponentialOperations<Quaternion>, NumbersAddOps<Quaternion>, ScaleOperations<Quaternion> {
|
||||
|
||||
override val bufferFactory: MutableBufferFactory<Quaternion> = MutableBufferFactory()
|
||||
|
||||
override val zero: Quaternion = Quaternion(0.0)
|
||||
public val one: Quaternion = Quaternion(1.0)
|
||||
|
||||
|
@ -9,7 +9,6 @@ kscience{
|
||||
wasm()
|
||||
|
||||
dependencies {
|
||||
api(projects.kmathMemory)
|
||||
api(projects.attributesKt)
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ public abstract class DSAlgebra<T, A : Ring<T>>(
|
||||
vararg derivatives: T,
|
||||
): DS<T, A> {
|
||||
require(derivatives.size == compiler.size) { "dimension mismatch: ${derivatives.size} and ${compiler.size}" }
|
||||
val data = derivatives.asBuffer()
|
||||
val data = derivatives.asList().asBuffer(algebra.type)
|
||||
|
||||
return DS(data)
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.WithType
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.operations.*
|
||||
|
@ -5,15 +5,12 @@
|
||||
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.kmath.PerformancePitfall
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.VirtualBuffer
|
||||
import space.kscience.kmath.structures.indices
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
|
||||
public class BufferedLinearSpace<T, out A : Ring<T>>(
|
||||
|
@ -6,11 +6,11 @@
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.WithType
|
||||
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
|
||||
|
||||
@ -173,15 +173,15 @@ public interface LinearSpace<T, out A : Ring<T>> : MatrixOperations<T> {
|
||||
public operator fun T.times(v: Point<T>): Point<T> = v * this
|
||||
|
||||
/**
|
||||
* Get an attribute value for the structure in this scope. Structure features take precedence other context features.
|
||||
* Get an attribute value for the structure in this scope. Structure attributes are preferred to computed attributes.
|
||||
*
|
||||
* @param structure the structure.
|
||||
* @param attribute to be computed.
|
||||
* @return a feature object or `null` if it isn't present.
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T, A : StructureAttribute<T>> attributeFor(structure: StructureND<*>, attribute: A): T? =
|
||||
structure.attributes[attribute]
|
||||
public fun <T, A : StructureAttribute<T>> attributeFor(structure: StructureND<*>, attribute: A): T =
|
||||
structure.attributes[attribute] ?: error("Can't compute attribute $attribute for $structure")
|
||||
|
||||
public companion object {
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.attributes.Attributes
|
||||
import space.kscience.attributes.PolymorphicAttribute
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
@ -19,32 +20,42 @@ import space.kscience.kmath.structures.*
|
||||
* *a* is the owning matrix.
|
||||
*
|
||||
* @param T the type of matrices' items.
|
||||
* @param l The lower triangular matrix in this decomposition. It may have [LowerTriangular].
|
||||
* @param u The upper triangular matrix in this decomposition. It may have [UpperTriangular].
|
||||
* @param lu combined L and U matrix
|
||||
*/
|
||||
public class LupDecomposition<T>(
|
||||
public val linearSpace: LinearSpace<T, Ring<T>>,
|
||||
public val l: Matrix<T>,
|
||||
public val u: Matrix<T>,
|
||||
private val lu: Matrix<T>,
|
||||
public val pivot: IntBuffer,
|
||||
private val even: Boolean,
|
||||
) {
|
||||
public val elementAlgebra: Ring<T> get() = linearSpace.elementAlgebra
|
||||
|
||||
public val pivotMatrix: VirtualMatrix<T>
|
||||
public val l: Matrix<T>
|
||||
get() = VirtualMatrix(lu.type, lu.rowNum, lu.colNum, attributes = Attributes(LowerTriangular)) { i, j ->
|
||||
when {
|
||||
j < i -> lu[i, j]
|
||||
j == i -> elementAlgebra.one
|
||||
else -> elementAlgebra.zero
|
||||
}
|
||||
}
|
||||
|
||||
public val u: Matrix<T>
|
||||
get() = VirtualMatrix(lu.type, lu.rowNum, lu.colNum, attributes = Attributes(UpperTriangular)) { i, j ->
|
||||
if (j >= i) lu[i, j] else elementAlgebra.zero
|
||||
}
|
||||
|
||||
public val pivotMatrix: Matrix<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 {
|
||||
public val determinant: T 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>>) :
|
||||
PolymorphicAttribute<LupDecomposition<T>>(type),
|
||||
MatrixAttribute<LupDecomposition<T>>
|
||||
@ -52,59 +63,6 @@ public class LupDecompositionAttribute<T>(type: SafeType<LupDecomposition<T>>) :
|
||||
public val <T> MatrixOperations<T>.LUP: LupDecompositionAttribute<T>
|
||||
get() = LupDecompositionAttribute(safeTypeOf())
|
||||
|
||||
|
||||
///**
|
||||
// * Common implementation of [LupDecomposition].
|
||||
// */
|
||||
//private class LupDecompositionImpl<T : Any>(
|
||||
// public val elementContext: Field<T>,
|
||||
// public val lu: Matrix<T>,
|
||||
// public val pivot: IntBuffer,
|
||||
// private val even: Boolean,
|
||||
//) : LupDecomposition<T> {
|
||||
// /**
|
||||
// * Returns the matrix L of the decomposition.
|
||||
// *
|
||||
// * L is a lower-triangular matrix with [Ring.one] in diagonal
|
||||
// */
|
||||
// override val l: Matrix<T> = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j ->
|
||||
// when {
|
||||
// j < i -> lu[i, j]
|
||||
// j == i -> elementContext.one
|
||||
// else -> elementContext.zero
|
||||
// }
|
||||
// }.withFeature(LowerTriangular)
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Returns the matrix U of the decomposition.
|
||||
// *
|
||||
// * U is an upper-triangular matrix including the diagonal
|
||||
// */
|
||||
// override val u: Matrix<T> = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j ->
|
||||
// if (j >= i) lu[i, j] else elementContext.zero
|
||||
// }.withFeature(UpperTriangular)
|
||||
//
|
||||
// /**
|
||||
// * Returns the P rows permutation matrix.
|
||||
// *
|
||||
// * P is a sparse matrix with exactly one element set to [Ring.one] in
|
||||
// * each row and each column, all other elements being set to [Ring.zero].
|
||||
// */
|
||||
// override val p: Matrix<T> = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j ->
|
||||
// if (j == pivot[i]) elementContext.one else elementContext.zero
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Return the determinant of the matrix
|
||||
// * @return determinant of the matrix
|
||||
// */
|
||||
// override val determinant: T by lazy {
|
||||
// elementContext { (0 until lu.shape[0]).fold(if(even) one else -one) { value, i -> value * lu[i, i] } }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Comparable<T>> LinearSpace<T, Ring<T>>.abs(value: T): T =
|
||||
if (value > elementAlgebra.zero) value else elementAlgebra { -value }
|
||||
@ -115,14 +73,14 @@ internal fun <T : Comparable<T>> LinearSpace<T, Ring<T>>.abs(value: T): T =
|
||||
public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
|
||||
matrix: Matrix<T>,
|
||||
checkSingular: (T) -> Boolean,
|
||||
): LupDecomposition<T> {
|
||||
): LupDecomposition<T> = elementAlgebra {
|
||||
require(matrix.rowNum == matrix.colNum) { "LU decomposition supports only square matrices" }
|
||||
val m = matrix.colNum
|
||||
val pivot = IntArray(matrix.rowNum)
|
||||
|
||||
//TODO just waits for multi-receivers
|
||||
BufferAccessor2D(matrix.rowNum, matrix.colNum, elementAlgebra.bufferFactory).run {
|
||||
elementAlgebra {
|
||||
with(BufferAccessor2D(matrix.rowNum, matrix.colNum, elementAlgebra.bufferFactory)){
|
||||
|
||||
val lu = create(matrix)
|
||||
|
||||
// Initialize the permutation array and parity
|
||||
@ -184,28 +142,12 @@ 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 ->
|
||||
when {
|
||||
j < i -> lu[i, j]
|
||||
j == i -> one
|
||||
else -> zero
|
||||
}
|
||||
}.withAttribute(LowerTriangular)
|
||||
|
||||
val u = VirtualMatrix(type, rowNum, colNum) { i, j ->
|
||||
if (j >= i) lu[i, j] else zero
|
||||
}.withAttribute(UpperTriangular)
|
||||
//
|
||||
// val p = VirtualMatrix(rowNum, colNum) { i, j ->
|
||||
// if (j == pivot[i]) one else zero
|
||||
// }.withAttribute(Determinant, if (even) one else -one)
|
||||
|
||||
return LupDecomposition(this@lup, l, u, pivot.asBuffer())
|
||||
}
|
||||
return LupDecomposition(this@lup, lu.toStructure2D(), pivot.asBuffer(), even)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public fun LinearSpace<Double, Float64Field>.lup(
|
||||
matrix: Matrix<Double>,
|
||||
singularityThreshold: Double = 1e-11,
|
||||
|
@ -7,9 +7,9 @@ package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.attributes.FlagAttribute
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.WithType
|
||||
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
|
||||
|
||||
|
@ -16,7 +16,7 @@ import space.kscience.kmath.operations.Ring
|
||||
*
|
||||
* @param T the type of items.
|
||||
*/
|
||||
public class MatrixWrapper<out T : Any> internal constructor(
|
||||
public class MatrixWrapper<out T> internal constructor(
|
||||
public val origin: Matrix<T>,
|
||||
override val attributes: Attributes,
|
||||
) : Matrix<T> by origin {
|
||||
|
@ -5,17 +5,12 @@
|
||||
|
||||
package space.kscience.kmath.nd
|
||||
|
||||
import space.kscience.attributes.Attribute
|
||||
import space.kscience.attributes.AttributeContainer
|
||||
import space.kscience.attributes.Attributes
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.*
|
||||
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
|
||||
import kotlin.math.abs
|
||||
|
||||
public interface StructureAttribute<T> : Attribute<T>
|
||||
@ -148,28 +143,20 @@ public inline fun <reified T : Any> BufferND(
|
||||
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(
|
||||
public fun <T : Any> BufferND(
|
||||
type: SafeType<T>,
|
||||
vararg shape: Int,
|
||||
crossinline initializer: (IntArray) -> T,
|
||||
initializer: (IntArray) -> T,
|
||||
): BufferND<T> = BufferND(type, ColumnStrides(ShapeND(shape)), initializer)
|
||||
|
||||
|
||||
|
@ -6,19 +6,12 @@
|
||||
package space.kscience.kmath.operations
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.WithType
|
||||
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>
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents an algebraic structure.
|
||||
*
|
||||
|
@ -5,20 +5,18 @@
|
||||
|
||||
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
|
||||
import space.kscience.kmath.operations.BigInt.Companion.BASE_SIZE
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
import kotlin.math.log2
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sign
|
||||
|
||||
private typealias Magnitude = UIntArray
|
||||
private typealias TBase = ULong
|
||||
|
||||
/**
|
||||
* Kotlin Multiplatform implementation of Big Integer numbers (KBigInteger).
|
||||
@ -29,7 +27,7 @@ private typealias TBase = ULong
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
public object BigIntField : Field<BigInt>, NumbersAddOps<BigInt>, ScaleOperations<BigInt> {
|
||||
|
||||
override val type: SafeType<BigInt> = safeTypeOf()
|
||||
override val bufferFactory: MutableBufferFactory<BigInt> = MutableBufferFactory()
|
||||
|
||||
override val zero: BigInt = BigInt.ZERO
|
||||
override val one: BigInt = BigInt.ONE
|
||||
|
@ -5,8 +5,6 @@
|
||||
|
||||
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
|
||||
@ -21,10 +19,10 @@ 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
|
||||
|
||||
override val bufferFactory: MutableBufferFactory<Buffer<T>> get() = MutableBufferFactory()
|
||||
|
||||
public fun buffer(size: Int, vararg elements: T): Buffer<T> {
|
||||
require(elements.size == size) { "Expected $size elements but found ${elements.size}" }
|
||||
return elementBufferFactory(size) { elements[it] }
|
||||
|
@ -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.structures.MutableBufferFactory
|
||||
|
||||
/**
|
||||
* An algebra for generic boolean logic
|
||||
@ -74,7 +73,7 @@ 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 val bufferFactory: MutableBufferFactory<Boolean> get() = MutableBufferFactory()
|
||||
|
||||
override fun const(boolean: Boolean): Boolean = boolean
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
package space.kscience.kmath.operations
|
||||
|
||||
import space.kscience.kmath.structures.*
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
import kotlin.math.pow as kpow
|
||||
|
||||
|
||||
@ -129,7 +129,7 @@ public val Double.Companion.algebra: Float64Field get() = Float64Field
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
||||
public object Float32Field : ExtendedField<Float>, Norm<Float, Float> {
|
||||
override val bufferFactory: MutableBufferFactory<Float> = MutableBufferFactory(::Float32Buffer)
|
||||
override val bufferFactory: MutableBufferFactory<Float> = MutableBufferFactory()
|
||||
|
||||
override val zero: Float get() = 0.0f
|
||||
override val one: Float get() = 1.0f
|
||||
@ -187,7 +187,7 @@ public val Float.Companion.algebra: Float32Field get() = Float32Field
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
||||
public object Int32Ring : Ring<Int>, Norm<Int, Int>, NumericAlgebra<Int> {
|
||||
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
|
||||
@ -212,7 +212,7 @@ public val Int.Companion.algebra: Int32Ring get() = Int32Ring
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
||||
public object Int16Ring : Ring<Short>, Norm<Short, Short>, NumericAlgebra<Short> {
|
||||
override val bufferFactory: MutableBufferFactory<Short> = MutableBufferFactory(::Int16Buffer)
|
||||
override val bufferFactory: MutableBufferFactory<Short> = MutableBufferFactory()
|
||||
|
||||
override val zero: Short get() = 0
|
||||
override val one: Short get() = 1
|
||||
@ -237,7 +237,7 @@ public val Short.Companion.algebra: Int16Ring get() = Int16Ring
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
||||
public object Int8Ring : Ring<Byte>, Norm<Byte, Byte>, NumericAlgebra<Byte> {
|
||||
override val bufferFactory: MutableBufferFactory<Byte> = MutableBufferFactory(::Int8Buffer)
|
||||
override val bufferFactory: MutableBufferFactory<Byte> = MutableBufferFactory()
|
||||
|
||||
override val zero: Byte get() = 0
|
||||
override val one: Byte get() = 1
|
||||
@ -262,7 +262,7 @@ public val Byte.Companion.algebra: Int8Ring get() = Int8Ring
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
||||
public object Int64Ring : Ring<Long>, Norm<Long, Long>, NumericAlgebra<Long> {
|
||||
override val bufferFactory: MutableBufferFactory<Long> = MutableBufferFactory(::Int64Buffer)
|
||||
override val bufferFactory: MutableBufferFactory<Long> = MutableBufferFactory()
|
||||
|
||||
override val zero: Long get() = 0L
|
||||
override val one: Long get() = 1L
|
||||
|
@ -5,13 +5,16 @@
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
|
||||
/**
|
||||
* [MutableBuffer] implementation over [Array].
|
||||
*
|
||||
* @param T the type of elements contained in the buffer.
|
||||
* @property array The underlying array.
|
||||
*/
|
||||
public class ArrayBuffer<T>(internal val array: Array<T>) : MutableBuffer<T> {
|
||||
public class ArrayBuffer<T>(override val type: SafeType<T>, internal val array: Array<T>) : MutableBuffer<T> {
|
||||
// Can't inline because array is invariant
|
||||
override val size: Int get() = array.size
|
||||
|
||||
@ -22,13 +25,17 @@ public class ArrayBuffer<T>(internal val array: Array<T>) : MutableBuffer<T> {
|
||||
}
|
||||
|
||||
override operator fun iterator(): Iterator<T> = array.iterator()
|
||||
override fun copy(): MutableBuffer<T> = ArrayBuffer(array.copyOf())
|
||||
override fun copy(): MutableBuffer<T> = ArrayBuffer(type, array.copyOf())
|
||||
|
||||
override fun toString(): String = Buffer.toString(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an [ArrayBuffer] that wraps the original array.
|
||||
*/
|
||||
public fun <T> Array<T>.asBuffer(type: SafeType<T>): ArrayBuffer<T> = ArrayBuffer(type, this)
|
||||
|
||||
/**
|
||||
* Returns an [ArrayBuffer] that wraps the original array.
|
||||
*/
|
||||
public fun <T> Array<T>.asBuffer(): ArrayBuffer<T> = ArrayBuffer(this)
|
||||
public inline fun <reified T> Array<T>.asBuffer(): ArrayBuffer<T> = ArrayBuffer(safeTypeOf<T>(), this)
|
@ -6,9 +6,9 @@
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.WithType
|
||||
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.reflect.typeOf
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
|
||||
/**
|
||||
@ -8,6 +9,8 @@ import space.kscience.kmath.UnstableKMathAPI
|
||||
public interface BufferView<T> : Buffer<T> {
|
||||
public val origin: Buffer<T>
|
||||
|
||||
override val type: SafeType<T> get() = origin.type
|
||||
|
||||
/**
|
||||
* Get the index in [origin] buffer from index in this buffer.
|
||||
* Return -1 if element not present in the original buffer
|
||||
@ -36,6 +39,7 @@ public class BufferSlice<T>(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun get(index: Int): T = if (index >= size) {
|
||||
throw IndexOutOfBoundsException("$index is out of ${0 until size} rage")
|
||||
} else {
|
||||
@ -100,7 +104,8 @@ public fun <T> Buffer<T>.slice(range: IntRange): BufferView<T> = if (this is Buf
|
||||
* Dynamically create a range from the initial range
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public inline fun <T> Buffer<T>.slice(rangeBuilder: IntRange.() -> IntRange): BufferView<T> = slice(rangeBuilder(indices))
|
||||
public inline fun <T> Buffer<T>.slice(rangeBuilder: IntRange.() -> IntRange): BufferView<T> =
|
||||
slice(rangeBuilder(indices))
|
||||
|
||||
/**
|
||||
* Resize original buffer to a given range using given [range], filling additional segments with [defaultValue].
|
||||
|
@ -72,15 +72,21 @@ public interface MutableBuffer<T> : Buffer<T> {
|
||||
* 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>
|
||||
public inline fun <T> MutableBuffer(
|
||||
type: SafeType<T>,
|
||||
size: Int,
|
||||
initializer: (Int) -> T,
|
||||
): MutableBuffer<T> = when (type.kType) {
|
||||
typeOf<Boolean>() -> TODO()
|
||||
typeOf<Int8>() -> Int8Buffer(size) { initializer(it) as Int8 } as MutableBuffer<T>
|
||||
typeOf<Int16>() -> MutableBuffer.short(size) { initializer(it) as Int16 } as MutableBuffer<T>
|
||||
typeOf<Int32>() -> MutableBuffer.int(size) { initializer(it) as Int32 } as MutableBuffer<T>
|
||||
typeOf<Int64>() -> MutableBuffer.long(size) { initializer(it) as Int64 } 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>
|
||||
typeOf<Double>() -> MutableBuffer.double(size) { initializer(it) as Double } as MutableBuffer<T>
|
||||
//TODO add unsigned types
|
||||
else -> MutableListBuffer(type, MutableList(size, initializer))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [MutableBuffer] of given type [T]. If the type is primitive, specialized buffers are used
|
||||
|
@ -8,7 +8,6 @@ package space.kscience.kmath.linear
|
||||
import space.kscience.kmath.PerformancePitfall
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.StructureND
|
||||
import space.kscience.kmath.nd.as2D
|
||||
import space.kscience.kmath.operations.algebra
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -22,7 +21,7 @@ class MatrixTest {
|
||||
@Test
|
||||
fun testTranspose() = Double.algebra.linearSpace.run {
|
||||
val matrix = one(3, 3)
|
||||
val transposed = matrix.transpose()
|
||||
val transposed = matrix.transposed
|
||||
assertTrue { StructureND.contentEquals(matrix, transposed) }
|
||||
}
|
||||
|
||||
@ -38,7 +37,7 @@ class MatrixTest {
|
||||
|
||||
@Test
|
||||
fun testMatrixExtension() = Double.algebra.linearSpace.run {
|
||||
val transitionMatrix: Matrix<Double> = VirtualMatrix(6, 6) { row, col ->
|
||||
val transitionMatrix: Matrix<Double> = VirtualMatrix(type,6, 6) { row, col ->
|
||||
when {
|
||||
col == 0 -> .50
|
||||
row + 1 == col -> .50
|
||||
@ -60,8 +59,8 @@ class MatrixTest {
|
||||
|
||||
@Test
|
||||
fun test2DDot() = Double.algebra.linearSpace.run {
|
||||
val firstMatrix = StructureND.auto(2, 3) { (i, j) -> (i + j).toDouble() }.as2D()
|
||||
val secondMatrix = StructureND.auto(3, 2) { (i, j) -> (i + j).toDouble() }.as2D()
|
||||
val firstMatrix = buildMatrix(2, 3) { i, j -> (i + j).toDouble() }
|
||||
val secondMatrix = buildMatrix(3, 2) { i, j -> (i + j).toDouble() }
|
||||
|
||||
// val firstMatrix = produce(2, 3) { i, j -> (i + j).toDouble() }
|
||||
// val secondMatrix = produce(3, 2) { i, j -> (i + j).toDouble() }
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package space.kscience.kmath.operations
|
||||
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
import java.math.MathContext
|
||||
@ -13,6 +14,8 @@ import java.math.MathContext
|
||||
* A field over [BigInteger].
|
||||
*/
|
||||
public object JBigIntegerField : Ring<BigInteger>, NumericAlgebra<BigInteger> {
|
||||
|
||||
override val bufferFactory: MutableBufferFactory<BigInteger> = MutableBufferFactory()
|
||||
override val zero: BigInteger get() = BigInteger.ZERO
|
||||
|
||||
override val one: BigInteger get() = BigInteger.ONE
|
||||
@ -33,6 +36,7 @@ public object JBigIntegerField : Ring<BigInteger>, NumericAlgebra<BigInteger> {
|
||||
public abstract class JBigDecimalFieldBase internal constructor(
|
||||
private val mathContext: MathContext = MathContext.DECIMAL64,
|
||||
) : Field<BigDecimal>, PowerOperations<BigDecimal>, NumericAlgebra<BigDecimal>, ScaleOperations<BigDecimal> {
|
||||
override val bufferFactory: MutableBufferFactory<BigDecimal> = MutableBufferFactory()
|
||||
override val zero: BigDecimal
|
||||
get() = BigDecimal.ZERO
|
||||
|
||||
|
@ -43,7 +43,7 @@ public interface BlockingBufferChain<out T> : BlockingChain<T>, BufferChain<T> {
|
||||
public suspend inline fun <reified T : Any> Chain<T>.nextBuffer(size: Int): Buffer<T> = if (this is BufferChain) {
|
||||
nextBuffer(size)
|
||||
} else {
|
||||
Buffer.auto(size) { next() }
|
||||
Buffer(size) { next() }
|
||||
}
|
||||
|
||||
public inline fun <reified T : Any> BlockingChain<T>.nextBufferBlocking(
|
||||
@ -51,5 +51,5 @@ public inline fun <reified T : Any> BlockingChain<T>.nextBufferBlocking(
|
||||
): Buffer<T> = if (this is BlockingBufferChain) {
|
||||
nextBufferBlocking(size)
|
||||
} else {
|
||||
Buffer.auto(size) { nextBlocking() }
|
||||
Buffer(size) { nextBlocking() }
|
||||
}
|
@ -14,6 +14,7 @@ import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.flatMapConcat
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import space.kscience.kmath.chains.BlockingDoubleChain
|
||||
import space.kscience.kmath.operations.Group
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.BufferFactory
|
||||
import space.kscience.kmath.structures.Float64Buffer
|
||||
@ -84,9 +85,9 @@ public fun Flow<Double>.chunked(bufferSize: Int): Flow<Float64Buffer> = flow {
|
||||
* Map a flow to a moving window buffer. The window step is one.
|
||||
* To get different steps, one could use skip operation.
|
||||
*/
|
||||
public fun <T> Flow<T>.windowed(window: Int): Flow<Buffer<T>> = flow {
|
||||
public fun <T> Flow<T>.windowed(window: Int, algebra: Group<T>): Flow<Buffer<T>> = flow {
|
||||
require(window > 1) { "Window size must be more than one" }
|
||||
val ringBuffer = RingBuffer.boxing<T>(window)
|
||||
val ringBuffer = RingBuffer(window, algebra)
|
||||
|
||||
this@windowed.collect { element ->
|
||||
ringBuffer.push(element)
|
||||
|
@ -7,6 +7,8 @@ package space.kscience.kmath.streaming
|
||||
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.kmath.operations.Group
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.MutableBuffer
|
||||
import space.kscience.kmath.structures.VirtualBuffer
|
||||
@ -14,12 +16,14 @@ import space.kscience.kmath.structures.VirtualBuffer
|
||||
/**
|
||||
* Thread-safe ring buffer
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public class RingBuffer<T>(
|
||||
private val buffer: MutableBuffer<T?>,
|
||||
private val buffer: MutableBuffer<T>,
|
||||
private var startIndex: Int = 0,
|
||||
size: Int = 0,
|
||||
) : Buffer<T> {
|
||||
|
||||
override val type: SafeType<T> get() = buffer.type
|
||||
|
||||
private val mutex: Mutex = Mutex()
|
||||
|
||||
override var size: Int = size
|
||||
@ -28,7 +32,7 @@ public class RingBuffer<T>(
|
||||
override operator fun get(index: Int): T {
|
||||
require(index >= 0) { "Index must be positive" }
|
||||
require(index < size) { "Index $index is out of circular buffer size $size" }
|
||||
return buffer[startIndex.forward(index)] as T
|
||||
return buffer[startIndex.forward(index)]
|
||||
}
|
||||
|
||||
public fun isFull(): Boolean = size == buffer.size
|
||||
@ -43,7 +47,7 @@ public class RingBuffer<T>(
|
||||
|
||||
override fun computeNext() {
|
||||
if (count == 0) done() else {
|
||||
setNext(copy[index] as T)
|
||||
setNext(copy[index])
|
||||
index = index.forward(1)
|
||||
count--
|
||||
}
|
||||
@ -55,7 +59,7 @@ public class RingBuffer<T>(
|
||||
*/
|
||||
public suspend fun snapshot(): Buffer<T> = mutex.withLock {
|
||||
val copy = buffer.copy()
|
||||
VirtualBuffer(size) { i -> copy[startIndex.forward(i)] as T }
|
||||
VirtualBuffer(type, size) { i -> copy[startIndex.forward(i)] }
|
||||
}
|
||||
|
||||
public suspend fun push(element: T) {
|
||||
@ -68,19 +72,17 @@ public class RingBuffer<T>(
|
||||
private fun Int.forward(n: Int): Int = (this + n) % (buffer.size)
|
||||
|
||||
override fun toString(): String = Buffer.toString(this)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public inline fun <reified T : Any> build(size: Int, empty: T): RingBuffer<T> {
|
||||
val buffer = MutableBuffer.auto(size) { empty } as MutableBuffer<T?>
|
||||
public inline fun <reified T : Any> RingBuffer(size: Int, empty: T): RingBuffer<T> {
|
||||
val buffer = MutableBuffer(size) { empty }
|
||||
return RingBuffer(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Slow yet universal buffer
|
||||
*/
|
||||
public fun <T> boxing(size: Int): RingBuffer<T> {
|
||||
val buffer: MutableBuffer<T?> = MutableBuffer.boxing(size) { null }
|
||||
public fun <T> RingBuffer(size: Int, algebra: Group<T>): RingBuffer<T> {
|
||||
val buffer: MutableBuffer<T> = MutableBuffer(algebra.type, size) { algebra.zero }
|
||||
return RingBuffer(buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.safeTypeOf
|
||||
import space.kscience.kmath.PerformancePitfall
|
||||
import space.kscience.kmath.coroutines.Math
|
||||
import space.kscience.kmath.nd.ColumnStrides
|
||||
@ -14,9 +16,11 @@ import space.kscience.kmath.nd.StructureND
|
||||
|
||||
public class LazyStructureND<out T>(
|
||||
public val scope: CoroutineScope,
|
||||
override val type: SafeType<T>,
|
||||
override val shape: ShapeND,
|
||||
public val function: suspend (IntArray) -> T,
|
||||
) : StructureND<T> {
|
||||
|
||||
private val cache: MutableMap<IntArray, Deferred<T>> = HashMap()
|
||||
|
||||
public fun async(index: IntArray): Deferred<T> = cache.getOrPut(index) {
|
||||
@ -47,13 +51,13 @@ public suspend fun <T> StructureND<T>.await(index: IntArray): T =
|
||||
* PENDING would benefit from KEEP-176
|
||||
*/
|
||||
@OptIn(PerformancePitfall::class)
|
||||
public inline fun <T, R> StructureND<T>.mapAsyncIndexed(
|
||||
public inline fun <T, reified R> StructureND<T>.mapAsyncIndexed(
|
||||
scope: CoroutineScope,
|
||||
crossinline function: suspend (T, index: IntArray) -> R,
|
||||
): LazyStructureND<R> = LazyStructureND(scope, shape) { index -> function(get(index), index) }
|
||||
): LazyStructureND<R> = LazyStructureND(scope, safeTypeOf(), shape) { index -> function(get(index), index) }
|
||||
|
||||
@OptIn(PerformancePitfall::class)
|
||||
public inline fun <T, R> StructureND<T>.mapAsync(
|
||||
public inline fun <T, reified R> StructureND<T>.mapAsync(
|
||||
scope: CoroutineScope,
|
||||
crossinline function: suspend (T) -> R,
|
||||
): LazyStructureND<R> = LazyStructureND(scope, shape) { index -> function(get(index)) }
|
||||
): LazyStructureND<R> = LazyStructureND(scope, safeTypeOf(), shape) { index -> function(get(index)) }
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package space.kscience.kmath.dimensions
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.kmath.linear.*
|
||||
import space.kscience.kmath.nd.ShapeND
|
||||
import space.kscience.kmath.nd.Structure2D
|
||||
@ -48,6 +49,9 @@ public interface DMatrix<out T, R : Dimension, C : Dimension> : Structure2D<T> {
|
||||
public value class DMatrixWrapper<out T, R : Dimension, C : Dimension>(
|
||||
private val structure: Structure2D<T>,
|
||||
) : DMatrix<T, R, C> {
|
||||
|
||||
override val type: SafeType<T> get() = structure.type
|
||||
|
||||
override val shape: ShapeND get() = structure.shape
|
||||
override val rowNum: Int get() = shape[0]
|
||||
override val colNum: Int get() = shape[1]
|
||||
@ -75,8 +79,10 @@ public interface DPoint<out T, D : Dimension> : Point<T> {
|
||||
* Dimension-safe point wrapper
|
||||
*/
|
||||
@JvmInline
|
||||
public value class DPointWrapper<out T, D : Dimension>(public val point: Point<T>) :
|
||||
DPoint<T, D> {
|
||||
public value class DPointWrapper<out T, D : Dimension>(public val point: Point<T>) : DPoint<T, D> {
|
||||
|
||||
override val type: SafeType<T> get() = point.type
|
||||
|
||||
override val size: Int get() = point.size
|
||||
|
||||
override operator fun get(index: Int): T = point[index]
|
||||
|
@ -6,14 +6,9 @@
|
||||
package space.kscience.kmath.ejml
|
||||
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.linear.InverseMatrixFeature
|
||||
import space.kscience.kmath.linear.LinearSpace
|
||||
import space.kscience.kmath.linear.Matrix
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.nd.Structure2D
|
||||
import space.kscience.kmath.linear.*
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* [LinearSpace] implementation specialized for a certain EJML type.
|
||||
@ -42,8 +37,7 @@ public abstract class EjmlLinearSpace<T : Any, out A : Ring<T>, out M : org.ejml
|
||||
|
||||
public abstract override fun buildVector(size: Int, initializer: A.(Int) -> T): EjmlVector<T, M>
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@UnstableKMathAPI
|
||||
public fun EjmlMatrix<T, *>.inverse(): Structure2D<Double> =
|
||||
attributeFor(this, InverseMatrixFeature::class)?.inverse as Structure2D<Double>
|
||||
public fun EjmlMatrix<T, *>.inverted(): Matrix<Double> =
|
||||
attributeFor(this, Float64Field.linearSpace.Inverted)
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ internal class EjmlMatrixTest {
|
||||
val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
||||
val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
|
||||
val matrix = space { l dot u }
|
||||
val inverted = matrix.toEjml().inverse()
|
||||
val inverted = matrix.toEjml().inverted()
|
||||
|
||||
val res = matrix dot inverted
|
||||
|
||||
|
@ -48,7 +48,7 @@ public fun Sequence<DoubleArray>.toMatrix(): RealMatrix = toList().let {
|
||||
}
|
||||
|
||||
public fun RealMatrix.repeatStackVertical(n: Int): RealMatrix =
|
||||
VirtualMatrix(rowNum * n, colNum) { row, col ->
|
||||
VirtualMatrix(type, rowNum * n, colNum) { row, col ->
|
||||
get(if (row == 0) 0 else row % rowNum, col)
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,12 @@
|
||||
|
||||
package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.Ring
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
|
||||
/**
|
||||
@ -67,6 +65,7 @@ public data class Polynomial<out C>(
|
||||
public open class PolynomialSpace<C, A>(
|
||||
public val ring: A,
|
||||
) : Ring<Polynomial<C>>, ScaleOperations<Polynomial<C>> where A : Ring<C>, A : ScaleOperations<C> {
|
||||
override val bufferFactory: MutableBufferFactory<Polynomial<C>> get() = MutableBufferFactory()
|
||||
|
||||
/**
|
||||
* Instance of zero constant (zero of the underlying ring).
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package space.kscience.kmath.integration
|
||||
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.mapToBuffer
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.Float64Buffer
|
||||
@ -32,11 +33,11 @@ public fun GaussIntegratorRuleFactory.build(
|
||||
val normalized: Pair<Buffer<Double>, Buffer<Double>> = build(numPoints)
|
||||
val length = range.endInclusive - range.start
|
||||
|
||||
val points = normalized.first.mapToBuffer(::Float64Buffer) {
|
||||
val points = normalized.first.mapToBuffer(Float64Field.bufferFactory) {
|
||||
range.start + length / 2 + length / 2 * it
|
||||
}
|
||||
|
||||
val weights = normalized.second.mapToBuffer(::Float64Buffer) {
|
||||
val weights = normalized.second.mapToBuffer(Float64Field.bufferFactory) {
|
||||
it * length / 2
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ public class SplineIntegrator<T : Comparable<T>>(
|
||||
public object DoubleSplineIntegrator : UnivariateIntegrator<Double> {
|
||||
override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||
val range = integrand[IntegrationRange] ?: 0.0..1.0
|
||||
val interpolator: PolynomialInterpolator<Double> = SplineInterpolator(Float64Field, ::Float64Buffer)
|
||||
val interpolator: PolynomialInterpolator<Double> = SplineInterpolator(Float64Field, Float64Field.bufferFactory)
|
||||
|
||||
val nodes: Buffer<Double> = integrand[UnivariateIntegrationNodes] ?: run {
|
||||
val numPoints = integrand[IntegrandMaxCalls] ?: 100
|
||||
@ -96,7 +96,7 @@ public object DoubleSplineIntegrator : UnivariateIntegrator<Double> {
|
||||
Float64Buffer(numPoints) { i -> range.start + i * step }
|
||||
}
|
||||
|
||||
val values = nodes.mapToBuffer(::Float64Buffer) { integrand.function(it) }
|
||||
val values = nodes.mapToBuffer(Float64Field.bufferFactory) { integrand.function(it) }
|
||||
val polynomials = interpolator.interpolatePolynomials(nodes, values)
|
||||
val res = polynomials.integrate(Float64Field, range)
|
||||
return integrand.withAttributes {
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
package space.kscience.kmath.interpolation
|
||||
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.attributes.WithType
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.data.XYColumnarData
|
||||
import space.kscience.kmath.functions.PiecewisePolynomial
|
||||
@ -26,9 +28,11 @@ public fun interface Interpolator<T, in X : T, Y : T> {
|
||||
/**
|
||||
* And interpolator returning [PiecewisePolynomial] function
|
||||
*/
|
||||
public interface PolynomialInterpolator<T : Comparable<T>> : Interpolator<T, T, T> {
|
||||
public interface PolynomialInterpolator<T : Comparable<T>> : Interpolator<T, T, T>, WithType<T> {
|
||||
public val algebra: Ring<T>
|
||||
|
||||
override val type: SafeType<T> get() = algebra.type
|
||||
|
||||
public fun getDefaultValue(): T = error("Out of bounds")
|
||||
|
||||
public fun interpolatePolynomials(points: XYColumnarData<T, T, T>): PiecewisePolynomial<T>
|
||||
@ -50,14 +54,14 @@ public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
|
||||
public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
|
||||
data: Map<T, T>,
|
||||
): PiecewisePolynomial<T> {
|
||||
val pointSet = XYColumnarData.of(data.keys.toList().asBuffer(), data.values.toList().asBuffer())
|
||||
val pointSet = XYColumnarData.of(data.keys.toList().asBuffer(type), data.values.toList().asBuffer(type))
|
||||
return interpolatePolynomials(pointSet)
|
||||
}
|
||||
|
||||
public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
|
||||
data: List<Pair<T, T>>,
|
||||
): PiecewisePolynomial<T> {
|
||||
val pointSet = XYColumnarData.of(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer())
|
||||
val pointSet = XYColumnarData.of(data.map { it.first }.asBuffer(type), data.map { it.second }.asBuffer(type))
|
||||
return interpolatePolynomials(pointSet)
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@ import space.kscience.kmath.functions.Polynomial
|
||||
import space.kscience.kmath.operations.Field
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.structures.Float64Buffer
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
|
||||
/**
|
||||
@ -80,4 +79,4 @@ public fun <T : Comparable<T>> Field<T>.splineInterpolator(
|
||||
): SplineInterpolator<T> = SplineInterpolator(this, bufferFactory)
|
||||
|
||||
public val Float64Field.splineInterpolator: SplineInterpolator<Double>
|
||||
get() = SplineInterpolator(this, ::Float64Buffer)
|
||||
get() = SplineInterpolator(this, bufferFactory)
|
@ -7,6 +7,10 @@ kscience {
|
||||
js()
|
||||
native()
|
||||
wasm()
|
||||
|
||||
dependencies {
|
||||
api(projects.kmathCore)
|
||||
}
|
||||
}
|
||||
|
||||
readme {
|
||||
|
@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright 2018-2022 KMath contributors.
|
||||
* 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.structures
|
||||
package space.kscience.kmath.memory
|
||||
|
||||
import space.kscience.kmath.memory.*
|
||||
import space.kscience.attributes.SafeType
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.MutableBuffer
|
||||
|
||||
/**
|
||||
* A non-boxing buffer over [Memory] object.
|
||||
@ -15,6 +17,9 @@ import space.kscience.kmath.memory.*
|
||||
* @property spec the spec of [T] type.
|
||||
*/
|
||||
public open class MemoryBuffer<T : Any>(protected val memory: Memory, protected val spec: MemorySpec<T>) : Buffer<T> {
|
||||
|
||||
override val type: SafeType<T> get() = spec.type
|
||||
|
||||
override val size: Int get() = memory.size / spec.objectSize
|
||||
|
||||
override operator fun get(index: Int): T = memory.read { read(spec, spec.objectSize * index) }
|
||||
@ -43,8 +48,10 @@ public open class MemoryBuffer<T : Any>(protected val memory: Memory, protected
|
||||
* @property memory the underlying memory segment.
|
||||
* @property spec the spec of [T] type.
|
||||
*/
|
||||
public class MutableMemoryBuffer<T : Any>(memory: Memory, spec: MemorySpec<T>) : MemoryBuffer<T>(memory, spec),
|
||||
MutableBuffer<T> {
|
||||
public class MutableMemoryBuffer<T : Any>(
|
||||
memory: Memory,
|
||||
spec: MemorySpec<T>,
|
||||
) : MemoryBuffer<T>(memory, spec), MutableBuffer<T> {
|
||||
|
||||
private val writer: MemoryWriter = memory.writer()
|
||||
|
@ -5,12 +5,15 @@
|
||||
|
||||
package space.kscience.kmath.memory
|
||||
|
||||
import space.kscience.attributes.WithType
|
||||
|
||||
/**
|
||||
* A specification to read or write custom objects with fixed size in bytes.
|
||||
*
|
||||
* @param T the type of object this spec manages.
|
||||
*/
|
||||
public interface MemorySpec<T : Any> {
|
||||
public interface MemorySpec<T : Any>: WithType<T> {
|
||||
|
||||
/**
|
||||
* Size of [T] in bytes after serialization.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user