diff --git a/libraries/stdlib/jdk8/src/kotlin/random/jdk8/PlatformThreadLocalRandom.kt b/libraries/stdlib/jdk8/src/kotlin/random/jdk8/PlatformThreadLocalRandom.kt index 538e84af061..86defeca088 100644 --- a/libraries/stdlib/jdk8/src/kotlin/random/jdk8/PlatformThreadLocalRandom.kt +++ b/libraries/stdlib/jdk8/src/kotlin/random/jdk8/PlatformThreadLocalRandom.kt @@ -12,11 +12,11 @@ internal class PlatformThreadLocalRandom : kotlin.random.AbstractPlatformRandom( // TODO no bridge generated for covariant override override val impl: java.util.Random get() = ThreadLocalRandom.current() - override fun nextInt(origin: Int, bound: Int): Int = ThreadLocalRandom.current().nextInt(origin, bound) - override fun nextLong(bound: Long): Long = ThreadLocalRandom.current().nextLong(bound) - override fun nextLong(origin: Long, bound: Long): Long = ThreadLocalRandom.current().nextLong(origin, bound) - override fun nextDouble(bound: Double): Double = ThreadLocalRandom.current().nextDouble(bound) + override fun nextInt(from: Int, until: Int): Int = ThreadLocalRandom.current().nextInt(from, until) + override fun nextLong(until: Long): Long = ThreadLocalRandom.current().nextLong(until) + override fun nextLong(from: Long, until: Long): Long = ThreadLocalRandom.current().nextLong(from, until) + override fun nextDouble(until: Double): Double = ThreadLocalRandom.current().nextDouble(until) // do not delegate this, as it's buggy in JDK8+ (up to 11 at the moment of writing) -// override fun nextDouble(origin: Double, bound: Double): Double = ThreadLocalRandom.current().nextDouble(origin, bound) +// override fun nextDouble(from: Double, until: Double): Double = ThreadLocalRandom.current().nextDouble(from, until) } \ No newline at end of file diff --git a/libraries/stdlib/jvm/src/kotlin/random/PlatformRandom.kt b/libraries/stdlib/jvm/src/kotlin/random/PlatformRandom.kt index 31ea8222c5b..32c9295e113 100644 --- a/libraries/stdlib/jvm/src/kotlin/random/PlatformRandom.kt +++ b/libraries/stdlib/jvm/src/kotlin/random/PlatformRandom.kt @@ -42,7 +42,7 @@ internal abstract class AbstractPlatformRandom : Random() { impl.nextInt().takeUpperBits(bitCount) override fun nextInt(): Int = impl.nextInt() - override fun nextInt(bound: Int): Int = impl.nextInt(bound) + override fun nextInt(until: Int): Int = impl.nextInt(until) override fun nextLong(): Long = impl.nextLong() override fun nextBoolean(): Boolean = impl.nextBoolean() override fun nextDouble(): Double = impl.nextDouble() diff --git a/libraries/stdlib/src/kotlin/random/Random.kt b/libraries/stdlib/src/kotlin/random/Random.kt index fde28fec069..4a64583a0fa 100644 --- a/libraries/stdlib/src/kotlin/random/Random.kt +++ b/libraries/stdlib/src/kotlin/random/Random.kt @@ -37,9 +37,9 @@ public abstract class Random { public open fun nextInt(): Int = nextBits(32) /** - * Gets the next random non-negative `Int` from the random number generator not greater than the specified [until]. + * Gets the next random non-negative `Int` from the random number generator not greater than the specified [until] bound. * - * Generates an `Int` random value uniformly distributed between `0` (inclusive) and the specified [until] (exclusive). + * Generates an `Int` random value uniformly distributed between `0` (inclusive) and the specified [until] bound (exclusive). * * @param until must be positive. * @@ -50,7 +50,7 @@ public abstract class Random { /** * Gets the next random `Int` from the random number generator in the specified range. * - * Generates an `Int` random value uniformly distributed between the specified [from] (inclusive) and the specified [until] (exclusive). + * Generates an `Int` random value uniformly distributed between the specified [from] (inclusive) and [until] (exclusive) bounds. * * @throws IllegalArgumentException if [from] is greater than or equal to [until]. */ @@ -101,9 +101,9 @@ public abstract class Random { public open fun nextLong(): Long = nextInt().toLong().shl(32) + nextInt() /** - * Gets the next random non-negative `Long` from the random number generator not greater than the specified [until]. + * Gets the next random non-negative `Long` from the random number generator not greater than the specified [until] bound. * - * Generates a `Long` random value uniformly distributed between `0` (inclusive) and the specified [until] (exclusive). + * Generates a `Long` random value uniformly distributed between `0` (inclusive) and the specified [until] bound (exclusive). * * @param until must be positive. * @@ -114,7 +114,7 @@ public abstract class Random { /** * Gets the next random `Long` from the random number generator in the specified range. * - * Generates a `Long` random value uniformly distributed between the specified [from] (inclusive) and the specified [until] (exclusive). + * Generates a `Long` random value uniformly distributed between the specified [from] (inclusive) and [until] (exclusive) bounds. * * @throws IllegalArgumentException if [from] is greater than or equal to [until]. */ @@ -183,7 +183,7 @@ public abstract class Random { public open fun nextDouble(): Double = doubleFromParts(nextBits(26), nextBits(27)) /** - * Gets the next random non-negative `Double` from the random number generator not greater than the specified [until]. + * Gets the next random non-negative `Double` from the random number generator not greater than the specified [until] bound. * * Generates a `Double` random value uniformly distributed between 0 (inclusive) and [until] (exclusive). * @@ -194,7 +194,7 @@ public abstract class Random { /** * Gets the next random `Double` from the random number generator in the specified range. * - * Generates a `Double` random value uniformly distributed between the specified [from] (inclusive) and the specified [until] (exclusive). + * Generates a `Double` random value uniformly distributed between the specified [from] (inclusive) and [until] (exclusive) bounds. * * [from] and [until] must be finite otherwise the behavior is unspecified. * @@ -331,9 +331,9 @@ public fun Random(seed: Long): Random = XorWowRandom(seed.toInt(), seed.shr(32). public fun Random.nextUInt(): UInt = nextInt().toUInt() /** - * Gets the next random [UInt] from the random number generator not greater than the specified [until]. + * Gets the next random [UInt] from the random number generator not greater than the specified [until] bound. * - * Generates a [UInt] random value uniformly distributed between `0` (inclusive) and the specified [until] (exclusive). + * Generates a [UInt] random value uniformly distributed between `0` (inclusive) and the specified [until] bound (exclusive). * * @throws IllegalArgumentException if [until] is zero. */ @@ -344,7 +344,7 @@ public fun Random.nextUInt(until: UInt): UInt = nextUInt(0u, until) /** * Gets the next random [UInt] from the random number generator in the specified range. * - * Generates a [UInt] random value uniformly distributed between the specified [from] (inclusive) and the specified [until] (exclusive). + * Generates a [UInt] random value uniformly distributed between the specified [from] (inclusive) and [until] (exclusive) bounds. * * @throws IllegalArgumentException if [from] is greater than or equal to [until]. */ @@ -353,12 +353,11 @@ public fun Random.nextUInt(until: UInt): UInt = nextUInt(0u, until) public fun Random.nextUInt(from: UInt, until: UInt): UInt { checkUIntRangeBounds(from, until) - val originTransformedToInt = from.toInt() xor Int.MIN_VALUE - val boundTransformedToInt = until.toInt() xor Int.MIN_VALUE + val signedFrom = from.toInt() xor Int.MIN_VALUE + val signedUntil = until.toInt() xor Int.MIN_VALUE - val randomValueTransformedBack = nextInt(originTransformedToInt, boundTransformedToInt) xor Int.MIN_VALUE - - return randomValueTransformedBack.toUInt() + val signedResult = nextInt(signedFrom, signedUntil) xor Int.MIN_VALUE + return signedResult.toUInt() } /** @@ -388,9 +387,9 @@ public fun Random.nextUInt(range: UIntRange): UInt = when { public fun Random.nextULong(): ULong = nextLong().toULong() /** - * Gets the next random [ULong] from the random number generator not greater than the specified [until]. + * Gets the next random [ULong] from the random number generator not greater than the specified [until] bound. * - * Generates a [ULong] random value uniformly distributed between `0` (inclusive) and the specified [until] (exclusive). + * Generates a [ULong] random value uniformly distributed between `0` (inclusive) and the specified [until] bound (exclusive). * * @throws IllegalArgumentException if [until] is zero. */ @@ -401,7 +400,7 @@ public fun Random.nextULong(until: ULong): ULong = nextULong(0uL, until) /** * Gets the next random [ULong] from the random number generator in the specified range. * - * Generates a [ULong] random value uniformly distributed between the specified [from] (inclusive) and the specified [until] (exclusive). + * Generates a [ULong] random value uniformly distributed between the specified [from] (inclusive) and [until] (exclusive) bounds. * * @throws IllegalArgumentException if [from] is greater than or equal to [until]. */ @@ -410,11 +409,11 @@ public fun Random.nextULong(until: ULong): ULong = nextULong(0uL, until) public fun Random.nextULong(from: ULong, until: ULong): ULong { checkULongRangeBounds(from, until) - val originTransformedToLong = from.toLong() xor Long.MIN_VALUE - val boundTransformedToLong = until.toLong() xor Long.MIN_VALUE + val signedFrom = from.toLong() xor Long.MIN_VALUE + val signedUntil = until.toLong() xor Long.MIN_VALUE - val randomValueTransformedBack = nextLong(originTransformedToLong, boundTransformedToLong) xor Long.MIN_VALUE - return randomValueTransformedBack.toULong() + val signedResult = nextLong(signedFrom, signedUntil) xor Long.MIN_VALUE + return signedResult.toULong() } /** @@ -473,10 +472,10 @@ internal expect fun doubleFromParts(hi26: Int, low27: Int): Double internal fun Int.takeUpperBits(bitCount: Int): Int = this.ushr(32 - bitCount) and (-bitCount).shr(31) -internal fun checkRangeBounds(origin: Int, bound: Int) = require(bound > origin) { boundsErrorMessage(origin, bound) } -internal fun checkUIntRangeBounds(origin: UInt, bound: UInt) = require(bound > origin) { boundsErrorMessage(origin, bound) } -internal fun checkRangeBounds(origin: Long, bound: Long) = require(bound > origin) { boundsErrorMessage(origin, bound) } -internal fun checkULongRangeBounds(origin: ULong, bound: ULong) = require(bound > origin) { boundsErrorMessage(origin, bound) } -internal fun checkRangeBounds(origin: Double, bound: Double) = require(bound > origin) { boundsErrorMessage(origin, bound) } +internal fun checkRangeBounds(from: Int, until: Int) = require(until > from) { boundsErrorMessage(from, until) } +internal fun checkUIntRangeBounds(from: UInt, until: UInt) = require(until > from) { boundsErrorMessage(from, until) } +internal fun checkRangeBounds(from: Long, until: Long) = require(until > from) { boundsErrorMessage(from, until) } +internal fun checkULongRangeBounds(from: ULong, until: ULong) = require(until > from) { boundsErrorMessage(from, until) } +internal fun checkRangeBounds(from: Double, until: Double) = require(until > from) { boundsErrorMessage(from, until) } -private fun boundsErrorMessage(origin: Any, bound: Any) = "Random range is empty: [$origin, $bound)." +private fun boundsErrorMessage(from: Any, until: Any) = "Random range is empty: [$from, $until)." diff --git a/libraries/stdlib/test/random/RandomTest.kt b/libraries/stdlib/test/random/RandomTest.kt index 338f3076885..9a0e59e99b0 100644 --- a/libraries/stdlib/test/random/RandomTest.kt +++ b/libraries/stdlib/test/random/RandomTest.kt @@ -112,11 +112,11 @@ abstract class RandomSmokeTest { assertEquals(n, subject.nextInt(n, n + 1)) } - for ((origin, bound) in listOf((0 to 2), (-1 to 5), (0 to 32), (0 to Int.MAX_VALUE), (-1 to Int.MAX_VALUE), (Int.MIN_VALUE to Int.MAX_VALUE))) { + for ((from, until) in listOf((0 to 2), (-1 to 5), (0 to 32), (0 to Int.MAX_VALUE), (-1 to Int.MAX_VALUE), (Int.MIN_VALUE to Int.MAX_VALUE))) { repeat(1000) { - val x = subject.nextInt(origin, bound) - if (x !in origin until bound) - fail("Value $x must be in range [$origin, $bound)") + val x = subject.nextInt(from, until) + if (x !in from until until) + fail("Value $x must be in range [$from, $until)") } } } @@ -134,11 +134,11 @@ abstract class RandomSmokeTest { assertEquals(n, subject.nextUInt(n, n + 1u)) } - for ((origin, bound) in listOf((0u to 2u), (1u to 6u), (0u to 32u), (0u to UInt.MAX_VALUE), (1u to (Int.MAX_VALUE.toUInt() + 1u)), (UInt.MIN_VALUE to UInt.MAX_VALUE))) { + for ((from, until) in listOf((0u to 2u), (1u to 6u), (0u to 32u), (0u to UInt.MAX_VALUE), (1u to (Int.MAX_VALUE.toUInt() + 1u)), (UInt.MIN_VALUE to UInt.MAX_VALUE))) { repeat(1000) { - val x = subject.nextUInt(origin, bound) - if (x !in origin until bound) - fail("Value $x must be in range [$origin, $bound)") + val x = subject.nextUInt(from, until) + if (x !in from until until) + fail("Value $x must be in range [$from, $until)") } } } @@ -266,12 +266,12 @@ abstract class RandomSmokeTest { assertEquals(n, subject.nextLong(n, n + 1)) } - for ((origin, bound) in listOf((0L to 32L), (-1L to 5L), (0L to 0x1_0000_0000), + for ((from, until) in listOf((0L to 32L), (-1L to 5L), (0L to 0x1_0000_0000), (0L to Long.MAX_VALUE), (-1L to Long.MAX_VALUE), (Long.MIN_VALUE to Long.MAX_VALUE))) { repeat(1000) { - val x = subject.nextLong(origin, bound) - if (x !in origin until bound) - fail("Value $x must be in range [$origin, $bound)") + val x = subject.nextLong(from, until) + if (x !in from until until) + fail("Value $x must be in range [$from, $until)") } } } @@ -286,16 +286,16 @@ abstract class RandomSmokeTest { assertEquals(n, subject.nextULong(n, n + 1uL)) } - for ((origin, bound) in listOf( + for ((from, until) in listOf( (0uL to 32uL), (1uL to 6uL), (0uL to 0x1_0000_0000.toULong()), (0uL to ULong.MAX_VALUE) )) { repeat(1000) { - val x = subject.nextULong(origin, bound) - if (x !in origin until bound) { - fail("Value $x must be in range [$origin, $bound)") + val x = subject.nextULong(from, until) + if (x !in from until until) { + fail("Value $x must be in range [$from, $until)") } } } @@ -409,11 +409,11 @@ abstract class RandomSmokeTest { assertTrue(fullRangeValues.size >= (size * 0.995), "All values should be distinct, but only ${fullRangeValues.size} of them are") } - for ((origin, bound) in listOf(0.0 to 1.0, -1.0 to 1.0, 0.0 to 100.0, -PI to PI, 0.0 to Double.MAX_VALUE)) { + for ((from, until) in listOf(0.0 to 1.0, -1.0 to 1.0, 0.0 to 100.0, -PI to PI, 0.0 to Double.MAX_VALUE)) { repeat(1000) { - val d = subject.nextDouble(origin, bound) - if (!(d >= origin && d < bound)) { - fail("Random double $d is out of range [$origin, $bound)") + val d = subject.nextDouble(from, until) + if (!(d >= from && d < until)) { + fail("Random double $d is out of range [$from, $until)") } } }