Skip to content

Commit 9a6900a

Browse files
committed
[stdlib] Refactor generic floating-point conversion fast paths
1 parent f40fd36 commit 9a6900a

File tree

1 file changed

+68
-69
lines changed

1 file changed

+68
-69
lines changed

stdlib/public/core/FloatingPoint.swift

Lines changed: 68 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,82 +1890,81 @@ extension BinaryFloatingPoint {
18901890
/// - Parameter value: A floating-point value to be converted.
18911891
@inlinable
18921892
public init<Source: BinaryFloatingPoint>(_ value: Source) {
1893+
// If two IEEE 754 binary interchange formats share the same exponent bit
1894+
// count and significand bit count, then they must share the same encoding
1895+
// for finite and infinite values.
1896+
switch (Source.exponentBitCount, Source.significandBitCount) {
18931897
#if !os(macOS) && !(os(iOS) && targetEnvironment(macCatalyst))
1894-
if #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
1895-
if case let value_ as Float16 = value {
1896-
self = Self(Float(value_))
1897-
return
1898-
}
1899-
}
1900-
#endif
1901-
switch value {
1902-
case let value_ as Float:
1903-
self = Self(value_)
1904-
case let value_ as Double:
1905-
self = Self(value_)
1906-
#if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
1907-
case let value_ as Float80:
1908-
self = Self(value_)
1909-
#endif
1910-
default:
1911-
if value.isFinite {
1912-
// According to IEEE 754:
1913-
// - The set of finite floating-point numbers representable within a
1914-
// particular format is determined by: the radix (b), the precision
1915-
// (p, the number of digits in the significand), and the maximum and
1916-
// minimum exponent (emax and emin, respectively, where
1917-
// emin = 1 - emax).
1918-
// - In a binary interchange format, each floating-point number has only
1919-
// one encoding.
1920-
//
1921-
// If two binary interchange formats have the same exponent bit count
1922-
// (w) and significand bit count (p - 1), then they must share the same
1923-
// encoding for finite values.
1924-
switch (Source.exponentBitCount, Source.significandBitCount) {
1925-
#if !os(macOS) && !(os(iOS) && targetEnvironment(macCatalyst))
1926-
case (5, 10):
1927-
if #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
1928-
let value_ = Float16(
1929-
sign: value.sign,
1930-
exponentBitPattern: Float16.RawExponent(value.exponentBitPattern),
1931-
significandBitPattern:
1932-
Float16.RawSignificand(value.significandBitPattern))
1933-
self = Self(Float(value_))
1934-
return
1935-
}
1936-
#endif
1937-
case (8, 23):
1938-
let value_ = Float(
1939-
sign: value.sign,
1940-
exponentBitPattern: Float.RawExponent(value.exponentBitPattern),
1941-
significandBitPattern:
1942-
Float.RawSignificand(value.significandBitPattern))
1943-
self = Self(value_)
1898+
case (5, 10):
1899+
if #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
1900+
if case let value_ as Float16 = value {
1901+
self = Self(Float(value_))
19441902
return
1945-
case (11, 52):
1946-
let value_ = Double(
1947-
sign: value.sign,
1948-
exponentBitPattern: Double.RawExponent(value.exponentBitPattern),
1949-
significandBitPattern:
1950-
Double.RawSignificand(value.significandBitPattern))
1951-
self = Self(value_)
1952-
return
1953-
#if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
1954-
case (15, 63):
1955-
let value_ = Float80(
1903+
}
1904+
if !value.isNaN {
1905+
let value_ = Float16(
19561906
sign: value.sign,
1957-
exponentBitPattern: Float80.RawExponent(value.exponentBitPattern),
1958-
significandBitPattern:
1959-
Float80.RawSignificand(value.significandBitPattern))
1960-
self = Self(value_)
1907+
exponentBitPattern: UInt(value.exponentBitPattern),
1908+
significandBitPattern: UInt16(value.significandBitPattern))
1909+
self = Self(Float(value_))
19611910
return
1962-
#endif
1963-
default:
1964-
break
19651911
}
19661912
}
1967-
self = Self._convert(from: value).value
1913+
#endif
1914+
case (8, 7):
1915+
if !value.isNaN {
1916+
let value_ = Float(
1917+
sign: value.sign,
1918+
exponentBitPattern: UInt(value.exponentBitPattern),
1919+
significandBitPattern: UInt32(value.significandBitPattern) &<< 16)
1920+
self = Self(value_)
1921+
return
1922+
}
1923+
case (8, 23):
1924+
if case let value_ as Float = value {
1925+
self = Self(value_)
1926+
return
1927+
}
1928+
if !value.isNaN {
1929+
let value_ = Float(
1930+
sign: value.sign,
1931+
exponentBitPattern: UInt(value.exponentBitPattern),
1932+
significandBitPattern: UInt32(value.significandBitPattern))
1933+
self = Self(value_)
1934+
return
1935+
}
1936+
case (11, 52):
1937+
if case let value_ as Double = value {
1938+
self = Self(value_)
1939+
return
1940+
}
1941+
if !value.isNaN {
1942+
let value_ = Double(
1943+
sign: value.sign,
1944+
exponentBitPattern: UInt(value.exponentBitPattern),
1945+
significandBitPattern: UInt64(value.significandBitPattern))
1946+
self = Self(value_)
1947+
return
1948+
}
1949+
#if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
1950+
case (15, 63):
1951+
if case let value_ as Float80 = value {
1952+
self = Self(value_)
1953+
return
1954+
}
1955+
if !value.isNaN {
1956+
let value_ = Float80(
1957+
sign: value.sign,
1958+
exponentBitPattern: UInt(value.exponentBitPattern),
1959+
significandBitPattern: UInt64(value.significandBitPattern))
1960+
self = Self(value_)
1961+
return
1962+
}
1963+
#endif
1964+
default:
1965+
break
19681966
}
1967+
self = Self._convert(from: value).value
19691968
}
19701969

19711970
/// Creates a new instance from the given value, if it can be represented

0 commit comments

Comments
 (0)