Skip to content

Commit 4ac18aa

Browse files
authored
Merge pull request #84576 from tbkka/tbkka-revert-floatingpointdescription
Revert "Merge pull request #82750 from tbkka/tbkka-swift-floatingpointtostring"
2 parents b46eddb + 7d85d75 commit 4ac18aa

File tree

12 files changed

+3238
-2648
lines changed

12 files changed

+3238
-2648
lines changed

Runtimes/Core/core/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ add_library(swiftCore
8080
FlatMap.swift
8181
Flatten.swift
8282
FloatingPoint.swift
83-
FloatingPointToString.swift
8483
Hashable.swift
8584
AnyHashable.swift # ORDER DEPENDENCY
8685
Hasher.swift

Runtimes/Core/runtime/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ add_library(swiftRuntime OBJECT
5252
RefCount.cpp
5353
ReflectionMirror.cpp
5454
RuntimeInvocationsTracking.cpp
55+
SwiftDtoa.cpp
5556
SwiftTLSContext.cpp
5657
ThreadingError.cpp
5758
Tracing.cpp

include/swift/Runtime/SwiftDtoa.h

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
//===--- SwiftDtoa.h ---------------------------------------------*- c -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2018, 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===---------------------------------------------------------------------===//
12+
//
13+
/// About SwiftDtoa
14+
/// ===============
15+
///
16+
/// SwiftDtoa is the C implementation that supports the `.description`
17+
/// and `.debugDescription` properties for the standard Swift
18+
/// floating-point types. These functions produce the "optimal form"
19+
/// for the binary floating point value. The optimal form is a
20+
/// decimal representation that satisfies the following properties:
21+
///
22+
/// 1. Accurate. Parsing the value back to a binary floating-point
23+
/// value of the same precision will exactly yield the original
24+
/// value. For example, `Double(d.description) == d` for all `Double`
25+
/// values `d` (except for NaN values, of course).
26+
///
27+
/// 2. Short. Of all accurate results, the returned value will
28+
/// contain the minimum number of significant digits. Note that
29+
/// this is not quite the same as C++ `to_chars` which promises the
30+
/// minimal number of characters.
31+
///
32+
/// 3. Close. Of all accurate, short results, the value printed will
33+
/// be the one that is closest to the exact binary floating-point
34+
/// value.
35+
///
36+
/// The optimal form is the ideal textual form for use in JSON and
37+
/// similar interchange formats because it is accurate, compact, and
38+
/// can be generated very quickly. It is also ideal for logging and
39+
/// debugging use; the accuracy guarantees that the result can be
40+
/// cut-and-pasted to obtain the exact original value, and the
41+
/// shortness property eliminates unnecessary digits that can be
42+
/// confusing to readers.
43+
///
44+
/// Algorithms that produce such output have been known since at least
45+
/// 1990, when Steele and White published their Dragon4 algorithm.
46+
/// However, the earliest algorithms required high-precision
47+
/// arithmetic which limited their use. Starting in 2010 with the
48+
/// publication of Grisu3, there has been a surge of interest and
49+
/// there are now a number of algorithms that can produce optimal
50+
/// forms very quickly. This particular implementation is loosely
51+
/// based on Grisu2 but incorporates concepts from Errol and Ryu that
52+
/// make it significantly faster and ensure accuracy in all cases.
53+
///
54+
/// About SwiftDtoa v1
55+
/// ------------------
56+
///
57+
/// The first version of SwiftDtoa was committed to the Swift runtime
58+
/// in 2018. It supported Swift's Float, Double, and Float80 formats.
59+
///
60+
/// About SwiftDtoa v1a
61+
/// -------------------
62+
///
63+
/// Version 1a of SwiftDtoa added support for Float16.
64+
///
65+
/// About SwiftDtoa v2
66+
/// ------------------
67+
///
68+
/// Version 2 of SwiftDtoa is a major overhaul with a number of
69+
/// algorithmic improvements to make it faster (especially for Float16
70+
/// and Float80), smaller, and more portable (the code only requires
71+
/// C99 and makes no use of C or C++ floating-point facilities). It
72+
/// also includes experimental support for IEEE 754 quad-precision
73+
/// binary128 format, which is not currently supported by Swift.
74+
//
75+
//===---------------------------------------------------------------------===//
76+
77+
#ifndef SWIFT_DTOA_H
78+
#define SWIFT_DTOA_H
79+
80+
#define __STDC_WANT_IEC_60559_TYPES_EXT__ // FLT16_MAX
81+
#include <float.h>
82+
#include <stdbool.h>
83+
#include <stdint.h>
84+
#include <stdlib.h>
85+
86+
//
87+
// IEEE 754 Binary16 support (also known as "half-precision")
88+
//
89+
90+
// Enable this by default.
91+
// Force disable: -DSWIFT_DTOA_BINARY16_SUPPORT=0
92+
#ifndef SWIFT_DTOA_BINARY16_SUPPORT
93+
#define SWIFT_DTOA_BINARY16_SUPPORT 1
94+
#endif
95+
96+
/// Does this platform support needs to pass _Float16 as a float in
97+
/// C function?
98+
#ifndef SWIFT_DTOA_PASS_FLOAT16_AS_FLOAT
99+
// Windows does not define FLT16_MAX even though it supports _Float16 as argument.
100+
# if (!defined(FLT16_MAX) || defined(__wasm__)) && !defined(_WIN32)
101+
# define SWIFT_DTOA_PASS_FLOAT16_AS_FLOAT 1
102+
# else
103+
# define SWIFT_DTOA_PASS_FLOAT16_AS_FLOAT 0
104+
# endif
105+
#endif
106+
107+
//
108+
// IEEE 754 Binary32 support (also known as "single-precision")
109+
//
110+
111+
// Does "float" on this system use binary32 format?
112+
// (Almost all modern systems do this.)
113+
#if (FLT_RADIX == 2) && (FLT_MANT_DIG == 24) && (FLT_MIN_EXP == -125) && (FLT_MAX_EXP == 128)
114+
#define FLOAT_IS_BINARY32 1
115+
#else
116+
#undef FLOAT_IS_BINARY32
117+
#endif
118+
119+
// We can format binary32 values even if the local C environment
120+
// does not support it. But `float` == binary32 almost everywhere,
121+
// so we enable it by default.
122+
// Force disable: -DSWIFT_DTOA_BINARY32_SUPPORT=0
123+
#ifndef SWIFT_DTOA_BINARY32_SUPPORT
124+
#define SWIFT_DTOA_BINARY32_SUPPORT 1
125+
#endif
126+
127+
//
128+
// IEEE 754 Binary64 support (also known as "double-precision")
129+
//
130+
131+
// Does "double" on this system use binary64 format?
132+
// (Almost all modern systems do this.)
133+
#if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MIN_EXP == -1021) && (DBL_MAX_EXP == 1024)
134+
#define DOUBLE_IS_BINARY64 1
135+
#else
136+
#undef DOUBLE_IS_BINARY64
137+
#endif
138+
139+
// Does "long double" on this system use binary64 format?
140+
// (Windows, for example.)
141+
#if (FLT_RADIX == 2) && (LDBL_MANT_DIG == 53) && (LDBL_MIN_EXP == -1021) && (LDBL_MAX_EXP == 1024)
142+
#define LONG_DOUBLE_IS_BINARY64 1
143+
#else
144+
#undef LONG_DOUBLE_IS_BINARY64
145+
#endif
146+
147+
// We can format binary64 values even if the local C environment
148+
// does not support it. But `double` == binary64 almost everywhere,
149+
// so we enable it by default.
150+
// Force disable: -DSWIFT_DTOA_BINARY64_SUPPORT=0
151+
#ifndef SWIFT_DTOA_BINARY64_SUPPORT
152+
#define SWIFT_DTOA_BINARY64_SUPPORT 1
153+
#endif
154+
155+
//
156+
// Intel x87 Float80 support
157+
//
158+
159+
// Is "long double" on this system the same as Float80?
160+
// (macOS, Linux, and FreeBSD when running on x86 or x86_64 processors.)
161+
#if (FLT_RADIX == 2) && (LDBL_MANT_DIG == 64) && (LDBL_MIN_EXP == -16381) && (LDBL_MAX_EXP == 16384)
162+
#define LONG_DOUBLE_IS_FLOAT80 1
163+
#else
164+
#undef LONG_DOUBLE_IS_FLOAT80
165+
#endif
166+
167+
// We can format float80 values even if the local C environment
168+
// does not support it. However, by default, we only enable it for
169+
// environments where float80 == long double.
170+
// Force enable: -DSWIFT_DTOA_FLOAT80_SUPPORT=1
171+
// Force disable: -DSWIFT_DTOA_FLOAT80_SUPPORT=0
172+
#ifndef SWIFT_DTOA_FLOAT80_SUPPORT
173+
#if LONG_DOUBLE_IS_FLOAT80
174+
#define SWIFT_DTOA_FLOAT80_SUPPORT 1
175+
#endif
176+
#endif
177+
178+
//
179+
// IEEE 754 Binary128 support
180+
//
181+
182+
// Is "long double" on this system the same as Binary128?
183+
// (Android on LP64 hardware.)
184+
#if (FLT_RADIX == 2) && (LDBL_MANT_DIG == 113) && (LDBL_MIN_EXP == -16381) && (LDBL_MAX_EXP == 16384)
185+
#define LONG_DOUBLE_IS_BINARY128 1
186+
#else
187+
#undef LONG_DOUBLE_IS_BINARY128
188+
#endif
189+
190+
// We can format binary128 values even if the local C environment
191+
// does not support it. However, by default, we only enable it for
192+
// environments where binary128 == long double.
193+
// Force enable: -DSWIFT_DTOA_BINARY128_SUPPORT=1
194+
// Force disable: -DSWIFT_DTOA_BINARY128_SUPPORT=0
195+
#ifndef SWIFT_DTOA_BINARY128_SUPPORT
196+
#if LONG_DOUBLE_IS_BINARY128
197+
#define SWIFT_DTOA_BINARY128_SUPPORT 1
198+
#endif
199+
#endif
200+
201+
#ifdef __cplusplus
202+
extern "C" {
203+
#endif
204+
205+
// Format a floating point value as an ASCII string
206+
//
207+
// Input:
208+
// * `d` is the number to be formatted
209+
// * `dest` is a buffer of length `length`
210+
//
211+
// Output:
212+
// * Return value is the length of the string placed into `dest`
213+
// or zero if the buffer is too small.
214+
// * For infinity, it copies "inf" or "-inf".
215+
// * For NaN, it outputs a Swift-style detailed dump, including
216+
// sign, signaling/quiet, and payload (if any). Typical output:
217+
// "nan", "-nan", "-snan(0x1234)".
218+
// * For zero, it outputs "0.0" or "-0.0" depending on the sign.
219+
// * The destination buffer is always null-terminated (even on error)
220+
// unless the length is zero.
221+
//
222+
// Note: If you want to customize the output for Infinity, zero, or
223+
// Nan, you can easily write a wrapper function that uses `fpclassify`
224+
// to identify those cases and only calls through to these functions
225+
// for normal and subnormal values.
226+
//
227+
// Guarantees:
228+
//
229+
// * Accurate. If you parse the result back to the same floating-point
230+
// format via an accurate algorithm (such as Clinger's algorithm),
231+
// the resulting value will be _exactly_ equal to the original value.
232+
// On most systems, this implies that using `strtod` to parse the
233+
// output of `swift_dtoa_optimal_double` will yield exactly the
234+
// original value.
235+
//
236+
// * Short. No other accurate result will have fewer digits.
237+
//
238+
// * Close. If there are multiple possible decimal forms that are
239+
// both accurate and short, the form computed here will be
240+
// closest to the original binary value.
241+
//
242+
// Naming: The `_p` forms take a `const void *` pointing to the value
243+
// in memory. These forms do not require any support from the local C
244+
// environment. In particular, they should work correctly even on
245+
// systems with no floating-point support. Forms ending in a C
246+
// floating-point type (e.g., "_float", "_double") are identical but
247+
// take the corresponding argument type. These forms obviously
248+
// require the C environment to support passing floating-point types as
249+
// function arguments.
250+
251+
#if SWIFT_DTOA_BINARY16_SUPPORT
252+
size_t swift_dtoa_optimal_binary16_p(const void *, char *dest, size_t length);
253+
#if !SWIFT_DTOA_PASS_FLOAT16_AS_FLOAT
254+
// If `_Float16` is defined, provide this convenience wrapper.
255+
size_t swift_dtoa_optimal_binary16(_Float16, char *dest, size_t length);
256+
#endif
257+
#endif
258+
259+
#if SWIFT_DTOA_BINARY32_SUPPORT
260+
size_t swift_dtoa_optimal_binary32_p(const void *, char *dest, size_t length);
261+
#if FLOAT_IS_BINARY32
262+
// If `float` happens to be binary32, define the convenience wrapper.
263+
size_t swift_dtoa_optimal_float(float, char *dest, size_t length);
264+
#endif
265+
#endif
266+
267+
#if SWIFT_DTOA_BINARY64_SUPPORT
268+
size_t swift_dtoa_optimal_binary64_p(const void *, char *dest, size_t length);
269+
#if DOUBLE_IS_BINARY64
270+
// If `double` happens to be binary64, define the convenience wrapper.
271+
size_t swift_dtoa_optimal_double(double, char *dest, size_t length);
272+
#endif
273+
#if LONG_DOUBLE_IS_BINARY64
274+
// If `long double` happens to be binary64, define the convenience wrapper.
275+
size_t swift_dtoa_optimal_long_double(long double, char *dest, size_t length);
276+
#endif
277+
#endif
278+
279+
#if SWIFT_DTOA_FLOAT80_SUPPORT
280+
// Universal entry point works on all platforms, regardless of
281+
// whether the local system has direct support for float80
282+
size_t swift_dtoa_optimal_float80_p(const void *, char *dest, size_t length);
283+
#if LONG_DOUBLE_IS_FLOAT80
284+
// If 'long double' happens to be float80, define a convenience wrapper.
285+
size_t swift_dtoa_optimal_long_double(long double, char *dest, size_t length);
286+
#endif
287+
#endif
288+
289+
#if SWIFT_DTOA_BINARY128_SUPPORT
290+
// Universal entry point works on all platforms, regardless of
291+
// whether the local system has direct support for float80
292+
size_t swift_dtoa_optimal_binary128_p(const void *, char *dest, size_t length);
293+
#if LONG_DOUBLE_IS_BINARY128
294+
// If 'long double' happens to be binary128, define a convenience wrapper.
295+
size_t swift_dtoa_optimal_long_double(long double, char *dest, size_t length);
296+
#endif
297+
#endif
298+
299+
#ifdef __cplusplus
300+
}
301+
#endif
302+
#endif

stdlib/public/core/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,6 @@ split_embedded_sources(
261261

262262
NORMAL AtomicInt.swift.gyb
263263
EMBEDDED FloatingPointParsing.swift.gyb
264-
EMBEDDED FloatingPointToString.swift
265264
EMBEDDED FloatingPointTypes.swift.gyb
266265
EMBEDDED IntegerTypes.swift.gyb
267266
EMBEDDED LegacyInt128.swift.gyb

0 commit comments

Comments
 (0)