Skip to content

Commit c8458ce

Browse files
ultramiraculousChris Williams
authored andcommitted
Create SwiftFloatingPointTypes for float-related helpers
1 parent 2f74e76 commit c8458ce

File tree

4 files changed

+71
-58
lines changed

4 files changed

+71
-58
lines changed

stdlib/public/core/FixedPoint.swift.gyb

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
%{
1414

1515
from SwiftIntTypes import all_integer_types, int_max_bits, should_define_truncating_bit_pattern_init
16+
from SwiftFloatingPointTypes import all_floating_point_types, getFtoIBounds
1617

1718
#
1819
# Utility code for later in this template
@@ -33,21 +34,6 @@ word_bits = int(CMAKE_SIZEOF_VOID_P) * 8
3334
# Number of bits in integer literals.
3435
builtinIntLiteralBits = 2048
3536

36-
# Mapping from float bits to significand bits
37-
allFloatBits = [32, 64, 80]
38-
floatName = { 32:'Float', 64:'Double', 80:'Float80' }
39-
explicitFloatSignificandBits = { 32:24, 64:53, 80:64 }
40-
41-
42-
def getFtoIBounds(floatBits, intBits, signed):
43-
if not signed:
44-
return (-1, 1 << intBits)
45-
upper = 1 << intBits - 1
46-
if intBits <= explicitFloatSignificandBits[floatBits]:
47-
return (-upper - 1, upper)
48-
ulp = 1 << intBits - explicitFloatSignificandBits[floatBits]
49-
return (-upper - ulp, upper)
50-
5137
def maskBits(n):
5238
"""Return an n-bit mask in hex"""
5339
return hexify((1 << n) - 1)
@@ -540,8 +526,9 @@ extension ${Self} {
540526

541527
extension ${Self} {
542528
// Construction of integers from floating point numbers.
543-
% for srcBits in allFloatBits:
544-
% Src = floatName[srcBits]
529+
% for src_type in all_floating_point_types():
530+
% Src = src_type.stdlib_name
531+
% srcBits = src_type.bits
545532
% (lower, upper) = getFtoIBounds(floatBits=srcBits, intBits=int(bits), signed=signed)
546533

547534
% if srcBits == 80:

stdlib/public/core/FloatingPointTypes.swift.gyb

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,12 @@
1313
import SwiftShims
1414

1515
%{
16+
from SwiftFloatingPointTypes import all_floating_point_types
17+
1618
#
1719
# Utility code for later in this template
1820
#
1921

20-
# // Bit counts for all floating point types.
21-
# // 80-bit floating point types are only permitted on x86 architectures. This
22-
# // restriction is handled via #if's in the generated code.
23-
allFloatBits = [32, 64, 80]
24-
2522
# Bit counts for all int types
2623
allIntBits = [8, 16, 32, 64, 'Int']
2724

@@ -31,12 +28,6 @@ word_bits = int(CMAKE_SIZEOF_VOID_P) * 8
3128
# Number of bits in integer literals.
3229
builtinIntLiteralBits = 2048
3330

34-
# Mapping from float bits to significand bits
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 }
39-
4031
def allInts():
4132
for bits in allIntBits:
4233
for signed in False, True:
@@ -50,21 +41,6 @@ def builtinIntName(name):
5041

5142
def intName(name, signed):
5243
return ('' if signed else 'U') + baseIntName(name)
53-
54-
floatName = { 32:'Float', 64:'Double', 80:'Float80' }
55-
56-
def cFuncSuffix(bits):
57-
if bits == 32:
58-
return 'f'
59-
if bits == 64:
60-
return ''
61-
if bits == 80:
62-
return 'l'
63-
64-
def intFormatFix(bits):
65-
if bits == 'Int':
66-
return int(CMAKE_SIZEOF_VOID_P) * 8
67-
return bits
6844
}%
6945

7046
// TODO: remove once integer proposal is available ----------------------------
@@ -79,12 +55,13 @@ extension UInt${bits} {
7955
}
8056
%end
8157

82-
% for bits in allFloatBits:
58+
% for self_type in all_floating_point_types():
8359
%{
84-
Self = floatName[bits]
85-
SignificandSize = SignificandSizes[bits]
86-
SignificandBitCount = SignificandBitCounts[bits]
87-
ExponentBitCount = ExponentBitCounts[bits]
60+
Self = self_type.stdlib_name
61+
bits = self_type.bits
62+
SignificandSize = self_type.significand_size
63+
SignificandBitCount = self_type.significand_bits
64+
ExponentBitCount = self_type.exponent_bits
8865
RawSignificand = 'UInt' + str(SignificandSize)
8966

9067
if Self == 'Float':
@@ -867,8 +844,9 @@ extension ${Self} {
867844
// Construction from other floating point numbers.
868845
@_transparent
869846
extension ${Self} {
870-
% for srcBits in allFloatBits:
871-
% That = floatName[srcBits]
847+
% for src_type in all_floating_point_types():
848+
% srcBits = src_type.bits
849+
% That = src_type.stdlib_name
872850

873851
% if srcBits == 80:
874852
#if !os(Windows) && (arch(i386) || arch(x86_64))
@@ -1080,4 +1058,4 @@ public postfix func -- (lhs: inout ${Self}) -> ${Self} {
10801058
% if bits == 80:
10811059
#endif
10821060
% end
1083-
% end # for bits in allFloatBits
1061+
% end # for bits in all_floating_point_types

utils/SwiftFloatingPointTypes.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# ===--- SwiftFloatingPointTypes.py ----------------------------*- coding: utf-8 -*-===//
2+
#
3+
# This source file is part of the Swift.org open source project
4+
#
5+
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
# Licensed under Apache License v2.0 with Runtime Library Exception
7+
#
8+
# See http://swift.org/LICENSE.txt for license information
9+
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
11+
# returns (lower, upper) exclusive bounds for the integer values
12+
# that can be stored into a float
13+
def getFtoIBounds(floatBits, intBits, signed):
14+
sigBits = floating_point_bits_to_type()[floatBits].explicit_significand_bits
15+
if not signed:
16+
return (-1, 1 << intBits)
17+
upper = 1 << (intBits - 1)
18+
if intBits <= sigBits:
19+
return (-upper - 1, upper)
20+
ulp = 1 << (intBits - sigBits)
21+
return (-upper - ulp, upper)
22+
23+
class SwiftFloatType(object):
24+
25+
def __init__(self, name, significandBits, exponentBits, significandSize, totalBits):
26+
self.stdlib_name = name
27+
self.significand_bits = significandBits
28+
self.significand_size = significandSize
29+
self.exponent_bits = exponentBits
30+
self.explicit_significand_bits = significandBits + 1
31+
self.bits = totalBits
32+
33+
34+
def floating_point_bits_to_type():
35+
return {
36+
32: SwiftFloatType(name="Float", significandBits=23, exponentBits=8, significandSize=32, totalBits=32),
37+
64: SwiftFloatType(name="Double", significandBits=52, exponentBits=11, significandSize=64, totalBits=64),
38+
80: SwiftFloatType(name="Float80", significandBits=63, exponentBits=15, significandSize=64, totalBits=80),
39+
}
40+
41+
def all_floating_point_types():
42+
return floating_point_bits_to_type().values()
43+
44+
# // Bit counts for all floating point types.
45+
# // 80-bit floating point types are only permitted on x86 architectures. This
46+
# // restriction is handled via #if's in the generated code.
47+
def all_floating_point_bits():
48+
return floating_point_bits_to_type().keys()

validation-test/stdlib/FixedPointConversion.swift.gyb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ int_to_int_conversion_template = gyb.parse_template("int_to_int_conversion",
4848
"""
4949
%{
5050
from SwiftIntTypes import all_integer_types, int_max, int_min
51-
52-
floatNameToSignificandBits = { 'Float32':24, 'Float64':53, 'Float80':64 }
51+
from SwiftFloatingPointTypes import all_floating_point_types
5352

5453
}%
5554
% for self_ty in all_integer_types(word_bits):
@@ -110,9 +109,10 @@ FixedPointConversionFailure.test("${Other}To${Self}Conversion/dest=${testValue}"
110109
% end # for testValue in ...
111110
% end # for in all_integer_types (Other)
112111

113-
% for Other, otherSignificandBits in floatNameToSignificandBits.iteritems():
114-
% otherMin = int_min(bits=otherSignificandBits, signed=False)
115-
% otherMax = int_max(bits=otherSignificandBits, signed=False)
112+
% for other_type in all_floating_point_types():
113+
% Other = "Float" + str(other_type.bits)
114+
% otherMin = -int_max(bits=other_type.explicit_significand_bits, signed=False)
115+
% otherMax = int_max(bits=other_type.explicit_significand_bits, signed=False)
116116

117117
% if Other == 'Float80':
118118
#if !os(Windows) && (arch(i386) || arch(x86_64))
@@ -123,7 +123,7 @@ FixedPointConversionFailure.test("${Other}To${Self}Conversion/dest=${testValue}"
123123
% if testValue < otherMin or testValue > otherMax:
124124
% # Can't construct `other` value to test from, do nothing and continue.
125125

126-
% elif testValue >= selfMin and testValue <= selfMax and testValue % 1 == 0:
126+
% elif testValue >= selfMin and testValue <= selfMax and testValue % 1 == 0 and testValue != -0.0:
127127

128128
FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValue}") {
129129
let input = get${Other}(${testValue})
@@ -213,7 +213,7 @@ FloatingPointConversionFailures.test("${Self}/${Other}/NaN") {
213213
#endif
214214
% end
215215

216-
% end # for in floatNameToSignificandBits (Other)
216+
% end # for in all_floating_point_types (Other)
217217
% end # for in all_integer_types (Self)
218218

219219
""")

0 commit comments

Comments
 (0)