All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.space.kscience.kmath.nd.BufferNDAlgebra.kt Maven / Gradle / Ivy

package space.kscience.kmath.nd

import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.RealField
import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.Space
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

public interface BufferNDAlgebra : NDAlgebra {
    public val strides: Strides
    public val bufferFactory: BufferFactory

    override fun produce(initializer: C.(IntArray) -> T): NDBuffer = NDBuffer(
        strides,
        bufferFactory(strides.linearSize) { offset ->
            elementContext.initializer(strides.index(offset))
        }
    )

    public val NDStructure.buffer: Buffer
        get() = when {
            !shape.contentEquals([email protected]) -> throw ShapeMismatchException(
                [email protected],
                shape
            )
            this is NDBuffer && this.strides == [email protected] -> this.buffer
            else -> bufferFactory(strides.linearSize) { offset -> get(strides.index(offset)) }
        }

    override fun NDStructure.map(transform: C.(T) -> T): NDBuffer {
        val buffer = bufferFactory(strides.linearSize) { offset ->
            elementContext.transform(buffer[offset])
        }
        return NDBuffer(strides, buffer)
    }

    override fun NDStructure.mapIndexed(transform: C.(index: IntArray, T) -> T): NDBuffer {
        val buffer = bufferFactory(strides.linearSize) { offset ->
            elementContext.transform(
                strides.index(offset),
                buffer[offset]
            )
        }
        return NDBuffer(strides, buffer)
    }

    override fun combine(a: NDStructure, b: NDStructure, transform: C.(T, T) -> T): NDBuffer {
        val buffer = bufferFactory(strides.linearSize) { offset ->
            elementContext.transform(a.buffer[offset], b.buffer[offset])
        }
        return NDBuffer(strides, buffer)
    }
}

public open class BufferedNDSpace>(
    final override val shape: IntArray,
    final override val elementContext: R,
    final override val bufferFactory: BufferFactory,
) : NDSpace, BufferNDAlgebra {
    override val strides: Strides = DefaultStrides(shape)
    override val zero: NDBuffer by lazy { produce { zero } }
}

public open class BufferedNDRing>(
    shape: IntArray,
    elementContext: R,
    bufferFactory: BufferFactory,
) : BufferedNDSpace(shape, elementContext, bufferFactory), NDRing {
    override val one: NDBuffer by lazy { produce { one } }
}

public open class BufferedNDField>(
    shape: IntArray,
    elementContext: R,
    bufferFactory: BufferFactory,
) : BufferedNDRing(shape, elementContext, bufferFactory), NDField

// space factories
public fun > NDAlgebra.Companion.space(
    space: A,
    bufferFactory: BufferFactory,
    vararg shape: Int,
): BufferedNDSpace = BufferedNDSpace(shape, space, bufferFactory)

public inline fun , R> A.ndSpace(
    noinline bufferFactory: BufferFactory,
    vararg shape: Int,
    action: BufferedNDSpace.() -> R,
): R {
    contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
    return NDAlgebra.space(this, bufferFactory, *shape).run(action)
}

//ring factories
public fun > NDAlgebra.Companion.ring(
    ring: A,
    bufferFactory: BufferFactory,
    vararg shape: Int,
): BufferedNDRing = BufferedNDRing(shape, ring, bufferFactory)

public inline fun , R> A.ndRing(
    noinline bufferFactory: BufferFactory,
    vararg shape: Int,
    action: BufferedNDRing.() -> R,
): R {
    contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
    return NDAlgebra.ring(this, bufferFactory, *shape).run(action)
}

//field factories
public fun > NDAlgebra.Companion.field(
    field: A,
    bufferFactory: BufferFactory,
    vararg shape: Int,
): BufferedNDField = BufferedNDField(shape, field, bufferFactory)

@Suppress("UNCHECKED_CAST")
public inline fun > NDAlgebra.Companion.auto(
    field: A,
    vararg shape: Int,
): NDField = when (field) {
    RealField -> RealNDField(shape) as NDField
    else -> BufferedNDField(shape, field, Buffer.Companion::auto)
}

public inline fun , R> A.ndField(
    noinline bufferFactory: BufferFactory,
    vararg shape: Int,
    action: BufferedNDField.() -> R,
): R {
    contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
    return NDAlgebra.field(this, bufferFactory, *shape).run(action)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy