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>) {
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 {

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
*/
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
*/
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)
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]) })
}
}

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
*/
@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>

View File

@ -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)
}
}

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)
/**
* 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)
}
}
}

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]
*/
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,

View File

@ -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 }