Skip to content

Commit 26623fd

Browse files
ultramiraculousChris Williams
authored andcommitted
SE-0080 - Failable initializers for Float->Float
1 parent a1f1976 commit 26623fd

File tree

1 file changed

+34
-16
lines changed

1 file changed

+34
-16
lines changed

stdlib/public/core/FloatingPointTypes.swift.gyb

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ builtinIntLiteralBits = 2048
3333

3434
# Mapping from float bits to significand bits
3535
explicitSignificandBits = { 32:24, 64:53, 80:64 }
36+
SignificandSizes = { 32:32, 64:64, 80:64 }
37+
SignificandBitCounts = { 32:23, 64:52, 80:63 }
38+
ExponentBitCounts = { 32:8, 64:11, 80:15 }
3639

3740
def allInts():
3841
for bits in allIntBits:
@@ -79,7 +82,9 @@ extension UInt${bits} {
7982
% for bits in allFloatBits:
8083
%{
8184
Self = floatName[bits]
82-
SignificandSize = {32:32, 64:64, 80:64}[bits]
85+
SignificandSize = SignificandSizes[bits]
86+
SignificandBitCount = SignificandBitCounts[bits]
87+
ExponentBitCount = ExponentBitCounts[bits]
8388
RawSignificand = 'UInt' + str(SignificandSize)
8489

8590
if Self == 'Float':
@@ -120,10 +125,6 @@ public struct ${Self} {
120125
init(_bits v: Builtin.FPIEEE${bits}) {
121126
self._value = v
122127
}
123-
124-
/// Create an instance initialized to `value`.
125-
@_transparent public
126-
init(_ value: ${Self}) { self = value }
127128
}
128129

129130
extension ${Self} : CustomStringConvertible {
@@ -146,11 +147,11 @@ extension ${Self}: BinaryFloatingPoint {
146147
public typealias RawSignificand = ${RawSignificand}
147148

148149
public static var exponentBitCount: Int {
149-
return ${{32:8, 64:11, 80:15}[bits]}
150+
return ${ExponentBitCount}
150151
}
151152

152153
public static var significandBitCount: Int {
153-
return ${{32:23, 64:52, 80:63}[bits]}
154+
return ${SignificandBitCount}
154155
}
155156

156157
// Implementation details.
@@ -760,25 +761,42 @@ extension ${Self} {
760761
extension ${Self} {
761762
% for srcBits in allFloatBits:
762763
% That = floatName[srcBits]
763-
% if Self != That:
764764

765-
% if srcBits == 80:
765+
% if srcBits == 80:
766766
#if !os(Windows) && (arch(i386) || arch(x86_64))
767-
% end
767+
% end
768768

769+
% if srcBits == bits:
770+
/// Create an instance initialized to `value`.
771+
% else:
769772
/// Construct an instance that approximates `other`.
773+
% end
774+
@_transparent
770775
public init(_ other: ${That}) {
771-
% if srcBits > bits:
776+
% if srcBits > bits:
772777
_value = Builtin.fptrunc_FPIEEE${srcBits}_FPIEEE${bits}(other._value)
773-
% else:
778+
% elif srcBits < bits:
774779
_value = Builtin.fpext_FPIEEE${srcBits}_FPIEEE${bits}(other._value)
775-
% end
780+
% else:
781+
_value = other._value
782+
% end
783+
}
784+
785+
/// Create a ${That} initialized to `value`, if `value` can be represented without rounding.
786+
/// - note: This is effectively checking that `inputValue == outputValue`, meaning `NaN` inputs will always return `nil`.
787+
@inline(__always)
788+
public init?(exactly other: ${That}) {
789+
self.init(other)
790+
// Converting the infinity value is considered value preserving.
791+
// In other cases, check that we can round-trip and get the same value.
792+
// NaN always fails.
793+
if ${That}(self) != other {
794+
return nil
795+
}
776796
}
777797

778-
% if srcBits == 80:
798+
% if srcBits == 80:
779799
#endif
780-
% end
781-
782800
% end
783801
% end
784802
}

0 commit comments

Comments
 (0)