forked from kscience/kmath
Refactor buffer factories
This commit is contained in:
parent
8af2f5eb31
commit
0e0deaeb72
@ -9,7 +9,7 @@
|
||||
- Exponential operations merged with hyperbolic functions
|
||||
- Space is replaced by Group. Space is reserved for vector spaces.
|
||||
- VectorSpace is now a vector space
|
||||
-
|
||||
- Buffer factories for primitives moved to MutableBuffer.Companion
|
||||
|
||||
### Deprecated
|
||||
|
||||
|
@ -432,7 +432,7 @@ public final class space/kscience/kmath/expressions/SymbolIndexerKt {
|
||||
public static final fun withSymbols ([Lspace/kscience/kmath/expressions/Symbol;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/linear/BufferLinearSpace : space/kscience/kmath/linear/LinearSpace {
|
||||
public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscience/kmath/linear/LinearSpace {
|
||||
public fun <init> (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V
|
||||
public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D;
|
||||
public fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer;
|
||||
@ -2115,7 +2115,6 @@ public abstract interface class space/kscience/kmath/structures/Buffer {
|
||||
public final class space/kscience/kmath/structures/Buffer$Companion {
|
||||
public final fun auto (Lkotlin/reflect/KClass;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer;
|
||||
public final fun boxing (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer;
|
||||
public final fun real-8hrHhI4 (ILkotlin/jvm/functions/Function1;)[D
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/structures/Buffer$DefaultImpls {
|
||||
@ -2123,15 +2122,17 @@ public final class space/kscience/kmath/structures/Buffer$DefaultImpls {
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/structures/BufferKt {
|
||||
public static final fun ListBuffer (ILkotlin/jvm/functions/Function1;)Ljava/util/List;
|
||||
public static final fun asBuffer (Ljava/util/List;)Ljava/util/List;
|
||||
public static final fun asBuffer ([Ljava/lang/Object;)Lspace/kscience/kmath/structures/ArrayBuffer;
|
||||
public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable;
|
||||
public static final fun asMutableBuffer (Ljava/util/List;)Ljava/util/List;
|
||||
public static final fun asReadOnly (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer;
|
||||
public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence;
|
||||
public static final fun getIndices (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/ranges/IntRange;
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/structures/BufferOperationKt {
|
||||
public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable;
|
||||
public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence;
|
||||
public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List;
|
||||
public static final fun toMutableList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List;
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/kmath/structures/FlaggedBuffer : space/kscience/kmath/structures/Buffer {
|
||||
@ -2316,7 +2317,11 @@ public abstract interface class space/kscience/kmath/structures/MutableBuffer :
|
||||
public final class space/kscience/kmath/structures/MutableBuffer$Companion {
|
||||
public final fun auto (Lkotlin/reflect/KClass;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer;
|
||||
public final fun boxing (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer;
|
||||
public final fun float-YxruXGw (ILkotlin/jvm/functions/Function1;)[F
|
||||
public final fun int-Ye6GY2U (ILkotlin/jvm/functions/Function1;)[I
|
||||
public final fun long-BuQOeTY (ILkotlin/jvm/functions/Function1;)[J
|
||||
public final fun real-8hrHhI4 (ILkotlin/jvm/functions/Function1;)[D
|
||||
public final fun short-1yRgbGw (ILkotlin/jvm/functions/Function1;)[S
|
||||
}
|
||||
|
||||
public final class space/kscience/kmath/structures/MutableBuffer$DefaultImpls {
|
||||
|
@ -9,7 +9,7 @@ import space.kscience.kmath.structures.VirtualBuffer
|
||||
import space.kscience.kmath.structures.indices
|
||||
|
||||
|
||||
public class BufferLinearSpace<T : Any, A : Ring<T>>(
|
||||
public class BufferedLinearSpace<T : Any, A : Ring<T>>(
|
||||
override val elementAlgebra: A,
|
||||
private val bufferFactory: BufferFactory<T>,
|
||||
) : LinearSpace<T, A> {
|
@ -6,9 +6,20 @@ import space.kscience.kmath.nd.as1D
|
||||
* A group of methods to resolve equation A dot X = B, where A and B are matrices or vectors
|
||||
*/
|
||||
public interface LinearSolver<T : Any> {
|
||||
/**
|
||||
* Solve a dot x = b matrix equation and return x
|
||||
*/
|
||||
public fun solve(a: Matrix<T>, b: Matrix<T>): Matrix<T>
|
||||
|
||||
/**
|
||||
* Solve a dot x = b vector equation and return b
|
||||
*/
|
||||
public fun solve(a: Matrix<T>, b: Point<T>): Point<T> = solve(a, b.asMatrix()).asVector()
|
||||
public fun inverse(a: Matrix<T>): Matrix<T>
|
||||
|
||||
/**
|
||||
* Get inverse of a matrix
|
||||
*/
|
||||
public fun inverse(matrix: Matrix<T>): Matrix<T>
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@ import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.BufferFactory
|
||||
import space.kscience.kmath.structures.RealBuffer
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
@ -174,9 +175,9 @@ public interface LinearSpace<T : Any, out A : Ring<T>> {
|
||||
public fun <T : Any, A : Ring<T>> buffered(
|
||||
algebra: A,
|
||||
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
|
||||
): LinearSpace<T, A> = BufferLinearSpace(algebra,bufferFactory)
|
||||
): LinearSpace<T, A> = BufferedLinearSpace(algebra,bufferFactory)
|
||||
|
||||
public val real: LinearSpace<Double, RealField> = buffered(RealField, Buffer.Companion::real)
|
||||
public val real: LinearSpace<Double, RealField> = buffered(RealField, ::RealBuffer)
|
||||
|
||||
/**
|
||||
* Automatic buffered matrix, unboxed if it is possible
|
||||
|
@ -3,10 +3,10 @@ package space.kscience.kmath.linear
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.getFeature
|
||||
import space.kscience.kmath.operations.*
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.BufferAccessor2D
|
||||
import space.kscience.kmath.structures.MutableBuffer
|
||||
import space.kscience.kmath.structures.MutableBufferFactory
|
||||
import space.kscience.kmath.structures.RealBuffer
|
||||
|
||||
/**
|
||||
* Common implementation of [LupDecompositionFeature].
|
||||
@ -152,7 +152,7 @@ public inline fun <reified T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
|
||||
): LupDecomposition<T> = lup(MutableBuffer.Companion::auto, matrix, checkSingular)
|
||||
|
||||
public fun LinearSpace<Double, RealField>.lup(matrix: Matrix<Double>): LupDecomposition<Double> =
|
||||
lup(Buffer.Companion::real, matrix) { it < 1e-11 }
|
||||
lup(::RealBuffer, matrix) { it < 1e-11 }
|
||||
|
||||
public fun <T : Any> LupDecomposition<T>.solveWithLup(
|
||||
factory: MutableBufferFactory<T>,
|
||||
@ -230,7 +230,7 @@ public inline fun <reified T : Comparable<T>> LinearSpace<T, Field<T>>.inverseWi
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
public fun LinearSpace<Double, RealField>.solveWithLup(a: Matrix<Double>, b: Matrix<Double>): Matrix<Double> {
|
||||
// Use existing decomposition if it is provided by matrix
|
||||
val bufferFactory: MutableBufferFactory<Double> = MutableBuffer.Companion::real
|
||||
val bufferFactory: MutableBufferFactory<Double> = ::RealBuffer
|
||||
val decomposition: LupDecomposition<Double> = a.getFeature() ?: lup(bufferFactory, a) { it < 1e-11 }
|
||||
return decomposition.solveWithLup(bufferFactory, b)
|
||||
}
|
||||
|
@ -48,8 +48,8 @@ public interface NDStructure<T> {
|
||||
public override fun hashCode(): Int
|
||||
|
||||
/**
|
||||
* Feature is additional property or hint that does not directly affect the structure, but could in some cases help
|
||||
* optimize operations and performance. If the feature is not present, null is defined.
|
||||
* Feature is some additional strucure information which allows to access it special properties or hints.
|
||||
* If the feature is not present, null is returned.
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <F : Any> getFeature(type: KClass<F>): F? = null
|
||||
|
@ -5,7 +5,6 @@ import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.NumbersAddOperations
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.operations.ScaleOperations
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.RealBuffer
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
@ -13,7 +12,7 @@ import kotlin.contracts.contract
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
public class RealNDField(
|
||||
shape: IntArray,
|
||||
) : BufferedNDField<Double, RealField>(shape, RealField, Buffer.Companion::real),
|
||||
) : BufferedNDField<Double, RealField>(shape, RealField, ::RealBuffer),
|
||||
NumbersAddOperations<NDStructure<Double>>,
|
||||
ScaleOperations<NDStructure<Double>>,
|
||||
ExtendedField<NDStructure<Double>> {
|
||||
|
@ -56,3 +56,12 @@ public fun <T> NDStructure<T>.as1D(): Structure1D<T> = this as? Structure1D<T> ?
|
||||
* Represent this buffer as 1D structure
|
||||
*/
|
||||
public fun <T> Buffer<T>.asND(): Structure1D<T> = Buffer1DWrapper(this)
|
||||
|
||||
/**
|
||||
* Expose inner buffer of this [Structure1D] if possible
|
||||
*/
|
||||
internal fun <T : Any> Structure1D<T>.unwrap(): Buffer<T> = when {
|
||||
this is Buffer1DWrapper<T> -> buffer
|
||||
this is Structure1DWrapper && structure is NDBuffer<T> -> structure.buffer
|
||||
else -> this
|
||||
}
|
||||
|
@ -86,4 +86,9 @@ public fun <T> NDStructure<T>.as2D(): Structure2D<T> = this as? Structure2D<T> ?
|
||||
else -> error("Can't create 2d-structure from ${shape.size}d-structure")
|
||||
}
|
||||
|
||||
internal fun <T> Structure2D<T>.unwrap(): NDStructure<T> = if (this is Structure2DWrapper) structure else this
|
||||
/**
|
||||
* Expose inner [NDStructure] if possible
|
||||
*/
|
||||
internal fun <T> Structure2D<T>.unwrap(): NDStructure<T> =
|
||||
if (this is Structure2DWrapper) structure
|
||||
else this
|
@ -44,21 +44,12 @@ public interface Buffer<out T> {
|
||||
asSequence().mapIndexed { index, value -> value == other[index] }.all { it }
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified
|
||||
* [initializer] function.
|
||||
*/
|
||||
public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer =
|
||||
RealBuffer(size) { initializer(it) }
|
||||
|
||||
/**
|
||||
* 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> =
|
||||
ListBuffer(List(size, initializer))
|
||||
|
||||
// TODO add resolution based on Annotation or companion resolution
|
||||
List(size, initializer).asBuffer()
|
||||
|
||||
/**
|
||||
* Creates a [Buffer] of given [type]. If the type is primitive, specialized buffers are used ([IntBuffer],
|
||||
@ -69,11 +60,11 @@ public interface Buffer<out T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public inline fun <T : Any> auto(type: KClass<T>, size: Int, initializer: (Int) -> T): Buffer<T> =
|
||||
when (type) {
|
||||
Double::class -> RealBuffer(size) { initializer(it) as Double } as Buffer<T>
|
||||
Short::class -> ShortBuffer(size) { initializer(it) as Short } as Buffer<T>
|
||||
Int::class -> IntBuffer(size) { initializer(it) as Int } as Buffer<T>
|
||||
Long::class -> LongBuffer(size) { initializer(it) as Long } as Buffer<T>
|
||||
Float::class -> FloatBuffer(size) { initializer(it) as Float } as Buffer<T>
|
||||
Double::class -> MutableBuffer.real(size) { initializer(it) as Double } as Buffer<T>
|
||||
Short::class -> MutableBuffer.short(size) { initializer(it) as Short } as Buffer<T>
|
||||
Int::class -> MutableBuffer.int(size) { initializer(it) as Int } as Buffer<T>
|
||||
Long::class -> MutableBuffer.long(size) { initializer(it) as Long } as Buffer<T>
|
||||
Float::class -> MutableBuffer.float(size) { initializer(it) as Float } as Buffer<T>
|
||||
else -> boxing(size, initializer)
|
||||
}
|
||||
|
||||
@ -89,41 +80,6 @@ public interface Buffer<out T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sequence that returns all elements from this [Buffer].
|
||||
*/
|
||||
public fun <T> Buffer<T>.asSequence(): Sequence<T> = Sequence(::iterator)
|
||||
|
||||
/**
|
||||
* Creates an iterable that returns all elements from this [Buffer].
|
||||
*/
|
||||
public fun <T> Buffer<T>.asIterable(): Iterable<T> = Iterable(::iterator)
|
||||
|
||||
/**
|
||||
* Returns a new [List] containing all elements of this buffer.
|
||||
*/
|
||||
public fun <T> Buffer<T>.toList(): List<T> = when (this) {
|
||||
is ArrayBuffer<T> -> array.toList()
|
||||
is ListBuffer<T> -> list.toList()
|
||||
is MutableListBuffer<T> -> list.toList()
|
||||
else -> asSequence().toList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new [MutableList] filled with all elements of this buffer.
|
||||
*/
|
||||
public fun <T> Buffer<T>.toMutableList(): MutableList<T> = when (this) {
|
||||
is ArrayBuffer<T> -> array.toMutableList()
|
||||
is ListBuffer<T> -> list.toMutableList()
|
||||
is MutableListBuffer<T> -> list.toMutableList()
|
||||
else -> asSequence().toMutableList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new [Array] containing all elements of this buffer.
|
||||
*/
|
||||
public inline fun <reified T> Buffer<T>.toTypedArray(): Array<T> = asSequence().toList().toTypedArray()
|
||||
|
||||
/**
|
||||
* Returns an [IntRange] of the valid indices for this [Buffer].
|
||||
*/
|
||||
@ -146,6 +102,44 @@ public interface MutableBuffer<T> : Buffer<T> {
|
||||
public fun copy(): MutableBuffer<T>
|
||||
|
||||
public companion object {
|
||||
|
||||
/**
|
||||
* Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified
|
||||
* [initializer] function.
|
||||
*/
|
||||
public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer =
|
||||
RealBuffer(size, initializer)
|
||||
|
||||
/**
|
||||
* Creates a [ShortBuffer] with the specified [size], where each element is calculated by calling the specified
|
||||
* [initializer] function.
|
||||
*/
|
||||
public inline fun short(size: Int, initializer: (Int) -> Short): ShortBuffer =
|
||||
ShortBuffer(size, initializer)
|
||||
|
||||
/**
|
||||
* Creates a [IntBuffer] with the specified [size], where each element is calculated by calling the specified
|
||||
* [initializer] function.
|
||||
*/
|
||||
public inline fun int(size: Int, initializer: (Int) -> Int): IntBuffer =
|
||||
IntBuffer(size, initializer)
|
||||
|
||||
/**
|
||||
* Creates a [LongBuffer] with the specified [size], where each element is calculated by calling the specified
|
||||
* [initializer] function.
|
||||
*/
|
||||
public inline fun long(size: Int, initializer: (Int) -> Long): LongBuffer =
|
||||
LongBuffer(size, initializer)
|
||||
|
||||
|
||||
/**
|
||||
* Creates a [FloatBuffer] with the specified [size], where each element is calculated by calling the specified
|
||||
* [initializer] function.
|
||||
*/
|
||||
public inline fun float(size: Int, initializer: (Int) -> Float): FloatBuffer =
|
||||
FloatBuffer(size, initializer)
|
||||
|
||||
|
||||
/**
|
||||
* Create a boxing mutable buffer of given type
|
||||
*/
|
||||
@ -161,11 +155,11 @@ public interface MutableBuffer<T> : Buffer<T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public inline fun <T : Any> auto(type: KClass<out T>, size: Int, initializer: (Int) -> T): MutableBuffer<T> =
|
||||
when (type) {
|
||||
Double::class -> RealBuffer(size) { initializer(it) as Double } as MutableBuffer<T>
|
||||
Short::class -> ShortBuffer(size) { initializer(it) as Short } as MutableBuffer<T>
|
||||
Int::class -> IntBuffer(size) { initializer(it) as Int } as MutableBuffer<T>
|
||||
Float::class -> FloatBuffer(size) { initializer(it) as Float } as MutableBuffer<T>
|
||||
Long::class -> LongBuffer(size) { initializer(it) as Long } as MutableBuffer<T>
|
||||
Double::class -> real(size) { initializer(it) as Double } as MutableBuffer<T>
|
||||
Short::class -> short(size) { initializer(it) as Short } as MutableBuffer<T>
|
||||
Int::class -> int(size) { initializer(it) as Int } as MutableBuffer<T>
|
||||
Float::class -> float(size) { initializer(it) as Float } as MutableBuffer<T>
|
||||
Long::class -> long(size) { initializer(it) as Long } as MutableBuffer<T>
|
||||
else -> boxing(size, initializer)
|
||||
}
|
||||
|
||||
@ -178,13 +172,6 @@ public interface MutableBuffer<T> : Buffer<T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public inline fun <reified T : Any> auto(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
|
||||
auto(T::class, size, initializer)
|
||||
|
||||
/**
|
||||
* Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified
|
||||
* [initializer] function.
|
||||
*/
|
||||
public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer =
|
||||
RealBuffer(size) { initializer(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,15 +194,6 @@ public inline class ListBuffer<T>(public val list: List<T>) : Buffer<T> {
|
||||
*/
|
||||
public fun <T> List<T>.asBuffer(): ListBuffer<T> = ListBuffer(this)
|
||||
|
||||
/**
|
||||
* Creates a new [ListBuffer] with the specified [size], where each element is calculated by calling the specified
|
||||
* [init] function.
|
||||
*
|
||||
* The function [init] is called for each array element sequentially starting from the first one.
|
||||
* It should return the value for an array element given its index.
|
||||
*/
|
||||
public inline fun <T> ListBuffer(size: Int, init: (Int) -> T): ListBuffer<T> = List(size, init).asBuffer()
|
||||
|
||||
/**
|
||||
* [MutableBuffer] implementation over [MutableList].
|
||||
*
|
||||
@ -236,6 +214,11 @@ public inline class MutableListBuffer<T>(public val list: MutableList<T>) : Muta
|
||||
override fun copy(): MutableBuffer<T> = MutableListBuffer(ArrayList(list))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an [ListBuffer] that wraps the original list.
|
||||
*/
|
||||
public fun <T> MutableList<T>.asMutableBuffer(): MutableListBuffer<T> = MutableListBuffer(this)
|
||||
|
||||
/**
|
||||
* [MutableBuffer] implementation over [Array].
|
||||
*
|
||||
@ -244,8 +227,7 @@ public inline class MutableListBuffer<T>(public val list: MutableList<T>) : Muta
|
||||
*/
|
||||
public class ArrayBuffer<T>(internal val array: Array<T>) : MutableBuffer<T> {
|
||||
// Can't inline because array is invariant
|
||||
override val size: Int
|
||||
get() = array.size
|
||||
override val size: Int get() = array.size
|
||||
|
||||
override operator fun get(index: Int): T = array[index]
|
||||
|
||||
@ -263,16 +245,6 @@ public class ArrayBuffer<T>(internal val array: Array<T>) : MutableBuffer<T> {
|
||||
*/
|
||||
public fun <T> Array<T>.asBuffer(): ArrayBuffer<T> = ArrayBuffer(this)
|
||||
|
||||
/**
|
||||
* Creates a new [ArrayBuffer] with the specified [size], where each element is calculated by calling the specified
|
||||
* [init] function.
|
||||
*
|
||||
* The function [init] is called for each array element sequentially starting from the first one.
|
||||
* It should return the value for an array element given its index.
|
||||
*/
|
||||
public inline fun <reified T> ArrayBuffer(size: Int, init: (Int) -> T): ArrayBuffer<T> =
|
||||
Array(size) { i -> init(i) }.asBuffer()
|
||||
|
||||
/**
|
||||
* Immutable wrapper for [MutableBuffer].
|
||||
*
|
||||
@ -314,13 +286,3 @@ public class VirtualBuffer<T>(override val size: Int, private val generator: (In
|
||||
* Convert this buffer to read-only buffer.
|
||||
*/
|
||||
public fun <T> Buffer<T>.asReadOnly(): Buffer<T> = if (this is MutableBuffer) ReadOnlyBuffer(this) else this
|
||||
|
||||
/**
|
||||
* Typealias for buffer transformations.
|
||||
*/
|
||||
public typealias BufferTransform<T, R> = (Buffer<T>) -> Buffer<R>
|
||||
|
||||
/**
|
||||
* Typealias for buffer transformations with suspend function.
|
||||
*/
|
||||
public typealias SuspendBufferTransform<T, R> = suspend (Buffer<T>) -> Buffer<R>
|
||||
|
@ -1,7 +1,84 @@
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
|
||||
/**
|
||||
* Typealias for buffer transformations.
|
||||
*/
|
||||
public typealias BufferTransform<T, R> = (Buffer<T>) -> Buffer<R>
|
||||
|
||||
/**
|
||||
* Typealias for buffer transformations with suspend function.
|
||||
*/
|
||||
public typealias SuspendBufferTransform<T, R> = suspend (Buffer<T>) -> Buffer<R>
|
||||
|
||||
|
||||
/**
|
||||
* Creates a sequence that returns all elements from this [Buffer].
|
||||
*/
|
||||
public fun <T> Buffer<T>.asSequence(): Sequence<T> = Sequence(::iterator)
|
||||
|
||||
/**
|
||||
* Creates an iterable that returns all elements from this [Buffer].
|
||||
*/
|
||||
public fun <T> Buffer<T>.asIterable(): Iterable<T> = Iterable(::iterator)
|
||||
|
||||
/**
|
||||
* Returns a new [List] containing all elements of this buffer.
|
||||
*/
|
||||
public fun <T> Buffer<T>.toList(): List<T> = when (this) {
|
||||
is ArrayBuffer<T> -> array.toList()
|
||||
is ListBuffer<T> -> list.toList()
|
||||
is MutableListBuffer<T> -> list.toList()
|
||||
else -> asSequence().toList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new [MutableList] filled with all elements of this buffer.
|
||||
* **NOTE:** this method uses a protective copy, so it should not be used in performance-critical code.
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T> Buffer<T>.toMutableList(): MutableList<T> = when (this) {
|
||||
is ArrayBuffer<T> -> array.toMutableList()
|
||||
is ListBuffer<T> -> list.toMutableList()
|
||||
is MutableListBuffer<T> -> list.toMutableList()
|
||||
else -> MutableList(size, ::get)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new [Array] containing all elements of this buffer.
|
||||
* **NOTE:** this method uses a protective copy, so it should not be used in performance-critical code.
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public inline fun <reified T> Buffer<T>.toTypedArray(): Array<T> = Array(size, ::get)
|
||||
|
||||
/**
|
||||
* Create a new buffer from this one with the given mapping function.
|
||||
* Provided [BufferFactory] is used to construct the new buffer.
|
||||
*/
|
||||
public inline fun <T : Any, reified R : Any> Buffer<T>.map(
|
||||
bufferFactory: BufferFactory<R> = Buffer.Companion::auto,
|
||||
crossinline block: (T) -> R,
|
||||
): Buffer<R> = bufferFactory(size) { block(get(it)) }
|
||||
|
||||
/**
|
||||
* Create a new buffer from this one with the given indexed mapping function.
|
||||
* Provided [BufferFactory] is used to construct the new buffer.
|
||||
*/
|
||||
public inline fun <T : Any, reified R : Any> Buffer<T>.mapIndexed(
|
||||
bufferFactory: BufferFactory<R> = Buffer.Companion::auto,
|
||||
crossinline block: (index: Int, value: T) -> R,
|
||||
): Buffer<R> = bufferFactory(size) { block(it, get(it)) }
|
||||
|
||||
/**
|
||||
* Zip two buffers using given [transform].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public inline fun <T1 : Any, T2 : Any, reified R : Any> Buffer<T1>.zip(
|
||||
other: Buffer<T2>,
|
||||
bufferFactory: BufferFactory<R> = Buffer.Companion::auto,
|
||||
crossinline transform: (T1, T2) -> R,
|
||||
): Buffer<R> {
|
||||
require(size == other.size) { "Buffer size mismatch in zip: expected $size but found ${other.size}" }
|
||||
return bufferFactory(size) { transform(get(it), other[it]) }
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
package space.kscience.kmath.real
|
||||
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.Norm
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.MutableBuffer.Companion.real
|
||||
import space.kscience.kmath.structures.asBuffer
|
||||
import space.kscience.kmath.structures.asIterable
|
||||
import space.kscience.kmath.structures.indices
|
||||
@ -20,15 +22,16 @@ public operator fun Buffer.Companion.invoke(vararg doubles: Double): RealVector
|
||||
/**
|
||||
* Fill the vector of given [size] with given [value]
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun Buffer.Companion.same(size: Int, value: Number): RealVector = real(size) { value.toDouble() }
|
||||
|
||||
// Transformation methods
|
||||
|
||||
public inline fun RealVector.map(transform: (Double) -> Double): RealVector =
|
||||
Buffer.real(size) { transform(get(it)) }
|
||||
real(size) { transform(get(it)) }
|
||||
|
||||
public inline fun RealVector.mapIndexed(transform: (index: Int, value: Double) -> Double): RealVector =
|
||||
Buffer.real(size) { transform(it, get(it)) }
|
||||
real(size) { transform(it, get(it)) }
|
||||
|
||||
public operator fun RealVector.plus(other: RealVector): RealVector {
|
||||
require(size == other.size) { "Vector size $size expected but ${other.size} found" }
|
||||
|
@ -4,30 +4,30 @@ import space.kscience.kmath.linear.LinearSpace
|
||||
import space.kscience.kmath.linear.asMatrix
|
||||
import space.kscience.kmath.linear.transpose
|
||||
import space.kscience.kmath.real.plus
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.RealBuffer
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class RealVectorTest {
|
||||
@Test
|
||||
fun testSum() {
|
||||
val vector1 = Buffer.real(5) { it.toDouble() }
|
||||
val vector2 = Buffer.real(5) { 5 - it.toDouble() }
|
||||
val vector1 = RealBuffer(5) { it.toDouble() }
|
||||
val vector2 = RealBuffer(5) { 5 - it.toDouble() }
|
||||
val sum = vector1 + vector2
|
||||
assertEquals(5.0, sum[2])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testVectorToMatrix() {
|
||||
val vector = Buffer.real(5) { it.toDouble() }
|
||||
val vector = RealBuffer(5) { it.toDouble() }
|
||||
val matrix = vector.asMatrix()
|
||||
assertEquals(4.0, matrix[4, 0])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDot() {
|
||||
val vector1 = Buffer.real(5) { it.toDouble() }
|
||||
val vector2 = Buffer.real(5) { 5 - it.toDouble() }
|
||||
val vector1 = RealBuffer(5) { it.toDouble() }
|
||||
val vector2 = RealBuffer(5) { 5 - it.toDouble() }
|
||||
val matrix1 = vector1.asMatrix()
|
||||
val matrix2 = vector2.asMatrix().transpose()
|
||||
val product = LinearSpace.real.run { matrix1 dot matrix2 }
|
||||
|
@ -2,8 +2,8 @@ package space.kscience.kmath.histogram
|
||||
|
||||
import space.kscience.kmath.domains.Domain
|
||||
import space.kscience.kmath.linear.Point
|
||||
import space.kscience.kmath.structures.ArrayBuffer
|
||||
import space.kscience.kmath.structures.RealBuffer
|
||||
import space.kscience.kmath.structures.asBuffer
|
||||
|
||||
/**
|
||||
* The binned data element. Could be a histogram bin with a number of counts or an artificial construct
|
||||
@ -40,7 +40,7 @@ public fun interface HistogramBuilder<T : Any> {
|
||||
|
||||
public fun <T : Any, B : Bin<T>> HistogramBuilder<T>.put(point: Point<out T>): Unit = putValue(point, 1.0)
|
||||
|
||||
public fun <T : Any> HistogramBuilder<T>.put(vararg point: T): Unit = put(ArrayBuffer(point))
|
||||
public fun <T : Any> HistogramBuilder<T>.put(vararg point: T): Unit = put(point.asBuffer())
|
||||
|
||||
public fun HistogramBuilder<Double>.put(vararg point: Number): Unit =
|
||||
put(RealBuffer(point.map { it.toDouble() }.toDoubleArray()))
|
||||
|
@ -4,6 +4,7 @@ import space.kscience.kmath.chains.Chain
|
||||
import space.kscience.kmath.chains.collect
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.BufferFactory
|
||||
import space.kscience.kmath.structures.RealBuffer
|
||||
|
||||
public interface Sampler<T : Any> {
|
||||
public fun sample(generator: RandomGenerator): Chain<T>
|
||||
@ -74,4 +75,4 @@ public fun <T : Any> Sampler<T>.sampleBuffer(
|
||||
* Generate a bunch of samples from real distributions
|
||||
*/
|
||||
public fun Sampler<Double>.sampleBuffer(generator: RandomGenerator, size: Int): Chain<Buffer<Double>> =
|
||||
sampleBuffer(generator, size, Buffer.Companion::real)
|
||||
sampleBuffer(generator, size, ::RealBuffer)
|
||||
|
Loading…
Reference in New Issue
Block a user