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

com.lightningkite.lightningdb.Aggregate.kt Maven / Gradle / Ivy

@file:SharedCode
package com.lightningkite.lightningdb

import com.lightningkite.khrysalis.SharedCode
import kotlin.math.sqrt

enum class Aggregate {
    Sum,
    Average,
    StandardDeviationSample,
    StandardDeviationPopulation
}

fun Aggregate.aggregator(): Aggregator = when(this) {
    Aggregate.Sum -> SumAggregator()
    Aggregate.Average -> AverageAggregator()
    Aggregate.StandardDeviationSample -> StandardDeviationSampleAggregator()
    Aggregate.StandardDeviationPopulation -> StandardDeviationPopulationAggregator()
}

interface Aggregator {
    fun consume(value: Double)
    fun complete(): Double?
}

class SumAggregator: Aggregator {
    var current: Double = 0.0
    var anyFound = false
    override fun consume(value: Double) {
        anyFound = true
        current += value
    }
    override fun complete(): Double? = if(anyFound) current else null
}
class AverageAggregator: Aggregator {
    var count: Int = 0
    var current: Double = 0.0
    override fun consume(value: Double) {
        count++
        current += (value - current) / count.toDouble()
    }
    override fun complete(): Double? = if(count == 0) null else current
}
class StandardDeviationSampleAggregator: Aggregator {
    var count: Int = 0
    var mean: Double = 0.0
    var m2: Double = 0.0
    override fun consume(value: Double) {
        count++
        val delta1 = value - mean
        mean += (delta1) / count.toDouble()
        val delta2 = value - mean
        m2 += delta1 * delta2
    }
    override fun complete(): Double? = if(count < 2) null else sqrt(m2 / (count.toDouble() - 1))
}
class StandardDeviationPopulationAggregator: Aggregator {
    var count: Int = 0
    var mean: Double = 0.0
    var m2: Double = 0.0
    override fun consume(value: Double) {
        count++
        val delta1 = value - mean
        mean += (delta1) / count.toDouble()
        val delta2 = value - mean
        m2 += delta1 * delta2
    }
    override fun complete(): Double? = if(count == 0) null else sqrt(m2 / count.toDouble())
}

fun Sequence.aggregate(aggregate: Aggregate): Double? {
    val aggregator = aggregate.aggregator()
    for(item in this) {
        aggregator.consume(item)
    }
    return aggregator.complete()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy