diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt index e2811602c..758e7969a 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt @@ -37,37 +37,53 @@ public class UniformHistogram1D( } } +/** + * An algebra for uniform histograms in 1D real space + */ public class UniformHistogram1DGroup( public val valueAlgebra: A, public val binSize: Double, public val startPoint: Double = 0.0, -) : Group>, ScaleOperations> where A : Ring, A : ScaleOperations { +) : Group>, ScaleOperations> where A : Ring, A : ScaleOperations { + override val zero: UniformHistogram1D by lazy { UniformHistogram1D(this, emptyMap()) } - public fun getIndex(at: Double): Int = floor((at - startPoint) / binSize).toInt() + /** + * Get index of a bin + */ + @PublishedApi + internal fun getIndex(at: Double): Int = floor((at - startPoint) / binSize).toInt() - override fun add(left: UniformHistogram1D, right: UniformHistogram1D): UniformHistogram1D = valueAlgebra { - require(left.group == this@UniformHistogram1DGroup) - require(right.group == this@UniformHistogram1DGroup) - val keys = left.values.keys + right.values.keys + override fun add( + left: Histogram1D, + right: Histogram1D, + ): UniformHistogram1D = valueAlgebra { + val leftUniform = produceFrom(left) + val rightUniform = produceFrom(right) + val keys = leftUniform.values.keys + rightUniform.values.keys UniformHistogram1D( this@UniformHistogram1DGroup, - keys.associateWith { (left.values[it] ?: valueAlgebra.zero) + (right.values[it] ?: valueAlgebra.zero) } + keys.associateWith { + (leftUniform.values[it] ?: valueAlgebra.zero) + (rightUniform.values[it] ?: valueAlgebra.zero) + } ) } - override fun UniformHistogram1D.unaryMinus(): UniformHistogram1D = valueAlgebra { - UniformHistogram1D(this@UniformHistogram1DGroup, values.mapValues { -it.value }) + override fun Histogram1D.unaryMinus(): UniformHistogram1D = valueAlgebra { + UniformHistogram1D(this@UniformHistogram1DGroup, produceFrom(this@unaryMinus).values.mapValues { -it.value }) } override fun scale( - a: UniformHistogram1D, + a: Histogram1D, value: Double, ): UniformHistogram1D = UniformHistogram1D( this@UniformHistogram1DGroup, - a.values.mapValues { valueAlgebra.scale(it.value, value) } + produceFrom(a).values.mapValues { valueAlgebra.scale(it.value, value) } ) + /** + * + */ public inline fun produce(block: Histogram1DBuilder.() -> Unit): UniformHistogram1D { val map = HashMap() val builder = object : Histogram1DBuilder { @@ -87,7 +103,7 @@ public class UniformHistogram1DGroup( * is increased by one. If not, all bins including values from this bin are increased by fraction * (conserving the norming). */ - @UnstableKMathAPI + @OptIn(UnstableKMathAPI::class) public fun produceFrom(histogram: Histogram1D): UniformHistogram1D = if ((histogram as? UniformHistogram1D)?.group == this) histogram else { diff --git a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt index 8d5cb8fb1..09bf3939d 100644 --- a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt @@ -34,9 +34,17 @@ internal class UniformHistogram1DTest { } @Test - fun rebin() = runTest { - val h1 = Histogram.uniform1D(DoubleField, 0.1).produce(generator.nextDoubleBuffer(10000)) - val h2 = Histogram.uniform1D(DoubleField,0.3).produceFrom(h1) + fun rebinDown() = runTest { + val h1 = Histogram.uniform1D(DoubleField, 0.01).produce(generator.nextDoubleBuffer(10000)) + val h2 = Histogram.uniform1D(DoubleField,0.03).produceFrom(h1) + + assertEquals(10000, h2.bins.sumOf { it.binValue }.toInt()) + } + + @Test + fun rebinUp() = runTest { + val h1 = Histogram.uniform1D(DoubleField, 0.03).produce(generator.nextDoubleBuffer(10000)) + val h2 = Histogram.uniform1D(DoubleField,0.01).produceFrom(h1) assertEquals(10000, h2.bins.sumOf { it.binValue }.toInt()) }