Move PRNG implementation to Kommons

Yurie — Сегодня, в 15:09
вопрос
почему все эти рандомы не в kommons
This commit is contained in:
DBotThePony 2025-03-08 16:45:38 +07:00
parent 322d89f2a2
commit 430bc70c7e
Signed by: DBot
GPG Key ID: DCC23B5715498507
7 changed files with 133 additions and 178 deletions

View File

@ -22,7 +22,7 @@ mixin_version=0.8.5
neogradle.subsystems.parchment.minecraftVersion=1.21.1
neogradle.subsystems.parchment.mappingsVersion=2024.11.17
kommons_version=3.1.3
kommons_version=3.2.1
caffeine_cache_version=3.1.5
jei_version=19.16.4.171

View File

@ -5,11 +5,11 @@ import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
import ru.dbotthepony.mc.otm.core.IMatteryLevel;
import ru.dbotthepony.mc.otm.core.util.Xoshiro256SSRandom;
import ru.dbotthepony.mc.otm.core.util.Xoshiro256Random;
@Mixin(Level.class)
public abstract class LevelMixin implements IMatteryLevel {
public final RandomSource otm_random = new Xoshiro256SSRandom();
public final RandomSource otm_random = new Xoshiro256Random();
@Override
public @NotNull RandomSource getOtmRandom() {

View File

@ -5,6 +5,7 @@ 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 java.lang.StringBuilder
import java.util.random.RandomGenerator

View File

@ -0,0 +1,30 @@
package ru.dbotthepony.mc.otm.core.util
import net.minecraft.util.RandomSource
import java.util.random.RandomGenerator
interface IRandomSourceGenerator : RandomSource, RandomGenerator {
override fun nextInt(): Int
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
}

View File

@ -6,8 +6,8 @@ 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
import java.util.random.RandomGenerator
/**
* Simple and insanely fast random number generator, which can be used for seeding (initializing internal state) of other number generators.
@ -19,7 +19,7 @@ import java.util.random.RandomGenerator
* * Always use upper 32 bits instead of implementing BitRandomSource and sampling some upper bits
* * Uses all bits from provided seed
*/
class LCG64Random(private var seed: Long = RandomSupport.generateUniqueSeed()) : RandomGenerator, RandomSource {
class LCG64RandomSource(seed: Long = RandomSupport.generateUniqueSeed()) : LCG64Random(seed), IRandomSourceGenerator {
private val gaussian = MarsagliaPolarGaussian(this)
override fun setSeed(seed: Long) {
@ -27,43 +27,12 @@ class LCG64Random(private var seed: Long = RandomSupport.generateUniqueSeed()) :
gaussian.reset()
}
override fun nextInt(): Int {
this.seed = MULTIPLIER * this.seed + INCREMENT
return this.seed.ushr(32).toInt()
}
override fun nextLong(): Long {
val a = nextInt().toLong()
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 LCG64Random(nextLong())
return LCG64RandomSource(nextLong())
}
override fun forkPositional(): PositionalRandomFactory {
@ -72,15 +41,15 @@ class LCG64Random(private var seed: Long = RandomSupport.generateUniqueSeed()) :
class Positional(val seed: Long) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource {
return LCG64Random(Mth.getSeed(x, y, z).xor(seed))
return LCG64RandomSource(Mth.getSeed(x, y, z).xor(seed))
}
override fun fromHashOf(name: String): RandomSource {
return LCG64Random(name.hashCode().toLong().xor(seed))
return LCG64RandomSource(name.hashCode().toLong().xor(seed))
}
override fun fromSeed(seed: Long): RandomSource {
return LCG64Random(seed)
return LCG64RandomSource(seed)
}
override fun parityConfigString(builder: StringBuilder) {

View File

@ -0,0 +1,93 @@
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(
val s0: Long,
val s1: Long,
val s2: Long,
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)
}
}
}

View File

@ -1,138 +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 java.util.random.RandomGenerator
/**
* Excellent number generator with guaranteed period of 2^255
*/
class Xoshiro256SSRandom private constructor(
private var s0: Long,
private var s1: Long,
private var s2: Long,
private var s3: Long,
marker: Nothing?
) : RandomGenerator, RandomSource {
private val gaussian = MarsagliaPolarGaussian(this)
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, 2L, 3L, 4L, null) {
setSeed(seed)
}
constructor() : this(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 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
}
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 Xoshiro256SSRandom(nextLong(), nextLong(), nextLong(), nextLong(), null)
}
override fun forkPositional(): PositionalRandomFactory {
return Positional(nextLong(), nextLong(), nextLong(), nextLong())
}
class Positional(
val s0: Long,
val s1: Long,
val s2: Long,
val s3: Long,
) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource {
val rng = LCG64Random(Mth.getSeed(x, y, z))
return Xoshiro256SSRandom(
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 Xoshiro256SSRandom(s0, HashCommon.murmurHash3(name.hashCode().toLong()).xor(s1), s2, s3)
}
override fun fromSeed(seed: Long): RandomSource {
return Xoshiro256SSRandom(seed)
}
override fun parityConfigString(builder: StringBuilder) {
throw UnsupportedOperationException()
}
}
companion object {
@JvmStatic
fun raw(s0: Long, s1: Long, s2: Long, s3: Long): Xoshiro256SSRandom {
return Xoshiro256SSRandom(s0, s1, s2, s3, null)
}
}
}