Extended documentation, code refactoring, API consistency changes #125
@ -5,19 +5,19 @@ import scientifik.kmath.operations.Ring
|
||||
import scientifik.kmath.operations.Space
|
||||
|
||||
/**
|
||||
* Create a functional expression on this [Space]
|
||||
* Creates a functional expression with this [Space].
|
||||
*/
|
||||
fun <T> Space<T>.spaceExpression(block: FunctionalExpressionSpace<T, Space<T>>.() -> Expression<T>): Expression<T> =
|
||||
FunctionalExpressionSpace(this).run(block)
|
||||
|
||||
/**
|
||||
* Create a functional expression on this [Ring]
|
||||
* Creates a functional expression with this [Ring].
|
||||
*/
|
||||
fun <T> Ring<T>.ringExpression(block: FunctionalExpressionRing<T, Ring<T>>.() -> Expression<T>): Expression<T> =
|
||||
FunctionalExpressionRing(this).run(block)
|
||||
|
||||
/**
|
||||
* Create a functional expression on this [Field]
|
||||
* Creates a functional expression with this [Field].
|
||||
*/
|
||||
fun <T> Field<T>.fieldExpression(block: FunctionalExpressionField<T, Field<T>>.() -> Expression<T>): Expression<T> =
|
||||
FunctionalExpressionField(this).run(block)
|
||||
|
@ -12,8 +12,21 @@ interface MathElement<C> {
|
||||
val context: C
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents element that can be wrapped to its "primitive" value.
|
||||
*
|
||||
* @param T the type wrapped by this wrapper.
|
||||
* @param I the type of this wrapper.
|
||||
*/
|
||||
interface MathWrapper<T, I> {
|
||||
/**
|
||||
* Unwraps [I] to [T].
|
||||
*/
|
||||
fun unwrap(): T
|
||||
|
||||
/**
|
||||
* Wraps [T] to [I].
|
||||
*/
|
||||
fun T.wrap(): I
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,11 @@ typealias BufferFactory<T> = (Int, (Int) -> T) -> Buffer<T>
|
||||
typealias MutableBufferFactory<T> = (Int, (Int) -> T) -> MutableBuffer<T>
|
||||
|
||||
/**
|
||||
* A generic random-access structure for both primitives and objects.
|
||||
* A generic immutable random-access structure for both primitives and objects.
|
||||
*
|
||||
* @param T the type of elements contained in the buffer.
|
||||
*/
|
||||
interface Buffer<T> {
|
||||
|
||||
/**
|
||||
* The size of this buffer.
|
||||
*/
|
||||
@ -45,7 +46,6 @@ interface Buffer<T> {
|
||||
asSequence().mapIndexed { index, value -> value == other[index] }.all { it }
|
||||
|
||||
companion object {
|
||||
|
||||
inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer {
|
||||
val array = DoubleArray(size) { initializer(it) }
|
||||
return RealBuffer(array)
|
||||
@ -95,6 +95,8 @@ val Buffer<*>.indices: IntRange get() = 0 until size
|
||||
|
||||
/**
|
||||
* A generic mutable random-access structure for both primitives and objects.
|
||||
*
|
||||
* @param T the type of elements contained in the buffer.
|
||||
*/
|
||||
interface MutableBuffer<T> : Buffer<T> {
|
||||
/**
|
||||
@ -138,8 +140,13 @@ interface MutableBuffer<T> : Buffer<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [Buffer] implementation over [List].
|
||||
*
|
||||
* @param T the type of elements contained in the buffer.
|
||||
* @property list The underlying list.
|
||||
*/
|
||||
inline class ListBuffer<T>(val list: List<T>) : Buffer<T> {
|
||||
|
||||
override val size: Int
|
||||
get() = list.size
|
||||
|
||||
@ -148,10 +155,26 @@ inline class ListBuffer<T>(val list: List<T>) : Buffer<T> {
|
||||
override fun iterator(): Iterator<T> = list.iterator()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an [ListBuffer] that wraps the original list.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
inline fun <T> ListBuffer(size: Int, init: (Int) -> T): ListBuffer<T> = List(size, init).asBuffer()
|
||||
|
||||
/**
|
||||
* [MutableBuffer] implementation over [MutableList].
|
||||
*
|
||||
* @param T the type of elements contained in the buffer.
|
||||
* @property list The underlying list.
|
||||
*/
|
||||
inline class MutableListBuffer<T>(val list: MutableList<T>) : MutableBuffer<T> {
|
||||
|
||||
override val size: Int
|
||||
@ -167,6 +190,12 @@ inline class MutableListBuffer<T>(val list: MutableList<T>) : MutableBuffer<T> {
|
||||
override fun copy(): MutableBuffer<T> = MutableListBuffer(ArrayList(list))
|
||||
}
|
||||
|
||||
/**
|
||||
* [MutableBuffer] implementation over [Array].
|
||||
*
|
||||
* @param T the type of elements contained in the buffer.
|
||||
* @property array The underlying array.
|
||||
*/
|
||||
class ArrayBuffer<T>(private val array: Array<T>) : MutableBuffer<T> {
|
||||
// Can't inline because array is invariant
|
||||
override val size: Int
|
||||
@ -183,8 +212,17 @@ class ArrayBuffer<T>(private val array: Array<T>) : MutableBuffer<T> {
|
||||
override fun copy(): MutableBuffer<T> = ArrayBuffer(array.copyOf())
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an [ArrayBuffer] that wraps the original array.
|
||||
*/
|
||||
fun <T> Array<T>.asBuffer(): ArrayBuffer<T> = ArrayBuffer(this)
|
||||
|
||||
/**
|
||||
* Immutable wrapper for [MutableBuffer].
|
||||
*
|
||||
* @param T the type of elements contained in the buffer.
|
||||
* @property buffer The underlying buffer.
|
||||
*/
|
||||
inline class ReadOnlyBuffer<T>(val buffer: MutableBuffer<T>) : Buffer<T> {
|
||||
override val size: Int get() = buffer.size
|
||||
|
||||
@ -196,6 +234,8 @@ inline class ReadOnlyBuffer<T>(val buffer: MutableBuffer<T>) : Buffer<T> {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param T the type of elements provided by the buffer.
|
||||
*/
|
||||
class VirtualBuffer<T>(override val size: Int, private val generator: (Int) -> T) : Buffer<T> {
|
||||
override fun get(index: Int): T {
|
||||
@ -215,17 +255,16 @@ class VirtualBuffer<T>(override val size: Int, private val generator: (Int) -> T
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this buffer to read-only buffer
|
||||
* Convert this buffer to read-only buffer.
|
||||
*/
|
||||
fun <T> Buffer<T>.asReadOnly(): Buffer<T> = if (this is MutableBuffer) {
|
||||
ReadOnlyBuffer(this)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
fun <T> Buffer<T>.asReadOnly(): Buffer<T> = if (this is MutableBuffer) ReadOnlyBuffer(this) else this
|
||||
|
||||
/**
|
||||
* Typealias for buffer transformations
|
||||
* Typealias for buffer transformations.
|
||||
*/
|
||||
typealias BufferTransform<T, R> = (Buffer<T>) -> Buffer<R>
|
||||
|
||||
/**
|
||||
* Typealias for buffer transformations with suspend function.
|
||||
*/
|
||||
typealias SuspendBufferTransform<T, R> = suspend (Buffer<T>) -> Buffer<R>
|
||||
|
@ -2,15 +2,35 @@ package scientifik.kmath.structures
|
||||
|
||||
import kotlin.experimental.and
|
||||
|
||||
/**
|
||||
* Represents flags to supply additional info about values of buffer.
|
||||
*
|
||||
* @property mask bit mask value of this flag.
|
||||
*/
|
||||
enum class ValueFlag(val mask: Byte) {
|
||||
/**
|
||||
* Reports the value is NaN.
|
||||
*/
|
||||
NAN(0b0000_0001),
|
||||
|
||||
/**
|
||||
* Reports the value doesn't present in the buffer (when the type of value doesn't support `null`).
|
||||
*/
|
||||
MISSING(0b0000_0010),
|
||||
|
||||
/**
|
||||
* Reports the value is negative infinity.
|
||||
*/
|
||||
NEGATIVE_INFINITY(0b0000_0100),
|
||||
|
||||
/**
|
||||
* Reports the value is positive infinity
|
||||
*/
|
||||
POSITIVE_INFINITY(0b0000_1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffer with flagged values
|
||||
* A buffer with flagged values.
|
||||
*/
|
||||
interface FlaggedBuffer<T> : Buffer<T> {
|
||||
fun getFlag(index: Int): Byte
|
||||
|
@ -0,0 +1,49 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
/**
|
||||
* Specialized [MutableBuffer] implementation over [FloatArray].
|
||||
*
|
||||
* @property array the underlying array.
|
||||
*/
|
||||
inline class FloatBuffer(val array: FloatArray) : MutableBuffer<Float> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
override fun get(index: Int): Float = array[index]
|
||||
|
||||
override fun set(index: Int, value: Float) {
|
||||
array[index] = value
|
||||
}
|
||||
|
||||
override fun iterator(): FloatIterator = array.iterator()
|
||||
|
||||
override fun copy(): MutableBuffer<Float> =
|
||||
FloatBuffer(array.copyOf())
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new [FloatBuffer] 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 buffer element given its index.
|
||||
*/
|
||||
inline fun FloatBuffer(size: Int, init: (Int) -> Float): FloatBuffer = FloatBuffer(FloatArray(size) { init(it) })
|
||||
|
||||
/**
|
||||
* Returns a new [FloatBuffer] of given elements.
|
||||
*/
|
||||
fun FloatBuffer(vararg floats: Float): FloatBuffer = FloatBuffer(floats)
|
||||
|
||||
/**
|
||||
* Returns a [FloatArray] containing all of the elements of this [MutableBuffer].
|
||||
*/
|
||||
val MutableBuffer<out Float>.array: FloatArray
|
||||
get() = (if (this is FloatBuffer) array else FloatArray(size) { get(it) })
|
||||
|
||||
/**
|
||||
* Returns [FloatBuffer] over this array.
|
||||
*
|
||||
* @receiver the array.
|
||||
* @return the new buffer.
|
||||
*/
|
||||
fun FloatArray.asBuffer(): FloatBuffer = FloatBuffer(this)
|
@ -26,15 +26,13 @@ inline class IntBuffer(val array: IntArray) : MutableBuffer<Int> {
|
||||
* [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.
|
||||
* It should return the value for an buffer element given its index.
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
inline fun IntBuffer(size: Int, init: (Int) -> Int): IntBuffer = IntBuffer(IntArray(size) { init(it) })
|
||||
|
||||
/**
|
||||
* Returns a new [IntBuffer] of given elements.
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
fun IntBuffer(vararg ints: Int): IntBuffer = IntBuffer(ints)
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,10 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
/**
|
||||
* Specialized [MutableBuffer] implementation over [LongArray].
|
||||
*
|
||||
* @property array the underlying array.
|
||||
*/
|
||||
inline class LongBuffer(val array: LongArray) : MutableBuffer<Long> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
@ -16,4 +21,30 @@ inline class LongBuffer(val array: LongArray) : MutableBuffer<Long> {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new [LongBuffer] 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 buffer element given its index.
|
||||
*/
|
||||
inline fun LongBuffer(size: Int, init: (Int) -> Long): LongBuffer = LongBuffer(LongArray(size) { init(it) })
|
||||
|
||||
/**
|
||||
* Returns a new [LongBuffer] of given elements.
|
||||
*/
|
||||
fun LongBuffer(vararg longs: Long): LongBuffer = LongBuffer(longs)
|
||||
|
||||
/**
|
||||
* Returns a [IntArray] containing all of the elements of this [MutableBuffer].
|
||||
*/
|
||||
val MutableBuffer<out Long>.array: LongArray
|
||||
get() = (if (this is LongBuffer) array else LongArray(size) { get(it) })
|
||||
|
||||
/**
|
||||
* Returns [LongBuffer] over this array.
|
||||
*
|
||||
* @receiver the array.
|
||||
* @return the new buffer.
|
||||
*/
|
||||
fun LongArray.asBuffer(): LongBuffer = LongBuffer(this)
|
||||
|
@ -4,12 +4,16 @@ import scientifik.memory.*
|
||||
|
||||
/**
|
||||
* A non-boxing buffer over [Memory] object.
|
||||
*
|
||||
* @param T the type of elements contained in the buffer.
|
||||
* @property memory the underlying memory segment.
|
||||
* @property spec the spec of [T] type.
|
||||
*/
|
||||
open class MemoryBuffer<T : Any>(protected val memory: Memory, protected val spec: MemorySpec<T>) : Buffer<T> {
|
||||
|
||||
override val size: Int get() = memory.size / spec.objectSize
|
||||
|
||||
private val reader = memory.reader()
|
||||
private val reader: MemoryReader = memory.reader()
|
||||
|
||||
override fun get(index: Int): T = reader.read(spec, spec.objectSize * index)
|
||||
|
||||
@ -33,6 +37,13 @@ open class MemoryBuffer<T : Any>(protected val memory: Memory, protected val spe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A mutable non-boxing buffer over [Memory] object.
|
||||
*
|
||||
* @param T the type of elements contained in the buffer.
|
||||
* @property memory the underlying memory segment.
|
||||
* @property spec the spec of [T] type.
|
||||
*/
|
||||
class MutableMemoryBuffer<T : Any>(memory: Memory, spec: MemorySpec<T>) : MemoryBuffer<T>(memory, spec),
|
||||
MutableBuffer<T> {
|
||||
|
||||
|
@ -107,8 +107,8 @@ interface NDRing<T, R : Ring<T>, N : NDStructure<T>> : Ring<N>, NDSpace<T, R, N>
|
||||
/**
|
||||
* Field for n-dimensional structures.
|
||||
*
|
||||
* @param T - the type of the element contained in ND structure
|
||||
* @param F - field of structure elements
|
||||
* @param T the type of the element contained in ND structure
|
||||
* @param F field of structure elements
|
||||
*/
|
||||
interface NDField<T, F : Field<T>, N : NDStructure<T>> : Field<N>, NDRing<T, F, N> {
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
/**
|
||||
* Specialized [MutableBuffer] implementation over [DoubleArray].
|
||||
*
|
||||
* @property array the underlying array.
|
||||
*/
|
||||
inline class RealBuffer(val array: DoubleArray) : MutableBuffer<Double> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
@ -16,19 +21,17 @@ inline class RealBuffer(val array: DoubleArray) : MutableBuffer<Double> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array with the specified [size], where each element is calculated by calling the specified
|
||||
* Creates a new [RealBuffer] 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.
|
||||
* It should return the value for an buffer element given its index.
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
inline fun RealBuffer(size: Int, init: (Int) -> Double): RealBuffer = RealBuffer(DoubleArray(size) { init(it) })
|
||||
|
||||
/**
|
||||
* Returns a new [RealBuffer] of given elements.
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles)
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,7 @@ import kotlin.math.*
|
||||
|
||||
|
||||
/**
|
||||
* A simple field over linear buffers of [Double]
|
||||
* [ExtendedFieldOperations] over [RealBuffer].
|
||||
*/
|
||||
object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
|
||||
override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
@ -109,6 +109,11 @@ object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
|
||||
RealBuffer(DoubleArray(arg.size) { ln(arg[it]) })
|
||||
}
|
||||
|
||||
/**
|
||||
* [ExtendedField] over [RealBuffer].
|
||||
*
|
||||
* @property size the size of buffers to operate on.
|
||||
*/
|
||||
class RealBufferField(val size: Int) : ExtendedField<Buffer<Double>> {
|
||||
override val zero: Buffer<Double> by lazy { RealBuffer(size) { 0.0 } }
|
||||
override val one: Buffer<Double> by lazy { RealBuffer(size) { 1.0 } }
|
||||
|
@ -1,5 +1,10 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
/**
|
||||
* Specialized [MutableBuffer] implementation over [ShortBuffer].
|
||||
*
|
||||
* @property array the underlying array.
|
||||
*/
|
||||
inline class ShortBuffer(val array: ShortArray) : MutableBuffer<Short> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
@ -16,4 +21,30 @@ inline class ShortBuffer(val array: ShortArray) : MutableBuffer<Short> {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new [ShortBuffer] 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 buffer element given its index.
|
||||
*/
|
||||
inline fun ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer = ShortBuffer(ShortArray(size) { init(it) })
|
||||
|
||||
/**
|
||||
* Returns a new [ShortBuffer] of given elements.
|
||||
*/
|
||||
fun ShortBuffer(vararg shorts: Short): ShortBuffer = ShortBuffer(shorts)
|
||||
|
||||
/**
|
||||
* Returns a [ShortArray] containing all of the elements of this [MutableBuffer].
|
||||
*/
|
||||
val MutableBuffer<out Short>.array: ShortArray
|
||||
get() = (if (this is ShortBuffer) array else ShortArray(size) { get(it) })
|
||||
|
||||
/**
|
||||
* Returns [ShortBuffer] over this array.
|
||||
*
|
||||
* @receiver the array.
|
||||
* @return the new buffer.
|
||||
*/
|
||||
fun ShortArray.asBuffer(): ShortBuffer = ShortBuffer(this)
|
||||
|
Loading…
Reference in New Issue
Block a user