mirror of
				https://github.com/GayPizzaSpecifications/voxelotl-engine.git
				synced 2025-11-04 10:59:39 +00:00 
			
		
		
		
	broader randomrange extensions
This commit is contained in:
		@ -33,7 +33,9 @@ class Game: GameDelegate {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private func generateWorld() {
 | 
					  private func generateWorld() {
 | 
				
			||||||
    var random = DarwinRandom(seed: Arc4Random.instance.next(in: DarwinRandom.max))
 | 
					    let newSeed = Arc4Random.instance.next(in: DarwinRandom.max)
 | 
				
			||||||
 | 
					    printErr(newSeed)
 | 
				
			||||||
 | 
					    var random = DarwinRandom(seed: newSeed)
 | 
				
			||||||
    self.chunk.fill(allBy: {
 | 
					    self.chunk.fill(allBy: {
 | 
				
			||||||
      if (random.next() & 0x1) == 0x1 {
 | 
					      if (random.next() & 0x1) == 0x1 {
 | 
				
			||||||
        .solid(.init(rgb888: UInt32(random.next(in: 0..<0xFFFFFF+1))).linear)
 | 
					        .solid(.init(rgb888: UInt32(random.next(in: 0..<0xFFFFFF+1))).linear)
 | 
				
			||||||
 | 
				
			|||||||
@ -17,12 +17,37 @@ public class Arc4Random: RandomProvider {
 | 
				
			|||||||
    arc4random()
 | 
					    arc4random()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public func next(in bound: Int) -> Int {
 | 
					  func next(in bound: UInt32) -> UInt32 {
 | 
				
			||||||
    assert(bound <= Self.max)
 | 
					    return arc4random_uniform(bound)
 | 
				
			||||||
    return Int(arc4random_uniform(UInt32(bound)))
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public func next(in range: Range<Int>) -> Int {
 | 
					  func next(in bound: Int) -> Int {
 | 
				
			||||||
    return range.lowerBound + next(in: range.upperBound - range.lowerBound)
 | 
					    assert(bound <= UInt32.max, "Maximum raw random provider output is smaller than requested bound")
 | 
				
			||||||
 | 
					    return Int(arc4random_uniform(UInt32(bound)))
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public extension Arc4Random {
 | 
				
			||||||
 | 
					  func next(in range: Range<UInt32>) -> UInt32 {
 | 
				
			||||||
 | 
					    assert(!range.isEmpty, "Ranged next called with empty range")
 | 
				
			||||||
 | 
					    return range.lowerBound + next(in: range.upperBound - range.lowerBound)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func next(in range: ClosedRange<UInt32>) -> UInt32 {
 | 
				
			||||||
 | 
					    if range == 0...UInt32.max {
 | 
				
			||||||
 | 
					      next()
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      next(in: range.upperBound - range.lowerBound + 1)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func next(in range: Range<Int>) -> Int {
 | 
				
			||||||
 | 
					    assert(!range.isEmpty, "Ranged next called with empty range")
 | 
				
			||||||
 | 
					    return range.lowerBound + next(in: range.upperBound - range.lowerBound)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func next(in range: ClosedRange<Int>) -> Int {
 | 
				
			||||||
 | 
					    assert(range.upperBound - range.lowerBound < Int.max, "Closed range exceeds Int.max")
 | 
				
			||||||
 | 
					    return range.lowerBound + next(in: range.upperBound - range.lowerBound + 1)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,15 +1,17 @@
 | 
				
			|||||||
public extension RandomProvider where Output: BinaryInteger {
 | 
					public extension RandomProvider where Output: BinaryInteger {
 | 
				
			||||||
  mutating func next(in range: Range<Int>) -> Int {
 | 
					  mutating func next(in range: Range<Int>) -> Int {
 | 
				
			||||||
    range.lowerBound + self.next(in: range.upperBound - range.lowerBound)
 | 
					    assert(!range.isEmpty, "Ranged next called with empty range")
 | 
				
			||||||
 | 
					    return range.lowerBound + self.next(in: range.upperBound - range.lowerBound)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mutating func next(in range: ClosedRange<Int>) -> Int {
 | 
					  mutating func next(in range: ClosedRange<Int>) -> Int {
 | 
				
			||||||
    range.lowerBound + self.next(in: range.upperBound - range.lowerBound + 1)
 | 
					    assert(range.upperBound - range.lowerBound < Int.max, "Closed range exceeds Int.max")
 | 
				
			||||||
 | 
					    return range.lowerBound + self.next(in: range.upperBound - range.lowerBound + 1)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mutating func next(in bound: Int) -> Int {
 | 
					  mutating func next(in bound: Int) -> Int {
 | 
				
			||||||
    assert(Self.min == 0)
 | 
					    assert(Self.min == 0, "Range operations are unsupported on random providers with a non-zero minimum")
 | 
				
			||||||
    assert(Self.max >= bound)
 | 
					    assert(Self.max >= bound, "Maximum raw random provider output is smaller than requested bound")
 | 
				
			||||||
    let threshold = Int(Self.max % Output(bound))
 | 
					    let threshold = Int(Self.max % Output(bound))
 | 
				
			||||||
    var result: Int
 | 
					    var result: Int
 | 
				
			||||||
    repeat {
 | 
					    repeat {
 | 
				
			||||||
@ -18,3 +20,70 @@ public extension RandomProvider where Output: BinaryInteger {
 | 
				
			|||||||
    return result % bound
 | 
					    return result % bound
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public extension RandomProvider where Output: UnsignedInteger {
 | 
				
			||||||
 | 
					  mutating func next(in range: Range<Output>) -> Output {
 | 
				
			||||||
 | 
					    assert(!range.isEmpty, "Ranged next called with empty range")
 | 
				
			||||||
 | 
					    return range.lowerBound + self.next(in: range.upperBound - range.lowerBound)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mutating func next(in range: ClosedRange<Output>) -> Output {
 | 
				
			||||||
 | 
					    if range == 0...Output.max {
 | 
				
			||||||
 | 
					      next()
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      range.lowerBound + self.next(in: range.upperBound - range.lowerBound + 1)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mutating func next(in bound: Output) -> Output {
 | 
				
			||||||
 | 
					    assert(Self.min == 0, "Range operations are unsupported on random providers with a non-zero minimum")
 | 
				
			||||||
 | 
					    assert(Self.max >= bound, "Maximum raw random provider output is smaller than requested bound")
 | 
				
			||||||
 | 
					    let threshold = (Self.max &- bound &+ 1) % bound
 | 
				
			||||||
 | 
					    var result: Output
 | 
				
			||||||
 | 
					    repeat {
 | 
				
			||||||
 | 
					      result = self.next()
 | 
				
			||||||
 | 
					    } while result < threshold
 | 
				
			||||||
 | 
					    return result % bound
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//MARK: - Experimental
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Uniform bounded random without modulos, WILL produce different results from the standard bounded next
 | 
				
			||||||
 | 
					public extension RandomProvider where Output: UnsignedInteger {
 | 
				
			||||||
 | 
					  mutating func nextModless(in range: Range<Output>) -> Output {
 | 
				
			||||||
 | 
					    assert(!range.isEmpty, "Ranged next called with empty range")
 | 
				
			||||||
 | 
					    return range.lowerBound + self.nextModless(in: range.upperBound - range.lowerBound)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mutating func nextModless(in range: ClosedRange<Output>) -> Output {
 | 
				
			||||||
 | 
					    if range == 0...Output.max {
 | 
				
			||||||
 | 
					      self.next()
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      range.lowerBound + self.nextModless(in: range.upperBound - range.lowerBound + 1)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mutating func nextModless(in bound: Output) -> Output {
 | 
				
			||||||
 | 
					    func pow2MaskFrom(range num: Output) -> Output {
 | 
				
			||||||
 | 
					      if num & (num - 1) == 0 {
 | 
				
			||||||
 | 
					        return num - 1
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      var result: Output = 1
 | 
				
			||||||
 | 
					      for _ in 0..<Output.bitWidth {
 | 
				
			||||||
 | 
					        if result >= num {
 | 
				
			||||||
 | 
					          return result - 1
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        result <<= 1
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return .max
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mask = pow2MaskFrom(range: bound)
 | 
				
			||||||
 | 
					    var result: Output
 | 
				
			||||||
 | 
					    repeat {
 | 
				
			||||||
 | 
					      result = next() & mask
 | 
				
			||||||
 | 
					    } while result >= bound
 | 
				
			||||||
 | 
					    return result
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user