Add _stdlib_random for more platforms (#1)

* Remove refs to Countable ranges

* Add `_stdlib_random` for more platforms

* Use `getrandom` (if available) for Android, Cygwin

* Reorder the `_stdlib_random` functions

* Also include <features.h> on Linux

* Add `#error TODO` in `_stdlib_random` for Windows

* Colon after Fatal Error

Performance improvement for Random

gybify ranges

Fix typo in 'basic random numbers'
Add _stdlib_random as a testable method

Switch to generic constraints

Hopefully link against bcrypt

Fix some implementation details

1. Uniform distribution is now uniform
2. Apply Jens' method for uniform floats

Fix a lineable attribute
This commit is contained in:
Ben Rimmington
2018-02-10 00:09:14 +00:00
committed by Azoy
parent d23d219e95
commit a5df0ef83d
11 changed files with 342 additions and 183 deletions

View File

@@ -2413,10 +2413,10 @@ where Self.RawSignificand : FixedWidthInteger,
/// - Parameter generator: The random number generator to use when getting
/// the random floating point.
/// - Returns: A random representation of this floating point.
@_inlineable
public static func random(
@inlinable
public static func random<T: RandomNumberGenerator>(
in range: ${Range}<Self>,
using generator: RandomNumberGenerator = Random.default
using generator: T
) -> Self {
% if 'Closed' not in Range:
_precondition(
@@ -2425,7 +2425,7 @@ where Self.RawSignificand : FixedWidthInteger,
)
% end
let delta = range.upperBound - range.lowerBound
let maxSignificand: Self.RawSignificand = 1 << Self.significandBitCount
let maxSignificand = Self.RawSignificand(1 << (Self.significandBitCount + 1))
% if 'Closed' not in Range:
let rand: Self.RawSignificand = generator.next(upperBound: maxSignificand)
% else:
@@ -2434,14 +2434,23 @@ where Self.RawSignificand : FixedWidthInteger,
return range.upperBound
}
% end
let unitRandom = Self.init(
sign: .plus,
exponentBitPattern: (1 as Self).exponentBitPattern,
significandBitPattern: rand
) - 1
let unitRandom = Self.init(rand) * Self.ulpOfOne / 2
return delta * unitRandom + range.lowerBound
}
/// Returns a random representation of this floating point within the range.
///
/// - Parameter range: A ${Range} to determine the bounds to get a random value
/// from.
/// - Parameter generator: The random number generator to use when getting
/// the random floating point.
/// - Returns: A random representation of this floating point.
///
/// This uses the standard library's default random number generator.
@inlinable
public static func random(in range: ${Range}<Self>) -> Self {
return Self.random(in: range, using: Random.default)
}
}
% end