diff --git a/gradle.properties b/gradle.properties index dfed0e3..226d1db 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ kotlin.code.style=official specifyKotlinAsDependency=false projectGroup=ru.dbotthepony.kommons -projectVersion=3.1.3 +projectVersion=3.2.0 guavaDepVersion=33.0.0 gsonDepVersion=2.8.9 diff --git a/src/main/kotlin/ru/dbotthepony/kommons/random/LCG64Random.kt b/src/main/kotlin/ru/dbotthepony/kommons/random/LCG64Random.kt new file mode 100644 index 0000000..ba25422 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kommons/random/LCG64Random.kt @@ -0,0 +1,27 @@ +package ru.dbotthepony.kommons.random + +import java.util.random.RandomGenerator + +/** + * Classical LCG PRNG, utilizing [MULTIPLIER] and [INCREMENT] as constants. + * + * Internal state is presented as 64-bit integer, and high-order bits of internal state are + * used to generate numbers. + */ +open class LCG64Random(private var seed: Long) : RandomGenerator { + final override fun nextLong(): Long { + val a = nextInt().toLong() + val b = nextInt().toLong() and 0xFFFFFFFFL + return a.shl(32) or b + } + + final override fun nextInt(): Int { + this.seed = MULTIPLIER * this.seed + INCREMENT + return this.seed.ushr(32).toInt() + } + + companion object { + const val MULTIPLIER = 6364136223846793005 + const val INCREMENT = 1442695040888963407 + } +} diff --git a/src/main/kotlin/ru/dbotthepony/kommons/random/Xoshiro256PlusPlusRandom.kt b/src/main/kotlin/ru/dbotthepony/kommons/random/Xoshiro256PlusPlusRandom.kt new file mode 100644 index 0000000..3706503 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kommons/random/Xoshiro256PlusPlusRandom.kt @@ -0,0 +1,58 @@ +package ru.dbotthepony.kommons.random + +import java.util.random.RandomGenerator + +open class Xoshiro256PlusPlusRandom protected constructor( + private var s0: Long, + private var s1: Long, + private var s2: Long, + private var s3: Long, + mark: Nothing? +) : RandomGenerator { + init { + if (s0 or s1 or s2 or s3 == 0L) { + s0 = 0x73CF3D83FFF44FF3L + s1 = 0x6412312B70F3CD37L + s2 = -0X6BB4C4E1327BFDCFL + s3 = -0X4BE0F5BB5F3F5240L + } + } + + constructor(s0: Long, s1: Long, s2: Long, s3: Long) : this(s0, s1, s2, s3, null) { + // discard some values so generator can get going if provided seed was "weak" + for (i in 0 until 32) + nextLong() + } + + constructor(seed: Long) : this(1L, 0L, 0L, 0L, null) { + val rng = LCG64Random(seed) + s0 = rng.nextLong() + s1 = rng.nextLong() + s2 = rng.nextLong() + s3 = rng.nextLong() + } + + final override fun nextLong(): Long { + val result = (s0 + s3).rotateLeft(23) + s1 + val t = s1.shl(17) + s2 = s2.xor(s0) + s3 = s3.xor(s1) + s1 = s1.xor(s2) + s0 = s0.xor(s3) + s2 = s2.xor(t) + s3 = s3.rotateLeft(45) + return result + } + + companion object { + @JvmStatic + fun raw( + s0: Long, + s1: Long, + s2: Long, + s3: Long, + ): Xoshiro256PlusPlusRandom { + return Xoshiro256PlusPlusRandom(s0, s1, s2, s3, null) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/kommons/random/Xoshiro256StarStarRandom.kt b/src/main/kotlin/ru/dbotthepony/kommons/random/Xoshiro256StarStarRandom.kt new file mode 100644 index 0000000..f06200d --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kommons/random/Xoshiro256StarStarRandom.kt @@ -0,0 +1,58 @@ +package ru.dbotthepony.kommons.random + +import java.util.random.RandomGenerator + +open class Xoshiro256StarStarRandom protected constructor( + private var s0: Long, + private var s1: Long, + private var s2: Long, + private var s3: Long, + mark: Nothing? +) : RandomGenerator { + init { + if (s0 or s1 or s2 or s3 == 0L) { + s0 = 0x73CF3D83FFF44FF3L + s1 = 0x6412312B70F3CD37L + s2 = -0X6BB4C4E1327BFDCFL + s3 = -0X4BE0F5BB5F3F5240L + } + } + + constructor(s0: Long, s1: Long, s2: Long, s3: Long) : this(s0, s1, s2, s3, null) { + // discard some values so generator can get going if provided seed was "weak" + for (i in 0 until 32) + nextLong() + } + + constructor(seed: Long) : this(1L, 0L, 0L, 0L, null) { + val rng = LCG64Random(seed) + s0 = rng.nextLong() + s1 = rng.nextLong() + s2 = rng.nextLong() + s3 = rng.nextLong() + } + + final override fun nextLong(): Long { + val result = (s1 * 5).rotateLeft(7) * 9 + val t = s1.shl(17) + s2 = s2.xor(s0) + s3 = s3.xor(s1) + s1 = s1.xor(s2) + s0 = s0.xor(s3) + s2 = s2.xor(t) + s3 = s3.rotateLeft(45) + return result + } + + companion object { + @JvmStatic + fun raw( + s0: Long, + s1: Long, + s2: Long, + s3: Long, + ): Xoshiro256StarStarRandom { + return Xoshiro256StarStarRandom(s0, s1, s2, s3, null) + } + } +}