| //===--- SwiftDtoa.h ---------------------------------------------*- c -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2018 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===---------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_DTOA_H |
| #define SWIFT_DTOA_H |
| |
| #include <stdbool.h> |
| #include <stdint.h> |
| #include <stdlib.h> |
| |
| // This implementation strongly assumes that `float` is |
| // IEEE 754 single-precision binary32 format and that |
| // `double` is IEEE 754 double-precision binary64 format. |
| |
| // Essentially all modern platforms use IEEE 754 floating point |
| // types now, so enable these by default: |
| #define SWIFT_DTOA_FLOAT16_SUPPORT 1 |
| #define SWIFT_DTOA_FLOAT_SUPPORT 1 |
| #define SWIFT_DTOA_DOUBLE_SUPPORT 1 |
| |
| // This implementation assumes `long double` is Intel 80-bit extended format. |
| #if defined(_WIN32) |
| // Windows has `long double` == `double` on all platforms, so disable this. |
| #undef SWIFT_DTOA_FLOAT80_SUPPORT |
| #elif defined(__ANDROID__) |
| // At least for now Float80 is disabled. See: https://github.com/apple/swift/pull/25502 |
| #elif defined(__APPLE__) || defined(__linux__) || defined(__OpenBSD__) |
| // macOS and Linux support Float80 on X86 hardware but not on ARM |
| #if defined(__x86_64__) || defined(__i386) |
| #define SWIFT_DTOA_FLOAT80_SUPPORT 1 |
| #endif |
| #endif |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #if SWIFT_DTOA_DOUBLE_SUPPORT |
| // Compute the optimal decimal digits and exponent for a double. |
| // |
| // Input: |
| // * `d` is the number to be decomposed |
| // * `digits` is an array of `digits_length` |
| // * `decimalExponent` is a pointer to an `int` |
| // |
| // Ouput: |
| // * `digits` will receive the decimal digits |
| // * `decimalExponent` will receive the decimal exponent |
| // * function returns the number of digits generated |
| // * the sign of the input number is ignored |
| // |
| // Guarantees: |
| // |
| // * Accurate. If you parse the result back to a double via an accurate |
| // algorithm (such as Clinger's algorithm), the resulting double will |
| // be exactly equal to the original value. On most systems, this |
| // implies that using `strtod` to parse the output of |
| // `swift_format_double` will yield exactly the original value. |
| // |
| // * Short. No other accurate result will have fewer digits. |
| // |
| // * Close. If there are multiple possible decimal forms that are |
| // both accurate and short, the form computed here will be |
| // closest to the original binary value. |
| // |
| // Notes: |
| // |
| // If the input value is infinity or NaN, or `digits_length < 17`, the |
| // function returns zero and generates no ouput. |
| // |
| // If the input value is zero, it will return `decimalExponent = 0` and |
| // a single digit of value zero. |
| // |
| int swift_decompose_double(double d, |
| int8_t *digits, size_t digits_length, int *decimalExponent); |
| |
| // Format a double as an ASCII string. |
| // |
| // For infinity, it outputs "inf" or "-inf". |
| // |
| // For NaN, it outputs a Swift-style detailed dump, including |
| // sign, signaling/quiet, and payload (if any). Typical output: |
| // "nan", "-nan", "-snan(0x1234)". |
| // |
| // For zero, it outputs "0.0" or "-0.0" depending on the sign. |
| // |
| // For other values, it uses `swift_decompose_double` to compute the |
| // digits, then uses either `swift_format_decimal` or |
| // `swift_format_exponential` to produce an ASCII string depending on |
| // the magnitude of the value. |
| // |
| // In all cases, it returns the number of ASCII characters actually |
| // written, or zero if the buffer was too small. |
| size_t swift_format_double(double, char *dest, size_t length); |
| #endif |
| |
| #if SWIFT_DTOA_FLOAT16_SUPPORT |
| // See swift_decompose_double. `digits_length` must be at least 5. |
| int swift_decompose_float16(const __fp16 *f, |
| int8_t *digits, size_t digits_length, int *decimalExponent); |
| // See swift_format_double. |
| size_t swift_format_float16(const __fp16 *, char *dest, size_t length); |
| #endif |
| |
| #if SWIFT_DTOA_FLOAT_SUPPORT |
| // See swift_decompose_double. `digits_length` must be at least 9. |
| int swift_decompose_float(float f, |
| int8_t *digits, size_t digits_length, int *decimalExponent); |
| // See swift_format_double. |
| size_t swift_format_float(float, char *dest, size_t length); |
| #endif |
| |
| #if SWIFT_DTOA_FLOAT80_SUPPORT |
| // See swift_decompose_double. `digits_length` must be at least 21. |
| int swift_decompose_float80(long double f, |
| int8_t *digits, size_t digits_length, int *decimalExponent); |
| // See swift_format_double. |
| size_t swift_format_float80(long double, char *dest, size_t length); |
| #endif |
| |
| // Generate an ASCII string from the raw exponent and digit information |
| // as generated by `swift_decompose_double`. Returns the number of |
| // bytes actually used. If `dest` was not big enough, these functions |
| // return zero. The generated string is always terminated with a zero |
| // byte unless `length` was zero. |
| |
| // "Exponential" form uses common exponential format, e.g., "-1.234e+56" |
| // The exponent always has a sign and at least two digits. The |
| // generated string is never longer than `digits_count + 9` bytes, |
| // including the trailing zero byte. |
| size_t swift_format_exponential(char *dest, size_t length, |
| bool negative, const int8_t *digits, int digits_count, int decimalExponent); |
| |
| // "Decimal" form writes the value without using exponents. This |
| // includes cases such as "0.000001234", "123.456", and "123456000.0". |
| // Note that the result always has a decimal point with at least one |
| // digit before and one digit after. The generated string is never |
| // longer than `digits_count + abs(exponent) + 4` bytes, including the |
| // trailing zero byte. |
| size_t swift_format_decimal(char *dest, size_t length, |
| bool negative, const int8_t *digits, int digits_count, int decimalExponent); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| #endif |