mirror of
				https://github.com/GayPizzaSpecifications/voxelotl-engine.git
				synced 2025-11-04 10:59:39 +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