Coverage Report

Created: 2026-10-17 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Python/pystrtod.c
Line
Count
Source
1
/* -*- Mode: C; c-file-style: "python" -*- */
2
3
#include <Python.h>
4
#include "pycore_dtoa.h"          // _Py_dg_strtod()
5
#include "pycore_pymath.h"        // _PY_SHORT_FLOAT_REPR
6
7
#include <locale.h>               // localeconv()
8
9
/* Case-insensitive string match used for nan and inf detection; t should be
10
   lower-case.  Returns 1 for a successful match, 0 otherwise. */
11
12
static int
13
case_insensitive_match(const char *s, const char *t)
14
53.0k
{
15
132k
    while(*t && Py_TOLOWER(*s) == *t) {
16
79.3k
        s++;
17
79.3k
        t++;
18
79.3k
    }
19
53.0k
    return *t ? 0 : 1;
20
53.0k
}
21
22
/* _Py_parse_inf_or_nan: Attempt to parse a string of the form "nan", "inf" or
23
   "infinity", with an optional leading sign of "+" or "-".  On success,
24
   return the NaN or Infinity as a double and set *endptr to point just beyond
25
   the successfully parsed portion of the string.  On failure, return -1.0 and
26
   set *endptr to point to the start of the string. */
27
double
28
_Py_parse_inf_or_nan(const char *p, char **endptr)
29
26.5k
{
30
26.5k
    double retval;
31
26.5k
    const char *s;
32
26.5k
    int negate = 0;
33
34
26.5k
    s = p;
35
26.5k
    if (*s == '-') {
36
35
        negate = 1;
37
35
        s++;
38
35
    }
39
26.4k
    else if (*s == '+') {
40
1
        s++;
41
1
    }
42
26.5k
    if (case_insensitive_match(s, "inf")) {
43
26.4k
        s += 3;
44
26.4k
        if (case_insensitive_match(s, "inity"))
45
0
            s += 5;
46
26.4k
        retval = negate ? -INFINITY : INFINITY;
47
26.4k
    }
48
75
    else if (case_insensitive_match(s, "nan")) {
49
8
        s += 3;
50
8
        retval = negate ? -fabs(Py_NAN) : fabs(Py_NAN);
51
8
    }
52
67
    else {
53
67
        s = p;
54
67
        retval = -1.0;
55
67
    }
56
26.5k
    *endptr = (char *)s;
57
26.5k
    return retval;
58
26.5k
}
59
60
61
/**
62
 * _PyOS_ascii_strtod:
63
 * @nptr:    the string to convert to a numeric value.
64
 * @endptr:  if non-%NULL, it returns the character after
65
 *           the last character used in the conversion.
66
 *
67
 * Converts a string to a #gdouble value.
68
 * This function behaves like the standard strtod() function
69
 * does in the C locale. It does this without actually
70
 * changing the current locale, since that would not be
71
 * thread-safe.
72
 *
73
 * This function is typically used when reading configuration
74
 * files or other non-user input that should be locale independent.
75
 * To handle input from the user you should normally use the
76
 * locale-sensitive system strtod() function.
77
 *
78
 * If the correct value would cause overflow, plus or minus %HUGE_VAL
79
 * is returned (according to the sign of the value), and %ERANGE is
80
 * stored in %errno. If the correct value would cause underflow,
81
 * zero is returned and %ERANGE is stored in %errno.
82
 * If memory allocation fails, %ENOMEM is stored in %errno.
83
 *
84
 * This function resets %errno before calling strtod() so that
85
 * you can reliably detect overflow and underflow.
86
 *
87
 * Return value: the #gdouble value.
88
 **/
