Skip to content

Commit 26cda27

Browse files
committed
[stdlib] Simplify 'BinaryFloatingPoint.init?<T: BinaryFloatingPoint>(exactly: T)'
1 parent b2fa269 commit 26cda27

File tree

2 files changed

+65
-3
lines changed

2 files changed

+65
-3
lines changed

stdlib/public/core/FloatingPoint.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,9 +1948,30 @@ extension BinaryFloatingPoint {
19481948
/// - Parameter value: A floating-point value to be converted.
19491949
@inlinable
19501950
public init?<Source: BinaryFloatingPoint>(exactly value: Source) {
1951-
let (value_, exact) = Self._convert(from: value)
1952-
guard exact else { return nil }
1953-
self = value_
1951+
// We define exactness by equality after roundtripping; since NaN is never
1952+
// equal to itself, it can never be converted exactly.
1953+
if value.isNaN { return nil }
1954+
1955+
if (Source.exponentBitCount > Self.exponentBitCount
1956+
|| Source.significandBitCount > Self.significandBitCount)
1957+
&& value.isFinite && !value.isZero {
1958+
let exponent = value.exponent
1959+
if exponent < Self.leastNormalMagnitude.exponent {
1960+
if exponent < Self.leastNonzeroMagnitude.exponent { return nil }
1961+
if value.significandWidth >
1962+
Int(Self.Exponent(exponent) - Self.leastNonzeroMagnitude.exponent) {
1963+
return nil
1964+
}
1965+
} else {
1966+
if exponent > Self.greatestFiniteMagnitude.exponent { return nil }
1967+
if value.significandWidth >
1968+
Self.greatestFiniteMagnitude.significandWidth {
1969+
return nil
1970+
}
1971+
}
1972+
}
1973+
1974+
self = Self(value)
19541975
}
19551976

19561977
@inlinable

test/stdlib/FloatingPoint.swift.gyb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,47 @@ FloatingPoint.test("BinaryFloatingPoint/genericIntegerConversion") {
116116
}
117117

118118
FloatingPoint.test("BinaryFloatingPoint/genericFloatingPointConversion") {
119+
func convert<
120+
T: BinaryFloatingPoint, U: BinaryFloatingPoint
121+
>(exactly value: T, to: U.Type) -> U { U(exactly: value) }
122+
123+
expectEqual(convert(exactly: 0 as Float, to: Double.self), 0.0)
124+
expectEqual(convert(exactly: -0.0 as Float, to: Double.self), -0.0)
125+
expectEqual(
126+
convert(exactly: -0.0 as Float, to: Double.self).sign,
127+
FloatingPointSign.minus)
128+
expectEqual(convert(exactly: 0 as Double, to: Float.self), 0.0 as Float)
129+
expectEqual(convert(exactly: -0.0 as Double, to: Float.self), -0.0 as Float)
130+
expectEqual(
131+
convert(exactly: -0.0 as Double, to: Float.self).sign,
132+
FloatingPointSign.minus)
133+
expectEqual(convert(exactly: 1 as Float, to: Double.self), 1.0)
134+
expectEqual(convert(exactly: -1 as Float, to: Double.self), -1.0)
135+
expectEqual(convert(exactly: 1 as Double, to: Float.self), 1.0 as Float)
136+
expectEqual(convert(exactly: -1 as Double, to: Float.self), -1.0 as Float)
137+
expectEqual(
138+
convert(exactly: Float.infinity, to: Double.self), Double.infinity)
139+
expectEqual(
140+
convert(exactly: -Float.infinity, to: Double.self), -Double.infinity)
141+
expectEqual(
142+
convert(exactly: Double.infinity, to: Float.self), Float.infinity)
143+
expectEqual(
144+
convert(exactly: -Double.infinity, to: Float.self), -Float.infinity)
145+
expectEqual(convert(exactly: Float.nan, to: Double.self), nil)
146+
expectEqual(convert(exactly: Double.nan, to: Float.self), nil)
147+
expectEqual(convert(exactly: Float.nan, to: Float.self), nil)
148+
expectEqual(convert(exactly: Double.nan, to: Double.self), nil)
149+
expectEqual(
150+
convert(exactly: Double.leastNonzeroMagnitude, to: Float.self), nil)
151+
expectEqual(
152+
convert(exactly: Float.leastNonzeroMagnitude, to: Double.self),
153+
Double(Float.leastNonzeroMagnitude))
154+
expectEqual(
155+
convert(exactly: Double.greatestFiniteMagnitude, to: Float.self), nil)
156+
expectEqual(
157+
convert(exactly: Float.greatestFiniteMagnitude, to: Double.self),
158+
Double(Float.greatestFiniteMagnitude))
159+
119160
expectTrue(Double._convert(from: 0 as Float) == (value: 0, exact: true))
120161
expectTrue(Double._convert(from: -0.0 as Float) == (value: -0.0, exact: true))
121162
expectTrue(Double._convert(from: 1 as Float) == (value: 1, exact: true))

0 commit comments

Comments
 (0)