public extension RandomProvider where Output: BinaryInteger { mutating func next(in range: Range) -> Int { 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 { 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 { 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 = Int(Self.max % Output(bound)) var result: Int repeat { result = Int(truncatingIfNeeded: self.next()) } while result < threshold return result % bound } } public extension RandomProvider where Output: UnsignedInteger { mutating func next(in range: Range) -> 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 { 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 { 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 { 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 { let shift = bound.leadingZeroBitCount let mask = Output.max &>> shift var result: Output repeat { result = next() & mask } while result >= bound return result } }