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

commonMain.space.kscience.kmath.structures.FlaggedBuffer.kt Maven / Gradle / Ivy

package space.kscience.kmath.structures

import kotlin.experimental.and

/**
 * Represents flags to supply additional info about values of buffer.
 *
 * @property mask bit mask value of this flag.
 */
public enum class ValueFlag(public val mask: Byte) {
    /**
     * Reports the value is NaN.
     */
    NAN(0b0000_0001),

    /**
     * Reports the value doesn't present in the buffer (when the type of value doesn't support `null`).
     */
    MISSING(0b0000_0010),

    /**
     * Reports the value is negative infinity.
     */
    NEGATIVE_INFINITY(0b0000_0100),

    /**
     * Reports the value is positive infinity
     */
    POSITIVE_INFINITY(0b0000_1000)
}

/**
 * A buffer with flagged values.
 */
public interface FlaggedBuffer : Buffer {
    public fun getFlag(index: Int): Byte
}

/**
 * The value is valid if all flags are down
 */
public fun FlaggedBuffer<*>.isValid(index: Int): Boolean = getFlag(index) != 0.toByte()

public fun FlaggedBuffer<*>.hasFlag(index: Int, flag: ValueFlag): Boolean = (getFlag(index) and flag.mask) != 0.toByte()

public fun FlaggedBuffer<*>.isMissing(index: Int): Boolean = hasFlag(index, ValueFlag.MISSING)

/**
 * A real buffer which supports flags for each value like NaN or Missing
 */
public class FlaggedRealBuffer(public val values: DoubleArray, public val flags: ByteArray) : FlaggedBuffer,
    Buffer {
    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 operator fun get(index: Int): Double? = if (isValid(index)) values[index] else null

    override operator fun iterator(): Iterator = values.indices.asSequence().map {
        if (isValid(it)) values[it] else null
    }.iterator()
}

public inline fun FlaggedRealBuffer.forEachValid(block: (Double) -> Unit) {
    indices
        .asSequence()
        .filter(::isValid)
        .forEach { block(values[it]) }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy