Adds a nextLong random method

Adds unbounded methods because they are faster.
This commit is contained in:
Vitor Pamplona
2025-12-20 12:26:16 -05:00
parent e4f3a56851
commit 37158a83dc
3 changed files with 56 additions and 8 deletions
@@ -23,7 +23,13 @@ package com.vitorpamplona.quartz.utils
object RandomInstance {
val randomizer = SecureRandom()
fun int(bound: Int = Int.MAX_VALUE) = randomizer.nextInt(bound)
fun int() = randomizer.nextInt()
fun long() = randomizer.nextLong()
fun int(bound: Int) = randomizer.nextInt(bound)
fun long(bound: Long) = randomizer.nextLong(bound)
fun bytes(size: Int) = ByteArray(size).also { randomizer.nextBytes(it) }
@@ -23,5 +23,11 @@ package com.vitorpamplona.quartz.utils
expect class SecureRandom() {
fun nextInt(bound: Int): Int
fun nextLong(bound: Long): Long
fun nextInt(): Int
fun nextLong(): Long
fun nextBytes(output: ByteArray)
}
@@ -24,8 +24,18 @@ import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.refTo
import platform.Security.SecRandomCopyBytes
import platform.Security.kSecRandomDefault
import kotlin.random.Random.Default.nextBytes
actual class SecureRandom {
actual fun nextInt(): Int {
val bytes = ByteArray(4)
nextBytes(bytes)
return ((bytes[0].toInt() and 0xFF) shl 24) or
((bytes[1].toInt() and 0xFF) shl 16) or
((bytes[2].toInt() and 0xFF) shl 8) or
(bytes[3].toInt() and 0xFF)
}
actual fun nextInt(bound: Int): Int {
require(bound > 0) { throw IllegalArgumentException("Bad Bound $bound") }
@@ -47,14 +57,40 @@ actual class SecureRandom {
return intValue
}
fun nextPositiveInt(): Int {
val bytes = ByteArray(4)
actual fun nextLong(): Long {
val bytes = ByteArray(8)
nextBytes(bytes)
val value =
((bytes[0].toInt() and 0xFF) shl 24) or
((bytes[1].toInt() and 0xFF) shl 16) or
((bytes[2].toInt() and 0xFF) shl 8) or
(bytes[3].toInt() and 0xFF)
return ((bytes[0].toLong() and 0xFFL) shl 56) or
((bytes[1].toLong() and 0xFFL) shl 48) or
((bytes[2].toLong() and 0xFFL) shl 40) or
((bytes[3].toLong() and 0xFFL) shl 32) or
((bytes[4].toLong() and 0xFFL) shl 24) or
((bytes[5].toLong() and 0xFFL) shl 16) or
((bytes[6].toLong() and 0xFFL) shl 8) or
(bytes[7].toLong() and 0xFFL)
}
actual fun nextLong(bound: Long): Long {
require(bound > 0) { throw IllegalArgumentException("Bad Bound $bound") }
if (bound < Int.MAX_VALUE) {
return nextInt(bound.toInt()).toLong()
}
return nextPositiveLong() % bound
}
fun nextPositiveInt(): Int {
val value = nextInt()
return if (value > 0) {
value
} else {
-value
}
}
fun nextPositiveLong(): Long {
val value = nextLong()
return if (value > 0) {
value
} else {