Dev #127
@ -2,7 +2,7 @@
|
||||
Buffer is one of main building blocks of kmath. It is a basic interface allowing random-access read and write (with `MutableBuffer`).
|
||||
There are different types of buffers:
|
||||
|
||||
* Primitive buffers wrapping like `DoubleBuffer` which are wrapping primitive arrays.
|
||||
* Primitive buffers wrapping like `RealBuffer` which are wrapping primitive arrays.
|
||||
* Boxing `ListBuffer` wrapping a list
|
||||
* Functionally defined `VirtualBuffer` which does not hold a state itself, but provides a function to calculate value
|
||||
* `MemoryBuffer` allows direct allocation of objects in continuous memory block.
|
||||
|
@ -10,8 +10,8 @@ import scientifik.kmath.operations.complex
|
||||
class BufferBenchmark {
|
||||
|
||||
@Benchmark
|
||||
fun genericDoubleBufferReadWrite() {
|
||||
val buffer = DoubleBuffer(size){it.toDouble()}
|
||||
fun genericRealBufferReadWrite() {
|
||||
val buffer = RealBuffer(size){it.toDouble()}
|
||||
|
||||
(0 until size).forEach {
|
||||
buffer[it]
|
||||
|
@ -6,7 +6,7 @@ fun main(args: Array<String>) {
|
||||
val n = 6000
|
||||
|
||||
val array = DoubleArray(n * n) { 1.0 }
|
||||
val buffer = DoubleBuffer(array)
|
||||
val buffer = RealBuffer(array)
|
||||
val strides = DefaultStrides(intArrayOf(n, n))
|
||||
|
||||
val structure = BufferNDStructure(strides, buffer)
|
||||
|
@ -26,10 +26,10 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
println("Array mapping finished in $time2 millis")
|
||||
|
||||
val buffer = DoubleBuffer(DoubleArray(n * n) { 1.0 })
|
||||
val buffer = RealBuffer(DoubleArray(n * n) { 1.0 })
|
||||
|
||||
val time3 = measureTimeMillis {
|
||||
val target = DoubleBuffer(DoubleArray(n * n))
|
||||
val target = RealBuffer(DoubleArray(n * n))
|
||||
val res = array.forEachIndexed { index, value ->
|
||||
target[index] = value + 1
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ object Transformations {
|
||||
private fun Buffer<Complex>.toArray(): Array<org.apache.commons.math3.complex.Complex> =
|
||||
Array(size) { org.apache.commons.math3.complex.Complex(get(it).re, get(it).im) }
|
||||
|
||||
private fun Buffer<Double>.asArray() = if (this is DoubleBuffer) {
|
||||
private fun Buffer<Double>.asArray() = if (this is RealBuffer) {
|
||||
array
|
||||
} else {
|
||||
DoubleArray(size) { i -> get(i) }
|
||||
|
@ -16,7 +16,7 @@
|
||||
package scientifik.kmath.domains
|
||||
|
||||
import scientifik.kmath.linear.Point
|
||||
import scientifik.kmath.structures.DoubleBuffer
|
||||
import scientifik.kmath.structures.RealBuffer
|
||||
import scientifik.kmath.structures.indices
|
||||
|
||||
/**
|
||||
@ -25,7 +25,7 @@ import scientifik.kmath.structures.indices
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
class HyperSquareDomain(private val lower: DoubleBuffer, private val upper: DoubleBuffer) : RealDomain {
|
||||
class HyperSquareDomain(private val lower: RealBuffer, private val upper: RealBuffer) : RealDomain {
|
||||
|
||||
override operator fun contains(point: Point<Double>): Boolean = point.indices.all { i ->
|
||||
point[i] in lower[i]..upper[i]
|
||||
@ -49,7 +49,7 @@ class HyperSquareDomain(private val lower: DoubleBuffer, private val upper: Doub
|
||||
else -> point[i]
|
||||
}
|
||||
}
|
||||
return DoubleBuffer(*res)
|
||||
return RealBuffer(*res)
|
||||
}
|
||||
|
||||
override fun volume(): Double {
|
||||
|
@ -30,11 +30,11 @@ object RealMatrixContext : GenericMatrixContext<Double, RealField> {
|
||||
override val elementContext get() = RealField
|
||||
|
||||
override inline fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): Matrix<Double> {
|
||||
val buffer = DoubleBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) }
|
||||
val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) }
|
||||
return BufferMatrix(rows, columns, buffer)
|
||||
}
|
||||
|
||||
override inline fun point(size: Int, initializer: (Int) -> Double): Point<Double> = DoubleBuffer(size,initializer)
|
||||
override inline fun point(size: Int, initializer: (Int) -> Double): Point<Double> = RealBuffer(size,initializer)
|
||||
}
|
||||
|
||||
class BufferMatrix<T : Any>(
|
||||
@ -102,7 +102,7 @@ infix fun BufferMatrix<Double>.dot(other: BufferMatrix<Double>): BufferMatrix<Do
|
||||
val array = DoubleArray(this.rowNum * other.colNum)
|
||||
|
||||
//convert to array to insure there is not memory indirection
|
||||
fun Buffer<out Double>.unsafeArray(): DoubleArray = if (this is DoubleBuffer) {
|
||||
fun Buffer<out Double>.unsafeArray(): DoubleArray = if (this is RealBuffer) {
|
||||
array
|
||||
} else {
|
||||
DoubleArray(size) { get(it) }
|
||||
@ -119,6 +119,6 @@ infix fun BufferMatrix<Double>.dot(other: BufferMatrix<Double>): BufferMatrix<Do
|
||||
}
|
||||
}
|
||||
|
||||
val buffer = DoubleBuffer(array)
|
||||
val buffer = RealBuffer(array)
|
||||
return BufferMatrix(rowNum, other.colNum, buffer)
|
||||
}
|
@ -37,9 +37,9 @@ interface Buffer<T> {
|
||||
|
||||
companion object {
|
||||
|
||||
inline fun real(size: Int, initializer: (Int) -> Double): DoubleBuffer {
|
||||
inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer {
|
||||
val array = DoubleArray(size) { initializer(it) }
|
||||
return DoubleBuffer(array)
|
||||
return RealBuffer(array)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,7 +51,7 @@ interface Buffer<T> {
|
||||
inline fun <T : Any> auto(type: KClass<T>, size: Int, crossinline initializer: (Int) -> T): Buffer<T> {
|
||||
//TODO add resolution based on Annotation or companion resolution
|
||||
return when (type) {
|
||||
Double::class -> DoubleBuffer(DoubleArray(size) { initializer(it) as Double }) as Buffer<T>
|
||||
Double::class -> RealBuffer(DoubleArray(size) { initializer(it) as Double }) as Buffer<T>
|
||||
Short::class -> ShortBuffer(ShortArray(size) { initializer(it) as Short }) as Buffer<T>
|
||||
Int::class -> IntBuffer(IntArray(size) { initializer(it) as Int }) as Buffer<T>
|
||||
Long::class -> LongBuffer(LongArray(size) { initializer(it) as Long }) as Buffer<T>
|
||||
@ -93,7 +93,7 @@ interface MutableBuffer<T> : Buffer<T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <T : Any> auto(type: KClass<out T>, size: Int, initializer: (Int) -> T): MutableBuffer<T> {
|
||||
return when (type) {
|
||||
Double::class -> DoubleBuffer(DoubleArray(size) { initializer(it) as Double }) as MutableBuffer<T>
|
||||
Double::class -> RealBuffer(DoubleArray(size) { initializer(it) as Double }) as MutableBuffer<T>
|
||||
Short::class -> ShortBuffer(ShortArray(size) { initializer(it) as Short }) as MutableBuffer<T>
|
||||
Int::class -> IntBuffer(IntArray(size) { initializer(it) as Int }) as MutableBuffer<T>
|
||||
Long::class -> LongBuffer(LongArray(size) { initializer(it) as Long }) as MutableBuffer<T>
|
||||
@ -109,12 +109,11 @@ interface MutableBuffer<T> : Buffer<T> {
|
||||
auto(T::class, size, initializer)
|
||||
|
||||
val real: MutableBufferFactory<Double> = { size: Int, initializer: (Int) -> Double ->
|
||||
DoubleBuffer(DoubleArray(size) { initializer(it) })
|
||||
RealBuffer(DoubleArray(size) { initializer(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline class ListBuffer<T>(val list: List<T>) : Buffer<T> {
|
||||
|
||||
override val size: Int
|
||||
@ -163,57 +162,6 @@ class ArrayBuffer<T>(private val array: Array<T>) : MutableBuffer<T> {
|
||||
|
||||
fun <T> Array<T>.asBuffer(): ArrayBuffer<T> = ArrayBuffer(this)
|
||||
|
||||
inline class ShortBuffer(val array: ShortArray) : MutableBuffer<Short> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
override fun get(index: Int): Short = array[index]
|
||||
|
||||
override fun set(index: Int, value: Short) {
|
||||
array[index] = value
|
||||
}
|
||||
|
||||
override fun iterator() = array.iterator()
|
||||
|
||||
override fun copy(): MutableBuffer<Short> = ShortBuffer(array.copyOf())
|
||||
|
||||
}
|
||||
|
||||
fun ShortArray.asBuffer() = ShortBuffer(this)
|
||||
|
||||
inline class IntBuffer(val array: IntArray) : MutableBuffer<Int> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
override fun get(index: Int): Int = array[index]
|
||||
|
||||
override fun set(index: Int, value: Int) {
|
||||
array[index] = value
|
||||
}
|
||||
|
||||
override fun iterator() = array.iterator()
|
||||
|
||||
override fun copy(): MutableBuffer<Int> = IntBuffer(array.copyOf())
|
||||
|
||||
}
|
||||
|
||||
fun IntArray.asBuffer() = IntBuffer(this)
|
||||
|
||||
inline class LongBuffer(val array: LongArray) : MutableBuffer<Long> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
override fun get(index: Int): Long = array[index]
|
||||
|
||||
override fun set(index: Int, value: Long) {
|
||||
array[index] = value
|
||||
}
|
||||
|
||||
override fun iterator() = array.iterator()
|
||||
|
||||
override fun copy(): MutableBuffer<Long> = LongBuffer(array.copyOf())
|
||||
|
||||
}
|
||||
|
||||
fun LongArray.asBuffer() = LongBuffer(this)
|
||||
|
||||
inline class ReadOnlyBuffer<T>(val buffer: MutableBuffer<T>) : Buffer<T> {
|
||||
override val size: Int get() = buffer.size
|
||||
|
||||
|
@ -0,0 +1,53 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
import kotlin.experimental.and
|
||||
|
||||
enum class ValueFlag(val mask: Byte) {
|
||||
NAN(0b0000_0001),
|
||||
MISSING(0b0000_0010),
|
||||
NEGATIVE_INFINITY(0b0000_0100),
|
||||
POSITIVE_INFINITY(0b0000_1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffer with flagged values
|
||||
*/
|
||||
interface FlaggedBuffer<T> : Buffer<T> {
|
||||
fun getFlag(index: Int): Byte
|
||||
}
|
||||
|
||||
/**
|
||||
* The value is valid if all flags are down
|
||||
*/
|
||||
fun FlaggedBuffer<*>.isValid(index: Int) = getFlag(index) != 0.toByte()
|
||||
|
||||
fun FlaggedBuffer<*>.hasFlag(index: Int, flag: ValueFlag) = (getFlag(index) and flag.mask) != 0.toByte()
|
||||
|
||||
fun FlaggedBuffer<*>.isMissing(index: Int) = hasFlag(index, ValueFlag.MISSING)
|
||||
|
||||
/**
|
||||
* A real buffer which supports flags for each value like NaN or Missing
|
||||
*/
|
||||
class FlaggedRealBuffer(val values: DoubleArray, val flags: ByteArray) : FlaggedBuffer<Double?>, Buffer<Double?> {
|
||||
init {
|
||||
require(values.size == flags.size) { "Values and flags must have the same dimensions" }
|
||||
}
|
||||
|
||||
override fun getFlag(index: Int): Byte = flags[index]
|
||||
|
||||
override val size: Int get() = values.size
|
||||
|
||||
override fun get(index: Int): Double? = if (isValid(index)) values[index] else null
|
||||
|
||||
override fun iterator(): Iterator<Double?> = values.indices.asSequence().map {
|
||||
if (isValid(it)) values[it] else null
|
||||
}.iterator()
|
||||
}
|
||||
|
||||
inline fun FlaggedRealBuffer.forEachValid(block: (Double) -> Unit) {
|
||||
for(i in indices){
|
||||
if(isValid(i)){
|
||||
block(values[i])
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
inline class IntBuffer(val array: IntArray) : MutableBuffer<Int> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
override fun get(index: Int): Int = array[index]
|
||||
|
||||
override fun set(index: Int, value: Int) {
|
||||
array[index] = value
|
||||
}
|
||||
|
||||
override fun iterator() = array.iterator()
|
||||
|
||||
override fun copy(): MutableBuffer<Int> =
|
||||
IntBuffer(array.copyOf())
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun IntArray.asBuffer() = IntBuffer(this)
|
@ -0,0 +1,19 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
inline class LongBuffer(val array: LongArray) : MutableBuffer<Long> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
override fun get(index: Int): Long = array[index]
|
||||
|
||||
override fun set(index: Int, value: Long) {
|
||||
array[index] = value
|
||||
}
|
||||
|
||||
override fun iterator() = array.iterator()
|
||||
|
||||
override fun copy(): MutableBuffer<Long> =
|
||||
LongBuffer(array.copyOf())
|
||||
|
||||
}
|
||||
|
||||
fun LongArray.asBuffer() = LongBuffer(this)
|
@ -1,6 +1,6 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
inline class DoubleBuffer(val array: DoubleArray) : MutableBuffer<Double> {
|
||||
inline class RealBuffer(val array: DoubleArray) : MutableBuffer<Double> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
override fun get(index: Int): Double = array[index]
|
||||
@ -12,23 +12,23 @@ inline class DoubleBuffer(val array: DoubleArray) : MutableBuffer<Double> {
|
||||
override fun iterator() = array.iterator()
|
||||
|
||||
override fun copy(): MutableBuffer<Double> =
|
||||
DoubleBuffer(array.copyOf())
|
||||
RealBuffer(array.copyOf())
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
inline fun DoubleBuffer(size: Int, init: (Int) -> Double): DoubleBuffer = DoubleBuffer(DoubleArray(size) { init(it) })
|
||||
inline fun RealBuffer(size: Int, init: (Int) -> Double): RealBuffer = RealBuffer(DoubleArray(size) { init(it) })
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun DoubleBuffer(vararg doubles: Double): DoubleBuffer = DoubleBuffer(doubles)
|
||||
fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles)
|
||||
|
||||
/**
|
||||
* Transform buffer of doubles into array for high performance operations
|
||||
*/
|
||||
val MutableBuffer<out Double>.array: DoubleArray
|
||||
get() = if (this is DoubleBuffer) {
|
||||
get() = if (this is RealBuffer) {
|
||||
array
|
||||
} else {
|
||||
DoubleArray(size) { get(it) }
|
||||
}
|
||||
|
||||
fun DoubleArray.asBuffer() = DoubleBuffer(this)
|
||||
fun DoubleArray.asBuffer() = RealBuffer(this)
|
@ -9,143 +9,143 @@ import kotlin.math.*
|
||||
* A simple field over linear buffers of [Double]
|
||||
*/
|
||||
object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
|
||||
override fun add(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
|
||||
override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
require(b.size == a.size) { "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " }
|
||||
return if (a is DoubleBuffer && b is DoubleBuffer) {
|
||||
return if (a is RealBuffer && b is RealBuffer) {
|
||||
val aArray = a.array
|
||||
val bArray = b.array
|
||||
DoubleBuffer(DoubleArray(a.size) { aArray[it] + bArray[it] })
|
||||
RealBuffer(DoubleArray(a.size) { aArray[it] + bArray[it] })
|
||||
} else {
|
||||
DoubleBuffer(DoubleArray(a.size) { a[it] + b[it] })
|
||||
RealBuffer(DoubleArray(a.size) { a[it] + b[it] })
|
||||
}
|
||||
}
|
||||
|
||||
override fun multiply(a: Buffer<Double>, k: Number): DoubleBuffer {
|
||||
override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
|
||||
val kValue = k.toDouble()
|
||||
return if (a is DoubleBuffer) {
|
||||
return if (a is RealBuffer) {
|
||||
val aArray = a.array
|
||||
DoubleBuffer(DoubleArray(a.size) { aArray[it] * kValue })
|
||||
RealBuffer(DoubleArray(a.size) { aArray[it] * kValue })
|
||||
} else {
|
||||
DoubleBuffer(DoubleArray(a.size) { a[it] * kValue })
|
||||
RealBuffer(DoubleArray(a.size) { a[it] * kValue })
|
||||
}
|
||||
}
|
||||
|
||||
override fun multiply(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
|
||||
override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
require(b.size == a.size) { "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " }
|
||||
return if (a is DoubleBuffer && b is DoubleBuffer) {
|
||||
return if (a is RealBuffer && b is RealBuffer) {
|
||||
val aArray = a.array
|
||||
val bArray = b.array
|
||||
DoubleBuffer(DoubleArray(a.size) { aArray[it] * bArray[it] })
|
||||
RealBuffer(DoubleArray(a.size) { aArray[it] * bArray[it] })
|
||||
} else {
|
||||
DoubleBuffer(DoubleArray(a.size) { a[it] * b[it] })
|
||||
RealBuffer(DoubleArray(a.size) { a[it] * b[it] })
|
||||
}
|
||||
}
|
||||
|
||||
override fun divide(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
|
||||
override fun divide(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
require(b.size == a.size) { "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " }
|
||||
return if (a is DoubleBuffer && b is DoubleBuffer) {
|
||||
return if (a is RealBuffer && b is RealBuffer) {
|
||||
val aArray = a.array
|
||||
val bArray = b.array
|
||||
DoubleBuffer(DoubleArray(a.size) { aArray[it] / bArray[it] })
|
||||
RealBuffer(DoubleArray(a.size) { aArray[it] / bArray[it] })
|
||||
} else {
|
||||
DoubleBuffer(DoubleArray(a.size) { a[it] / b[it] })
|
||||
RealBuffer(DoubleArray(a.size) { a[it] / b[it] })
|
||||
}
|
||||
}
|
||||
|
||||
override fun sin(arg: Buffer<Double>): DoubleBuffer {
|
||||
return if (arg is DoubleBuffer) {
|
||||
override fun sin(arg: Buffer<Double>): RealBuffer {
|
||||
return if (arg is RealBuffer) {
|
||||
val array = arg.array
|
||||
DoubleBuffer(DoubleArray(arg.size) { sin(array[it]) })
|
||||
RealBuffer(DoubleArray(arg.size) { sin(array[it]) })
|
||||
} else {
|
||||
DoubleBuffer(DoubleArray(arg.size) { sin(arg[it]) })
|
||||
RealBuffer(DoubleArray(arg.size) { sin(arg[it]) })
|
||||
}
|
||||
}
|
||||
|
||||
override fun cos(arg: Buffer<Double>): DoubleBuffer {
|
||||
return if (arg is DoubleBuffer) {
|
||||
override fun cos(arg: Buffer<Double>): RealBuffer {
|
||||
return if (arg is RealBuffer) {
|
||||
val array = arg.array
|
||||
DoubleBuffer(DoubleArray(arg.size) { cos(array[it]) })
|
||||
RealBuffer(DoubleArray(arg.size) { cos(array[it]) })
|
||||
} else {
|
||||
DoubleBuffer(DoubleArray(arg.size) { cos(arg[it]) })
|
||||
RealBuffer(DoubleArray(arg.size) { cos(arg[it]) })
|
||||
}
|
||||
}
|
||||
|
||||
override fun power(arg: Buffer<Double>, pow: Number): DoubleBuffer {
|
||||
return if (arg is DoubleBuffer) {
|
||||
override fun power(arg: Buffer<Double>, pow: Number): RealBuffer {
|
||||
return if (arg is RealBuffer) {
|
||||
val array = arg.array
|
||||
DoubleBuffer(DoubleArray(arg.size) { array[it].pow(pow.toDouble()) })
|
||||
RealBuffer(DoubleArray(arg.size) { array[it].pow(pow.toDouble()) })
|
||||
} else {
|
||||
DoubleBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) })
|
||||
RealBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) })
|
||||
}
|
||||
}
|
||||
|
||||
override fun exp(arg: Buffer<Double>): DoubleBuffer {
|
||||
return if (arg is DoubleBuffer) {
|
||||
override fun exp(arg: Buffer<Double>): RealBuffer {
|
||||
return if (arg is RealBuffer) {
|
||||
val array = arg.array
|
||||
DoubleBuffer(DoubleArray(arg.size) { exp(array[it]) })
|
||||
RealBuffer(DoubleArray(arg.size) { exp(array[it]) })
|
||||
} else {
|
||||
DoubleBuffer(DoubleArray(arg.size) { exp(arg[it]) })
|
||||
RealBuffer(DoubleArray(arg.size) { exp(arg[it]) })
|
||||
}
|
||||
}
|
||||
|
||||
override fun ln(arg: Buffer<Double>): DoubleBuffer {
|
||||
return if (arg is DoubleBuffer) {
|
||||
override fun ln(arg: Buffer<Double>): RealBuffer {
|
||||
return if (arg is RealBuffer) {
|
||||
val array = arg.array
|
||||
DoubleBuffer(DoubleArray(arg.size) { ln(array[it]) })
|
||||
RealBuffer(DoubleArray(arg.size) { ln(array[it]) })
|
||||
} else {
|
||||
DoubleBuffer(DoubleArray(arg.size) { ln(arg[it]) })
|
||||
RealBuffer(DoubleArray(arg.size) { ln(arg[it]) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RealBufferField(val size: Int) : ExtendedField<Buffer<Double>> {
|
||||
|
||||
override val zero: Buffer<Double> by lazy { DoubleBuffer(size) { 0.0 } }
|
||||
override val zero: Buffer<Double> by lazy { RealBuffer(size) { 0.0 } }
|
||||
|
||||
override val one: Buffer<Double> by lazy { DoubleBuffer(size) { 1.0 } }
|
||||
override val one: Buffer<Double> by lazy { RealBuffer(size) { 1.0 } }
|
||||
|
||||
override fun add(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
|
||||
override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.add(a, b)
|
||||
}
|
||||
|
||||
override fun multiply(a: Buffer<Double>, k: Number): DoubleBuffer {
|
||||
override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
|
||||
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.multiply(a, k)
|
||||
}
|
||||
|
||||
override fun multiply(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
|
||||
override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.multiply(a, b)
|
||||
}
|
||||
|
||||
|
||||
override fun divide(a: Buffer<Double>, b: Buffer<Double>): DoubleBuffer {
|
||||
override fun divide(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
|
||||
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.divide(a, b)
|
||||
}
|
||||
|
||||
override fun sin(arg: Buffer<Double>): DoubleBuffer {
|
||||
override fun sin(arg: Buffer<Double>): RealBuffer {
|
||||
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.sin(arg)
|
||||
}
|
||||
|
||||
override fun cos(arg: Buffer<Double>): DoubleBuffer {
|
||||
override fun cos(arg: Buffer<Double>): RealBuffer {
|
||||
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.cos(arg)
|
||||
}
|
||||
|
||||
override fun power(arg: Buffer<Double>, pow: Number): DoubleBuffer {
|
||||
override fun power(arg: Buffer<Double>, pow: Number): RealBuffer {
|
||||
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.power(arg, pow)
|
||||
}
|
||||
|
||||
override fun exp(arg: Buffer<Double>): DoubleBuffer {
|
||||
override fun exp(arg: Buffer<Double>): RealBuffer {
|
||||
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.exp(arg)
|
||||
}
|
||||
|
||||
override fun ln(arg: Buffer<Double>): DoubleBuffer {
|
||||
override fun ln(arg: Buffer<Double>): RealBuffer {
|
||||
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
|
||||
return RealBufferFieldOperations.ln(arg)
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class RealNDField(override val shape: IntArray) :
|
||||
override val one by lazy { produce { one } }
|
||||
|
||||
inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer<Double> =
|
||||
DoubleBuffer(DoubleArray(size) { initializer(it) })
|
||||
RealBuffer(DoubleArray(size) { initializer(it) })
|
||||
|
||||
/**
|
||||
* Inline transform an NDStructure to
|
||||
@ -82,7 +82,7 @@ class RealNDField(override val shape: IntArray) :
|
||||
*/
|
||||
inline fun BufferedNDField<Double, RealField>.produceInline(crossinline initializer: RealField.(Int) -> Double): RealNDElement {
|
||||
val array = DoubleArray(strides.linearSize) { offset -> RealField.initializer(offset) }
|
||||
return BufferedNDFieldElement(this, DoubleBuffer(array))
|
||||
return BufferedNDFieldElement(this, RealBuffer(array))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,7 +96,7 @@ inline fun RealNDElement.mapIndexed(crossinline transform: RealField.(index: Int
|
||||
*/
|
||||
inline fun RealNDElement.map(crossinline transform: RealField.(Double) -> Double): RealNDElement {
|
||||
val array = DoubleArray(strides.linearSize) { offset -> RealField.transform(buffer[offset]) }
|
||||
return BufferedNDFieldElement(context, DoubleBuffer(array))
|
||||
return BufferedNDFieldElement(context, RealBuffer(array))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,20 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
inline class ShortBuffer(val array: ShortArray) : MutableBuffer<Short> {
|
||||
override val size: Int get() = array.size
|
||||
|
||||
override fun get(index: Int): Short = array[index]
|
||||
|
||||
override fun set(index: Int, value: Short) {
|
||||
array[index] = value
|
||||
}
|
||||
|
||||
override fun iterator() = array.iterator()
|
||||
|
||||
override fun copy(): MutableBuffer<Short> =
|
||||
ShortBuffer(array.copyOf())
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun ShortArray.asBuffer() = ShortBuffer(this)
|
@ -5,7 +5,7 @@ import kotlinx.coroutines.flow.*
|
||||
import scientifik.kmath.chains.BlockingRealChain
|
||||
import scientifik.kmath.structures.Buffer
|
||||
import scientifik.kmath.structures.BufferFactory
|
||||
import scientifik.kmath.structures.DoubleBuffer
|
||||
import scientifik.kmath.structures.RealBuffer
|
||||
import scientifik.kmath.structures.asBuffer
|
||||
|
||||
/**
|
||||
@ -45,7 +45,7 @@ fun <T> Flow<T>.chunked(bufferSize: Int, bufferFactory: BufferFactory<T>): Flow<
|
||||
/**
|
||||
* Specialized flow chunker for real buffer
|
||||
*/
|
||||
fun Flow<Double>.chunked(bufferSize: Int): Flow<DoubleBuffer> = flow {
|
||||
fun Flow<Double>.chunked(bufferSize: Int): Flow<RealBuffer> = flow {
|
||||
require(bufferSize > 0) { "Resulting chunk size must be more than zero" }
|
||||
|
||||
if (this@chunked is BlockingRealChain) {
|
||||
@ -61,13 +61,13 @@ fun Flow<Double>.chunked(bufferSize: Int): Flow<DoubleBuffer> = flow {
|
||||
array[counter] = element
|
||||
counter++
|
||||
if (counter == bufferSize) {
|
||||
val buffer = DoubleBuffer(array)
|
||||
val buffer = RealBuffer(array)
|
||||
emit(buffer)
|
||||
counter = 0
|
||||
}
|
||||
}
|
||||
if (counter > 0) {
|
||||
emit(DoubleBuffer(counter) { array[it] })
|
||||
emit(RealBuffer(counter) { array[it] })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import scientifik.kmath.operations.Norm
|
||||
import scientifik.kmath.operations.RealField
|
||||
import scientifik.kmath.operations.SpaceElement
|
||||
import scientifik.kmath.structures.Buffer
|
||||
import scientifik.kmath.structures.DoubleBuffer
|
||||
import scientifik.kmath.structures.RealBuffer
|
||||
import scientifik.kmath.structures.asBuffer
|
||||
import scientifik.kmath.structures.asIterable
|
||||
import kotlin.math.sqrt
|
||||
@ -41,7 +41,7 @@ inline class RealVector(private val point: Point<Double>) :
|
||||
private val spaceCache = HashMap<Int, BufferVectorSpace<Double, RealField>>()
|
||||
|
||||
inline operator fun invoke(dim: Int, initializer: (Int) -> Double) =
|
||||
RealVector(DoubleBuffer(dim, initializer))
|
||||
RealVector(RealBuffer(dim, initializer))
|
||||
|
||||
operator fun invoke(vararg values: Double): RealVector = values.asVector()
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package scientifik.kmath.real
|
||||
|
||||
import scientifik.kmath.structures.DoubleBuffer
|
||||
import scientifik.kmath.structures.RealBuffer
|
||||
|
||||
/**
|
||||
* Simplified [DoubleBuffer] to array comparison
|
||||
* Simplified [RealBuffer] to array comparison
|
||||
*/
|
||||
fun DoubleBuffer.contentEquals(vararg doubles: Double) = array.contentEquals(doubles)
|
||||
fun RealBuffer.contentEquals(vararg doubles: Double) = array.contentEquals(doubles)
|
@ -5,8 +5,8 @@ import scientifik.kmath.linear.RealMatrixContext.elementContext
|
||||
import scientifik.kmath.linear.VirtualMatrix
|
||||
import scientifik.kmath.operations.sum
|
||||
import scientifik.kmath.structures.Buffer
|
||||
import scientifik.kmath.structures.DoubleBuffer
|
||||
import scientifik.kmath.structures.Matrix
|
||||
import scientifik.kmath.structures.RealBuffer
|
||||
import scientifik.kmath.structures.asIterable
|
||||
import kotlin.math.pow
|
||||
|
||||
@ -133,22 +133,22 @@ fun Matrix<Double>.extractColumns(columnRange: IntRange): RealMatrix =
|
||||
fun Matrix<Double>.extractColumn(columnIndex: Int): RealMatrix =
|
||||
extractColumns(columnIndex..columnIndex)
|
||||
|
||||
fun Matrix<Double>.sumByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j ->
|
||||
fun Matrix<Double>.sumByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
val column = columns[j]
|
||||
with(elementContext) {
|
||||
sum(column.asIterable())
|
||||
}
|
||||
}
|
||||
|
||||
fun Matrix<Double>.minByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j ->
|
||||
fun Matrix<Double>.minByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
columns[j].asIterable().min() ?: throw Exception("Cannot produce min on empty column")
|
||||
}
|
||||
|
||||
fun Matrix<Double>.maxByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j ->
|
||||
fun Matrix<Double>.maxByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
columns[j].asIterable().max() ?: throw Exception("Cannot produce min on empty column")
|
||||
}
|
||||
|
||||
fun Matrix<Double>.averageByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j ->
|
||||
fun Matrix<Double>.averageByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
columns[j].asIterable().average()
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ package scientifik.kmath.histogram
|
||||
import scientifik.kmath.domains.Domain
|
||||
import scientifik.kmath.linear.Point
|
||||
import scientifik.kmath.structures.ArrayBuffer
|
||||
import scientifik.kmath.structures.DoubleBuffer
|
||||
import scientifik.kmath.structures.RealBuffer
|
||||
|
||||
/**
|
||||
* The bin in the histogram. The histogram is by definition always done in the real space
|
||||
@ -43,9 +43,9 @@ interface MutableHistogram<T : Any, out B : Bin<T>> : Histogram<T, B> {
|
||||
fun <T : Any> MutableHistogram<T, *>.put(vararg point: T) = put(ArrayBuffer(point))
|
||||
|
||||
fun MutableHistogram<Double, *>.put(vararg point: Number) =
|
||||
put(DoubleBuffer(point.map { it.toDouble() }.toDoubleArray()))
|
||||
put(RealBuffer(point.map { it.toDouble() }.toDoubleArray()))
|
||||
|
||||
fun MutableHistogram<Double, *>.put(vararg point: Double) = put(DoubleBuffer(point))
|
||||
fun MutableHistogram<Double, *>.put(vararg point: Double) = put(RealBuffer(point))
|
||||
|
||||
fun <T : Any> MutableHistogram<T, *>.fill(sequence: Iterable<Point<T>>) = sequence.forEach { put(it) }
|
||||
|
||||
|
@ -50,7 +50,7 @@ class RealHistogram(
|
||||
override val dimension: Int get() = lower.size
|
||||
|
||||
|
||||
private val binSize = DoubleBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] }
|
||||
private val binSize = RealBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] }
|
||||
|
||||
init {
|
||||
// argument checks
|
||||
|
Loading…
Reference in New Issue
Block a user