@@ -33,6 +33,9 @@ builtinIntLiteralBits = 2048
33
33
34
34
# Mapping from float bits to significand bits
35
35
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 }
36
39
37
40
def allInts( ) :
38
41
for bits in allIntBits:
@@ -79,7 +82,9 @@ extension UInt${bits} {
79
82
% for bits in allFloatBits:
80
83
% {
81
84
Self = floatName [ bits]
82
- SignificandSize = { 32 : 32 , 64 : 64 , 80 : 64 } [ bits]
85
+ SignificandSize = SignificandSizes [ bits]
86
+ SignificandBitCount = SignificandBitCounts [ bits]
87
+ ExponentBitCount = ExponentBitCounts [ bits]
83
88
RawSignificand = 'UInt' + str( SignificandSize)
84
89
85
90
if Self == 'Float':
@@ -120,10 +125,6 @@ public struct ${Self} {
120
125
init ( _bits v: Builtin . FPIEEE ${ bits} ) {
121
126
self . _value = v
122
127
}
123
-
124
- /// Create an instance initialized to `value`.
125
- @_transparent public
126
- init ( _ value: ${ Self} ) { self = value }
127
128
}
128
129
129
130
extension ${ Self} : CustomStringConvertible {
@@ -146,11 +147,11 @@ extension ${Self}: BinaryFloatingPoint {
146
147
public typealias RawSignificand = ${ RawSignificand}
147
148
148
149
public static var exponentBitCount : Int {
149
- return ${ { 32 : 8 , 64 : 11 , 80 : 15 } [ bits ] }
150
+ return ${ ExponentBitCount }
150
151
}
151
152
152
153
public static var significandBitCount : Int {
153
- return ${ { 32 : 23 , 64 : 52 , 80 : 63 } [ bits ] }
154
+ return ${ SignificandBitCount }
154
155
}
155
156
156
157
// Implementation details.
@@ -760,25 +761,42 @@ extension ${Self} {
760
761
extension ${ Self} {
761
762
% for srcBits in allFloatBits:
762
763
% That = floatName [ srcBits]
763
- % if Self != That:
764
764
765
- % if srcBits == 80 :
765
+ % if srcBits == 80 :
766
766
#if !os(Windows) && (arch(i386) || arch(x86_64))
767
- % end
767
+ % end
768
768
769
+ % if srcBits == bits:
770
+ /// Create an instance initialized to `value`.
771
+ % else:
769
772
/// Construct an instance that approximates `other`.
773
+ % end
774
+ @_transparent
770
775
public init( _ other: ${ That} ) {
771
- % if srcBits > bits:
776
+ % if srcBits > bits:
772
777
_value = Builtin . fptrunc_FPIEEE ${ srcBits} _FPIEEE${ bits} ( other. _value)
773
- % else :
778
+ % elif srcBits < bits :
774
779
_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
+ }
776
796
}
777
797
778
- % if srcBits == 80 :
798
+ % if srcBits == 80 :
779
799
#endif
780
- % end
781
-
782
800
% end
783
801
% end
784
802
}
0 commit comments