89
90
#if _PY_SHORT_FLOAT_REPR == 1
91
92
static double
93
_PyOS_ascii_strtod(const char *nptr, char **endptr)
94
794k
{
95
794k
    double result;
96
794k
    _Py_SET_53BIT_PRECISION_HEADER;
97
98
794k
    assert(nptr != NULL);
99
    /* Set errno to zero, so that we can distinguish zero results
100
       and underflows */
101
794k
    errno = 0;
102
103
794k
    _Py_SET_53BIT_PRECISION_START;
104
794k
    result = _Py_dg_strtod(nptr, endptr);
105
794k
    _Py_SET_53BIT_PRECISION_END;
106
107
794k
    if (*endptr == nptr)
108
        /* string might represent an inf or nan */
109
26.5k
        result = _Py_parse_inf_or_nan(nptr, endptr);
110
111
794k
    return result;
112
113
794k
}
114
115
#else
116
117
/*
118
   Use system strtod;  since strtod is locale aware, we may
119
   have to first fix the decimal separator.
120
121
   Note that unlike _Py_dg_strtod, the system strtod may not always give
122
   correctly rounded results.
123
*/
124
125
static double
126
_PyOS_ascii_strtod(const char *nptr, char **endptr)
127
{
128
    char *fail_pos;
129
    double val;
130
    struct lconv *locale_data;
131
    const char *decimal_point;
132
    size_t decimal_point_len;
133
    const char *p, *decimal_point_pos;
134
    const char *end = NULL; /* Silence gcc */
135
    const char *digits_pos = NULL;
136
    int negate = 0;
137
138
    assert(nptr != NULL);
139
140
    fail_pos = NULL;
141
142
    locale_data = localeconv();
143
    decimal_point = locale_data->decimal_point;
144
    decimal_point_len = strlen(decimal_point);
145
146
    assert(decimal_point_len != 0);
147
148
    decimal_point_pos = NULL;
149
150
    /* Parse infinities and nans */
151
    val = _Py_parse_inf_or_nan(nptr, endptr);
152
    if (*endptr != nptr)
153
        return val;
154
155
    /* Set errno to zero, so that we can distinguish zero results
156
       and underflows */
157
    errno = 0;
158
159
    /* We process the optional sign manually, then pass the remainder to
160
       the system strtod.  This ensures that the result of an underflow
161
       has the correct sign. (bug #1725)  */
162
    p = nptr;
163
    /* Process leading sign, if present */
164
    if (*p == '-') {
165
        negate = 1;
166
        p++;
167
    }
168
    else if (*p == '+') {
169
        p++;
170
    }
171
172
    /* Some platform strtods accept hex floats; Python shouldn't (at the
173
       moment), so we check explicitly for strings starting with '0x'. */
174
    if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X'))
175
        goto invalid_string;
176
177
    /* Check that what's left begins with a digit or decimal point */
178
    if (!Py_ISDIGIT(*p) && *p != '.')
179
        goto invalid_string;
180
181
    digits_pos = p;
182
    if (decimal_point[0] != '.' ||
183
        decimal_point[1] != 0)
184
    {
185
        /* Look for a '.' in the input; if present, it'll need to be
186
           swapped for the current locale's decimal point before we
187
           call strtod.  On the other hand, if we find the current
188
           locale's decimal point then the input is invalid. */
189
        while (Py_ISDIGIT(*p))
190
            p++;
191
192
        if (*p == '.')
193
        {
194
            decimal_point_pos = p++;
195
196
            /* locate end of number */
197
            while (Py_ISDIGIT(*p))
198
                p++;
199
200
            if (*p == 'e' || *p == 'E')
201
                p++;
202
            if (*p == '+' || *p == '-')
203
                p++;
204
            while (Py_ISDIGIT(*p))
205
                p++;
206
            end = p;
207
        }
208
        else if (strncmp(p, decimal_point, decimal_point_len) == 0)
209
            /* Python bug #1417699 */
210
            goto invalid_string;
211
        /* For the other cases, we need not convert the decimal
212
           point */
213
    }
214
215
    if (decimal_point_pos) {
216
        char *copy, *c;
217
        /* Create a copy of the input, with the '.' converted to the
218
           locale-specific decimal point */
219
        copy = (char *)PyMem_Malloc(end - digits_pos +
220
                                    1 + decimal_point_len);
221
        if (copy == NULL) {
222
            *endptr = (char *)nptr;
223
            errno = ENOMEM;
224
            return val;
225
        }
226
227
        c = copy;
228
        memcpy(c, digits_pos, decimal_point_pos - digits_pos);
229
        c += decimal_point_pos - digits_pos;
230
        memcpy(c, decimal_point, decimal_point_len);
231
        c += decimal_point_len;
232
        memcpy(c, decimal_point_pos + 1,
233
               end - (decimal_point_pos + 1));
234
        c += end - (decimal_point_pos + 1);
235
        *c = 0;
236
237
        val = strtod(copy, &fail_pos);
238
239
        if (fail_pos)
240
        {
241
            if (fail_pos > decimal_point_pos)
242
                fail_pos = (char *)digits_pos +
243
                    (fail_pos - copy) -
244
                    (decimal_point_len - 1);
245
            else
246
                fail_pos = (char *)digits_pos +
247
                    (fail_pos - copy);
248
        }
249
250
        PyMem_Free(copy);
251
252
    }
253
    else {
254
        val = strtod(digits_pos, &fail_pos);
255
    }
256
257
    if (fail_pos == digits_pos)
258
        goto invalid_string;
259
260
    if (negate && fail_pos != nptr)
261
        val = -val;
262
    *endptr = fail_pos;
263
264
    return val;
265
266
  invalid_string:
267
    *endptr = (char*)nptr;
268
    errno = EINVAL;
269
    return -1.0;
270
}
271
272
#endif
273
274
/* PyOS_string_to_double converts a null-terminated byte string s (interpreted
275
   as a string of ASCII characters) to a float.  The string should not have
276
   leading or trailing whitespace.  The conversion is independent of the
277
   current locale.
278
279
   If endptr is NULL, try to convert the whole string.  Raise ValueError and
280
   return -1.0 if the string is not a valid representation of a floating-point
281
   number.
282
283
   If endptr is non-NULL, try to convert as much of the string as possible.
284
   If no initial segment of the string is the valid representation of a
285
   floating-point number then *endptr is set to point to the beginning of the
286
   string, -1.0 is returned and again ValueError is raised.
287
288
   On overflow (e.g., when trying to convert '1e500' on an IEEE 754 machine),
289
   if overflow_exception is NULL then +-INFINITY is returned, and no Python
290
   exception is raised.  Otherwise, overflow_exception should point to
291
   a Python exception, this exception will be raised, -1.0 will be returned,
292
   and *endptr will point just past the end of the converted value.
293
294
   If any other failure occurs (for example lack of memory), -1.0 is returned
295
   and the appropriate Python exception will have been set.
296
*/
297
298
double
299
PyOS_string_to_double(const char *s,
300
                      char **endptr,
301
                      PyObject *overflow_exception)
302
794k
{
303
794k
    double x, result=-1.0;
304
794k
    char *fail_pos;
305
306
794k
    errno = 0;
307
794k
    x = _PyOS_ascii_strtod(s, &fail_pos);
308
309
794k
    if (errno == ENOMEM) {
310
0
        PyErr_NoMemory();
311
0
        fail_pos = (char *)s;
312
0
    }
313
794k
    else if (!endptr && (fail_pos == s || *fail_pos != '\0'))
314
0
        PyErr_Format(PyExc_ValueError,
315
0
                      "could not convert string to float: "
316
0
                      "'%.200s'", s);
317
794k
    else if (fail_pos == s)
318
67
        PyErr_Format(PyExc_ValueError,
319
67
                      "could not convert string to float: "
320
67
                      "'%.200s'", s);
321
794k
    else if (errno == ERANGE && fabs(x) >= 1.0 && overflow_exception)
322
0
        PyErr_Format(overflow_exception,
323
0
                      "value too large to convert to float: "
324
0
                      "'%.200s'", s);
325
794k
    else
326
794k
        result = x;
327
328
794k
    if (endptr != NULL)
329
765k
        *endptr = fail_pos;
330
794k
    return result;
331
794k
}
332
333
/* Remove underscores that follow the underscore placement rule from
334
   the string and then call the `innerfunc` function on the result.
335
   It should return a new object or NULL on exception.
336
337
   `what` is used for the error message emitted when underscores are detected
338
   that don't follow the rule. `arg` is an opaque pointer passed to the inner
339
   function.
340
341
   This is used to implement underscore-agnostic conversion for floats
342
   and complex numbers.
343
*/
344
PyObject *
345
_Py_string_to_number_with_underscores(
346
    const char *s, Py_ssize_t orig_len, const char *what, PyObject *obj, void *arg,
347
    PyObject *(*innerfunc)(const char *, Py_ssize_t, void *))
348
757k
{
349
757k
    char prev;
350
757k
    const char *p, *last;
351
757k
    char *dup, *end;
352
757k
    PyObject *result;
353
354
757k
    assert(s[orig_len] == '\0');
355
356
757k
    if (strchr(s, '_') == NULL) {
357
753k
        return innerfunc(s, orig_len, arg);
358
753k
    }
359
360
3.55k
    dup = PyMem_Malloc(orig_len + 1);
361
3.55k
    if (dup == NULL) {
362
0
        return PyErr_NoMemory();
363
0
    }
364
3.55k
    end = dup;
365
3.55k
    prev = '\0';
366
3.55k
    last = s + orig_len;
367
378k
    for (p = s; *p; p++) {
368
374k
        if (*p == '_') {
369
            /* Underscores are only allowed after digits. */
370
7.42k
            if (!(prev >= '0' && prev <= '9')) {
371
7
                goto error;
372
7
            }
373
7.42k
        }
374
367k
        else {
375
367k
            *end++ = *p;
376
            /* Underscores are only allowed before digits. */
377
367k
            if (prev == '_' && !(*p >= '0' && *p <= '9')) {
378
2
                goto error;
379
2
            }
380
367k
        }
381
374k
        prev = *p;
382
374k
    }
383
    /* Underscores are not allowed at the end. */
384
3.54k
    if (prev == '_') {
385
2
        goto error;
386
2
    }
387
    /* No embedded NULs allowed. */
388
3.53k
    if (p != last) {
389
0
        goto error;
390
0
    }
391
3.53k
    *end = '\0';
392
3.53k
    result = innerfunc(dup, end - dup, arg);
393
3.53k
    PyMem_Free(dup);
394
3.53k
    return result;
395
396
11
  error:
397
11
    PyMem_Free(dup);
398
11
    PyErr_Format(PyExc_ValueError,
399
11
                 "could not convert string to %s: "
400
11
                 "%R", what, obj);
401
11
    return NULL;
402
3.53k
}
403
404
/* Largest precision magnitude accepted by PyOS_double_to_string().  The
405
   output buffer sizes computed below and within _Py_dg_dtoa() use int and
406
   Py_ssize_t arithmetic on roughly precision + (digits before the point, at
407
   most DBL_MAX_10_EXP + 1 == 309) + a few bytes of sign, point and exponent.
408
   Staying this far inside the int range keeps all of those sums in range.
409
   (Only C callers can pass a negative precision.)  _Py_dg_dtoa() applies
410
   the same bound to its ndigits argument. */
411
133k
#define DOUBLE_TO_STRING_PRECISION_MAX (INT_MAX - 1024)
412
413
#if _PY_SHORT_FLOAT_REPR == 0
414
415
/* Given a string that may have a decimal point in the current
416
   locale, change it back to a dot.  Since the string cannot get
417
   longer, no need for a maximum buffer size parameter. */
418
Py_LOCAL_INLINE(void)
419
change_decimal_from_locale_to_dot(char* buffer)
420
{
421
    struct lconv *locale_data = localeconv();
422
    const char *decimal_point = locale_data->decimal_point;
423
424
    if (decimal_point[0] != '.' || decimal_point[1] != 0) {
425
        size_t decimal_point_len = strlen(decimal_point);
426
427
        if (*buffer == '+' || *buffer == '-')
428
            buffer++;
429
        while (Py_ISDIGIT(*buffer))
430
            buffer++;
431
        if (strncmp(buffer, decimal_point, decimal_point_len) == 0) {
432
            *buffer = '.';
433
            buffer++;
434
            if (decimal_point_len > 1) {
435
                /* buffer needs to get smaller */
436
                size_t rest_len = strlen(buffer +
437
                                     (decimal_point_len - 1));
438
                memmove(buffer,
439
                    buffer + (decimal_point_len - 1),
440
                    rest_len);
441
                buffer[rest_len] = 0;
442
            }
443
        }
444
    }
445
}
446
447
448
/* From the C99 standard, section 7.19.6:
449
The exponent always contains at least two digits, and only as many more digits
450
as necessary to represent the exponent.
451
*/
452
#define MIN_EXPONENT_DIGITS 2
453
454
/* Ensure that any exponent, if present, is at least MIN_EXPONENT_DIGITS
455
   in length. */
456
Py_LOCAL_INLINE(void)
457
ensure_minimum_exponent_length(char* buffer, size_t buf_size)
458
{
459
    char *p = strpbrk(buffer, "eE");
460
    if (p && (*(p + 1) == '-' || *(p + 1) == '+')) {
461
        char *start = p + 2;
462
        int exponent_digit_cnt = 0;
463
        int leading_zero_cnt = 0;
464
        int in_leading_zeros = 1;
465
        int significant_digit_cnt;
466
467
        /* Skip over the exponent and the sign. */
468
        p += 2;
469
470
        /* Find the end of the exponent, keeping track of leading
471
           zeros. */
472
        while (*p && Py_ISDIGIT(*p)) {
473
            if (in_leading_zeros && *p == '0')
474
                ++leading_zero_cnt;
475
            if (*p != '0')
476
                in_leading_zeros = 0;
477
            ++p;
478
            ++exponent_digit_cnt;
479
        }
480
481
        significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt;
482
        if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) {
483
            /* If there are 2 exactly digits, we're done,
484
               regardless of what they contain */
485
        }
486
        else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) {
487
            int extra_zeros_cnt;
488
489
            /* There are more than 2 digits in the exponent.  See
490
               if we can delete some of the leading zeros */
491
            if (significant_digit_cnt < MIN_EXPONENT_DIGITS)
492
                significant_digit_cnt = MIN_EXPONENT_DIGITS;
493
            extra_zeros_cnt = exponent_digit_cnt -
494
                significant_digit_cnt;
495
496
            /* Delete extra_zeros_cnt worth of characters from the
497
               front of the exponent */
498
            assert(extra_zeros_cnt >= 0);
499
500
            /* Add one to significant_digit_cnt to copy the
501
               trailing 0 byte, thus setting the length */
502
            memmove(start,
503
                start + extra_zeros_cnt,
504
                significant_digit_cnt + 1);
505
        }
506
        else {
507
            /* If there are fewer than 2 digits, add zeros
508
               until there are 2, if there's enough room */
509
            int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt;
510
            if (start + zeros + exponent_digit_cnt + 1
511
                  < buffer + buf_size) {
512
                memmove(start + zeros, start,
513
                    exponent_digit_cnt + 1);
514
                memset(start, '0', zeros);
515
            }
516
        }
517
    }
518
}
519
520
/* Remove trailing zeros after the decimal point from a numeric string; also
521
   remove the decimal point if all digits following it are zero.  The numeric
522
   string must end in '\0', and should not have any leading or trailing
523
   whitespace.  Assumes that the decimal point is '.'. */
524
Py_LOCAL_INLINE(void)
525
remove_trailing_zeros(char *buffer)
526
{
527
    char *old_fraction_end, *new_fraction_end, *end, *p;
528
529
    p = buffer;
530
    if (*p == '-' || *p == '+')
531
        /* Skip leading sign, if present */
532
        ++p;
533
    while (Py_ISDIGIT(*p))
534
        ++p;
535
536
    /* if there's no decimal point there's nothing to do */
537
    if (*p++ != '.')
538
        return;
539
540
    /* scan any digits after the point */
541
    while (Py_ISDIGIT(*p))
542
        ++p;
543
    old_fraction_end = p;
544
545
    /* scan up to ending '\0' */
546
    while (*p != '\0')
547
        p++;
548
    /* +1 to make sure that we move the null byte as well */
549
    end = p+1;
550
551
    /* scan back from fraction_end, looking for removable zeros */
552
    p = old_fraction_end;
553
    while (*(p-1) == '0')
554
        --p;
555
    /* and remove point if we've got that far */
556
    if (*(p-1) == '.')
557
        --p;
558
    new_fraction_end = p;
559
560
    memmove(new_fraction_end, old_fraction_end, end-old_fraction_end);
561
}
562
563
/* Ensure that buffer has a decimal point in it.  The decimal point will not
564
   be in the current locale, it will always be '.'. Don't add a decimal point
565
   if an exponent is present.  Also, convert to exponential notation where
566
   adding a '.0' would produce too many significant digits (see issue 5864).
567
568
   Returns a pointer to the fixed buffer, or NULL on failure.
569
*/
570
Py_LOCAL_INLINE(char *)
571
ensure_decimal_point(char* buffer, size_t buf_size, int precision)
572
{
573
    int digit_count, insert_count = 0, convert_to_exp = 0;
574
    const char *chars_to_insert;
575
    char *digits_start;
576
577
    /* search for the first non-digit character */
578
    char *p = buffer;
579
    if (*p == '-' || *p == '+')
580
        /* Skip leading sign, if present.  I think this could only
581
           ever be '-', but it can't hurt to check for both. */
582
        ++p;
583
    digits_start = p;
584
    while (*p && Py_ISDIGIT(*p))
585
        ++p;
586
    digit_count = Py_SAFE_DOWNCAST(p - digits_start, Py_ssize_t, int);
587
588
    if (*p == '.') {
589
        if (Py_ISDIGIT(*(p+1))) {
590
            /* Nothing to do, we already have a decimal
591
               point and a digit after it */
592
        }
593
        else {
594
            /* We have a decimal point, but no following
595
               digit.  Insert a zero after the decimal. */
596
            /* can't ever get here via PyOS_double_to_string */
597
            assert(precision == -1);
598
            ++p;
599
            chars_to_insert = "0";
600
            insert_count = 1;
601
        }
602
    }
603
    else if (!(*p == 'e' || *p == 'E')) {
604
        /* Don't add ".0" if we have an exponent. */
605
        if (digit_count == precision) {
606
            /* issue 5864: don't add a trailing .0 in the case
607
               where the '%g'-formatted result already has as many
608
               significant digits as were requested.  Switch to
609
               exponential notation instead. */
610
            convert_to_exp = 1;
611
            /* no exponent, no point, and we shouldn't land here
612
               for infs and nans, so we must be at the end of the
613
               string. */
614
            assert(*p == '\0');
615
        }
616
        else {
617
            assert(precision == -1 || digit_count < precision);
618
            chars_to_insert = ".0";
619
            insert_count = 2;
620
        }
621
    }
622
    if (insert_count) {
623
        size_t buf_len = strlen(buffer);
624
        if (buf_len + insert_count + 1 >= buf_size) {
625
            /* If there is not enough room in the buffer
626
               for the additional text, just skip it.  It's
627
               not worth generating an error over. */
628
        }
629
        else {
630
            memmove(p + insert_count, p,
631
                buffer + strlen(buffer) - p + 1);
632
            memcpy(p, chars_to_insert, insert_count);
633
        }
634
    }
635
    if (convert_to_exp) {
636
        int written;
637
        size_t buf_avail;
638
        p = digits_start;
639
        /* insert decimal point */
640
        assert(digit_count >= 1);
641
        memmove(p+2, p+1, digit_count); /* safe, but overwrites nul */
642
        p[1] = '.';
643
        p += digit_count+1;
644
        assert(p <= buf_size+buffer);
645
        buf_avail = buf_size+buffer-p;
646
        if (buf_avail == 0)
647
            return NULL;
648
        /* Add exponent.  It's okay to use lower case 'e': we only
649
           arrive here as a result of using the empty format code or
650
           repr/str builtins and those never want an upper case 'E' */
651
        written = PyOS_snprintf(p, buf_avail, "e%+.02d", digit_count-1);
652
        if (!(0 <= written &&
653
              written < Py_SAFE_DOWNCAST(buf_avail, size_t, int)))
654
            /* output truncated, or something else bad happened */
655
            return NULL;
656
        remove_trailing_zeros(buffer);
657
    }
658
    return buffer;
659
}
660
661
/* see FORMATBUFLEN in unicodeobject.c */
662
#define FLOAT_FORMATBUFLEN 120
663
664
/**
665
 * _PyOS_ascii_formatd:
666
 * @buffer: A buffer to place the resulting string in
667
 * @buf_size: The length of the buffer.
668
 * @format: The printf()-style format to use for the
669
 *          code to use for converting.
670
 * @d: The #gdouble to convert
671
 * @precision: The precision to use when formatting.
672
 *
673
 * Converts a #gdouble to a string, using the '.' as
674
 * decimal point. To format the number you pass in
675
 * a printf()-style format string. Allowed conversion
676
 * specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'Z'.
677
 *
678
 * 'Z' is the same as 'g', except it always has a decimal and
679
 *     at least one digit after the decimal.
680
 *
681
 * Return value: The pointer to the buffer with the converted string.
682
 * On failure returns NULL but does not set any Python exception.
683
 **/
