From 557f12c8c354354bfd05927db0faadf3e68de16a Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Jun 2021 17:57:33 +0700 Subject: [PATCH] Exact conversions from Long to Int, Int indexing of Dimension --- .../kmath/structures/typeSafeDimensions.kt | 2 +- .../commons/random/CMRandomGeneratorWrapper.kt | 3 ++- .../kotlin/space/kscience/kmath/misc/numbers.kt | 8 ++++++++ .../kotlin/space/kscience/kmath/misc/numbers.kt | 12 ++++++++++++ .../space/kscience/kmath/misc/numbersJVM.kt | 8 ++++++++ .../kotlin/space/kscience/kmath/misc/numbers.kt | 12 ++++++++++++ .../dimensions/{Dimensions.kt => Dimension.kt} | 16 ++++++++-------- .../space/kscience/kmath/dimensions/Wrappers.kt | 16 ++++++++-------- .../kmath/dimensions/{dimJs.kt => Dimension.kt} | 8 ++++---- .../kmath/dimensions/{dimJvm.kt => Dimension.kt} | 14 ++++++++------ .../dimensions/{dimNative.kt => Dimension.kt} | 8 ++++---- .../kotlin/space/kscience/kmath/nd4j/arrays.kt | 4 +++- .../kscience/kmath/samplers/PoissonSampler.kt | 5 +++-- .../ZigguratNormalizedGaussianSampler.kt | 3 ++- 14 files changed, 83 insertions(+), 36 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt create mode 100644 kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt create mode 100644 kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt create mode 100644 kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt rename kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/{Dimensions.kt => Dimension.kt} (67%) rename kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/{dimJs.kt => Dimension.kt} (62%) rename kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/{dimJvm.kt => Dimension.kt} (69%) rename kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/{dimNative.kt => Dimension.kt} (65%) diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt index 955f86fa9..c28b566b9 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt @@ -19,7 +19,7 @@ private fun DMatrixContext.simple() { } private object D5 : Dimension { - override val dim: UInt = 5u + override val dim: Int = 5 } private fun DMatrixContext.custom() { diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt index afbfd9a24..6aeebb68c 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt @@ -8,6 +8,7 @@ package space.kscience.kmath.commons.random import kotlinx.coroutines.runBlocking import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.samplers.GaussianSampler +import space.kscience.kmath.misc.toIntExact import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.stat.next @@ -28,7 +29,7 @@ public class CMRandomGeneratorWrapper( } override fun setSeed(seed: Long) { - setSeed(seed.toInt()) + setSeed(seed.toIntExact()) } override fun nextBytes(bytes: ByteArray) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt new file mode 100644 index 000000000..f879a06d5 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.misc + +public expect fun Long.toIntExact(): Int diff --git a/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt b/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt new file mode 100644 index 000000000..68a3c995b --- /dev/null +++ b/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.misc + +public actual fun Long.toIntExact(): Int { + val i = toInt() + if (i.toLong() == this) throw ArithmeticException("integer overflow") + return i +} diff --git a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt new file mode 100644 index 000000000..5ba0dbc9b --- /dev/null +++ b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.misc + +public actual fun Long.toIntExact(): Int = Math.toIntExact(this) diff --git a/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt b/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt new file mode 100644 index 000000000..68a3c995b --- /dev/null +++ b/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.misc + +public actual fun Long.toIntExact(): Int { + val i = toInt() + if (i.toLong() == this) throw ArithmeticException("integer overflow") + return i +} diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimensions.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt similarity index 67% rename from kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimensions.kt rename to kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index 8b17d252f..e57c22834 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimensions.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -8,47 +8,47 @@ package space.kscience.kmath.dimensions import kotlin.reflect.KClass /** - * Represents a quantity of dimensions in certain structure. + * Represents a quantity of dimensions in certain structure. **This interface must be implemented only by objects.** * * @property dim The number of dimensions. */ public interface Dimension { - public val dim: UInt + public val dim: Int public companion object } -public fun KClass.dim(): UInt = Dimension.resolve(this).dim +public fun KClass.dim(): Int = Dimension.resolve(this).dim public expect fun Dimension.Companion.resolve(type: KClass): D /** * Finds or creates [Dimension] with [Dimension.dim] equal to [dim]. */ -public expect fun Dimension.Companion.of(dim: UInt): Dimension +public expect fun Dimension.Companion.of(dim: Int): Dimension /** * Finds [Dimension.dim] of given type [D]. */ -public inline fun Dimension.Companion.dim(): UInt = D::class.dim() +public inline fun Dimension.Companion.dim(): Int = D::class.dim() /** * Type representing 1 dimension. */ public object D1 : Dimension { - override val dim: UInt get() = 1U + override val dim: Int get() = 1 } /** * Type representing 2 dimensions. */ public object D2 : Dimension { - override val dim: UInt get() = 2U + override val dim: Int get() = 2 } /** * Type representing 3 dimensions. */ public object D3 : Dimension { - override val dim: UInt get() = 3U + override val dim: Int get() = 3 } diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt index a2ee14301..deb297913 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt @@ -23,11 +23,11 @@ public interface DMatrix : Structure2D { * Coerces a regular matrix to a matrix with type-safe dimensions and throws a error if coercion failed */ public inline fun coerce(structure: Structure2D): DMatrix { - require(structure.rowNum == Dimension.dim().toInt()) { + require(structure.rowNum == Dimension.dim()) { "Row number mismatch: expected ${Dimension.dim()} but found ${structure.rowNum}" } - require(structure.colNum == Dimension.dim().toInt()) { + require(structure.colNum == Dimension.dim()) { "Column number mismatch: expected ${Dimension.dim()} but found ${structure.colNum}" } @@ -61,7 +61,7 @@ public value class DMatrixWrapper( public interface DPoint : Point { public companion object { public inline fun coerce(point: Point): DPoint { - require(point.size == Dimension.dim().toInt()) { + require(point.size == Dimension.dim()) { "Vector dimension mismatch: expected ${Dimension.dim()}, but found ${point.size}" } @@ -92,11 +92,11 @@ public value class DPointWrapper(public val point: Point>(public val context: LinearSpace) { public inline fun Matrix.coerce(): DMatrix { - require(rowNum == Dimension.dim().toInt()) { + require(rowNum == Dimension.dim()) { "Row number mismatch: expected ${Dimension.dim()} but found $rowNum" } - require(colNum == Dimension.dim().toInt()) { + require(colNum == Dimension.dim()) { "Column number mismatch: expected ${Dimension.dim()} but found $colNum" } @@ -111,7 +111,7 @@ public value class DMatrixContext>(public val context: ): DMatrix { val rows = Dimension.dim() val cols = Dimension.dim() - return context.buildMatrix(rows.toInt(), cols.toInt(), initializer).coerce() + return context.buildMatrix(rows, cols, initializer).coerce() } public inline fun point(noinline initializer: A.(Int) -> T): DPoint { @@ -119,7 +119,7 @@ public value class DMatrixContext>(public val context: return DPoint.coerceUnsafe( context.buildVector( - size.toInt(), + size, initializer ) ) @@ -167,4 +167,4 @@ public inline fun DMatrixContext.on public inline fun DMatrixContext.zero(): DMatrix = produce { _, _ -> 0.0 - } \ No newline at end of file + } diff --git a/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/dimJs.kt b/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt similarity index 62% rename from kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/dimJs.kt rename to kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index 27912f5bc..610e8b4c0 100644 --- a/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/dimJs.kt +++ b/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -7,17 +7,17 @@ package space.kscience.kmath.dimensions import kotlin.reflect.KClass -private val dimensionMap: MutableMap = hashMapOf(1u to D1, 2u to D2, 3u to D3) +private val dimensionMap: MutableMap = hashMapOf(1 to D1, 2 to D2, 3 to D3) @Suppress("UNCHECKED_CAST") public actual fun Dimension.Companion.resolve(type: KClass): D = dimensionMap .entries - .map(MutableMap.MutableEntry::value) + .map(MutableMap.MutableEntry::value) .find { it::class == type } as? D ?: error("Can't resolve dimension $type") -public actual fun Dimension.Companion.of(dim: UInt): Dimension = dimensionMap.getOrPut(dim) { +public actual fun Dimension.Companion.of(dim: Int): Dimension = dimensionMap.getOrPut(dim) { object : Dimension { - override val dim: UInt get() = dim + override val dim: Int get() = dim } } diff --git a/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/dimJvm.kt b/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt similarity index 69% rename from kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/dimJvm.kt rename to kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index f21a3e18f..e6d8b3b35 100644 --- a/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/dimJvm.kt +++ b/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -3,6 +3,8 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:JvmName("DimensionJVM") + package space.kscience.kmath.dimensions import kotlin.reflect.KClass @@ -10,12 +12,12 @@ import kotlin.reflect.KClass public actual fun Dimension.Companion.resolve(type: KClass): D = type.objectInstance ?: error("No object instance for dimension class") -public actual fun Dimension.Companion.of(dim: UInt): Dimension = when (dim) { - 1u -> D1 - 2u -> D2 - 3u -> D3 +public actual fun Dimension.Companion.of(dim: Int): Dimension = when (dim) { + 1 -> D1 + 2 -> D2 + 3 -> D3 else -> object : Dimension { - override val dim: UInt get() = dim + override val dim: Int get() = dim } -} \ No newline at end of file +} diff --git a/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/dimNative.kt b/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt similarity index 65% rename from kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/dimNative.kt rename to kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index 9aa58e64a..64edbe935 100644 --- a/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/dimNative.kt +++ b/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -9,17 +9,17 @@ import kotlin.native.concurrent.ThreadLocal import kotlin.reflect.KClass @ThreadLocal -private val dimensionMap: MutableMap = hashMapOf(1u to D1, 2u to D2, 3u to D3) +private val dimensionMap: MutableMap = hashMapOf(1 to D1, 2 to D2, 3 to D3) @Suppress("UNCHECKED_CAST") public actual fun Dimension.Companion.resolve(type: KClass): D = dimensionMap .entries - .map(MutableMap.MutableEntry::value) + .map(MutableMap.MutableEntry::value) .find { it::class == type } as? D ?: error("Can't resolve dimension $type") -public actual fun Dimension.Companion.of(dim: UInt): Dimension = dimensionMap.getOrPut(dim) { +public actual fun Dimension.Companion.of(dim: Int): Dimension = dimensionMap.getOrPut(dim) { object : Dimension { - override val dim: UInt get() = dim + override val dim: Int get() = dim } } diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt index 75a334ca7..3ca756600 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt @@ -5,4 +5,6 @@ package space.kscience.kmath.nd4j -internal fun LongArray.toIntArray(): IntArray = IntArray(size) { this[it].toInt() } +import space.kscience.kmath.misc.toIntExact + +internal fun LongArray.toIntArray(): IntArray = IntArray(size) { this[it].toIntExact() } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt index 2177e41ab..96131aa4b 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingIntChain import space.kscience.kmath.internal.InternalUtils +import space.kscience.kmath.misc.toIntExact import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.stat.Sampler import space.kscience.kmath.structures.IntBuffer @@ -119,7 +120,7 @@ public class LargeMeanPoissonSampler(public val mean: Double) : Sampler { val gaussian = ZigguratNormalizedGaussianSampler.sample(generator) val smallMeanPoissonSampler = if (mean - lambda < Double.MIN_VALUE) { - null + null } else { KempSmallMeanPoissonSampler(mean - lambda).sample(generator) } @@ -188,7 +189,7 @@ public class LargeMeanPoissonSampler(public val mean: Double) : Sampler { } } - return min(y2 + y.toLong(), Int.MAX_VALUE.toLong()).toInt() + return min(y2 + y.toLong(), Int.MAX_VALUE.toLong()).toIntExact() } override fun nextBufferBlocking(size: Int): IntBuffer = IntBuffer(size) { nextBlocking() } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt index 24148271d..81b8c3d4b 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain +import space.kscience.kmath.misc.toIntExact import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.DoubleBuffer import kotlin.math.* @@ -58,7 +59,7 @@ public object ZigguratNormalizedGaussianSampler : NormalizedGaussianSampler { private fun sampleOne(generator: RandomGenerator): Double { val j = generator.nextLong() - val i = (j and LAST.toLong()).toInt() + val i = (j and LAST.toLong()).toIntExact() return if (abs(j) < K[i]) j * W[i] else fix(generator, j, i) }