mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-02 21:00:57 +00:00
split split mix sixty four
This commit is contained in:
parent
c99155fb47
commit
1f74b79ea2
@ -28,6 +28,7 @@ add_executable(Voxelotl MACOSX_BUNDLE
|
||||
Random/PerlinNoiseGenerator.swift
|
||||
Random/SimplexNoise.swift
|
||||
Random/RandomCollectionExtensions.swift
|
||||
Random/SplitMix64.swift
|
||||
|
||||
# Resource classes
|
||||
NSImageLoader.swift
|
||||
|
@ -1,5 +1,6 @@
|
||||
public struct PCG32Random: RandomProvider, RandomStateAccess {
|
||||
public struct PCG32Random: RandomProvider, RandomSeedable, RandomStateAccess {
|
||||
public typealias Output = UInt32
|
||||
public typealias SeedType = (UInt64, UInt64)
|
||||
public typealias StateType = (UInt64, UInt64)
|
||||
|
||||
public static var min: UInt32 { .min }
|
||||
@ -21,11 +22,20 @@ public struct PCG32Random: RandomProvider, RandomStateAccess {
|
||||
}
|
||||
|
||||
public init(state: (UInt64, UInt64)) {
|
||||
self.init()
|
||||
self.reset(state: state.0, sequence: state.1)
|
||||
self._state = state.0
|
||||
self._inc = state.1
|
||||
}
|
||||
|
||||
public mutating func reset(state: UInt64, sequence: UInt64) {
|
||||
public init(seed: (UInt64, UInt64)) {
|
||||
self.init()
|
||||
self.seed(state: seed.0, sequence: seed.1)
|
||||
}
|
||||
|
||||
public mutating func seed(_ seed: (UInt64, UInt64)) {
|
||||
self.seed(state: seed.0, sequence: seed.1)
|
||||
}
|
||||
|
||||
public mutating func seed(state: UInt64, sequence: UInt64) {
|
||||
self._state = 0
|
||||
self._inc = sequence << 1 | 0x1
|
||||
_ = next()
|
||||
|
@ -8,7 +8,7 @@ public protocol RandomProvider {
|
||||
}
|
||||
|
||||
public protocol RandomSeedable {
|
||||
associatedtype SeedType: FixedWidthInteger
|
||||
associatedtype SeedType
|
||||
|
||||
init(seed: SeedType)
|
||||
mutating func seed(_ value: SeedType)
|
||||
|
25
Sources/Voxelotl/Random/SplitMix64.swift
Normal file
25
Sources/Voxelotl/Random/SplitMix64.swift
Normal file
@ -0,0 +1,25 @@
|
||||
public struct SplitMix64: RandomProvider, RandomSeedable {
|
||||
public typealias Output = UInt64
|
||||
public typealias SeedType = UInt64
|
||||
|
||||
public static var min: UInt64 { .max }
|
||||
public static var max: UInt64 { .min }
|
||||
|
||||
private var _state: UInt64
|
||||
|
||||
public init(seed: UInt64) {
|
||||
self._state = seed
|
||||
}
|
||||
|
||||
public mutating func seed(_ value: UInt64) {
|
||||
self._state = value
|
||||
}
|
||||
|
||||
public mutating func next() -> UInt64 {
|
||||
var x = self._state &+ 0x9E3779B97F4A7C15
|
||||
x = (x ^ x &>> 30) &* 0xBF58476D1CE4E5B9
|
||||
x = (x ^ x &>> 27) &* 0x94D049BB133111EB
|
||||
self._state = x ^ x &>> 31
|
||||
return self._state
|
||||
}
|
||||
}
|
@ -1,10 +1,9 @@
|
||||
struct Xoroshiro128Plus: RandomProvider, RandomSeedable, RandomStateAccess {
|
||||
public struct Xoroshiro128Plus: RandomProvider, RandomStateAccess {
|
||||
public typealias Output = UInt64
|
||||
public typealias SeedType = UInt64
|
||||
public typealias StateType = (UInt64, UInt64)
|
||||
|
||||
static public var min: UInt64 { .min }
|
||||
static public var max: UInt64 { .max }
|
||||
public static var min: UInt64 { .min }
|
||||
public static var max: UInt64 { .max }
|
||||
|
||||
public var state: (UInt64, UInt64)
|
||||
|
||||
@ -16,16 +15,6 @@ struct Xoroshiro128Plus: RandomProvider, RandomSeedable, RandomStateAccess {
|
||||
self.state = (state.0, state.1)
|
||||
}
|
||||
|
||||
public init(seed: UInt64) {
|
||||
let s0 = splitMix64(seed: seed)
|
||||
self.init(state: (s0, splitMix64(seed: s0)))
|
||||
}
|
||||
|
||||
public mutating func seed(_ seed: UInt64) {
|
||||
let s0 = splitMix64(seed: seed)
|
||||
self.state = (s0, splitMix64(seed: s0))
|
||||
}
|
||||
|
||||
public mutating func next() -> UInt64 {
|
||||
let result = self.state.0 &+ self.state.1
|
||||
|
||||
@ -38,13 +27,12 @@ struct Xoroshiro128Plus: RandomProvider, RandomSeedable, RandomStateAccess {
|
||||
}
|
||||
}
|
||||
|
||||
struct Xoroshiro128PlusPlus: RandomProvider, RandomSeedable, RandomStateAccess {
|
||||
public struct Xoroshiro128PlusPlus: RandomProvider, RandomStateAccess {
|
||||
public typealias Output = UInt64
|
||||
public typealias SeedType = UInt64
|
||||
public typealias StateType = (UInt64, UInt64)
|
||||
|
||||
static public var min: UInt64 { .min }
|
||||
static public var max: UInt64 { .max }
|
||||
public static var min: UInt64 { .min }
|
||||
public static var max: UInt64 { .max }
|
||||
|
||||
public var state: (UInt64, UInt64)
|
||||
|
||||
@ -56,16 +44,6 @@ struct Xoroshiro128PlusPlus: RandomProvider, RandomSeedable, RandomStateAccess {
|
||||
self.state = (state.0, state.1)
|
||||
}
|
||||
|
||||
public init(seed: UInt64) {
|
||||
let s0 = splitMix64(seed: seed)
|
||||
self.init(state: (s0, splitMix64(seed: s0)))
|
||||
}
|
||||
|
||||
public mutating func seed(_ seed: UInt64) {
|
||||
let s0 = splitMix64(seed: seed)
|
||||
self.state = (s0, splitMix64(seed: s0))
|
||||
}
|
||||
|
||||
public mutating func next() -> UInt64 {
|
||||
let result = (self.state.0 &+ self.state.1).rotate(left: 17) &+ self.state.0
|
||||
|
||||
@ -78,13 +56,12 @@ struct Xoroshiro128PlusPlus: RandomProvider, RandomSeedable, RandomStateAccess {
|
||||
}
|
||||
}
|
||||
|
||||
struct Xoroshiro128StarStar: RandomProvider, RandomSeedable, RandomStateAccess {
|
||||
public struct Xoroshiro128StarStar: RandomProvider, RandomStateAccess {
|
||||
public typealias Output = UInt64
|
||||
public typealias SeedType = UInt64
|
||||
public typealias StateType = (UInt64, UInt64)
|
||||
|
||||
static public var min: UInt64 { .min }
|
||||
static public var max: UInt64 { .max }
|
||||
public static var min: UInt64 { .min }
|
||||
public static var max: UInt64 { .max }
|
||||
|
||||
public var state: (UInt64, UInt64)
|
||||
|
||||
@ -96,16 +73,6 @@ struct Xoroshiro128StarStar: RandomProvider, RandomSeedable, RandomStateAccess {
|
||||
self.state = (state.0, state.1)
|
||||
}
|
||||
|
||||
public init(seed: UInt64) {
|
||||
let s0 = splitMix64(seed: seed)
|
||||
self.init(state: (s0, splitMix64(seed: s0)))
|
||||
}
|
||||
|
||||
public mutating func seed(_ seed: UInt64) {
|
||||
let s0 = splitMix64(seed: seed)
|
||||
self.state = (s0, splitMix64(seed: s0))
|
||||
}
|
||||
|
||||
public mutating func next() -> UInt64 {
|
||||
let result = (self.state.0 &* 5).rotate(left: 7) &* 9
|
||||
|
||||
@ -119,14 +86,7 @@ struct Xoroshiro128StarStar: RandomProvider, RandomSeedable, RandomStateAccess {
|
||||
}
|
||||
|
||||
fileprivate extension UInt64 {
|
||||
func rotate(left count: Int) -> Self {
|
||||
@inline(__always) func rotate(left count: Int) -> Self {
|
||||
self &<< count | self &>> (Self.bitWidth &- count)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func splitMix64(seed: UInt64) -> UInt64 {
|
||||
var x = seed &+ 0x9E3779B97F4A7C15
|
||||
x = (x ^ x &>> 30) &* 0xBF58476D1CE4E5B9
|
||||
x = (x ^ x &>> 27) &* 0x94D049BB133111EB
|
||||
return x ^ x &>> 31
|
||||
}
|
||||
|
@ -3,13 +3,11 @@ struct WorldGenerator {
|
||||
|
||||
public mutating func reset(seed: UInt64) {
|
||||
var random: any RandomProvider
|
||||
let initialState = SplitMix64.createState(seed: seed)
|
||||
#if true
|
||||
random = Xoroshiro128PlusPlus(seed: seed)
|
||||
random = Xoroshiro128PlusPlus(state: initialState)
|
||||
#else
|
||||
//TODO: Fill seed with a hash
|
||||
random = PCG32Random(state: (
|
||||
UInt64(Arc4Random.instance.next()) | UInt64(Arc4Random.instance.next()) << 32,
|
||||
UInt64(Arc4Random.instance.next()) | UInt64(Arc4Random.instance.next()) << 32))
|
||||
random = PCG32Random(seed: initialState)
|
||||
#endif
|
||||
|
||||
self.noise = ImprovedPerlin<Float>(random: &random)
|
||||
@ -38,3 +36,11 @@ struct WorldGenerator {
|
||||
return chunk
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension RandomProvider where Output == UInt64, Self: RandomSeedable, SeedType == UInt64 {
|
||||
static func createState(seed value: UInt64) -> (UInt64, UInt64) {
|
||||
var hash = Self(seed: value)
|
||||
let state = (hash.next(), hash.next())
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user