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