mirror of
				https://github.com/GayPizzaSpecifications/voxelotl-engine.git
				synced 2025-11-04 02:59:37 +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/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
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user