More efficient double generation in JS

This commit is contained in:
Ilya Gorbunov
2018-07-05 06:06:39 +03:00
parent b96803248f
commit 35c927214d
3 changed files with 13 additions and 2 deletions
@@ -5,6 +5,8 @@
package kotlin.random package kotlin.random
import kotlin.math.pow
internal actual fun defaultPlatformRandom(): Random = internal actual fun defaultPlatformRandom(): Random =
Random(js("(Math.random() * Math.pow(2, 32)) | 0").unsafeCast<Int>()) Random(js("(Math.random() * Math.pow(2, 32)) | 0").unsafeCast<Int>())
@@ -19,3 +21,8 @@ internal actual fun fastLog2(value: Int): Int {
} }
return log return log
} }
private val INV_2_26: Double = 2.0.pow(-26)
private val INV_2_53: Double = 2.0.pow(-53)
internal actual fun doubleFromParts(hi26: Int, low27: Int): Double =
hi26 * INV_2_26 + low27 * INV_2_53
@@ -31,6 +31,9 @@ internal actual inline fun defaultPlatformRandom(): Random =
internal actual fun fastLog2(value: Int): Int = internal actual fun fastLog2(value: Int): Int =
31 - Integer.numberOfLeadingZeros(value) 31 - Integer.numberOfLeadingZeros(value)
internal actual fun doubleFromParts(hi26: Int, low27: Int): Double =
(hi26.toLong().shl(27) + low27) / (1L shl 53).toDouble()
internal abstract class AbstractPlatformRandom : Random() { internal abstract class AbstractPlatformRandom : Random() {
abstract val impl: java.util.Random abstract val impl: java.util.Random
+2 -1
View File
@@ -179,7 +179,7 @@ public abstract class Random {
/** /**
* Gets the next random [Double] value uniformly distributed between 0 (inclusive) and 1 (exclusive). * Gets the next random [Double] value uniformly distributed between 0 (inclusive) and 1 (exclusive).
*/ */
public open fun nextDouble(): Double = (nextBits(26).toLong().shl(27) + nextBits(27)) / (1L shl 53).toDouble() 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 [bound]. * Gets the next random non-negative `Double` from the random number generator not greater than the specified [bound].
@@ -327,6 +327,7 @@ public fun Random(seed: Long): Random = XorWowRandom(seed.toInt(), seed.shr(32).
internal expect fun defaultPlatformRandom(): Random internal expect fun defaultPlatformRandom(): Random
internal expect fun fastLog2(value: Int): Int // 31 - Integer.numberOfLeadingZeros(value) internal expect fun fastLog2(value: Int): Int // 31 - Integer.numberOfLeadingZeros(value)
internal expect fun doubleFromParts(hi26: Int, low27: Int): Double
/** Takes upper [bitCount] bits (0..32) from this number. */ /** Takes upper [bitCount] bits (0..32) from this number. */
internal fun Int.takeUpperBits(bitCount: Int): Int = internal fun Int.takeUpperBits(bitCount: Int): Int =