Cleanup after nd-fields upgrade

This commit is contained in:
Alexander Nozik 2019-01-05 12:31:47 +03:00
parent 600d8a64b8
commit b883455bd3
9 changed files with 54 additions and 61 deletions

View File

@ -5,9 +5,9 @@ import kotlin.system.measureTimeMillis
fun main(args: Array<String>) { fun main(args: Array<String>) {
val dim = 1000 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 specializedField = NDField.real(intArrayOf(dim, dim))
val genericField = NDField.generic(intArrayOf(dim, dim), RealField) val genericField = NDField.generic(intArrayOf(dim, dim), RealField)
val lazyNDField = NDField.lazy(intArrayOf(dim, dim), RealField) val lazyNDField = NDField.lazy(intArrayOf(dim, dim), RealField)
@ -20,7 +20,6 @@ fun main(args: Array<String>) {
// } // }
val doubleTime = measureTimeMillis { val doubleTime = measureTimeMillis {
bufferedField.run { bufferedField.run {

View File

@ -59,7 +59,7 @@ interface MatrixSpace<T : Any, R : Ring<T>> : Space<Matrix<T, R>> {
* Automatic buffered matrix, unboxed if it is possible * 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> = 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)
} }
} }

View File

@ -56,7 +56,7 @@ interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
* Automatic buffered vector, unboxed if it is possible * Automatic buffered vector, unboxed if it is possible
*/ */
inline fun <reified T : Any, S : Space<T>> smart(size: Int, space: S): VectorSpace<T, S> = inline fun <reified T : Any, S : Space<T>> smart(size: Int, space: S): VectorSpace<T, S> =
buffered(size, space, ::inlineBuffer) buffered(size, space, ::autoBuffer)
} }
} }

View File

@ -8,6 +8,20 @@ abstract class StridedNDField<T, F : Field<T>>(shape: IntArray, elementField: F)
val strides = DefaultStrides(shape) val strides = DefaultStrides(shape)
abstract fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer<T> 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 zero by lazy { produce { zero } }
override val one by lazy { produce { one } } override val one by lazy { produce { one } }
@Suppress("OVERRIDE_BY_INLINE") override fun produce(initializer: F.(IntArray) -> T): BufferNDElement<T, F> =
override inline fun produce(crossinline initializer: F.(IntArray) -> T): BufferNDElement<T, F> =
BufferNDElement( BufferNDElement(
this, this,
bufferFactory(strides.linearSize) { offset -> elementField.initializer(strides.index(offset)) }) buildBuffer(strides.linearSize) { offset -> elementField.initializer(strides.index(offset)) })
@Suppress("OVERRIDE_BY_INLINE") override fun map(arg: NDBuffer<T>, transform: F.(T) -> T): BufferNDElement<T, F> {
override inline fun map(arg: NDBuffer<T>, crossinline transform: F.(T) -> T): BufferNDElement<T, F> {
check(arg) check(arg)
return BufferNDElement( return BufferNDElement(
this, 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 fun mapIndexed(
override inline fun mapIndexed(
arg: NDBuffer<T>, arg: NDBuffer<T>,
crossinline transform: F.(index: IntArray, T) -> T transform: F.(index: IntArray, T) -> T
): BufferNDElement<T, F> { ): BufferNDElement<T, F> {
check(arg) check(arg)
return BufferNDElement( return BufferNDElement(
this, this,
bufferFactory(arg.strides.linearSize) { offset -> buildBuffer(arg.strides.linearSize) { offset ->
elementField.transform( elementField.transform(
arg.strides.index(offset), arg.strides.index(offset),
arg.buffer[offset] arg.buffer[offset]
@ -56,30 +67,15 @@ class BufferNDField<T, F : Field<T>>(
}) })
} }
@Suppress("OVERRIDE_BY_INLINE") override fun combine(
override inline fun combine(
a: NDBuffer<T>, a: NDBuffer<T>,
b: NDBuffer<T>, b: NDBuffer<T>,
crossinline transform: F.(T, T) -> T transform: F.(T, T) -> T
): BufferNDElement<T, F> { ): BufferNDElement<T, F> {
check(a, b) check(a, b)
return BufferNDElement( return BufferNDElement(
this, this,
bufferFactory(strides.linearSize) { offset -> elementField.transform(a.buffer[offset], b.buffer[offset]) }) buildBuffer(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) }
}
} }
} }

View File

@ -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 * Create most appropriate immutable buffer for given type avoiding boxing wherever possible
*/ */
@Suppress("UNCHECKED_CAST") @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) { return when (T::class) {
Double::class -> DoubleBuffer(DoubleArray(size) { initializer(it) as Double }) as Buffer<T> Double::class -> DoubleBuffer(DoubleArray(size) { initializer(it) as Double }) as Buffer<T>
Int::class -> IntBuffer(IntArray(size) { initializer(it) as Int }) 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 * Create most appropriate mutable buffer for given type avoiding boxing wherever possible
*/ */
@Suppress("UNCHECKED_CAST") @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) { return when (T::class) {
Double::class -> DoubleBuffer(DoubleArray(size) { initializer(it) as Double }) as MutableBuffer<T> Double::class -> DoubleBuffer(DoubleArray(size) { initializer(it) as Double }) as MutableBuffer<T>
Int::class -> IntBuffer(IntArray(size) { initializer(it) as Int }) as MutableBuffer<T> Int::class -> IntBuffer(IntArray(size) { initializer(it) as Int }) as MutableBuffer<T>

View File

@ -51,7 +51,7 @@ object NDElements {
noinline initializer: F.(IntArray) -> T noinline initializer: F.(IntArray) -> T
): GenericNDElement<T, F> { ): GenericNDElement<T, F> {
val ndField = GenericNDField(shape, field) 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) return GenericNDElement(ndField, structure)
} }
} }

View File

@ -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) 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) = inline fun <reified T : Any, F : Field<T>> auto(shape: IntArray, field: F): BufferNDField<T, F> {
BufferNDField(shape, field, ::inlineBuffer) return BufferNDField(shape, field, ::autoBuffer)
}
} }
} }