684
static char *
685
_PyOS_ascii_formatd(char       *buffer,
686
                   size_t      buf_size,
687
                   const char *format,
688
                   double      d,
689
                   int         precision)
690
{
691
    char format_char;
692
    size_t format_len = strlen(format);
693
694
    /* Issue 2264: code 'Z' requires copying the format.  'Z' is 'g', but
695
       also with at least one character past the decimal. */
696
    char tmp_format[FLOAT_FORMATBUFLEN];
697
698
    /* The last character in the format string must be the format char */
699
    format_char = format[format_len - 1];
700
701
    if (format[0] != '%')
702
        return NULL;
703
704
    /* I'm not sure why this test is here.  It's ensuring that the format
705
       string after the first character doesn't have a single quote, a
706
       lowercase l, or a percent. This is the reverse of the commented-out
707
       test about 10 lines ago. */
708
    if (strpbrk(format + 1, "'l%"))
709
        return NULL;
710
711
    /* Also curious about this function is that it accepts format strings
712
       like "%xg", which are invalid for floats.  In general, the
713
       interface to this function is not very good, but changing it is
714
       difficult because it's a public API. */
715
716
    if (!(format_char == 'e' || format_char == 'E' ||
717
          format_char == 'f' || format_char == 'F' ||
718
          format_char == 'g' || format_char == 'G' ||
719
          format_char == 'Z'))
720
        return NULL;
721
722
    /* Map 'Z' format_char to 'g', by copying the format string and
723
       replacing the final char with a 'g' */
724
    if (format_char == 'Z') {
725
        if (format_len + 1 >= sizeof(tmp_format)) {
726
            /* The format won't fit in our copy.  Error out.  In
727
               practice, this will never happen and will be
728
               detected by returning NULL */
729
            return NULL;
730
        }
731
        strcpy(tmp_format, format);
732
        tmp_format[format_len - 1] = 'g';
733
        format = tmp_format;
734
    }
735
736
737
    /* Have PyOS_snprintf do the hard work */
738
    PyOS_snprintf(buffer, buf_size, format, d);
739
740
    /* Do various fixups on the return string */
741
742
    /* Get the current locale, and find the decimal point string.
743
       Convert that string back to a dot. */
744
    change_decimal_from_locale_to_dot(buffer);
745
746
    /* If an exponent exists, ensure that the exponent is at least
747
       MIN_EXPONENT_DIGITS digits, providing the buffer is large enough
748
       for the extra zeros.  Also, if there are more than
749
       MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get
750
       back to MIN_EXPONENT_DIGITS */
751
    ensure_minimum_exponent_length(buffer, buf_size);
752
753
    /* If format_char is 'Z', make sure we have at least one character
754
       after the decimal point (and make sure we have a decimal point);
755
       also switch to exponential notation in some edge cases where the
756
       extra character would produce more significant digits that we
757
       really want. */
758
    if (format_char == 'Z')
759
        buffer = ensure_decimal_point(buffer, buf_size, precision);
760
761
    return buffer;
762
}
763
764
/* The fallback code to use if _Py_dg_dtoa is not available. */
765
766
char * PyOS_double_to_string(double val,
767
                                         char format_code,
768
                                         int precision,
769
                                         int flags,
770
                                         int *type)
771
{
772
    char format[32];
773
    Py_ssize_t bufsize;
774
    char *buf;
775
    int t, exp;
776
    int upper = 0;
777
778
    if (precision > DOUBLE_TO_STRING_PRECISION_MAX
779
        || precision < -DOUBLE_TO_STRING_PRECISION_MAX)
780
    {
781
        PyErr_SetString(PyExc_ValueError, "precision too big");
782
        return NULL;
783
    }
784
785
    /* Validate format_code, and map upper and lower case */
786
    switch (format_code) {
787
    case 'e':          /* exponent */
788
    case 'f':          /* fixed */
789
    case 'g':          /* general */
790
        break;
791
    case 'E':
792
        upper = 1;
793
        format_code = 'e';
794
        break;
795
    case 'F':
796
        upper = 1;
797
        format_code = 'f';
798
        break;
799
    case 'G':
800
        upper = 1;
801
        format_code = 'g';
802
        break;
803
    case 'r':          /* repr format */
804
        /* Supplied precision is unused, must be 0. */
805
        if (precision != 0) {
806
            PyErr_BadInternalCall();
807
            return NULL;
808
        }
809
        /* The repr() precision (17 significant decimal digits) is the
810
           minimal number that is guaranteed to have enough precision
811
           so that if the number is read back in the exact same binary
812
           value is recreated.  This is true for IEEE floating point
813
           by design, and also happens to work for all other modern
814
           hardware. */
815
        precision = 17;
816
        format_code = 'g';
817
        break;
818
    default:
819
        PyErr_BadInternalCall();
820
        return NULL;
821
    }
822
823
    /* Here's a quick-and-dirty calculation to figure out how big a buffer
824
       we need.  In general, for a finite float we need:
825
826
         1 byte for each digit of the decimal significand, and
827
828
         1 for a possible sign
829
         1 for a possible decimal point
830
         2 for a possible [eE][+-]
831
         1 for each digit of the exponent;  if we allow 19 digits
832
           total then we're safe up to exponents of 2**63.
833
         1 for the trailing nul byte
834
835
       This gives a total of 24 + the number of digits in the significand,
836
       and the number of digits in the significand is:
837
838
         for 'g' format: at most precision, except possibly
839
           when precision == 0, when it's 1.
840
         for 'e' format: precision+1
841
         for 'f' format: precision digits after the point, at least 1
842
           before.  To figure out how many digits appear before the point
843
           we have to examine the size of the number.  If fabs(val) < 1.0
844
           then there will be only one digit before the point.  If
845
           fabs(val) >= 1.0, then there are at most
846
847
         1+floor(log10(ceiling(fabs(val))))
848
849
           digits before the point (where the 'ceiling' allows for the
850
           possibility that the rounding rounds the integer part of val
851
           up).  A safe upper bound for the above quantity is
852
           1+floor(exp/3), where exp is the unique integer such that 0.5
853
           <= fabs(val)/2**exp < 1.0.  This exp can be obtained from
854
           frexp.
855
856
       So we allow room for precision+1 digits for all formats, plus an
857
       extra floor(exp/3) digits for 'f' format.
858
859
    */
860
861
    if (isnan(val) || isinf(val))
862
        /* 3 for 'inf'/'nan', 1 for sign, 1 for '\0' */
863
        bufsize = 5;
864
    else {
865
        bufsize = 25 + precision;
866
        if (format_code == 'f' && fabs(val) >= 1.0) {
867
            frexp(val, &exp);
868
            bufsize += exp/3;
869
        }
870
    }
871
872
    buf = PyMem_Malloc(bufsize);
873
    if (buf == NULL) {
874
        PyErr_NoMemory();
875
        return NULL;
876
    }
877
878
    /* Handle nan and inf. */
879
    if (isnan(val)) {
880
        strcpy(buf, "nan");
881
        t = Py_DTST_NAN;
882
    } else if (isinf(val)) {
883
        if (copysign(1., val) == 1.)
884
            strcpy(buf, "inf");
885
        else
886
            strcpy(buf, "-inf");
887
        t = Py_DTST_INFINITE;
888
    } else {
889
        t = Py_DTST_FINITE;
890
        if (flags & Py_DTSF_ADD_DOT_0)
891
            format_code = 'Z';
892
893
        PyOS_snprintf(format, sizeof(format), "%%%s.%i%c",
894
                      (flags & Py_DTSF_ALT ? "#" : ""), precision,
895
                      format_code);
896
        _PyOS_ascii_formatd(buf, bufsize, format, val, precision);
897
898
        if (flags & Py_DTSF_NO_NEG_0 && buf[0] == '-') {
899
            char *buf2 = buf + 1;
900
            while (*buf2 == '0' || *buf2 == '.') {
901
                ++buf2;
902
            }
903
            if (*buf2 == 0 || *buf2 == 'e') {
904
                size_t len = buf2 - buf + strlen(buf2);
905
                assert(buf[len] == 0);
906
                memmove(buf, buf+1, len);
907
            }
908
        }
909
    }
910
911
    /* Add sign when requested.  It's convenient (esp. when formatting
912
     complex numbers) to include a sign even for inf and nan. */
913
    if (flags & Py_DTSF_SIGN && buf[0] != '-') {
914
        size_t len = strlen(buf);
915
        /* the bufsize calculations above should ensure that we've got
916
           space to add a sign */
917
        assert((size_t)bufsize >= len+2);
918
        memmove(buf+1, buf, len+1);
919
        buf[0] = '+';
920
    }
921
    if (upper) {
922
        /* Convert to upper case. */
923
        char *p1;
924
        for (p1 = buf; *p1; p1++)
925
            *p1 = Py_TOUPPER(*p1);
926
    }
927
928
    if (type)
929
        *type = t;
930
    return buf;
931
}
932
933
#else  // _PY_SHORT_FLOAT_REPR == 1
934
935
/* _Py_dg_dtoa is available. */
936
937
/* I'm using a lookup table here so that I don't have to invent a non-locale
938
   specific way to convert to uppercase */
