forked from kscience/kmath
Cleanup after nd-fields upgrade
This commit is contained in:
parent
600d8a64b8
commit
b883455bd3
@ -5,9 +5,9 @@ import kotlin.system.measureTimeMillis
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val dim = 1000
|
||||
val n = 100
|
||||
val n = 1000
|
||||
|
||||
val bufferedField = NDField.buffered(intArrayOf(dim, dim), RealField)
|
||||
val bufferedField = NDField.auto(intArrayOf(dim, dim), RealField)
|
||||
val specializedField = NDField.real(intArrayOf(dim, dim))
|
||||
val genericField = NDField.generic(intArrayOf(dim, dim), RealField)
|
||||
val lazyNDField = NDField.lazy(intArrayOf(dim, dim), RealField)
|
||||
@ -20,7 +20,6 @@ fun main(args: Array<String>) {
|
||||
// }
|
||||
|
||||
|
||||
|
||||
val doubleTime = measureTimeMillis {
|
||||
|
||||
bufferedField.run {
|
@ -59,7 +59,7 @@ interface MatrixSpace<T : Any, R : Ring<T>> : Space<Matrix<T, R>> {
|
||||
* Automatic buffered matrix, unboxed if it is possible
|
||||
*/
|
||||
inline fun <reified T : Any, R : Ring<T>> smart(rows: Int, columns: Int, ring: R): MatrixSpace<T, R> =
|
||||
buffered(rows, columns, ring, ::inlineBuffer)
|
||||
buffered(rows, columns, ring, ::autoBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
|
||||
* Automatic buffered vector, unboxed if it is possible
|
||||
*/
|
||||
inline fun <reified T : Any, S : Space<T>> smart(size: Int, space: S): VectorSpace<T, S> =
|
||||
buffered(size, space, ::inlineBuffer)
|
||||
buffered(size, space, ::autoBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,20 @@ abstract class StridedNDField<T, F : Field<T>>(shape: IntArray, elementField: F)
|
||||
val strides = DefaultStrides(shape)
|
||||
|
||||
abstract fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer<T>
|
||||
|
||||
/**
|
||||
* Convert any [NDStructure] to buffered structure using strides from this context.
|
||||
* If the structure is already [NDBuffer], conversion is free. If not, it could be expensive because iteration over indexes
|
||||
*
|
||||
* If the argument is [NDBuffer] with different strides structure, the new element will be produced.
|
||||
*/
|
||||
fun NDStructure<T>.toBuffer(): NDBuffer<T> {
|
||||
return if (this is NDBuffer<T> && this.strides == this@StridedNDField.strides) {
|
||||
this
|
||||
} else {
|
||||
produce { index -> get(index) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,29 +40,26 @@ class BufferNDField<T, F : Field<T>>(
|
||||
override val zero by lazy { produce { zero } }
|
||||
override val one by lazy { produce { one } }
|
||||
|
||||
@Suppress("OVERRIDE_BY_INLINE")
|
||||
override inline fun produce(crossinline initializer: F.(IntArray) -> T): BufferNDElement<T, F> =
|
||||
override fun produce(initializer: F.(IntArray) -> T): BufferNDElement<T, F> =
|
||||
BufferNDElement(
|
||||
this,
|
||||
bufferFactory(strides.linearSize) { offset -> elementField.initializer(strides.index(offset)) })
|
||||
buildBuffer(strides.linearSize) { offset -> elementField.initializer(strides.index(offset)) })
|
||||
|
||||
@Suppress("OVERRIDE_BY_INLINE")
|
||||
override inline fun map(arg: NDBuffer<T>, crossinline transform: F.(T) -> T): BufferNDElement<T, F> {
|
||||
override fun map(arg: NDBuffer<T>, transform: F.(T) -> T): BufferNDElement<T, F> {
|
||||
check(arg)
|
||||
return BufferNDElement(
|
||||
this,
|
||||
bufferFactory(arg.strides.linearSize) { offset -> elementField.transform(arg.buffer[offset]) })
|
||||
buildBuffer(arg.strides.linearSize) { offset -> elementField.transform(arg.buffer[offset]) })
|
||||
}
|
||||
|
||||
@Suppress("OVERRIDE_BY_INLINE")
|
||||
override inline fun mapIndexed(
|
||||
override fun mapIndexed(
|
||||
arg: NDBuffer<T>,
|
||||
crossinline transform: F.(index: IntArray, T) -> T
|
||||
transform: F.(index: IntArray, T) -> T
|
||||
): BufferNDElement<T, F> {
|
||||
check(arg)
|
||||
return BufferNDElement(
|
||||
this,
|
||||
bufferFactory(arg.strides.linearSize) { offset ->
|
||||
buildBuffer(arg.strides.linearSize) { offset ->
|
||||
elementField.transform(
|
||||
arg.strides.index(offset),
|
||||
arg.buffer[offset]
|
||||
@ -56,30 +67,15 @@ class BufferNDField<T, F : Field<T>>(
|
||||
})
|
||||
}
|
||||
|
||||
@Suppress("OVERRIDE_BY_INLINE")
|
||||
override inline fun combine(
|
||||
override fun combine(
|
||||
a: NDBuffer<T>,
|
||||
b: NDBuffer<T>,
|
||||
crossinline transform: F.(T, T) -> T
|
||||
transform: F.(T, T) -> T
|
||||
): BufferNDElement<T, F> {
|
||||
check(a, b)
|
||||
return BufferNDElement(
|
||||
this,
|
||||
bufferFactory(strides.linearSize) { offset -> elementField.transform(a.buffer[offset], b.buffer[offset]) })
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any [NDStructure] to buffered structure using strides from this context.
|
||||
* If the structure is already [NDBuffer], conversion is free. If not, it could be expensive because iteration over indexes
|
||||
*
|
||||
* If the argument is [NDBuffer] with different strides structure, the new element will be produced.
|
||||
*/
|
||||
fun NDStructure<T>.toBuffer(): NDBuffer<T> {
|
||||
return if (this is NDBuffer<T> && this.strides == this@BufferNDField.strides) {
|
||||
this
|
||||
} else {
|
||||
produce { index -> get(index) }
|
||||
}
|
||||
buildBuffer(strides.linearSize) { offset -> elementField.transform(a.buffer[offset], b.buffer[offset]) })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ inline fun <T> boxingBuffer(size: Int, initializer: (Int) -> T): Buffer<T> = Lis
|
||||
* Create most appropriate immutable buffer for given type avoiding boxing wherever possible
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <reified T : Any> inlineBuffer(size: Int, initializer: (Int) -> T): Buffer<T> {
|
||||
inline fun <reified T : Any> autoBuffer(size: Int, initializer: (Int) -> T): Buffer<T> {
|
||||
return when (T::class) {
|
||||
Double::class -> DoubleBuffer(DoubleArray(size) { initializer(it) as Double }) as Buffer<T>
|
||||
Int::class -> IntBuffer(IntArray(size) { initializer(it) as Int }) as Buffer<T>
|
||||
@ -159,7 +159,7 @@ inline fun <T : Any> boxingMutableBuffer(size: Int, initializer: (Int) -> T): Mu
|
||||
* Create most appropriate mutable buffer for given type avoiding boxing wherever possible
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <reified T : Any> inlineMutableBuffer(size: Int, initializer: (Int) -> T): MutableBuffer<T> {
|
||||
inline fun <reified T : Any> autoMutableBuffer(size: Int, initializer: (Int) -> T): MutableBuffer<T> {
|
||||
return when (T::class) {
|
||||
Double::class -> DoubleBuffer(DoubleArray(size) { initializer(it) as Double }) as MutableBuffer<T>
|
||||
Int::class -> IntBuffer(IntArray(size) { initializer(it) as Int }) as MutableBuffer<T>
|
||||
|
@ -51,7 +51,7 @@ object NDElements {
|
||||
noinline initializer: F.(IntArray) -> T
|
||||
): GenericNDElement<T, F> {
|
||||
val ndField = GenericNDField(shape, field)
|
||||
val structure = ndStructure(shape, ::inlineBuffer) { index -> field.initializer(index) }
|
||||
val structure = ndStructure(shape, ::autoBuffer) { index -> field.initializer(index) }
|
||||
return GenericNDElement(ndField, structure)
|
||||
}
|
||||
}
|
||||
|
@ -71,10 +71,11 @@ interface NDField<T, F : Field<T>, N : NDStructure<T>> : Field<N> {
|
||||
fun <T : Any, F : Field<T>> generic(shape: IntArray, field: F) = GenericNDField(shape, field)
|
||||
|
||||
/**
|
||||
* Create a most suitable implementation for nd-field using reified class
|
||||
* Create a most suitable implementation for nd-field using reified class.
|
||||
*/
|
||||
inline fun <reified T : Any, F : Field<T>> buffered(shape: IntArray, field: F) =
|
||||
BufferNDField(shape, field, ::inlineBuffer)
|
||||
inline fun <reified T : Any, F : Field<T>> auto(shape: IntArray, field: F): BufferNDField<T, F> {
|
||||
return BufferNDField(shape, field, ::autoBuffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ data class BufferNDStructure<T>(
|
||||
* Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferNDStructure]
|
||||
*/
|
||||
inline fun <T, reified R : Any> NDStructure<T>.mapToBuffer(
|
||||
factory: BufferFactory<R> = ::inlineBuffer,
|
||||
factory: BufferFactory<R> = ::autoBuffer,
|
||||
crossinline transform: (T) -> R
|
||||
): BufferNDStructure<R> {
|
||||
return if (this is BufferNDStructure<T>) {
|
||||
@ -186,7 +186,7 @@ fun <T> ndStructure(strides: Strides, bufferFactory: BufferFactory<T> = ::boxing
|
||||
* Inline create NDStructure with non-boxing buffer implementation if it is possible
|
||||
*/
|
||||
inline fun <reified T : Any> inlineNDStructure(strides: Strides, crossinline initializer: (IntArray) -> T) =
|
||||
BufferNDStructure(strides, inlineBuffer(strides.linearSize) { i -> initializer(strides.index(i)) })
|
||||
BufferNDStructure(strides, autoBuffer(strides.linearSize) { i -> initializer(strides.index(i)) })
|
||||
|
||||
fun <T> ndStructure(shape: IntArray, bufferFactory: BufferFactory<T> = ::boxingBuffer, initializer: (IntArray) -> T) =
|
||||
ndStructure(DefaultStrides(shape), bufferFactory, initializer)
|
||||
@ -195,7 +195,7 @@ inline fun <reified T : Any> inlineNdStructure(shape: IntArray, crossinline init
|
||||
inlineNDStructure(DefaultStrides(shape), initializer)
|
||||
|
||||
/**
|
||||
* Mutable ND buffer based on linear [inlineBuffer]
|
||||
* Mutable ND buffer based on linear [autoBuffer]
|
||||
*/
|
||||
class MutableBufferNDStructure<T>(
|
||||
override val strides: Strides,
|
||||
@ -222,7 +222,7 @@ fun <T : Any> mutableNdStructure(
|
||||
MutableBufferNDStructure(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) })
|
||||
|
||||
inline fun <reified T : Any> inlineMutableNdStructure(strides: Strides, crossinline initializer: (IntArray) -> T) =
|
||||
MutableBufferNDStructure(strides, inlineMutableBuffer(strides.linearSize) { i -> initializer(strides.index(i)) })
|
||||
MutableBufferNDStructure(strides, autoMutableBuffer(strides.linearSize) { i -> initializer(strides.index(i)) })
|
||||
|
||||
fun <T : Any> mutableNdStructure(
|
||||
shape: IntArray,
|
||||
|
@ -8,32 +8,30 @@ class RealNDField(shape: IntArray) :
|
||||
StridedNDField<Double, RealField>(shape, RealField),
|
||||
ExtendedNDField<Double, RealField, NDBuffer<Double>> {
|
||||
|
||||
override fun buildBuffer(size: Int, initializer: (Int) -> Double): Buffer<Double> =
|
||||
DoubleBuffer(DoubleArray(size, initializer))
|
||||
@Suppress("OVERRIDE_BY_INLINE")
|
||||
override inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer<Double> =
|
||||
DoubleBuffer(DoubleArray(size){initializer(it)})
|
||||
|
||||
/**
|
||||
* Inline transform an NDStructure to
|
||||
*/
|
||||
@Suppress("OVERRIDE_BY_INLINE")
|
||||
override inline fun map(
|
||||
override fun map(
|
||||
arg: NDBuffer<Double>,
|
||||
crossinline transform: RealField.(Double) -> Double
|
||||
transform: RealField.(Double) -> Double
|
||||
): RealNDElement {
|
||||
check(arg)
|
||||
val array = DoubleArray(arg.strides.linearSize) { offset -> RealField.transform(arg.buffer[offset]) }
|
||||
return BufferNDElement(this, DoubleBuffer(array))
|
||||
val array = buildBuffer(arg.strides.linearSize) { offset -> RealField.transform(arg.buffer[offset]) }
|
||||
return BufferNDElement(this, array)
|
||||
}
|
||||
|
||||
@Suppress("OVERRIDE_BY_INLINE")
|
||||
override inline fun produce(crossinline initializer: RealField.(IntArray) -> Double): RealNDElement {
|
||||
val array = DoubleArray(strides.linearSize) { offset -> elementField.initializer(strides.index(offset)) }
|
||||
return BufferNDElement(this, DoubleBuffer(array))
|
||||
override fun produce(initializer: RealField.(IntArray) -> Double): RealNDElement {
|
||||
val array = buildBuffer(strides.linearSize) { offset -> elementField.initializer(strides.index(offset)) }
|
||||
return BufferNDElement(this, array)
|
||||
}
|
||||
|
||||
@Suppress("OVERRIDE_BY_INLINE")
|
||||
override inline fun mapIndexed(
|
||||
override fun mapIndexed(
|
||||
arg: NDBuffer<Double>,
|
||||
crossinline transform: RealField.(index: IntArray, Double) -> Double
|
||||
transform: RealField.(index: IntArray, Double) -> Double
|
||||
): BufferNDElement<Double, RealField> {
|
||||
check(arg)
|
||||
return BufferNDElement(
|
||||
@ -46,11 +44,10 @@ class RealNDField(shape: IntArray) :
|
||||
})
|
||||
}
|
||||
|
||||
@Suppress("OVERRIDE_BY_INLINE")
|
||||
override inline fun combine(
|
||||
override fun combine(
|
||||
a: NDBuffer<Double>,
|
||||
b: NDBuffer<Double>,
|
||||
crossinline transform: RealField.(Double, Double) -> Double
|
||||
transform: RealField.(Double, Double) -> Double
|
||||
): BufferNDElement<Double, RealField> {
|
||||
check(a, b)
|
||||
return BufferNDElement(
|
||||
@ -105,4 +102,4 @@ operator fun RealNDElement.plus(arg: Double) =
|
||||
* Subtraction operation between [BufferNDElement] and single element
|
||||
*/
|
||||
operator fun RealNDElement.minus(arg: Double) =
|
||||
context.produceInline { i -> buffer[i] - arg }
|
||||
context.produceInline { i -> buffer[i] - arg }
|
Loading…
Reference in New Issue
Block a user