Skip to content

Commit a62bf48

Browse files
authored
[stdlib] [NFC] FloatingPointRandom.swift created (swiftlang#33463)
* Moved `random` methods out of FloatingPoint.swift * Added `random` methods to FloatingPointRandom.swift * Added FloatingPointRandom.swift to CMakeLists.txt * Added FloatingPointRandom.swift to GroupInfo.json * Moved filename within CMakeLists.txt
1 parent c98d04b commit a62bf48

File tree

4 files changed

+218
-202
lines changed

4 files changed

+218
-202
lines changed

stdlib/public/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ set(SWIFTLIB_SOURCES
211211
CollectionOfOne.swift
212212
DiscontiguousSlice.swift
213213
Diffing.swift
214+
FloatingPointRandom.swift
214215
Mirror.swift
215216
PlaygroundDisplay.swift
216217
CommandLine.swift

stdlib/public/core/FloatingPoint.swift

Lines changed: 0 additions & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,205 +2013,4 @@ extension BinaryFloatingPoint where Self.RawSignificand: FixedWidthInteger {
20132013
guard exact else { return nil }
20142014
self = value_
20152015
}
2016-
2017-
/// Returns a random value within the specified range, using the given
2018-
/// generator as a source for randomness.
2019-
///
2020-
/// Use this method to generate a floating-point value within a specific
2021-
/// range when you are using a custom random number generator. This example
2022-
/// creates three new values in the range `10.0 ..< 20.0`.
2023-
///
2024-
/// for _ in 1...3 {
2025-
/// print(Double.random(in: 10.0 ..< 20.0, using: &myGenerator))
2026-
/// }
2027-
/// // Prints "18.1900709259179"
2028-
/// // Prints "14.2286325689993"
2029-
/// // Prints "13.1485686260762"
2030-
///
2031-
/// The `random(in:using:)` static method chooses a random value from a
2032-
/// continuous uniform distribution in `range`, and then converts that value
2033-
/// to the nearest representable value in this type. Depending on the size
2034-
/// and span of `range`, some concrete values may be represented more
2035-
/// frequently than others.
2036-
///
2037-
/// - Note: The algorithm used to create random values may change in a future
2038-
/// version of Swift. If you're passing a generator that results in the
2039-
/// same sequence of floating-point values each time you run your program,
2040-
/// that sequence may change when your program is compiled using a
2041-
/// different version of Swift.
2042-
///
2043-
/// - Parameters:
2044-
/// - range: The range in which to create a random value.
2045-
/// `range` must be finite and non-empty.
2046-
/// - generator: The random number generator to use when creating the
2047-
/// new random value.
2048-
/// - Returns: A random value within the bounds of `range`.
2049-
@inlinable
2050-
public static func random<T: RandomNumberGenerator>(
2051-
in range: Range<Self>,
2052-
using generator: inout T
2053-
) -> Self {
2054-
_precondition(
2055-
!range.isEmpty,
2056-
"Can't get random value with an empty range"
2057-
)
2058-
let delta = range.upperBound - range.lowerBound
2059-
// TODO: this still isn't quite right, because the computation of delta
2060-
// can overflow (e.g. if .upperBound = .maximumFiniteMagnitude and
2061-
// .lowerBound = -.upperBound); this should be re-written with an
2062-
// algorithm that handles that case correctly, but this precondition
2063-
// is an acceptable short-term fix.
2064-
_precondition(
2065-
delta.isFinite,
2066-
"There is no uniform distribution on an infinite range"
2067-
)
2068-
let rand: Self.RawSignificand
2069-
if Self.RawSignificand.bitWidth == Self.significandBitCount + 1 {
2070-
rand = generator.next()
2071-
} else {
2072-
let significandCount = Self.significandBitCount + 1
2073-
let maxSignificand: Self.RawSignificand = 1 << significandCount
2074-
// Rather than use .next(upperBound:), which has to work with arbitrary
2075-
// upper bounds, and therefore does extra work to avoid bias, we can take
2076-
// a shortcut because we know that maxSignificand is a power of two.
2077-
rand = generator.next() & (maxSignificand - 1)
2078-
}
2079-
let unitRandom = Self.init(rand) * (Self.ulpOfOne / 2)
2080-
let randFloat = delta * unitRandom + range.lowerBound
2081-
if randFloat == range.upperBound {
2082-
return Self.random(in: range, using: &generator)
2083-
}
2084-
return randFloat
2085-
}
2086-
2087-
/// Returns a random value within the specified range.
2088-
///
2089-
/// Use this method to generate a floating-point value within a specific
2090-
/// range. This example creates three new values in the range
2091-
/// `10.0 ..< 20.0`.
2092-
///
2093-
/// for _ in 1...3 {
2094-
/// print(Double.random(in: 10.0 ..< 20.0))
2095-
/// }
2096-
/// // Prints "18.1900709259179"
2097-
/// // Prints "14.2286325689993"
2098-
/// // Prints "13.1485686260762"
2099-
///
2100-
/// The `random()` static method chooses a random value from a continuous
2101-
/// uniform distribution in `range`, and then converts that value to the
2102-
/// nearest representable value in this type. Depending on the size and span
2103-
/// of `range`, some concrete values may be represented more frequently than
2104-
/// others.
2105-
///
2106-
/// This method is equivalent to calling `random(in:using:)`, passing in the
2107-
/// system's default random generator.
2108-
///
2109-
/// - Parameter range: The range in which to create a random value.
2110-
/// `range` must be finite and non-empty.
2111-
/// - Returns: A random value within the bounds of `range`.
2112-
@inlinable
2113-
public static func random(in range: Range<Self>) -> Self {
2114-
var g = SystemRandomNumberGenerator()
2115-
return Self.random(in: range, using: &g)
2116-
}
2117-
2118-
/// Returns a random value within the specified range, using the given
2119-
/// generator as a source for randomness.
2120-
///
2121-
/// Use this method to generate a floating-point value within a specific
2122-
/// range when you are using a custom random number generator. This example
2123-
/// creates three new values in the range `10.0 ... 20.0`.
2124-
///
2125-
/// for _ in 1...3 {
2126-
/// print(Double.random(in: 10.0 ... 20.0, using: &myGenerator))
2127-
/// }
2128-
/// // Prints "18.1900709259179"
2129-
/// // Prints "14.2286325689993"
2130-
/// // Prints "13.1485686260762"
2131-
///
2132-
/// The `random(in:using:)` static method chooses a random value from a
2133-
/// continuous uniform distribution in `range`, and then converts that value
2134-
/// to the nearest representable value in this type. Depending on the size
2135-
/// and span of `range`, some concrete values may be represented more
2136-
/// frequently than others.
2137-
///
2138-
/// - Note: The algorithm used to create random values may change in a future
2139-
/// version of Swift. If you're passing a generator that results in the
2140-
/// same sequence of floating-point values each time you run your program,
2141-
/// that sequence may change when your program is compiled using a
2142-
/// different version of Swift.
2143-
///
2144-
/// - Parameters:
2145-
/// - range: The range in which to create a random value. Must be finite.
2146-
/// - generator: The random number generator to use when creating the
2147-
/// new random value.
2148-
/// - Returns: A random value within the bounds of `range`.
2149-
@inlinable
2150-
public static func random<T: RandomNumberGenerator>(
2151-
in range: ClosedRange<Self>,
2152-
using generator: inout T
2153-
) -> Self {
2154-
_precondition(
2155-
!range.isEmpty,
2156-
"Can't get random value with an empty range"
2157-
)
2158-
let delta = range.upperBound - range.lowerBound
2159-
// TODO: this still isn't quite right, because the computation of delta
2160-
// can overflow (e.g. if .upperBound = .maximumFiniteMagnitude and
2161-
// .lowerBound = -.upperBound); this should be re-written with an
2162-
// algorithm that handles that case correctly, but this precondition
2163-
// is an acceptable short-term fix.
2164-
_precondition(
2165-
delta.isFinite,
2166-
"There is no uniform distribution on an infinite range"
2167-
)
2168-
let rand: Self.RawSignificand
2169-
if Self.RawSignificand.bitWidth == Self.significandBitCount + 1 {
2170-
rand = generator.next()
2171-
let tmp: UInt8 = generator.next() & 1
2172-
if rand == Self.RawSignificand.max && tmp == 1 {
2173-
return range.upperBound
2174-
}
2175-
} else {
2176-
let significandCount = Self.significandBitCount + 1
2177-
let maxSignificand: Self.RawSignificand = 1 << significandCount
2178-
rand = generator.next(upperBound: maxSignificand + 1)
2179-
if rand == maxSignificand {
2180-
return range.upperBound
2181-
}
2182-
}
2183-
let unitRandom = Self.init(rand) * (Self.ulpOfOne / 2)
2184-
let randFloat = delta * unitRandom + range.lowerBound
2185-
return randFloat
2186-
}
2187-
2188-
/// Returns a random value within the specified range.
2189-
///
2190-
/// Use this method to generate a floating-point value within a specific
2191-
/// range. This example creates three new values in the range
2192-
/// `10.0 ... 20.0`.
2193-
///
2194-
/// for _ in 1...3 {
2195-
/// print(Double.random(in: 10.0 ... 20.0))
2196-
/// }
2197-
/// // Prints "18.1900709259179"
2198-
/// // Prints "14.2286325689993"
2199-
/// // Prints "13.1485686260762"
2200-
///
2201-
/// The `random()` static method chooses a random value from a continuous
2202-
/// uniform distribution in `range`, and then converts that value to the
2203-
/// nearest representable value in this type. Depending on the size and span
2204-
/// of `range`, some concrete values may be represented more frequently than
2205-
/// others.
2206-
///
2207-
/// This method is equivalent to calling `random(in:using:)`, passing in the
2208-
/// system's default random generator.
2209-
///
2210-
/// - Parameter range: The range in which to create a random value. Must be finite.
2211-
/// - Returns: A random value within the bounds of `range`.
2212-
@inlinable
2213-
public static func random(in range: ClosedRange<Self>) -> Self {
2214-
var g = SystemRandomNumberGenerator()
2215-
return Self.random(in: range, using: &g)
2216-
}
22172016
}

0 commit comments

Comments
 (0)