Skip to content

Commit

Permalink
Remove refs to Countable ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
Azoy committed Feb 3, 2018
1 parent 4f4f65e commit e61e1f5
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 2 deletions.
51 changes: 51 additions & 0 deletions stdlib/public/core/ClosedRange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,57 @@ extension ClosedRange where Bound: Strideable, Bound.Stride : SignedInteger {
}
}

extension ClosedRange
where Bound : FixedWidthInteger,
Bound.Magnitude : UnsignedInteger {

/// Returns a random element from this collection.
///
/// - Parameter generator: The random number generator to use when getting
/// a random element.
/// - Returns: A random element from this collection.
///
/// A good example of this is getting a random greeting from an array:
///
/// let greetings = ["hi", "hey", "hello", "hola"]
/// let randomGreeting = greetings.random()
///
/// If the collection is empty, the value of this function is `nil`.
///
/// let numbers = [10, 20, 30, 40, 50]
/// if let randomNumber = numbers.random() {
/// print(randomNumber)
/// }
/// // Could print "20", perhaps
@_inlineable
public func random(
using generator: RandomNumberGenerator = Random.default
) -> Element? {
let isLowerNegative = Bound.isSigned && lowerBound < 0
let sameSign = !Bound.isSigned || isLowerNegative == (upperBound < 0)
var delta: Bound.Magnitude
if isLowerNegative {
delta = sameSign
? lowerBound.magnitude - upperBound.magnitude
: lowerBound.magnitude + upperBound.magnitude
} else {
delta = upperBound.magnitude - lowerBound.magnitude
}
if delta == Bound.Magnitude.max {
return Bound(truncatingIfNeeded: generator.next() as Bound.Magnitude)
}
delta += 1
let randomMagnitude = generator.next(upperBound: delta)
if sameSign {
return lowerBound + Bound(randomMagnitude)
} else {
return Bound.isSigned && randomMagnitude <= upperBound.magnitude
? Bound(randomMagnitude)
: 0 - Bound(randomMagnitude - upperBound.magnitude)
}
}
}

extension ClosedRange {
@_inlineable
public func overlaps(_ other: ClosedRange<Bound>) -> Bool {
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/Integers.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -2344,7 +2344,7 @@ ${assignmentOperatorComment(x.operator, False)}
% end
}

% for Range in ['CountableRange', 'CountableClosedRange']:
% for Range in ['Range', 'ClosedRange']:

extension FixedWidthInteger
where Self.Stride : SignedInteger,
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/Random.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ extension RandomNumberGenerator {
/// Using the preferred way:
///
/// let random = UInt8.random(in: .min ... .max)
/// let randomToTen = UInt32.random(in: 0 ... 128)
/// let randomToTen = UInt32.random(in: 0 ..< 10)
///
/// - Note: The default implementation of randomness is cryptographically secure.
/// It utilizes arc4random(3) on newer versions of macOS, iOS, etc. On older
Expand Down
50 changes: 50 additions & 0 deletions stdlib/public/core/Range.swift
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,56 @@ extension Range where Bound: Strideable, Bound.Stride : SignedInteger {
}
}

extension Range
where Bound : FixedWidthInteger,
Bound.Magnitude : UnsignedInteger {

/// Returns a random element from this collection.
///
/// - Parameter generator: The random number generator to use when getting
/// a random element.
/// - Returns: A random element from this collection.
///
/// A good example of this is getting a random greeting from an array:
///
/// let greetings = ["hi", "hey", "hello", "hola"]
/// let randomGreeting = greetings.random()
///
/// If the collection is empty, the value of this function is `nil`.
///
/// let numbers = [10, 20, 30, 40, 50]
/// if let randomNumber = numbers.random() {
/// print(randomNumber)
/// }
/// // Could print "20", perhaps
@_inlineable
public func random(
using generator: RandomNumberGenerator = Random.default
) -> Element? {
guard lowerBound != upperBound else {
return nil
}
let isLowerNegative = Bound.isSigned && lowerBound < 0
let sameSign = !Bound.isSigned || isLowerNegative == (upperBound < 0)
let delta: Bound.Magnitude
if isLowerNegative {
delta = sameSign
? lowerBound.magnitude - upperBound.magnitude
: lowerBound.magnitude + upperBound.magnitude
} else {
delta = upperBound.magnitude - lowerBound.magnitude
}
let randomMagnitude = generator.next(upperBound: delta)
if sameSign {
return lowerBound + Bound(randomMagnitude)
} else {
return randomMagnitude < upperBound.magnitude
? Bound(randomMagnitude)
: -1 - Bound(randomMagnitude - upperBound.magnitude)
}
}
}

extension Range: RangeExpression {
@_inlineable // FIXME(sil-serialize-all)
public func relative<C: Collection>(to collection: C) -> Range<Bound>
Expand Down

0 comments on commit e61e1f5

Please sign in to comment.