From d793221a7b447d935827591d7f9e777d8e9b8135 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Mon, 17 Sep 2018 19:25:48 +0300 Subject: [PATCH] Extract unsigned type related extensions to separate classes - Rename class with unsigned number to string conversions to UStringsKt - Extract Random unsigned extensions to URandomKt --- libraries/stdlib/src/kotlin/random/Random.kt | 148 +---------------- libraries/stdlib/src/kotlin/random/URandom.kt | 156 ++++++++++++++++++ ...StringNumberConversions.kt => UStrings.kt} | 2 + .../kotlin-stdlib-runtime-merged.txt | 5 +- 4 files changed, 163 insertions(+), 148 deletions(-) create mode 100644 libraries/stdlib/src/kotlin/random/URandom.kt rename libraries/stdlib/unsigned/src/kotlin/{UStringNumberConversions.kt => UStrings.kt} (99%) diff --git a/libraries/stdlib/src/kotlin/random/Random.kt b/libraries/stdlib/src/kotlin/random/Random.kt index 264c3e3dee6..a89d4a4e162 100644 --- a/libraries/stdlib/src/kotlin/random/Random.kt +++ b/libraries/stdlib/src/kotlin/random/Random.kt @@ -320,148 +320,6 @@ public fun Random.nextLong(range: LongRange): Long = when { else -> nextLong() } -/** - * Gets the next random [UInt] from the random number generator. - * - * Generates a [UInt] random value uniformly distributed between [UInt.MIN_VALUE] and [UInt.MAX_VALUE] (inclusive). - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -public fun Random.nextUInt(): UInt = nextInt().toUInt() - -/** - * 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] bound (exclusive). - * - * @throws IllegalArgumentException if [until] is zero. - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -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 [until] (exclusive) bounds. - * - * @throws IllegalArgumentException if [from] is greater than or equal to [until]. - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -public fun Random.nextUInt(from: UInt, until: UInt): UInt { - checkUIntRangeBounds(from, until) - - val signedFrom = from.toInt() xor Int.MIN_VALUE - val signedUntil = until.toInt() xor Int.MIN_VALUE - - val signedResult = nextInt(signedFrom, signedUntil) xor Int.MIN_VALUE - return signedResult.toUInt() -} - -/** - * Gets the next random [UInt] from the random number generator in the specified [range]. - * - * Generates a [UInt] random value uniformly distributed in the specified [range]: - * from `range.start` inclusive to `range.endInclusive` inclusive. - * - * @throws IllegalArgumentException if [range] is empty. - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -public fun Random.nextUInt(range: UIntRange): UInt = when { - range.isEmpty() -> throw IllegalArgumentException("Cannot get random in empty range: $range") - range.last < UInt.MAX_VALUE -> nextUInt(range.first, range.last + 1u) - range.first > UInt.MIN_VALUE -> nextUInt(range.first - 1u, range.last) + 1u - else -> nextUInt() -} - -/** - * Gets the next random [ULong] from the random number generator. - * - * Generates a [ULong] random value uniformly distributed between [ULong.MIN_VALUE] and [ULong.MAX_VALUE] (inclusive). - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -public fun Random.nextULong(): ULong = nextLong().toULong() - -/** - * 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] bound (exclusive). - * - * @throws IllegalArgumentException if [until] is zero. - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -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 [until] (exclusive) bounds. - * - * @throws IllegalArgumentException if [from] is greater than or equal to [until]. - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -public fun Random.nextULong(from: ULong, until: ULong): ULong { - checkULongRangeBounds(from, until) - - val signedFrom = from.toLong() xor Long.MIN_VALUE - val signedUntil = until.toLong() xor Long.MIN_VALUE - - val signedResult = nextLong(signedFrom, signedUntil) xor Long.MIN_VALUE - return signedResult.toULong() -} - -/** - * Gets the next random [ULong] from the random number generator in the specified [range]. - * - * Generates a [ULong] random value uniformly distributed in the specified [range]: - * from `range.start` inclusive to `range.endInclusive` inclusive. - * - * @throws IllegalArgumentException if [range] is empty. - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -public fun Random.nextULong(range: ULongRange): ULong = when { - range.isEmpty() -> throw IllegalArgumentException("Cannot get random in empty range: $range") - range.last < ULong.MAX_VALUE -> nextULong(range.first, range.last + 1u) - range.first > ULong.MIN_VALUE -> nextULong(range.first - 1u, range.last) + 1u - else -> nextULong() -} - -/** - * Fills the specified unsigned byte [array] with random bytes and returns it. - * - * @return [array] filled with random bytes. - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -public fun Random.nextUBytes(array: UByteArray): UByteArray { - nextBytes(array.asByteArray()) - return array -} - -/** - * Creates an unsigned byte array of the specified [size], filled with random bytes. - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -public fun Random.nextUBytes(size: Int): UByteArray = nextBytes(size).asUByteArray() - -/** - * Fills a subrange of the specified `UByte` [array] starting from [fromIndex] inclusive and ending [toIndex] exclusive with random UBytes. - * - * @return [array] with the subrange filled with random bytes. - */ -@SinceKotlin("1.3") -@ExperimentalUnsignedTypes -public fun Random.nextUBytes(array: UByteArray, fromIndex: Int = 0, toIndex: Int = array.size): UByteArray { - nextBytes(array.asByteArray(), fromIndex, toIndex) - return array -} internal expect fun defaultPlatformRandom(): Random internal expect fun fastLog2(value: Int): Int // 31 - Integer.numberOfLeadingZeros(value) @@ -472,11 +330,7 @@ internal fun Int.takeUpperBits(bitCount: Int): Int = this.ushr(32 - bitCount) and (-bitCount).shr(31) internal fun checkRangeBounds(from: Int, until: Int) = require(until > from) { boundsErrorMessage(from, until) } -@ExperimentalUnsignedTypes -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) } -@ExperimentalUnsignedTypes -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(from: Any, until: Any) = "Random range is empty: [$from, $until)." +internal fun boundsErrorMessage(from: Any, until: Any) = "Random range is empty: [$from, $until)." diff --git a/libraries/stdlib/src/kotlin/random/URandom.kt b/libraries/stdlib/src/kotlin/random/URandom.kt new file mode 100644 index 00000000000..46078bce8a4 --- /dev/null +++ b/libraries/stdlib/src/kotlin/random/URandom.kt @@ -0,0 +1,156 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package kotlin.random + + +/** + * Gets the next random [UInt] from the random number generator. + * + * Generates a [UInt] random value uniformly distributed between [UInt.MIN_VALUE] and [UInt.MAX_VALUE] (inclusive). + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Random.nextUInt(): UInt = nextInt().toUInt() + +/** + * 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] bound (exclusive). + * + * @throws IllegalArgumentException if [until] is zero. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +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 [until] (exclusive) bounds. + * + * @throws IllegalArgumentException if [from] is greater than or equal to [until]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Random.nextUInt(from: UInt, until: UInt): UInt { + checkUIntRangeBounds(from, until) + + val signedFrom = from.toInt() xor Int.MIN_VALUE + val signedUntil = until.toInt() xor Int.MIN_VALUE + + val signedResult = nextInt(signedFrom, signedUntil) xor Int.MIN_VALUE + return signedResult.toUInt() +} + +/** + * Gets the next random [UInt] from the random number generator in the specified [range]. + * + * Generates a [UInt] random value uniformly distributed in the specified [range]: + * from `range.start` inclusive to `range.endInclusive` inclusive. + * + * @throws IllegalArgumentException if [range] is empty. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Random.nextUInt(range: UIntRange): UInt = when { + range.isEmpty() -> throw IllegalArgumentException("Cannot get random in empty range: $range") + range.last < UInt.MAX_VALUE -> nextUInt(range.first, range.last + 1u) + range.first > UInt.MIN_VALUE -> nextUInt(range.first - 1u, range.last) + 1u + else -> nextUInt() +} + +/** + * Gets the next random [ULong] from the random number generator. + * + * Generates a [ULong] random value uniformly distributed between [ULong.MIN_VALUE] and [ULong.MAX_VALUE] (inclusive). + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Random.nextULong(): ULong = nextLong().toULong() + +/** + * 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] bound (exclusive). + * + * @throws IllegalArgumentException if [until] is zero. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +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 [until] (exclusive) bounds. + * + * @throws IllegalArgumentException if [from] is greater than or equal to [until]. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Random.nextULong(from: ULong, until: ULong): ULong { + checkULongRangeBounds(from, until) + + val signedFrom = from.toLong() xor Long.MIN_VALUE + val signedUntil = until.toLong() xor Long.MIN_VALUE + + val signedResult = nextLong(signedFrom, signedUntil) xor Long.MIN_VALUE + return signedResult.toULong() +} + +/** + * Gets the next random [ULong] from the random number generator in the specified [range]. + * + * Generates a [ULong] random value uniformly distributed in the specified [range]: + * from `range.start` inclusive to `range.endInclusive` inclusive. + * + * @throws IllegalArgumentException if [range] is empty. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Random.nextULong(range: ULongRange): ULong = when { + range.isEmpty() -> throw IllegalArgumentException("Cannot get random in empty range: $range") + range.last < ULong.MAX_VALUE -> nextULong(range.first, range.last + 1u) + range.first > ULong.MIN_VALUE -> nextULong(range.first - 1u, range.last) + 1u + else -> nextULong() +} + +/** + * Fills the specified unsigned byte [array] with random bytes and returns it. + * + * @return [array] filled with random bytes. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Random.nextUBytes(array: UByteArray): UByteArray { + nextBytes(array.asByteArray()) + return array +} + +/** + * Creates an unsigned byte array of the specified [size], filled with random bytes. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Random.nextUBytes(size: Int): UByteArray = nextBytes(size).asUByteArray() + +/** + * Fills a subrange of the specified `UByte` [array] starting from [fromIndex] inclusive and ending [toIndex] exclusive with random UBytes. + * + * @return [array] with the subrange filled with random bytes. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public fun Random.nextUBytes(array: UByteArray, fromIndex: Int = 0, toIndex: Int = array.size): UByteArray { + nextBytes(array.asByteArray(), fromIndex, toIndex) + return array +} + + +@ExperimentalUnsignedTypes +internal fun checkUIntRangeBounds(from: UInt, until: UInt) = require(until > from) { boundsErrorMessage(from, until) } +@ExperimentalUnsignedTypes +internal fun checkULongRangeBounds(from: ULong, until: ULong) = require(until > from) { boundsErrorMessage(from, until) } diff --git a/libraries/stdlib/unsigned/src/kotlin/UStringNumberConversions.kt b/libraries/stdlib/unsigned/src/kotlin/UStrings.kt similarity index 99% rename from libraries/stdlib/unsigned/src/kotlin/UStringNumberConversions.kt rename to libraries/stdlib/unsigned/src/kotlin/UStrings.kt index 249e56fa202..1e7848fdcf9 100644 --- a/libraries/stdlib/unsigned/src/kotlin/UStringNumberConversions.kt +++ b/libraries/stdlib/unsigned/src/kotlin/UStrings.kt @@ -3,6 +3,8 @@ * that can be found in the license/LICENSE.txt file. */ +@file:kotlin.jvm.JvmName("UStringsKt") // string representation of unsigned numbers + package kotlin.text /** diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt index 48209b8e670..c8ee37e1e80 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt @@ -3909,6 +3909,9 @@ public final class kotlin/random/RandomKt { public static final fun Random (J)Lkotlin/random/Random; public static final fun nextInt (Lkotlin/random/Random;Lkotlin/ranges/IntRange;)I public static final fun nextLong (Lkotlin/random/Random;Lkotlin/ranges/LongRange;)J +} + +public final class kotlin/random/URandomKt { public static final fun nextUBytes (Lkotlin/random/Random;I)[B public static final fun nextUBytes-EVgfTAA (Lkotlin/random/Random;[B)[B public static final fun nextUBytes-Wvrt4B4 (Lkotlin/random/Random;[BII)[B @@ -5136,7 +5139,7 @@ public final class kotlin/text/Typography { public static final field tm C } -public final class kotlin/text/UStringNumberConversionsKt { +public final class kotlin/text/UStringsKt { public static final fun toString-JSWoG40 (JI)Ljava/lang/String; public static final fun toString-LxnNnR4 (BI)Ljava/lang/String; public static final fun toString-V7xB4Y4 (II)Ljava/lang/String;