Skip to content

Commit cc31865

Browse files
benrimmingtonlorentey
authored andcommitted
Consolidate _stdlib_random functions (#2)
* Use the `__has_include` and `GRND_RANDOM` macros * Use `getentropy` instead of `getrandom` * Use `std::min` from the <algorithm> header * Move `#if` out of the `_stdlib_random` function * Use `getrandom` with "/dev/urandom" fallback * Use `#pragma comment` to import "Bcrypt.lib" * <https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp> * <https://clang.llvm.org/docs/UsersManual.html#microsoft-extensions> * Use "/dev/urandom" instead of `SecRandomCopyBytes` * Use `swift::StaticMutex` for shared "/dev/urandom" * Add `getrandom_available`; use `O_CLOEXEC` flag Add platform impl docs Update copyrights Fix docs Add _stdlib_random test Update _stdlib_random test Add missing & Notice about _stdlib_random Fix docs Guard on upperBound = 0 Test full range of 8 bit integers Remove some gyb Clean up integerRangeTest Remove FixedWidthInteger constraint Use arc4random universally Fix randomElement Constrain shuffle to RandomAccessCollection warning instead of error Move Apple's implementation Fix failing test on 32 bit systems (cherry picked from commit b65d0c1)
1 parent c615e59 commit cc31865

File tree

13 files changed

+203
-171
lines changed

13 files changed

+203
-171
lines changed

benchmark/single-source/RandomShuffle.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information

benchmark/single-source/RandomValues.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information

benchmark/utils/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information

stdlib/public/SwiftShims/LibcShims.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information

stdlib/public/core/Bool.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -87,23 +87,21 @@ public struct Bool {
8787
self = value
8888
}
8989

90-
/// Returns a random Boolean
90+
/// Returns a random Boolean value
9191
///
9292
/// - Parameter generator: The random number generator to use when getting a
9393
/// random Boolean.
94-
/// - Returns: A random Boolean.
94+
/// - Returns: A random Boolean value.
9595
@inlinable
9696
public static func random<T: RandomNumberGenerator>(
9797
using generator: inout T
9898
) -> Bool {
9999
return (generator.next() >> 17) & 1 == 0
100100
}
101101

102-
/// Returns a random Boolean
102+
/// Returns a random Boolean value
103103
///
104-
/// - Parameter generator: The random number generator to use when getting a
105-
/// random Boolean.
106-
/// - Returns: A random Boolean.
104+
/// - Returns: A random Boolean value.
107105
///
108106
/// This uses the standard library's default random number generator.
109107
@inlinable

stdlib/public/core/CMakeLists.txt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# This source file is part of the Swift.org open source project
44
#
5-
# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
# Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
# Licensed under Apache License v2.0 with Runtime Library Exception
77
#
88
# See https://swift.org/LICENSE.txt for license information
@@ -194,7 +194,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
194194
list(APPEND swift_core_link_flags "-all_load")
195195
list(APPEND swift_core_framework_depends Foundation)
196196
list(APPEND swift_core_framework_depends CoreFoundation)
197-
list(APPEND swift_core_framework_depends Security)
198197
list(APPEND swift_core_private_link_libraries icucore)
199198
else()
200199
# With the GNU linker the equivalent of -all_load is to tell the linker
@@ -229,10 +228,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
229228
${EXECINFO_LIBRARY})
230229
endif()
231230

232-
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
233-
list(APPEND swift_core_link_flags "$ENV{SystemRoot}/system32/bcrypt.dll")
234-
endif()
235-
236231
option(SWIFT_CHECK_ESSENTIAL_STDLIB
237232
"Check core standard library layering by linking its essential subset"
238233
FALSE)

stdlib/public/core/Collection.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -803,6 +803,25 @@ public protocol Collection: Sequence where SubSequence: Collection {
803803
/// `endIndex`.
804804
func formIndex(after i: inout Index)
805805

806+
/// Returns a random element of the collection, using the given generator as
807+
/// a source for randomness.
808+
///
809+
/// You use this method to select a random element from a collection when you
810+
/// are using a custom random number generator. For example, call
811+
/// `randomElement(using:)` to select a random element from an array of names.
812+
///
813+
/// let names = ["Zoey", "Chloe", "Amani", "Amaia"]
814+
/// let randomName = names.randomElement(using: &myGenerator)!
815+
/// // randomName == "Amani" (maybe)
816+
///
817+
/// - Parameter generator: The random number generator to use when choosing
818+
/// a random element.
819+
/// - Returns: A random element from the collection. If the collection is
820+
/// empty, the method returns `nil`.
821+
func randomElement<T: RandomNumberGenerator>(
822+
using generator: inout T
823+
) -> Element?
824+
806825
@available(*, deprecated, message: "all index distances are now of type Int")
807826
typealias IndexDistance = Int
808827
}
@@ -1038,9 +1057,8 @@ extension Collection {
10381057
guard !isEmpty else { return nil }
10391058
let random = generator.next(upperBound: UInt(count))
10401059
let index = self.index(
1041-
self.startIndex,
1042-
offsetBy: IndexDistance(random),
1043-
limitedBy: self.endIndex
1060+
startIndex,
1061+
offsetBy: numericCast(random)
10441062
)
10451063
return self[index]
10461064
}

