|
| 1 | +//===--- SwiftDtoa.h ---------------------------------------------*- c -*-===// |
| 2 | +// |
| 3 | +// This source file is part of the Swift.org open source project |
| 4 | +// |
| 5 | +// Copyright (c) 2018 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 | +#ifndef SWIFT_DTOA_H |
| 14 | +#define SWIFT_DTOA_H |
| 15 | + |
| 16 | +#include <stdbool.h> |
| 17 | +#include <stdint.h> |
| 18 | +#include <stdlib.h> |
| 19 | + |
| 20 | +// This implementation strongly assumes that `float` is |
| 21 | +// IEEE 754 single-precision binary32 format and that |
| 22 | +// `double` is IEEE 754 double-precision binary64 format. |
| 23 | + |
| 24 | +// Essentially all modern platforms use IEEE 754 floating point |
| 25 | +// types now, so enable these by default: |
| 26 | +#define SWIFT_DTOA_FLOAT_SUPPORT 1 |
| 27 | +#define SWIFT_DTOA_DOUBLE_SUPPORT 1 |
| 28 | + |
| 29 | +// This implementation assumes `long double` is Intel 80-bit extended format. |
| 30 | +#if defined(_WIN32) |
| 31 | + // Windows has `long double` == `double` on all platforms, so disable this. |
| 32 | + #undef SWIFT_DTOA_FLOAT80_SUPPORT |
| 33 | +#elif defined(__APPLE__) || defined(__linux__) |
| 34 | + // macOS and Linux support Float80 on X86 hardware but not on ARM |
| 35 | + #if defined(__x86_64__) || defined(__i386) |
| 36 | + #define SWIFT_DTOA_FLOAT80_SUPPORT 1 |
| 37 | + #endif |
| 38 | +#endif |
| 39 | + |
| 40 | +#ifdef __cplusplus |
| 41 | +extern "C" { |
| 42 | +#endif |
| 43 | + |
| 44 | +#if SWIFT_DTOA_DOUBLE_SUPPORT |
| 45 | +// Compute the optimal decimal digits and exponent for a double. |
| 46 | +// |
| 47 | +// Input: |
| 48 | +// * `d` is the number to be decomposed |
| 49 | +// * `digits` is an array of `digits_length` |
| 50 | +// * `decimalExponent` is a pointer to an `int` |
| 51 | +// |
| 52 | +// Ouput: |
| 53 | +// * `digits` will receive the decimal digits |
| 54 | +// * `decimalExponent` will receive the decimal exponent |
| 55 | +// * function returns the number of digits generated |
| 56 | +// * the sign of the input number is ignored |
| 57 | +// |
| 58 | +// Guarantees: |
| 59 | +// |
| 60 | +// * Accurate. If you parse the result back to a double via an accurate |
| 61 | +// algorithm (such as Clinger's algorithm), the resulting double will |
| 62 | +// be exactly equal to the original value. On most systems, this |
| 63 | +// implies that using `strtod` to parse the output of |
| 64 | +// `swift_format_double` will yield exactly the original value. |
| 65 | +// |
| 66 | +// * Short. No other accurate result will have fewer digits. |
| 67 | +// |
| 68 | +// * Close. If there are multiple possible decimal forms that are |
| 69 | +// both accurate and short, the form computed here will be |
| 70 | +// closest to the original binary value. |
| 71 | +// |
| 72 | +// Notes: |
| 73 | +// |
| 74 | +// If the input value is infinity or NaN, or `digits_length < 17`, the |
| 75 | +// function returns zero and generates no ouput. |
| 76 | +// |
| 77 | +// If the input value is zero, it will return `decimalExponent = 0` and |
| 78 | +// a single digit of value zero. |
| 79 | +// |
| 80 | +int swift_decompose_double(double d, |
| 81 | + int8_t *digits, size_t digits_length, int *decimalExponent); |
| 82 | + |
| 83 | +// Format a double as an ASCII string. |
| 84 | +// |
| 85 | +// For infinity, it outputs "inf" or "-inf". |
| 86 | +// |
| 87 | +// For NaN, it outputs a Swift-style detailed dump, including |
| 88 | +// sign, signaling/quiet, and payload (if any). Typical output: |
| 89 | +// "nan", "-nan", "-snan(0x1234)". |
| 90 | +// |
| 91 | +// For zero, it outputs "0.0" or "-0.0" depending on the sign. |
| 92 | +// |
| 93 | +// For other values, it uses `swift_decompose_double` to compute the |
| 94 | +// digits, then uses either `swift_format_decimal` or |
| 95 | +// `swift_format_exponential` to produce an ASCII string depending on |
| 96 | +// the magnitude of the value. |
| 97 | +// |
| 98 | +// In all cases, it returns the number of ASCII characters actually |
| 99 | +// written, or zero if the buffer was too small. |
| 100 | +size_t swift_format_double(double, char *dest, size_t length); |
| 101 | +#endif |
| 102 | + |
| 103 | +#if SWIFT_DTOA_FLOAT_SUPPORT |
| 104 | +// See swift_decompose_double. `digits_length` must be at least 9. |
| 105 | +int swift_decompose_float(float f, |
| 106 | + int8_t *digits, size_t digits_length, int *decimalExponent); |
| 107 | +// See swift_format_double. |
| 108 | +size_t swift_format_float(float, char *dest, size_t length); |
| 109 | +#endif |
| 110 | + |
| 111 | +#if SWIFT_DTOA_FLOAT80_SUPPORT |
| 112 | +// See swift_decompose_double. `digits_length` must be at least 21. |
| 113 | +int swift_decompose_float80(long double f, |
| 114 | + int8_t *digits, size_t digits_length, int *decimalExponent); |
| 115 | +// See swift_format_double. |
| 116 | +size_t swift_format_float80(long double, char *dest, size_t length); |
| 117 | +#endif |
| 118 | + |
| 119 | +// Generate an ASCII string from the raw exponent and digit information |
| 120 | +// as generated by `swift_decompose_double`. Returns the number of |
| 121 | +// bytes actually used. If `dest` was not big enough, these functions |
| 122 | +// return zero. The generated string is always terminated with a zero |
| 123 | +// byte unless `length` was zero. |
| 124 | + |
| 125 | +// "Exponential" form uses common exponential format, e.g., "-1.234e+56" |
| 126 | +// The exponent always has a sign and at least two digits. The |
| 127 | +// generated string is never longer than `digits_count + 9` bytes, |
| 128 | +// including the trailing zero byte. |
| 129 | +size_t swift_format_exponential(char *dest, size_t length, |
| 130 | + bool negative, const int8_t *digits, int digits_count, int decimalExponent); |
| 131 | + |
| 132 | +// "Decimal" form writes the value without using exponents. This |
| 133 | +// includes cases such as "0.000001234", "123.456", and "123456000.0". |
| 134 | +// Note that the result always has a decimal point with at least one |
| 135 | +// digit before and one digit after. The generated string is never |
| 136 | +// longer than `digits_count + abs(exponent) + 4` bytes, including the |
| 137 | +// trailing zero byte. |
| 138 | +size_t swift_format_decimal(char *dest, size_t length, |
| 139 | + bool negative, const int8_t *digits, int digits_count, int decimalExponent); |
| 140 | + |
| 141 | +#ifdef __cplusplus |
| 142 | +} |
| 143 | +#endif |
| 144 | +#endif |
0 commit comments