939
686
#define OFS_INF 0
940
2
#define OFS_NAN 1
941
21.4k
#define OFS_E 2
942
943
/* The lengths of these are known to the code below, so don't change them */
944
static const char * const lc_float_strings[] = {
945
    "inf",
946
    "nan",
947
    "e",
948
};
949
static const char * const uc_float_strings[] = {
950
    "INF",
951
    "NAN",
952
    "E",
953
};
954
955
956
/* Convert a double d to a string, and return a PyMem_Malloc'd block of
957
   memory contain the resulting string.
958
959
   Arguments:
960
     d is the double to be converted
961
     format_code is one of 'e', 'f', 'g', 'r'.  'e', 'f' and 'g'
962
       correspond to '%e', '%f' and '%g';  'r' corresponds to repr.
963
     mode is one of '0', '2' or '3', and is completely determined by
964
       format_code: 'e' and 'g' use mode 2; 'f' mode 3, 'r' mode 0.
965
     precision is the desired precision
966
     always_add_sign is nonzero if a '+' sign should be included for positive
967
       numbers
968
     add_dot_0_if_integer is nonzero if integers in non-exponential form
969
       should have ".0" added.  Only applies to format codes 'r' and 'g'.
970
     use_alt_formatting is nonzero if alternative formatting should be
971
       used.  Only applies to format codes 'e', 'f' and 'g'.  For code 'g',
972
       at most one of use_alt_formatting and add_dot_0_if_integer should
973
       be nonzero.
974
     type, if non-NULL, will be set to one of these constants to identify
975
       the type of the 'd' argument:
976
     Py_DTST_FINITE
977
     Py_DTST_INFINITE
978
     Py_DTST_NAN
979
980
   Returns a PyMem_Malloc'd block of memory containing the resulting string,
981
    or NULL on error. If NULL is returned, the Python error has been set.
982
 */
983
984
static char *
985
format_float_short(double d, char format_code,
986
                   int mode, int precision,
987
                   int always_add_sign, int add_dot_0_if_integer,
988
                   int use_alt_formatting, int no_negative_zero,
989
                   const char * const *float_strings, int *type)