stdlib/public/core/CollectionAlgorithms.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -411,8 +411,6 @@ extension Sequence {
411411
/// to `numbers.shuffled()` above is equivalent to calling
412412
/// `numbers.shuffled(using: &Random.default)`.
413413
///
414-
/// - Parameter generator: The random number generator to use when shuffling
415-
/// the sequence.
416414
/// - Returns: A shuffled array of this sequence's elements.
417415
///
418416
/// - Complexity: O(*n*)
@@ -422,7 +420,7 @@ extension Sequence {
422420
}
423421
}
424422

425-
extension MutableCollection {
423+
extension MutableCollection where Self : RandomAccessCollection {
426424
/// Shuffles the collection in place, using the given generator as a source
427425
/// for randomness.
428426
///
@@ -442,6 +440,7 @@ extension MutableCollection {
442440
public mutating func shuffle<T: RandomNumberGenerator>(
443441
using generator: inout T
444442
) {
443+
let count = self.count
445444
guard count > 1 else { return }
446445
var amount = count
447446
var currentIndex = startIndex

stdlib/public/core/FloatingPoint.swift.gyb

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -2403,7 +2403,7 @@ extension BinaryFloatingPoint {
24032403
% exampleRange = '10.0..<20.0' if Range == 'Range' else '10.0...20.0'
24042404
extension BinaryFloatingPoint
24052405
where Self.RawSignificand : FixedWidthInteger,
2406-
Self.RawSignificand.Stride : SignedInteger & FixedWidthInteger,
2406+
Self.RawSignificand.Stride : SignedInteger,
24072407
Self.RawSignificand.Magnitude : UnsignedInteger {
24082408

24092409
/// Returns a random value within the specified range, using the given
@@ -2420,7 +2420,7 @@ where Self.RawSignificand : FixedWidthInteger,
24202420
/// // Prints "14.2286325689993"
24212421
/// // Prints "13.1485686260762"
24222422
///
2423-
/// The `random(using:)` static method chooses a random value from a
2423+
/// The `random(in:using:)` static method chooses a random value from a
24242424
/// continuous uniform distribution in `range`, and then converts that value
24252425
/// to the nearest representable value in this type. Depending on the size and
24262426
/// span of `range`, some concrete values may be represented more frequently
@@ -2439,12 +2439,10 @@ where Self.RawSignificand : FixedWidthInteger,
24392439
in range: ${Range}<Self>,
24402440
using generator: inout T
24412441
) -> Self {
2442-
% if 'Closed' not in Range:
24432442
_precondition(
2444-
range.lowerBound != range.upperBound,
2445-
"Can't get random value with lowerBound == upperBound"
2443+
!range.isEmpty,
2444+
"Can't get random value with an empty range"
24462445
)
2447-
% end
24482446
let delta = range.upperBound - range.lowerBound
24492447
let rand: Self.RawSignificand
24502448
if Self.RawSignificand.bitWidth == Self.significandBitCount + 1 {
@@ -2456,7 +2454,8 @@ where Self.RawSignificand : FixedWidthInteger,
24562454
}
24572455
% end
24582456
} else {
2459-
let maxSignificand = Self.RawSignificand(1 << (Self.significandBitCount + 1))
2457+
let significandCount = Self.significandBitCount + 1
2458+
let maxSignificand: Self.RawSignificand = 1 << significandCount
24602459
% if 'Closed' not in Range:
24612460
rand = generator.next(upperBound: maxSignificand)
24622461
% else:

stdlib/public/core/Integers.swift.gyb

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -2560,11 +2560,9 @@ extension ${Range}
25602560
public func randomElement<T: RandomNumberGenerator>(
25612561
using generator: inout T
25622562
) -> Element? {
2563-
% if 'Closed' not in Range:
2564-
guard lowerBound != upperBound else {
2563+
guard !isEmpty else {
25652564
return nil
25662565
}
2567-
% end
25682566
let isLowerNegative = Bound.isSigned && lowerBound < 0
25692567
let sameSign = !Bound.isSigned || isLowerNegative == (upperBound < 0)
25702568
% if 'Closed' not in Range:
@@ -2658,12 +2656,10 @@ where Self.Stride : SignedInteger,
26582656
in range: ${Range}<Self>,
26592657
using generator: inout T
26602658
) -> Self {
2661-
% if 'Closed' not in Range:
26622659
_precondition(
2663-
range.lowerBound != range.upperBound,
2664-
"Can't get random value with lowerBound == upperBound"
2660+
!range.isEmpty,
2661+
"Can't get random value with an empty range"
26652662
)
2666-
% end
26672663
return range.randomElement(using: &generator)!
26682664
}
26692665

0 commit comments

Comments
 (0)