View File

@ -163,7 +163,7 @@ data class BufferNDStructure<T>(
* Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferNDStructure] * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferNDStructure]
*/ */
inline fun <T, reified R : Any> NDStructure<T>.mapToBuffer( inline fun <T, reified R : Any> NDStructure<T>.mapToBuffer(
factory: BufferFactory<R> = ::inlineBuffer, factory: BufferFactory<R> = ::autoBuffer,
crossinline transform: (T) -> R crossinline transform: (T) -> R
): BufferNDStructure<R> { ): BufferNDStructure<R> {
return if (this is BufferNDStructure<T>) { 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 create NDStructure with non-boxing buffer implementation if it is possible
*/ */
inline fun <reified T : Any> inlineNDStructure(strides: Strides, crossinline initializer: (IntArray) -> T) = 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) = fun <T> ndStructure(shape: IntArray, bufferFactory: BufferFactory<T> = ::boxingBuffer, initializer: (IntArray) -> T) =
ndStructure(DefaultStrides(shape), bufferFactory, initializer) ndStructure(DefaultStrides(shape), bufferFactory, initializer)
@ -195,7 +195,7 @@ inline fun <reified T : Any> inlineNdStructure(shape: IntArray, crossinline init
inlineNDStructure(DefaultStrides(shape), initializer) inlineNDStructure(DefaultStrides(shape), initializer)
/** /**
* Mutable ND buffer based on linear [inlineBuffer] * Mutable ND buffer based on linear [autoBuffer]
*/ */
class MutableBufferNDStructure<T>( class MutableBufferNDStructure<T>(
override val strides: Strides, override val strides: Strides,
@ -222,7 +222,7 @@ fun <T : Any> mutableNdStructure(
MutableBufferNDStructure(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) }) MutableBufferNDStructure(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) })
inline fun <reified T : Any> inlineMutableNdStructure(strides: Strides, crossinline initializer: (IntArray) -> T) = 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( fun <T : Any> mutableNdStructure(
shape: IntArray, shape: IntArray,

View File

@ -8,32 +8,30 @@ class RealNDField(shape: IntArray) :
StridedNDField<Double, RealField>(shape, RealField), StridedNDField<Double, RealField>(shape, RealField),
ExtendedNDField<Double, RealField, NDBuffer<Double>> { ExtendedNDField<Double, RealField, NDBuffer<Double>> {
override fun buildBuffer(size: Int, initializer: (Int) -> Double): Buffer<Double> = @Suppress("OVERRIDE_BY_INLINE")
DoubleBuffer(DoubleArray(size, initializer)) override inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer<Double> =
DoubleBuffer(DoubleArray(size){initializer(it)})
/** /**
* Inline transform an NDStructure to * Inline transform an NDStructure to
*/ */
@Suppress("OVERRIDE_BY_INLINE") override fun map(
override inline fun map(
arg: NDBuffer<Double>, arg: NDBuffer<Double>,
crossinline transform: RealField.(Double) -> Double transform: RealField.(Double) -> Double
): RealNDElement { ): RealNDElement {
check(arg) check(arg)
val array = DoubleArray(arg.strides.linearSize) { offset -> RealField.transform(arg.buffer[offset]) } val array = buildBuffer(arg.strides.linearSize) { offset -> RealField.transform(arg.buffer[offset]) }
return BufferNDElement(this, DoubleBuffer(array)) return BufferNDElement(this, array)
} }
@Suppress("OVERRIDE_BY_INLINE") override fun produce(initializer: RealField.(IntArray) -> Double): RealNDElement {
override inline fun produce(crossinline initializer: RealField.(IntArray) -> Double): RealNDElement { val array = buildBuffer(strides.linearSize) { offset -> elementField.initializer(strides.index(offset)) }
val array = DoubleArray(strides.linearSize) { offset -> elementField.initializer(strides.index(offset)) } return BufferNDElement(this, array)
return BufferNDElement(this, DoubleBuffer(array))
} }
@Suppress("OVERRIDE_BY_INLINE") override fun mapIndexed(
override inline fun mapIndexed(
arg: NDBuffer<Double>, arg: NDBuffer<Double>,
crossinline transform: RealField.(index: IntArray, Double) -> Double transform: RealField.(index: IntArray, Double) -> Double
): BufferNDElement<Double, RealField> { ): BufferNDElement<Double, RealField> {
check(arg) check(arg)
return BufferNDElement( return BufferNDElement(
@ -46,11 +44,10 @@ class RealNDField(shape: IntArray) :
}) })
} }
@Suppress("OVERRIDE_BY_INLINE") override fun combine(
override inline fun combine(
a: NDBuffer<Double>, a: NDBuffer<Double>,
b: NDBuffer<Double>, b: NDBuffer<Double>,
crossinline transform: RealField.(Double, Double) -> Double transform: RealField.(Double, Double) -> Double
): BufferNDElement<Double, RealField> { ): BufferNDElement<Double, RealField> {
check(a, b) check(a, b)
return BufferNDElement( return BufferNDElement(