Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions stdlib/public/core/FloatingPoint.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -2441,23 +2441,23 @@ where Self.RawSignificand : FixedWidthInteger {
delta.isFinite,
"There is no uniform distribution on an infinite range"
)
let rand: Self.RawSignificand
if Self.RawSignificand.bitWidth == Self.significandBitCount + 1 {
rand = generator.next()
let rand: RawSignificand
if RawSignificand.bitWidth == Self.significandBitCount + 1 {
rand = RawSignificand._random(using: &generator)
% if 'Closed' in Range:
let tmp: UInt8 = generator.next() & 1
if rand == Self.RawSignificand.max && tmp == 1 {
let tmp = UInt8._random(using: &generator) & 1
if rand == RawSignificand.max && tmp == 1 {
return range.upperBound
}
% end
} else {
let significandCount = Self.significandBitCount + 1
let maxSignificand: Self.RawSignificand = 1 << significandCount
let maxSignificand: RawSignificand = 1 << significandCount
% if 'Closed' not in Range:
// Rather than use .next(upperBound:), which has to work with arbitrary
// upper bounds, and therefore does extra work to avoid bias, we can take
// a shortcut because we know that maxSignificand is a power of two.
rand = generator.next() & (maxSignificand - 1)
rand = RawSignificand._random(using: &generator) & (maxSignificand - 1)
% else:
rand = generator.next(upperBound: maxSignificand + 1)
if rand == maxSignificand {
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/Integers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2621,7 +2621,7 @@ extension FixedWidthInteger {
// If we used &+ instead, the result would be zero, which isn't helpful,
// so we actually need to handle this case separately.
if delta == Magnitude.max {
return Self(truncatingIfNeeded: generator.next() as Magnitude)
return Self(truncatingIfNeeded: Magnitude._random(using: &generator))
}
// Need to widen delta to account for the right-endpoint of a closed range.
delta += 1
Expand Down
52 changes: 18 additions & 34 deletions stdlib/public/core/Random.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,38 +67,6 @@ public protocol RandomNumberGenerator {
}

extension RandomNumberGenerator {
@inlinable
public mutating func _fill(bytes buffer: UnsafeMutableRawBufferPointer) {
// FIXME: Optimize
var chunk: UInt64 = 0
var chunkBytes = 0
for i in 0..<buffer.count {
if chunkBytes == 0 {
chunk = next()
chunkBytes = UInt64.bitWidth / 8
}
buffer[i] = UInt8(truncatingIfNeeded: chunk)
chunk >>= UInt8.bitWidth
chunkBytes -= 1
}
}
}

extension RandomNumberGenerator {
/// Returns a value from a uniform, independent distribution of binary data.
///
/// Use this method when you need random binary data to generate another
/// value. If you need an integer value within a specific range, use the
/// static `random(in:using:)` method on that integer type instead of this
/// method.
///
/// - Returns: A random value of `T`. Bits are randomly distributed so that
/// every value of `T` is equally likely to be returned.
@inlinable
public mutating func next<T: FixedWidthInteger & UnsignedInteger>() -> T {
return T._random(using: &self)
}

/// Returns a random value that is less than the given upper bound.
///
/// Use this method when you need random binary data to generate another
Expand All @@ -111,7 +79,7 @@ extension RandomNumberGenerator {
/// - Returns: A random value of `T` in the range `0..<upperBound`. Every
/// value in the range `0..<upperBound` is equally likely to be returned.
@inlinable
public mutating func next<T: FixedWidthInteger & UnsignedInteger>(
internal mutating func next<T: FixedWidthInteger & UnsignedInteger>(
upperBound: T
) -> T {
_precondition(upperBound != 0, "upperBound cannot be zero.")
Expand All @@ -120,11 +88,27 @@ extension RandomNumberGenerator {
var random: T = 0

repeat {
random = next()
random = T._random(using: &self)
} while random < range

return random % upperBound
}

@inlinable
public mutating func _fill(bytes buffer: UnsafeMutableRawBufferPointer) {
// FIXME: Optimize
var chunk: UInt64 = 0
var chunkBytes = 0
for i in 0..<buffer.count {
if chunkBytes == 0 {
chunk = UInt64._random(using: &self)
chunkBytes = UInt64.bitWidth / 8
}
buffer[i] = UInt8(truncatingIfNeeded: chunk)
chunk >>= UInt8.bitWidth
chunkBytes -= 1
}
}
}

/// The system's default source of random data.
Expand Down