990
44.5k
{
991
44.5k
    char *buf = NULL;
992
44.5k
    char *p = NULL;
993
44.5k
    Py_ssize_t bufsize = 0;
994
44.5k
    char *digits, *digits_end;
995
44.5k
    int decpt_as_int, sign, exp_len, exp = 0, use_exp = 0;
996
44.5k
    Py_ssize_t decpt, digits_len, vdigits_start, vdigits_end;
997
44.5k
    _Py_SET_53BIT_PRECISION_HEADER;
998
999
    /* _Py_dg_dtoa returns a digit string (no decimal point or exponent).
1000
       Must be matched by a call to _Py_dg_freedtoa. */
1001
44.5k
    _Py_SET_53BIT_PRECISION_START;
1002
44.5k
    digits = _Py_dg_dtoa(d, mode, precision, &decpt_as_int, &sign,
1003
44.5k
                         &digits_end);
1004
44.5k
    _Py_SET_53BIT_PRECISION_END;
1005
1006
44.5k
    decpt = (Py_ssize_t)decpt_as_int;
1007
44.5k
    if (digits == NULL) {
1008
        /* The only failure mode is no memory. */
1009
0
        PyErr_NoMemory();
1010
0
        goto exit;
1011
0
    }
1012
44.5k
    assert(digits_end != NULL && digits_end >= digits);
1013
44.5k
    digits_len = digits_end - digits;
1014
1015
44.5k
    if (no_negative_zero && sign == 1 &&
1016
0
            (digits_len == 0 || (digits_len == 1 && digits[0] == '0'))) {
1017
0
        sign = 0;
1018
0
    }
1019
1020
44.5k
    if (digits_len && !Py_ISDIGIT(digits[0])) {
1021
        /* Infinities and nans here; adapt Gay's output,
1022
           so convert Infinity to inf and NaN to nan, and
1023
           ignore sign of nan. Then return. */
1024
1025
        /* ignore the actual sign of a nan */
1026
688
        if (digits[0] == 'n' || digits[0] == 'N')
1027
2
            sign = 0;
1028
1029
        /* We only need 5 bytes to hold the result "+inf\0" . */
1030
688
        bufsize = 5; /* Used later in an assert. */
1031
688
        buf = (char *)PyMem_Malloc(bufsize);
1032
688
        if (buf == NULL) {
1033
0
            PyErr_NoMemory();
1034
0
            goto exit;
1035
0
        }
1036
688
        p = buf;
1037
1038
688
        if (sign == 1) {
1039
0
            *p++ = '-';
1040
0
        }
1041
688
        else if (always_add_sign) {
1042
0
            *p++ = '+';
1043
0
        }
1044
688
        if (digits[0] == 'i' || digits[0] == 'I') {
1045
686
            strncpy(p, float_strings[OFS_INF], 3);
1046
686
            p += 3;
1047
1048
686
            if (type)
1049
0
                *type = Py_DTST_INFINITE;
1050
686
        }
1051
2
        else if (digits[0] == 'n' || digits[0] == 'N') {
1052
2
            strncpy(p, float_strings[OFS_NAN], 3);
1053
2
            p += 3;
1054
1055
2
            if (type)
1056
0
                *type = Py_DTST_NAN;
1057
2
        }
1058
0
        else {
1059
            /* shouldn't get here: Gay's code should always return
1060
               something starting with a digit, an 'I',  or 'N' */
1061
0
            Py_UNREACHABLE();
1062
0
        }
1063
688
        goto exit;
1064
688
    }
1065
1066
    /* The result must be finite (not inf or nan). */
1067
43.8k
    if (type)
1068
0
        *type = Py_DTST_FINITE;
1069
1070
1071
    /* We got digits back, format them.  We may need to pad 'digits'
1072
       either on the left or right (or both) with extra zeros, so in
1073
       general the resulting string has the form
1074
1075
         [<sign>]<zeros><digits><zeros>[<exponent>]
1076
1077
       where either of the <zeros> pieces could be empty, and there's a
1078
       decimal point that could appear either in <digits> or in the
1079
       leading or trailing <zeros>.
1080
1081
       Imagine an infinite 'virtual' string vdigits, consisting of the
1082
       string 'digits' (starting at index 0) padded on both the left and
1083
       right with infinite strings of zeros.  We want to output a slice
1084
1085
         vdigits[vdigits_start : vdigits_end]
1086
1087
       of this virtual string.  Thus if vdigits_start < 0 then we'll end
1088
       up producing some leading zeros; if vdigits_end > digits_len there
1089
       will be trailing zeros in the output.  The next section of code
1090
       determines whether to use an exponent or not, figures out the
1091
       position 'decpt' of the decimal point, and computes 'vdigits_start'
1092
       and 'vdigits_end'. */
1093
43.8k
    vdigits_end = digits_len;
1094
43.8k
    switch (format_code) {
1095
0
    case 'e':
1096
0
        use_exp = 1;
1097
0
        vdigits_end = precision;
1098
0
        break;
1099
90
    case 'f':
1100
90
        vdigits_end = decpt + precision;
1101
90
        break;
1102
0
    case 'g':
1103
0
        if (decpt <= -4 || decpt >
1104
0
            (add_dot_0_if_integer ? precision-1 : precision))
1105
0
            use_exp = 1;
1106
0
        if (use_alt_formatting)
1107
0
            vdigits_end = precision;
1108
0
        break;
1109
43.7k
    case 'r':
1110
        /* convert to exponential format at 1e16.  We used to convert
1111
           at 1e17, but that gives odd-looking results for some values
1112
           when a 16-digit 'shortest' repr is padded with bogus zeros.
1113
           For example, repr(2e16+8) would give 20000000000000010.0;
1114
           the true value is 20000000000000008.0. */
1115
43.7k
        if (decpt <= -4 || decpt > 16)
1116
21.4k
            use_exp = 1;
1117
43.7k
        break;
1118
0
    default:
1119
0
        PyErr_BadInternalCall();
1120
0
        goto exit;
1121
43.8k
    }
1122
1123
    /* if using an exponent, reset decimal point position to 1 and adjust
1124
       exponent accordingly.*/
1125
43.8k
    if (use_exp) {
1126
21.4k
        exp = (int)decpt - 1;
1127
21.4k
        decpt = 1;
1128
21.4k
    }
1129
    /* ensure vdigits_start < decpt <= vdigits_end, or vdigits_start <
1130
       decpt < vdigits_end if add_dot_0_if_integer and no exponent */
1131
43.8k
    vdigits_start = decpt <= 0 ? decpt-1 : 0;
1132
43.8k
    if (!use_exp && add_dot_0_if_integer)
1133
19.5k
        vdigits_end = vdigits_end > decpt ? vdigits_end : decpt + 1;
1134
24.2k
    else
1135
24.2k
        vdigits_end = vdigits_end > decpt ? vdigits_end : decpt;
1136
1137
    /* double check inequalities */
1138
43.8k
    assert(vdigits_start <= 0 &&
1139
43.8k
           0 <= digits_len &&
1140
43.8k
           digits_len <= vdigits_end);
1141
    /* decimal point should be in (vdigits_start, vdigits_end] */
1142
43.8k
    assert(vdigits_start < decpt && decpt <= vdigits_end);
1143
1144
    /* Compute an upper bound how much memory we need. This might be a few
1145
       chars too long, but no big deal. */
1146
43.8k
    bufsize =
1147
        /* sign, decimal point and trailing 0 byte */
1148
43.8k
        3 +
1149
1150
        /* total digit count (including zero padding on both sides) */
1151
43.8k
        (vdigits_end - vdigits_start) +
1152
1153
        /* exponent "e+100", max 3 numerical digits */
1154
43.8k
        (use_exp ? 5 : 0);
1155
1156
    /* Now allocate the memory and initialize p to point to the start of
1157
       it. */
1158
43.8k
    buf = (char *)PyMem_Malloc(bufsize);
1159
43.8k
    if (buf == NULL) {
1160
0
        PyErr_NoMemory();
1161
0
        goto exit;
1162
0
    }
1163
43.8k
    p = buf;
1164
1165
    /* Add a negative sign if negative, and a plus sign if non-negative
1166
       and always_add_sign is true. */
1167
43.8k
    if (sign == 1)
1168
10.8k
        *p++ = '-';
1169
33.0k
    else if (always_add_sign)
1170
0
        *p++ = '+';
1171
1172
    /* note that exactly one of the three 'if' conditions is true,
1173
       so we include exactly one decimal point */
1174
    /* Zero padding on left of digit string */
1175
43.8k
    if (decpt <= 0) {
1176
5.31k
        memset(p, '0', decpt-vdigits_start);
1177
5.31k
        p += decpt - vdigits_start;
1178
5.31k
        *p++ = '.';
1179
5.31k
        memset(p, '0', 0-decpt);
1180
5.31k
        p += 0-decpt;
1181
5.31k
    }
1182
38.5k
    else {
1183
38.5k
        memset(p, '0', 0-vdigits_start);
1184
38.5k
        p += 0 - vdigits_start;
1185
38.5k
    }
1186
1187
    /* Digits, with included decimal point */
1188
43.8k
    if (0 < decpt && decpt <= digits_len) {
1189
33.0k
        strncpy(p, digits, decpt-0);
1190
33.0k
        p += decpt-0;
1191
33.0k
        *p++ = '.';
1192
33.0k
        strncpy(p, digits+decpt, digits_len-decpt);
1193
33.0k
        p += digits_len-decpt;
1194
33.0k
    }
1195
10.8k
    else {
1196
10.8k
        strncpy(p, digits, digits_len);
1197
10.8k
        p += digits_len;
1198
10.8k
    }
1199
1200
    /* And zeros on the right */
1201
43.8k
    if (digits_len < decpt) {
1202
5.49k
        memset(p, '0', decpt-digits_len);
1203
5.49k
        p += decpt-digits_len;
1204
5.49k
        *p++ = '.';
1205
5.49k
        memset(p, '0', vdigits_end-decpt);
1206
5.49k
        p += vdigits_end-decpt;
1207
5.49k
    }
1208
38.3k
    else {
1209
38.3k
        memset(p, '0', vdigits_end-digits_len);
1210
38.3k
        p += vdigits_end-digits_len;
1211
38.3k
    }
1212
1213
    /* Delete a trailing decimal pt unless using alternative formatting. */
1214
43.8k
    if (p[-1] == '.' && !use_alt_formatting)
1215
18.8k
        p--;
1216
1217
    /* Now that we've done zero padding, add an exponent if needed. */
1218
43.8k
    if (use_exp) {
1219
21.4k
        *p++ = float_strings[OFS_E][0];
1220
21.4k
        exp_len = sprintf(p, "%+.02d", exp);
1221
21.4k
        p += exp_len;
1222
21.4k
    }
1223
44.5k
  exit:
1224
44.5k
    if (buf) {
1225
44.5k
        *p = '\0';
1226
        /* It's too late if this fails, as we've already stepped on
1227
           memory that isn't ours. But it's an okay debugging test. */
1228
44.5k
        assert(p-buf < bufsize);
1229
44.5k
    }
1230
44.5k
    if (digits)
1231
44.5k
        _Py_dg_freedtoa(digits);
1232
1233
44.5k
    return buf;
1234
43.8k
}
1235
1236
1237
char * PyOS_double_to_string(double val,
1238
                                         char format_code,
1239
                                         int precision,
1240
                                         int flags,
1241
                                         int *type)
