Remove custom random generators except for gjrand64 which is used for worldgen
This commit is contained in:
parent
5a016bef1b
commit
a6ba428518
@ -1,117 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.core.util
|
|
||||||
|
|
||||||
import net.minecraft.util.Mth
|
|
||||||
import net.minecraft.util.RandomSource
|
|
||||||
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
|
|
||||||
import net.minecraft.world.level.levelgen.PositionalRandomFactory
|
|
||||||
import net.minecraft.world.level.levelgen.RandomSupport
|
|
||||||
import ru.dbotthepony.kommons.random.PCG32Random
|
|
||||||
import java.lang.StringBuilder
|
|
||||||
import java.util.random.RandomGenerator
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Random number generator with insane period of at least 2^511
|
|
||||||
*/
|
|
||||||
class CMWCRandom(seed: Long = RandomSupport.generateUniqueSeed()) : RandomGenerator, RandomSource {
|
|
||||||
private val state = IntArray(CMWC_STATE_SIZE)
|
|
||||||
private var carry = 0
|
|
||||||
private var stateIndex = 0
|
|
||||||
private val gaussian = MarsagliaPolarGaussian(this)
|
|
||||||
|
|
||||||
init {
|
|
||||||
setSeed(seed)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setSeed(seed: Long) {
|
|
||||||
val rng = PCG32Random(seed)
|
|
||||||
|
|
||||||
// init state with regular LCG produced values
|
|
||||||
for (i in 1 until state.size) {
|
|
||||||
state[i] = rng.nextInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
carry = rng.nextInt()
|
|
||||||
} while(carry !in 0 until CMWC_CARRY_MAX)
|
|
||||||
|
|
||||||
stateIndex = state.size - 1
|
|
||||||
gaussian.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextInt(): Int {
|
|
||||||
stateIndex = (stateIndex + 1).and(CMWC_STATE_SIZE - 1)
|
|
||||||
val t = 18782L * state[stateIndex] + carry
|
|
||||||
|
|
||||||
carry = t.ushr(32).toInt()
|
|
||||||
var x = t.toInt() + carry
|
|
||||||
|
|
||||||
if (x < carry) {
|
|
||||||
x++
|
|
||||||
carry++
|
|
||||||
}
|
|
||||||
|
|
||||||
state[stateIndex] = 0xfffffffe.toInt() - x
|
|
||||||
return state[stateIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextLong(): Long {
|
|
||||||
val a = nextInt().toLong() and 0xFFFFFFFFL
|
|
||||||
val b = nextInt().toLong() and 0xFFFFFFFFL
|
|
||||||
return a.shl(32) or b
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextInt(bound: Int): Int {
|
|
||||||
return super<RandomGenerator>.nextInt(bound)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextInt(origin: Int, bound: Int): Int {
|
|
||||||
return super<RandomGenerator>.nextInt(origin, bound)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextBoolean(): Boolean {
|
|
||||||
return super.nextBoolean()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextFloat(): Float {
|
|
||||||
return super.nextFloat()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextDouble(): Double {
|
|
||||||
return super.nextDouble()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextGaussian(): Double {
|
|
||||||
return gaussian.nextGaussian()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fork(): RandomSource {
|
|
||||||
return CMWCRandom(nextLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun forkPositional(): PositionalRandomFactory {
|
|
||||||
return Positional(nextLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
class Positional(private val seed: Long) : PositionalRandomFactory {
|
|
||||||
override fun at(x: Int, y: Int, z: Int): RandomSource {
|
|
||||||
return CMWCRandom(Mth.getSeed(x, y, z).xor(seed))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromHashOf(name: String): RandomSource {
|
|
||||||
return CMWCRandom(name.hashCode().toLong().xor(seed))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromSeed(seed: Long): RandomSource {
|
|
||||||
return CMWCRandom(seed)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun parityConfigString(builder: StringBuilder) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val CMWC_STATE_SIZE = 32 // 4096
|
|
||||||
const val CMWC_CARRY_MAX = 809430660
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.core.util
|
|
||||||
|
|
||||||
import net.minecraft.util.Mth
|
|
||||||
import net.minecraft.util.RandomSource
|
|
||||||
import net.minecraft.world.level.levelgen.LegacyRandomSource
|
|
||||||
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
|
|
||||||
import net.minecraft.world.level.levelgen.PositionalRandomFactory
|
|
||||||
import net.minecraft.world.level.levelgen.RandomSupport
|
|
||||||
import ru.dbotthepony.kommons.random.LCG64Random
|
|
||||||
import java.lang.StringBuilder
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple and insanely fast random number generator, which can be used for seeding (initializing internal state) of other number generators.
|
|
||||||
*
|
|
||||||
* While can be used on its own, it probably shouldn't.
|
|
||||||
*
|
|
||||||
* Differs from [LegacyRandomSource] (also LCG, created by [RandomSource.create]) Minecraft uses in:
|
|
||||||
* * Different constants (with supposedly/expected better statistical properties)
|
|
||||||
* * Always use upper 32 bits instead of implementing BitRandomSource and sampling some upper bits
|
|
||||||
* * Uses all bits from provided seed
|
|
||||||
*/
|
|
||||||
class LCG64RandomSource(seed: Long = RandomSupport.generateUniqueSeed()) : LCG64Random(seed), IRandomSourceGenerator {
|
|
||||||
private val gaussian = MarsagliaPolarGaussian(this)
|
|
||||||
|
|
||||||
override fun setSeed(seed: Long) {
|
|
||||||
this.seed = seed
|
|
||||||
gaussian.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextGaussian(): Double {
|
|
||||||
return gaussian.nextGaussian()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fork(): RandomSource {
|
|
||||||
return LCG64RandomSource(nextLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun forkPositional(): PositionalRandomFactory {
|
|
||||||
return Positional(nextLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
class Positional(private val seed: Long) : PositionalRandomFactory {
|
|
||||||
override fun at(x: Int, y: Int, z: Int): RandomSource {
|
|
||||||
return LCG64RandomSource(Mth.getSeed(x, y, z).xor(seed))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromHashOf(name: String): RandomSource {
|
|
||||||
return LCG64RandomSource(name.hashCode().toLong().xor(seed))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromSeed(seed: Long): RandomSource {
|
|
||||||
return LCG64RandomSource(seed)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun parityConfigString(builder: StringBuilder) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.core.util
|
|
||||||
|
|
||||||
import net.minecraft.util.Mth
|
|
||||||
import net.minecraft.util.RandomSource
|
|
||||||
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
|
|
||||||
import net.minecraft.world.level.levelgen.PositionalRandomFactory
|
|
||||||
import net.minecraft.world.level.levelgen.RandomSupport
|
|
||||||
import ru.dbotthepony.kommons.random.PCG32Random
|
|
||||||
import java.lang.StringBuilder
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see PCG32Random
|
|
||||||
*/
|
|
||||||
class PCG32RandomSource(seed: Long = RandomSupport.generateUniqueSeed()) : PCG32Random(seed), IRandomSourceGenerator {
|
|
||||||
private val gaussian = MarsagliaPolarGaussian(this)
|
|
||||||
|
|
||||||
override fun setSeed(seed: Long) {
|
|
||||||
this.seed = seed
|
|
||||||
gaussian.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextGaussian(): Double {
|
|
||||||
return gaussian.nextGaussian()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fork(): RandomSource {
|
|
||||||
return PCG32RandomSource(nextLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun forkPositional(): PositionalRandomFactory {
|
|
||||||
return Positional(nextLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
class Positional(private val seed: Long) : PositionalRandomFactory {
|
|
||||||
override fun at(x: Int, y: Int, z: Int): RandomSource {
|
|
||||||
return PCG32RandomSource(Mth.getSeed(x, y, z).xor(seed))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromHashOf(name: String): RandomSource {
|
|
||||||
return PCG32RandomSource(name.hashCode().toLong().xor(seed))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromSeed(seed: Long): RandomSource {
|
|
||||||
return PCG32RandomSource(seed)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun parityConfigString(builder: StringBuilder) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.core.util
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.HashCommon
|
|
||||||
import net.minecraft.util.Mth
|
|
||||||
import net.minecraft.util.RandomSource
|
|
||||||
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
|
|
||||||
import net.minecraft.world.level.levelgen.PositionalRandomFactory
|
|
||||||
import net.minecraft.world.level.levelgen.RandomSupport
|
|
||||||
import ru.dbotthepony.kommons.random.LCG64Random
|
|
||||||
import ru.dbotthepony.kommons.random.Xoshiro256StarStarRandom
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Excellent number generator with guaranteed period of 2^255
|
|
||||||
*/
|
|
||||||
class Xoshiro256Random : Xoshiro256StarStarRandom, IRandomSourceGenerator {
|
|
||||||
private val gaussian = MarsagliaPolarGaussian(this)
|
|
||||||
|
|
||||||
// raw
|
|
||||||
private constructor(s0: Long, s1: Long, s2: Long, s3: Long, marker: Nothing?): super(s0, s1, s2, s3, null)
|
|
||||||
// normal
|
|
||||||
constructor(s0: Long, s1: Long, s2: Long, s3: Long) : super(s0, s1, s2, s3)
|
|
||||||
|
|
||||||
// 64-bit seeded
|
|
||||||
constructor(seed: Long) : super(1L, 2L, 3L, 4L, null) {
|
|
||||||
setSeed(seed)
|
|
||||||
}
|
|
||||||
|
|
||||||
// completely random
|
|
||||||
constructor() : super(RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), null)
|
|
||||||
|
|
||||||
override fun setSeed(seed: Long) {
|
|
||||||
val rng = LCG64Random(seed)
|
|
||||||
s0 = rng.nextLong()
|
|
||||||
s1 = rng.nextLong()
|
|
||||||
s2 = rng.nextLong()
|
|
||||||
s3 = rng.nextLong()
|
|
||||||
gaussian.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextInt(): Int {
|
|
||||||
// sample upper bits
|
|
||||||
return nextLong().ushr(32).toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nextGaussian(): Double {
|
|
||||||
return gaussian.nextGaussian()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fork(): RandomSource {
|
|
||||||
return Xoshiro256Random(nextLong(), nextLong(), nextLong(), nextLong(), null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun forkPositional(): PositionalRandomFactory {
|
|
||||||
return Positional(nextLong(), nextLong(), nextLong(), nextLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
class Positional(
|
|
||||||
private val s0: Long,
|
|
||||||
private val s1: Long,
|
|
||||||
private val s2: Long,
|
|
||||||
private val s3: Long,
|
|
||||||
) : PositionalRandomFactory {
|
|
||||||
override fun at(x: Int, y: Int, z: Int): RandomSource {
|
|
||||||
val rng = LCG64RandomSource(Mth.getSeed(x, y, z))
|
|
||||||
|
|
||||||
return Xoshiro256Random(
|
|
||||||
s0.rotateLeft(11).xor(rng.nextLong()),
|
|
||||||
s1.rotateLeft(22).xor(rng.nextLong()),
|
|
||||||
s2.rotateLeft(33).xor(rng.nextLong()),
|
|
||||||
s3.rotateLeft(44).xor(rng.nextLong()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromHashOf(name: String): RandomSource {
|
|
||||||
return Xoshiro256Random(s0, HashCommon.murmurHash3(name.hashCode().toLong()).xor(s1), s2, s3)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromSeed(seed: Long): RandomSource {
|
|
||||||
return Xoshiro256Random(seed)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun parityConfigString(builder: StringBuilder) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@JvmStatic
|
|
||||||
fun raw(s0: Long, s1: Long, s2: Long, s3: Long): Xoshiro256Random {
|
|
||||||
return Xoshiro256Random(s0, s1, s2, s3, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user