1242
44.5k
{
1243
44.5k
    const char * const *float_strings = lc_float_strings;
1244
44.5k
    int mode;
1245
1246
44.5k
    if (precision > DOUBLE_TO_STRING_PRECISION_MAX
1247
44.5k
        || precision < -DOUBLE_TO_STRING_PRECISION_MAX)
1248
0
    {
1249
0
        PyErr_SetString(PyExc_ValueError, "precision too big");
1250
0
        return NULL;
1251
0
    }
1252
1253
    /* Validate format_code, and map upper and lower case. Compute the
1254
       mode and make any adjustments as needed. */
1255
44.5k
    switch (format_code) {
1256
    /* exponent */
1257
0
    case 'E':
1258
0
        float_strings = uc_float_strings;
1259
0
        format_code = 'e';
1260
0
        _Py_FALLTHROUGH;
1261
0
    case 'e':
1262
0
        mode = 2;
1263
0
        precision++;
1264
0
        break;
1265
1266
    /* fixed */
1267
0
    case 'F':
1268
0
        float_strings = uc_float_strings;
1269
0
        format_code = 'f';
1270
0
        _Py_FALLTHROUGH;
1271
90
    case 'f':
1272
90
        mode = 3;
1273
90
        break;
1274
1275
    /* general */
1276
0
    case 'G':
1277
0
        float_strings = uc_float_strings;
1278
0
        format_code = 'g';
1279
0
        _Py_FALLTHROUGH;
1280
0
    case 'g':
1281
0
        mode = 2;
1282
        /* precision 0 makes no sense for 'g' format; interpret as 1 */
1283
0
        if (precision == 0)
1284
0
            precision = 1;
1285
0
        break;
1286
1287
    /* repr format */
1288
44.4k
    case 'r':
1289
44.4k
        mode = 0;
1290
        /* Supplied precision is unused, must be 0. */
1291
44.4k
        if (precision != 0) {
1292
0
            PyErr_BadInternalCall();
1293
0
            return NULL;
1294
0
        }
1295
44.4k
        break;
1296
1297
44.4k
    default:
1298
0
        PyErr_BadInternalCall();
1299
0
        return NULL;
1300
44.5k
    }
1301
1302
44.5k
    return format_float_short(val, format_code, mode, precision,
1303
44.5k
                              flags & Py_DTSF_SIGN,
1304
44.5k
                              flags & Py_DTSF_ADD_DOT_0,
1305
44.5k
                              flags & Py_DTSF_ALT,
1306
44.5k
                              flags & Py_DTSF_NO_NEG_0,
1307
44.5k
                              float_strings, type);
1308
44.5k
}
1309
#endif  // _PY_SHORT_FLOAT_REPR == 1