Coverage Report

Created: 2026-01-10 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quickjs/dtoa.c
Line
Count
Source
1
/*
2
 * Tiny float64 printing and parsing library
3
 *
4
 * Copyright (c) 2024 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <stdarg.h>
27
#include <inttypes.h>
28
#include <string.h>
29
#include <assert.h>
30
#include <ctype.h>
31
#include <sys/time.h>
32
#include <math.h>
33
#include <setjmp.h>
34
35
#include "cutils.h"
36
#include "dtoa.h"
37
38
/* 
39
   TODO:
40
   - test n_digits=101 instead of 100
41
   - simplify subnormal handling
42
   - reduce max memory usage
43
   - free format: could add shortcut if exact result
44
   - use 64 bit limb_t when possible
45
   - use another algorithm for free format dtoa in base 10 (ryu ?)
46
*/
47
48
#define USE_POW5_TABLE
49
/* use fast path to print small integers in free format */
50
#define USE_FAST_INT
51
52
742k
#define LIMB_LOG2_BITS 5
53
54
742k
#define LIMB_BITS (1 << LIMB_LOG2_BITS)
55
56
typedef int32_t slimb_t;
57
typedef uint32_t limb_t;
58
typedef uint64_t dlimb_t;
59
60
#define LIMB_DIGITS 9
61
62
#define JS_RADIX_MAX 36
63
64
162k
#define DBIGNUM_LEN_MAX 52 /* ~ 2^(1072+53)*36^100 (dtoa) */
65
14.6k
#define MANT_LEN_MAX 18 /* < 36^100 */
66
67
typedef intptr_t mp_size_t;
68
69
/* the represented number is sum(i, tab[i]*2^(LIMB_BITS * i)) */
70
typedef struct {
71
    int len; /* >= 1 */
72
    limb_t tab[];
73
} mpb_t;
74
75
static limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n)
76
75
{
77
75
    size_t i;
78
75
    limb_t k, a;
79
80
75
    k=b;
81
150
    for(i=0;i<n;i++) {
82
150
        if (k == 0)
83
75
            break;
84
75
        a = tab[i] + k;
85
75
        k = (a < k);
86
75
        tab[i] = a;
87
75
    }
88
75
    return k;
89
75
}
90
91
/* tabr[] = taba[] * b + l. Return the high carry */
92
static limb_t mp_mul1(limb_t *tabr, const limb_t *taba, limb_t n, 
93
                      limb_t b, limb_t l)
94
332
{
95
332
    limb_t i;
96
332
    dlimb_t t;
97
98
900
    for(i = 0; i < n; i++) {
99
568
        t = (dlimb_t)taba[i] * (dlimb_t)b + l;
100
568
        tabr[i] = t;
101
568
        l = t >> LIMB_BITS;
102
568
    }
103
332
    return l;
104
332
}
105
106
/* WARNING: d must be >= 2^(LIMB_BITS-1) */
107
static inline limb_t udiv1norm_init(limb_t d)
108
0
{
109
0
    limb_t a0, a1;
110
0
    a1 = -d - 1;
111
0
    a0 = -1;
112
0
    return (((dlimb_t)a1 << LIMB_BITS) | a0) / d;
113
0
}
114
115
/* return the quotient and the remainder in '*pr'of 'a1*2^LIMB_BITS+a0
116
   / d' with 0 <= a1 < d. */
117
static inline limb_t udiv1norm(limb_t *pr, limb_t a1, limb_t a0,
118
                                limb_t d, limb_t d_inv)
119
88
{
120
88
    limb_t n1m, n_adj, q, r, ah;
121
88
    dlimb_t a;
122
88
    n1m = ((slimb_t)a0 >> (LIMB_BITS - 1));
123
88
    n_adj = a0 + (n1m & d);
124
88
    a = (dlimb_t)d_inv * (a1 - n1m) + n_adj;
125
88
    q = (a >> LIMB_BITS) + a1;
126
    /* compute a - q * r and update q so that the remainder is between
127
       0 and d - 1 */
128
88
    a = ((dlimb_t)a1 << LIMB_BITS) | a0;
129
88
    a = a - (dlimb_t)q * d - d;
130
88
    ah = a >> LIMB_BITS;
131
88
    q += 1 + ah;
132
88
    r = (limb_t)a + (ah & d);
133
88
    *pr = r;
134
88
    return q;
135
88
}
136
137
static limb_t mp_div1(limb_t *tabr, const limb_t *taba, limb_t n,
138
                      limb_t b, limb_t r)
139
10
{
140
10
    slimb_t i;
141
10
    dlimb_t a1;
142
25
    for(i = n - 1; i >= 0; i--) {
143
15
        a1 = ((dlimb_t)r << LIMB_BITS) | taba[i];
144
15
        tabr[i] = a1 / b;
145
15
        r = a1 % b;
146
15
    }
147
10
    return r;
148
10
}
149
150
/* r = (a + high*B^n) >> shift. Return the remainder r (0 <= r < 2^shift). 
151
   1 <= shift <= LIMB_BITS - 1 */
152
static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n, 
153
                     int shift, limb_t high)
154
118
{
155
118
    mp_size_t i;
156
118
    limb_t l, a;
157
158
118
    assert(shift >= 1 && shift < LIMB_BITS);
159
118
    l = high;
160
425
    for(i = n - 1; i >= 0; i--) {
161
307
        a = tab[i];
162
307
        tab_r[i] = (a >> shift) | (l << (LIMB_BITS - shift));
163
307
        l = a;
164
307
    }
165
118
    return l & (((limb_t)1 << shift) - 1);
166
118
}
167
168
/* r = (a << shift) + low. 1 <= shift <= LIMB_BITS - 1, 0 <= low <
169
   2^shift. */
170
static limb_t mp_shl(limb_t *tab_r, const limb_t *tab, mp_size_t n, 
171
              int shift, limb_t low)
172
148k
{
173
148k
    mp_size_t i;
174
148k
    limb_t l, a;
175
176
148k
    assert(shift >= 1 && shift < LIMB_BITS);
177
148k
    l = low;
178
296k
    for(i = 0; i < n; i++) {
179
148k
        a = tab[i];
180
148k
        tab_r[i] = (a << shift) | l;
181
148k
        l = (a >> (LIMB_BITS - shift)); 
182
148k
    }
183
148k
    return l;
184
148k
}
185
186
static no_inline limb_t mp_div1norm(limb_t *tabr, const limb_t *taba, limb_t n,
187
                                    limb_t b, limb_t r, limb_t b_inv, int shift)
188
26
{
189
26
    slimb_t i;
190
191
26
    if (shift != 0) {
192
26
        r = (r << shift) | mp_shl(tabr, taba, n, shift, 0);
193
26
    }
194
114
    for(i = n - 1; i >= 0; i--) {
195
88
        tabr[i] = udiv1norm(&r, r, taba[i], b, b_inv);
196
88
    }
197
26
    r >>= shift;
198
26
    return r;
199
26
}
200
201
static __maybe_unused void mpb_dump(const char *str, const mpb_t *a)
202
0
{
203
0
    int i;
204
0
    
205
0
    printf("%s= 0x", str);
206
0
    for(i = a->len - 1; i >= 0; i--) {
207
0
        printf("%08x", a->tab[i]);
208
0
        if (i != 0)
209
0
            printf("_");
210
0
    }
211
0
    printf("\n");
212
0
}
213
214
static void mpb_renorm(mpb_t *r)
215
148k
{
216
296k
    while (r->len > 1 && r->tab[r->len - 1] == 0)
217
148k
        r->len--;
218
148k
}
219
220
#ifdef USE_POW5_TABLE
221
static const uint32_t pow5_table[17] = {
222
    0x00000005, 0x00000019, 0x0000007d, 0x00000271, 
223
    0x00000c35, 0x00003d09, 0x0001312d, 0x0005f5e1, 
224
    0x001dcd65, 0x009502f9, 0x02e90edd, 0x0e8d4a51, 
225
    0x48c27395, 0x6bcc41e9, 0x1afd498d, 0x86f26fc1, 
226
    0xa2bc2ec5, 
227
};
228
229
static const uint8_t pow5h_table[4] = {
230
    0x00000001, 0x00000007, 0x00000023, 0x000000b1, 
231
};
232
233
static const uint32_t pow5_inv_table[13] = {
234
    0x99999999, 0x47ae147a, 0x0624dd2f, 0xa36e2eb1,
235
    0x4f8b588e, 0x0c6f7a0b, 0xad7f29ab, 0x5798ee23,
236
    0x12e0be82, 0xb7cdfd9d, 0x5fd7fe17, 0x19799812,
237
    0xc25c2684,
238
};
239
#endif
240
241
/* return a^b */
242
static uint64_t pow_ui(uint32_t a, uint32_t b)
243
148k
{
244
148k
    int i, n_bits;
245
148k
    uint64_t r;
246
148k
    if (b == 0)
247
0
        return 1;
248
148k
    if (b == 1)
249
88.2k
        return a;
250
59.9k
#ifdef USE_POW5_TABLE
251
59.9k
    if ((a == 5 || a == 10) && b <= 17) {
252
59.9k
        r = pow5_table[b - 1];
253
59.9k
        if (b >= 14) {
254
10
            r |= (uint64_t)pow5h_table[b - 14] << 32;
255
10
        }
256
59.9k
        if (a == 10)
257
59.9k
            r <<= b;
258
59.9k
        return r;
259
59.9k
    }
260
0
#endif
261
0
    r = a;
262
0
    n_bits = 32 - clz32(b);
263
0
    for(i = n_bits - 2; i >= 0; i--) {
264
0
        r *= r;
265
0
        if ((b >> i) & 1)
266
0
            r *= a;
267
0
    }
268
0
    return r;
269
59.9k
}
270
271
static uint32_t pow_ui_inv(uint32_t *pr_inv, int *pshift, uint32_t a, uint32_t b)
272
25
{
273
25
    uint32_t r_inv, r;
274
25
    int shift;
275
25
#ifdef USE_POW5_TABLE
276
25
    if (a == 5 && b >= 1 && b <= 13) {
277
25
        r = pow5_table[b - 1];
278
25
        shift = clz32(r);
279
25
        r <<= shift;
280
25
        r_inv = pow5_inv_table[b - 1];
281
25
    } else
282
0
#endif
283
0
    {
284
0
        r = pow_ui(a, b);
285
0
        shift = clz32(r);
286
0
        r <<= shift;
287
0
        r_inv = udiv1norm_init(r);
288
0
    }
289
25
    *pshift = shift;
290
25
    *pr_inv = r_inv;
291
25
    return r;
292
25
}
293
294
enum {
295
    JS_RNDN, /* round to nearest, ties to even */
296
    JS_RNDNA, /* round to nearest, ties away from zero */
297
    JS_RNDZ,
298
};
299
300
static int mpb_get_bit(const mpb_t *r, int k)
301
119
{
302
119
    int l;
303
    
304
119
    l = (unsigned)k / LIMB_BITS;
305
119
    k = k & (LIMB_BITS - 1);
306
119
    if (l >= r->len)
307
0
        return 0;
308
119
    else
309
119
        return (r->tab[l] >> k) & 1;
310
119
}
311
312
/* compute round(r / 2^shift). 'shift' can be negative */
313
static void mpb_shr_round(mpb_t *r, int shift, int rnd_mode)
314
148k
{
315
148k
    int l, i;
316
317
148k
    if (shift == 0)
318
22
        return;
319
148k
    if (shift < 0) {
320
148k
        shift = -shift;
321
148k
        l = (unsigned)shift / LIMB_BITS;
322
148k
        shift = shift & (LIMB_BITS - 1);
323
148k
        if (shift != 0) {
324
148k
            r->tab[r->len] = mp_shl(r->tab, r->tab, r->len, shift, 0);
325
148k
            r->len++;
326
148k
            mpb_renorm(r);
327
148k
        }
328
148k
        if (l > 0) {
329
295k
            for(i = r->len - 1; i >= 0; i--)
330
147k
                r->tab[i + l] = r->tab[i];
331
295k
            for(i = 0; i < l; i++)
332
147k
                r->tab[i] = 0;
333
147k
            r->len += l;
334
147k
        }
335
148k
    } else {
336
119
        limb_t bit1, bit2;
337
119
        int k, add_one;
338
        
339
119
        switch(rnd_mode) {
340
0
        default:
341
0
        case JS_RNDZ:
342
0
            add_one = 0;
343
0
            break;
344
119
        case JS_RNDN:
345
119
        case JS_RNDNA:
346
119
            bit1 = mpb_get_bit(r, shift - 1);
347
119
            if (bit1) {
348
75
                if (rnd_mode == JS_RNDNA) {
349
0
                    bit2 = 1;
350
75
                } else {
351
                    /* bit2 = oring of all the bits after bit1 */
352
75
                    bit2 = 0;
353
75
                    if (shift >= 2) {
354
75
                        k = shift - 1;
355
75
                        l = (unsigned)k / LIMB_BITS;
356
75
                        k = k & (LIMB_BITS - 1);
357
109
                        for(i = 0; i < min_int(l, r->len); i++)
358
34
                            bit2 |= r->tab[i];
359
75
                        if (l < r->len)
360
75
                            bit2 |= r->tab[l] & (((limb_t)1 << k) - 1);
361
75
                    }
362
75
                }
363
75
                if (bit2) {
364
75
                    add_one = 1;
365
75
                } else {
366
                    /* round to even */
367
0
                    add_one = mpb_get_bit(r, shift);
368
0
                }
369
75
            } else {
370
44
                add_one = 0;
371
44
            }
372
119
            break;
373
119
        }
374
375
119
        l = (unsigned)shift / LIMB_BITS;
376
119
        shift = shift & (LIMB_BITS - 1);
377
119
        if (l >= r->len) {
378
0
            r->len = 1;
379
0
            r->tab[0] = add_one;
380
119
        } else {
381
119
            if (l > 0) {
382
60
                r->len -= l;
383
215
                for(i = 0; i < r->len; i++)
384
155
                    r->tab[i] = r->tab[i + l];
385
60
            }
386
119
            if (shift != 0) {
387
118
                mp_shr(r->tab, r->tab, r->len, shift, 0);
388
118
                mpb_renorm(r);
389
118
            }
390
119
            if (add_one) {
391
75
                limb_t a;
392
75
                a = mp_add_ui(r->tab, 1, r->len);
393
75
                if (a)
394
0
                    r->tab[r->len++] = a;
395
75
            }
396
119
        }
397
119
    }
398
148k
}
399
400
/* return -1, 0 or 1 */
401
static int mpb_cmp(const mpb_t *a, const mpb_t *b)
402
0
{
403
0
    mp_size_t i;
404
0
    if (a->len < b->len)
405
0
        return -1;
406
0
    else if (a->len > b->len)
407
0
        return 1;
408
0
    for(i = a->len - 1; i >= 0; i--) {
409
0
        if (a->tab[i] != b->tab[i]) {
410
0
            if (a->tab[i] < b->tab[i])
411
0
                return -1;
412
0
            else
413
0
                return 1;
414
0
        }
415
0
    }
416
0
    return 0;
417
0
}
418
419
static void mpb_set_u64(mpb_t *r, uint64_t m)
420
30
{
421
#if LIMB_BITS == 64
422
    r->tab[0] = m;
423
    r->len = 1;
424
#else
425
30
    r->tab[0] = m;
426
30
    r->tab[1] = m >> LIMB_BITS;
427
30
    if (r->tab[1] == 0)
428
0
        r->len = 1;
429
30
    else
430
30
        r->len = 2;
431
30
#endif
432
30
}
433
434
static uint64_t mpb_get_u64(mpb_t *r)
435
148k
{
436
#if LIMB_BITS == 64
437
    return r->tab[0];
438
#else
439
148k
    if (r->len == 1) {
440
0
        return r->tab[0];
441
148k
    } else {
442
148k
        return r->tab[0] | ((uint64_t)r->tab[1] << LIMB_BITS);
443
148k
    }
444
148k
#endif
445
148k
}
446
447
/* floor_log2() = position of the first non zero bit or -1 if zero. */
448
static int mpb_floor_log2(mpb_t *a)
449
148k
{
450
148k
    limb_t v;
451
148k
    v = a->tab[a->len - 1];
452
148k
    if (v == 0)
453
0
        return -1;
454
148k
    else
455
148k
        return a->len * LIMB_BITS - 1 - clz32(v);
456
148k
}
457
458
5
#define MUL_LOG2_RADIX_BASE_LOG2 24
459
460
/* round((1 << MUL_LOG2_RADIX_BASE_LOG2)/log2(i + 2)) */
461
static const uint32_t mul_log2_radix_table[JS_RADIX_MAX - 1] = {
462
    0x000000, 0xa1849d, 0x000000, 0x6e40d2, 
463
    0x6308c9, 0x5b3065, 0x000000, 0x50c24e, 
464
    0x4d104d, 0x4a0027, 0x4768ce, 0x452e54, 
465
    0x433d00, 0x418677, 0x000000, 0x3ea16b, 
466
    0x3d645a, 0x3c43c2, 0x3b3b9a, 0x3a4899, 
467
    0x39680b, 0x3897b3, 0x37d5af, 0x372069, 
468
    0x367686, 0x35d6df, 0x354072, 0x34b261, 
469
    0x342bea, 0x33ac62, 0x000000, 0x32bfd9, 
470
    0x3251dd, 0x31e8d6, 0x318465,
471
};
472
473
/* return floor(a / log2(radix)) for -2048 <= a <= 2047 */
474
static int mul_log2_radix(int a, int radix)
475
5
{
476
5
    int radix_bits, mult;
477
478
5
    if ((radix & (radix - 1)) == 0) {
479
        /* if the radix is a power of two better to do it exactly */
480
0
        radix_bits = 31 - clz32(radix);
481
0
        if (a < 0)
482
0
            a -= radix_bits - 1;
483
0
        return a / radix_bits;
484
5
    } else {
485
5
        mult = mul_log2_radix_table[radix - 2];
486
5
        return ((int64_t)a * mult) >> MUL_LOG2_RADIX_BASE_LOG2;
487
5
    }
488
5
}
489
490
#if 0
491
static void build_mul_log2_radix_table(void)
492
{
493
    int base, radix, mult, col, base_log2;
494
495
    base_log2 = 24;
496
    base = 1 << base_log2;
497
    col = 0;
498
    for(radix = 2; radix <= 36; radix++) {
499
        if ((radix & (radix - 1)) == 0)
500
            mult = 0;
501
        else
502
            mult = lrint((double)base / log2(radix));
503
        printf("0x%06x, ", mult);
504
        if (++col == 4) {
505
            printf("\n");
506
            col = 0;
507
        }
508
    }
509
    printf("\n");
510
}
511
512
static void mul_log2_radix_test(void)
513
{
514
    int radix, i, ref, r;
515
    
516
    for(radix = 2; radix <= 36; radix++) {
517
        for(i = -2048; i <= 2047; i++) {
518
            ref = (int)floor((double)i / log2(radix));
519
            r = mul_log2_radix(i, radix);
520
            if (ref != r) {
521
                printf("ERROR: radix=%d i=%d r=%d ref=%d\n",
522
                       radix, i, r, ref);
523
                exit(1);
524
            }
525
        }
526
    }
527
    if (0)
528
        build_mul_log2_radix_table();
529
}
530
#endif
531
532
static void u32toa_len(char *buf, uint32_t n, size_t len)
533
10
{
534
10
    int digit, i;
535
95
    for(i = len - 1; i >= 0; i--) {
536
85
        digit = n % 10;
537
85
        n = n / 10;
538
85
        buf[i] = digit + '0';
539
85
    }
540
10
}
541
542
/* for power of 2 radixes. len >= 1 */
543
static void u64toa_bin_len(char *buf, uint64_t n, unsigned int radix_bits, int len)
544
0
{
545
0
    int digit, i;
546
0
    unsigned int mask;
547
548
0
    mask = (1 << radix_bits) - 1;
549
0
    for(i = len - 1; i >= 0; i--) {
550
0
        digit = n & mask;
551
0
        n >>= radix_bits;
552
0
        if (digit < 10)
553
0
            digit += '0';
554
0
        else
555
0
            digit += 'a' - 10;
556
0
        buf[i] = digit;
557
0
    }
558
0
}
559
560
/* len >= 1. 2 <= radix <= 36 */
561
static void limb_to_a(char *buf, limb_t n, unsigned int radix, int len)
562
10
{
563
10
    int digit, i;
564
565
10
    if (radix == 10) {
566
        /* specific case with constant divisor */
567
10
#if LIMB_BITS == 32
568
10
        u32toa_len(buf, n, len);
569
#else
570
        /* XXX: optimize */
571
        for(i = len - 1; i >= 0; i--) {
572
            digit = (limb_t)n % 10;
573
            n = (limb_t)n / 10;
574
            buf[i] = digit + '0';
575
        }
576
#endif
577
10
    } else {
578
0
        for(i = len - 1; i >= 0; i--) {
579
0
            digit = (limb_t)n % radix;
580
0
            n = (limb_t)n / radix;
581
0
            if (digit < 10)
582
0
                digit += '0';
583
0
            else
584
0
                digit += 'a' - 10;
585
0
            buf[i] = digit;
586
0
        }
587
0
    }
588
10
}
589
590
size_t u32toa(char *buf, uint32_t n)
591
289k
{
592
289k
    char buf1[10], *q;
593
289k
    size_t len;
594
    
595
289k
    q = buf1 + sizeof(buf1);
596
1.06M
    do {
597
1.06M
        *--q = n % 10 + '0';
598
1.06M
        n /= 10;
599
1.06M
    } while (n != 0);
600
289k
    len = buf1 + sizeof(buf1) - q;
601
289k
    memcpy(buf, q, len);
602
289k
    return len;
603
289k
}
604
605
size_t i32toa(char *buf, int32_t n)
606
71.9k
{
607
71.9k
    if (n >= 0) {
608
71.9k
        return u32toa(buf, n);
609
71.9k
    } else {
610
0
        buf[0] = '-';
611
0
        return u32toa(buf + 1, -(uint32_t)n) + 1;
612
0
    }
613
71.9k
}
614
615
#ifdef USE_FAST_INT
616
size_t u64toa(char *buf, uint64_t n)
617
129k
{
618
129k
    if (n < 0x100000000) {
619
129k
        return u32toa(buf, n);
620
129k
    } else {
621
0
        uint64_t n1;
622
0
        char *q = buf;
623
0
        uint32_t n2;
624
        
625
0
        n1 = n / 1000000000;
626
0
        n %= 1000000000;
627
0
        if (n1 >= 0x100000000) {
628
0
            n2 = n1 / 1000000000;
629
0
            n1 = n1 % 1000000000;
630
            /* at most two digits */
631
0
            if (n2 >= 10) {
632
0
                *q++ = n2 / 10 + '0';
633
0
                n2 %= 10;
634
0
            }
635
0
            *q++ = n2 + '0';
636
0
            u32toa_len(q, n1, 9);
637
0
            q += 9;
638
0
        } else {
639
0
            q += u32toa(q, n1);
640
0
        }
641
0
        u32toa_len(q, n, 9);
642
0
        q += 9;
643
0
        return q - buf;
644
0
    }
645
129k
}
646
647
size_t i64toa(char *buf, int64_t n)
648
0
{
649
0
    if (n >= 0) {
650
0
        return u64toa(buf, n);
651
0
    } else {
652
0
        buf[0] = '-';
653
0
        return u64toa(buf + 1, -(uint64_t)n) + 1;
654
0
    }
655
0
}
656
657
/* XXX: only tested for 1 <= n < 2^53 */
658
size_t u64toa_radix(char *buf, uint64_t n, unsigned int radix)
659
129k
{
660
129k
    int radix_bits, l;
661
129k
    if (likely(radix == 10))
662
129k
        return u64toa(buf, n);
663
0
    if ((radix & (radix - 1)) == 0) {
664
0
        radix_bits = 31 - clz32(radix);
665
0
        if (n == 0)
666
0
            l = 1;
667
0
        else
668
0
            l = (64 - clz64(n) + radix_bits - 1) / radix_bits;
669
0
        u64toa_bin_len(buf, n, radix_bits, l);
670
0
        return l;
671
0
    } else {
672
0
        char buf1[41], *q; /* maximum length for radix = 3 */
673
0
        size_t len;
674
0
        int digit;
675
0
        q = buf1 + sizeof(buf1);
676
0
        do {
677
0
            digit = n % radix;
678
0
            n /= radix;
679
0
            if (digit < 10)
680
0
                digit += '0';
681
0
            else
682
0
                digit += 'a' - 10;
683
0
            *--q = digit;
684
0
        } while (n != 0);
685
0
        len = buf1 + sizeof(buf1) - q;
686
0
        memcpy(buf, q, len);
687
0
        return len;
688
0
    }
689
0
}
690
691
size_t i64toa_radix(char *buf, int64_t n, unsigned int radix)
692
129k
{
693
129k
    if (n >= 0) {
694
129k
        return u64toa_radix(buf, n, radix);
695
129k
    } else {
696
176
        buf[0] = '-';
697
176
        return u64toa_radix(buf + 1, -(uint64_t)n, radix) + 1;
698
176
    }
699
129k
}
700
#endif /* USE_FAST_INT */
701
702
static const uint8_t digits_per_limb_table[JS_RADIX_MAX - 1] = {
703
#if LIMB_BITS == 32
704
32,20,16,13,12,11,10,10, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
705
#else
706
64,40,32,27,24,22,21,20,19,18,17,17,16,16,16,15,15,15,14,14,14,14,13,13,13,13,13,13,13,12,12,12,12,12,12,
707
#endif
708
};
709
710
static const uint32_t radix_base_table[JS_RADIX_MAX - 1] = {
711
 0x00000000, 0xcfd41b91, 0x00000000, 0x48c27395,
712
 0x81bf1000, 0x75db9c97, 0x40000000, 0xcfd41b91,
713
 0x3b9aca00, 0x8c8b6d2b, 0x19a10000, 0x309f1021,
714
 0x57f6c100, 0x98c29b81, 0x00000000, 0x18754571,
715
 0x247dbc80, 0x3547667b, 0x4c4b4000, 0x6b5a6e1d,
716
 0x94ace180, 0xcaf18367, 0x0b640000, 0x0e8d4a51,
717
 0x1269ae40, 0x17179149, 0x1cb91000, 0x23744899,
718
 0x2b73a840, 0x34e63b41, 0x40000000, 0x4cfa3cc1,
719
 0x5c13d840, 0x6d91b519, 0x81bf1000,
720
};
721
722
/* XXX: remove the table ? */
723
static uint8_t dtoa_max_digits_table[JS_RADIX_MAX - 1] = {
724
    54, 35, 28, 24, 22, 20, 19, 18, 17, 17, 16, 16, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12,
725
};
726
727
/* we limit the maximum number of significant digits for atod to about
728
   128 bits of precision for non power of two bases. The only
729
   requirement for Javascript is at least 20 digits in base 10. For
730
   power of two bases, we do an exact rounding in all the cases. */
731
static uint8_t atod_max_digits_table[JS_RADIX_MAX - 1] = {
732
     64, 80, 32, 55, 49, 45, 21, 40, 38, 37, 35, 34, 33, 32, 16, 31, 30, 30, 29, 29, 28, 28, 27, 27, 27, 26, 26, 26, 26, 25, 12, 25, 25, 24, 24,
733
};
734
735
/* if abs(d) >= B^max_exponent, it is an overflow */
736
static const int16_t max_exponent[JS_RADIX_MAX - 1] = {
737
 1024,   647,   512,   442,   397,   365,   342,   324, 
738
  309,   297,   286,   277,   269,   263,   256,   251, 
739
  246,   242,   237,   234,   230,   227,   224,   221, 
740
  218,   216,   214,   211,   209,   207,   205,   203, 
741
  202,   200,   199, 
742
};
743
744
/* if abs(d) <= B^min_exponent, it is an underflow */
745
static const int16_t min_exponent[JS_RADIX_MAX - 1] = {
746
-1075,  -679,  -538,  -463,  -416,  -383,  -359,  -340, 
747
 -324,  -311,  -300,  -291,  -283,  -276,  -269,  -263, 
748
 -258,  -254,  -249,  -245,  -242,  -238,  -235,  -232, 
749
 -229,  -227,  -224,  -222,  -220,  -217,  -215,  -214, 
750
 -212,  -210,  -208, 
751
};
752
753
#if 0
754
void build_tables(void)
755
{
756
    int r, j, radix, n, col, i;
757
    
758
    /* radix_base_table */
759
    for(radix = 2; radix <= 36; radix++) {
760
        r = 1;
761
        for(j = 0; j < digits_per_limb_table[radix - 2]; j++) {
762
            r *= radix;
763
        }
764
        printf(" 0x%08x,", r);
765
        if ((radix % 4) == 1)
766
            printf("\n");
767
    }
768
    printf("\n");
769
770
    /* dtoa_max_digits_table */
771
    for(radix = 2; radix <= 36; radix++) {
772
        /* Note: over estimated when the radix is a power of two */
773
        printf(" %d,", 1 + (int)ceil(53.0 / log2(radix)));
774
    }
775
    printf("\n");
776
777
    /* atod_max_digits_table */
778
    for(radix = 2; radix <= 36; radix++) {
779
        if ((radix & (radix - 1)) == 0) {
780
            /* 64 bits is more than enough */
781
            n = (int)floor(64.0 / log2(radix));
782
        } else {
783
            n = (int)floor(128.0 / log2(radix));
784
        }
785
        printf(" %d,", n);
786
    }
787
    printf("\n");
788
789
    printf("static const int16_t max_exponent[JS_RADIX_MAX - 1] = {\n");
790
    col = 0;
791
    for(radix = 2; radix <= 36; radix++) {
792
        printf("%5d, ", (int)ceil(1024 / log2(radix)));
793
        if (++col == 8) {
794
            col = 0;
795
            printf("\n");
796
        }
797
    }
798
    printf("\n};\n\n");
799
800
    printf("static const int16_t min_exponent[JS_RADIX_MAX - 1] = {\n");
801
    col = 0; 
802
    for(radix = 2; radix <= 36; radix++) {
803
        printf("%5d, ", (int)floor(-1075 / log2(radix)));
804
        if (++col == 8) {
805
            col = 0;
806
            printf("\n");
807
        }
808
    }
809
    printf("\n};\n\n");
810
811
    printf("static const uint32_t pow5_table[16] = {\n");
812
    col = 0; 
813
    for(i = 2; i <= 17; i++) {
814
        r = 1;
815
        for(j = 0; j < i; j++) {
816
            r *= 5;
817
        }
818
        printf("0x%08x, ", r);
819
        if (++col == 4) {
820
            col = 0;
821
            printf("\n");
822
        }
823
    }
824
    printf("\n};\n\n");
825
826
    /* high part */
827
    printf("static const uint8_t pow5h_table[4] = {\n");
828
    col = 0; 
829
    for(i = 14; i <= 17; i++) {
830
        uint64_t r1;
831
        r1 = 1;
832
        for(j = 0; j < i; j++) {
833
            r1 *= 5;
834
        }
835
        printf("0x%08x, ", (uint32_t)(r1 >> 32));
836
        if (++col == 4) {
837
            col = 0;
838
            printf("\n");
839
        }
840
    }
841
    printf("\n};\n\n");
842
}
843
#endif
844
845
/* n_digits >= 1. 0 <= dot_pos <= n_digits. If dot_pos == n_digits,
846
   the dot is not displayed. 'a' is modified. */
847
static int output_digits(char *buf,
848
                         mpb_t *a, int radix, int n_digits1,
849
                         int dot_pos)
850
5
{
851
5
    int n_digits, digits_per_limb, radix_bits, n, len;
852
853
5
    n_digits = n_digits1;
854
5
    if ((radix & (radix - 1)) == 0) {
855
        /* radix = 2^radix_bits */
856
0
        radix_bits = 31 - clz32(radix);
857
5
    } else {
858
5
        radix_bits = 0;
859
5
    }
860
5
    digits_per_limb = digits_per_limb_table[radix - 2];
861
5
    if (radix_bits != 0) {
862
0
        for(;;) {
863
0
            n = min_int(n_digits, digits_per_limb);
864
0
            n_digits -= n;
865
0
            u64toa_bin_len(buf + n_digits, a->tab[0], radix_bits, n);
866
0
            if (n_digits == 0)
867
0
                break;
868
0
            mpb_shr_round(a, digits_per_limb * radix_bits, JS_RNDZ);
869
0
        }
870
5
    } else {
871
5
        limb_t r;
872
15
        while (n_digits != 0) {
873
10
            n = min_int(n_digits, digits_per_limb);
874
10
            n_digits -= n;
875
10
            r = mp_div1(a->tab, a->tab, a->len, radix_base_table[radix - 2], 0);
876
10
            mpb_renorm(a);
877
10
            limb_to_a(buf + n_digits, r, radix, n);
878
10
        }
879
5
    }
880
881
    /* add the dot */
882
5
    len = n_digits1;
883
5
    if (dot_pos != n_digits1) {
884
5
        memmove(buf + dot_pos + 1, buf + dot_pos, n_digits1 - dot_pos);
885
5
        buf[dot_pos] = '.';
886
5
        len++;
887
5
    }
888
5
    return len;
889
5
}
890
891
/* return (a, e_offset) such that a = a * (radix1*2^radix_shift)^f *
892
   2^-e_offset. 'f' can be negative. */
893
static int mul_pow(mpb_t *a, int radix1, int radix_shift, int f, BOOL is_int, int e)
894
148k
{
895
148k
    int e_offset, d, n, n0;
896
897
148k
    e_offset = -f * radix_shift;
898
148k
    if (radix1 != 1) {
899
148k
        d = digits_per_limb_table[radix1 - 2];
900
148k
        if (f >= 0) {
901
148k
            limb_t h, b;
902
            
903
148k
            b = 0;
904
148k
            n0 = 0;
905
148k
            while (f != 0) {
906
20
                n = min_int(f, d);
907
20
                if (n != n0) {
908
20
                    b = pow_ui(radix1, n);
909
20
                    n0 = n;
910
20
                }
911
20
                h = mp_mul1(a->tab, a->tab, a->len, b, 0);
912
20
                if (h != 0) {
913
0
                    a->tab[a->len++] = h;
914
0
                }
915
20
                f -= n;
916
20
            }
917
148k
        } else {
918
24
            int extra_bits, l, shift;
919
24
            limb_t r, rem, b, b_inv;
920
            
921
24
            f = -f;
922
24
            l = (f + d - 1) / d; /* high bound for the number of limbs (XXX: make it better) */
923
24
            e_offset += l * LIMB_BITS;
924
24
            if (!is_int) {
925
                /* at least 'e' bits are needed in the final result for rounding */
926
24
                extra_bits = max_int(e - mpb_floor_log2(a), 0);
927
24
            } else {
928
                /* at least two extra bits are needed in the final result
929
                   for rounding */
930
0
                extra_bits = max_int(2 + e - e_offset, 0);
931
0
            }
932
24
            e_offset += extra_bits;
933
24
            mpb_shr_round(a, -(l * LIMB_BITS + extra_bits), JS_RNDZ);
934
            
935
24
            b = 0;
936
24
            b_inv = 0;
937
24
            shift = 0;
938
24
            n0 = 0;
939
24
            rem = 0;
940
50
            while (f != 0) {
941
26
                n = min_int(f, d);
942
26
                if (n != n0) {
943
25
                    b = pow_ui_inv(&b_inv, &shift, radix1, n);
944
25
                    n0 = n;
945
25
                }
946
26
                r = mp_div1norm(a->tab, a->tab, a->len, b, 0, b_inv, shift);
947
26
                rem |= r;
948
26
                mpb_renorm(a);
949
26
                f -= n;
950
26
            }
951
            /* if the remainder is non zero, use it for rounding */
952
24
            a->tab[0] |= (rem != 0);
953
24
        }
954
148k
    }
955
148k
    return e_offset;
956
148k
}
957
958
/* tmp1 = round(m*2^e*radix^f). 'tmp0' is a temporary storage */
959
static void mul_pow_round(mpb_t *tmp1, uint64_t m, int e, int radix1, int radix_shift, int f,
960
                          int rnd_mode)
961
20
{
962
20
    int e_offset;
963
964
20
    mpb_set_u64(tmp1, m);
965
20
    e_offset = mul_pow(tmp1, radix1, radix_shift, f, TRUE, e);
966
20
    mpb_shr_round(tmp1, -e + e_offset, rnd_mode);
967
20
}
968
969
/* return round(a*2^e_offset) rounded as a float64. 'a' is modified */
970
static uint64_t round_to_d(int *pe, mpb_t *a, int e_offset, int rnd_mode)
971
148k
{
972
148k
    int e;
973
148k
    uint64_t m;
974
975
148k
    if (a->tab[0] == 0 && a->len == 1) {
976
        /* zero result */
977
0
        m = 0;
978
0
        e = 0; /* don't care */
979
148k
    } else {
980
148k
        int prec, prec1, e_min;
981
148k
        e = mpb_floor_log2(a) + 1 - e_offset;
982
148k
        prec1 = 53;
983
148k
        e_min = -1021;
984
148k
        if (e < e_min) {
985
            /* subnormal result or zero */
986
0
            prec = prec1 - (e_min - e);
987
148k
        } else {
988
148k
            prec = prec1;
989
148k
        }
990
148k
        mpb_shr_round(a, e + e_offset - prec, rnd_mode);
991
148k
        m = mpb_get_u64(a);
992
148k
        m <<= (53 - prec);
993
        /* mantissa overflow due to rounding */
994
148k
        if (m >= (uint64_t)1 << 53) {
995
0
            m >>= 1;
996
0
            e++;
997
0
        }
998
148k
    }
999
148k
    *pe = e;
1000
148k
    return m;
1001
148k
}
1002
1003
/* return (m, e) such that m*2^(e-53) = round(a * radix^f) with 2^52
1004
   <= m < 2^53 or m = 0.
1005
   'a' is modified. */
1006
static uint64_t mul_pow_round_to_d(int *pe, mpb_t *a,
1007
                                   int radix1, int radix_shift, int f, int rnd_mode)
1008
148k
{
1009
148k
    int e_offset;
1010
1011
148k
    e_offset = mul_pow(a, radix1, radix_shift, f, FALSE, 55);
1012
148k
    return round_to_d(pe, a, e_offset, rnd_mode);
1013
148k
}
1014
1015
#ifdef JS_DTOA_DUMP_STATS
1016
static int out_len_count[17];
1017
1018
void js_dtoa_dump_stats(void)
1019
{
1020
    int i, sum;
1021
    sum = 0;
1022
    for(i = 0; i < 17; i++)
1023
        sum += out_len_count[i];
1024
    for(i = 0; i < 17; i++) {
1025
        printf("%2d %8d %5.2f%%\n",
1026
               i + 1, out_len_count[i], (double)out_len_count[i] / sum * 100);
1027
    }
1028
}
1029
#endif
1030
1031
/* return a maximum bound of the string length. The bound depends on
1032
   'd' only if format = JS_DTOA_FORMAT_FRAC or if JS_DTOA_EXP_DISABLED
1033
   is enabled. */
1034
int js_dtoa_max_len(double d, int radix, int n_digits, int flags)
1035
14.6k
{
1036
14.6k
    int fmt = flags & JS_DTOA_FORMAT_MASK;
1037
14.6k
    int n, e;
1038
14.6k
    uint64_t a;
1039
1040
14.6k
    if (fmt != JS_DTOA_FORMAT_FRAC) {
1041
14.6k
        if (fmt == JS_DTOA_FORMAT_FREE) {
1042
14.6k
            n = dtoa_max_digits_table[radix - 2];
1043
14.6k
        } else {
1044
0
            n = n_digits;
1045
0
        }
1046
14.6k
        if ((flags & JS_DTOA_EXP_MASK) == JS_DTOA_EXP_DISABLED) {
1047
            /* no exponential */
1048
0
            a = float64_as_uint64(d);
1049
0
            e = (a >> 52) & 0x7ff;
1050
0
            if (e == 0x7ff) {
1051
                /* NaN, Infinity */
1052
0
                n = 0;
1053
0
            } else {
1054
0
                e -= 1023;
1055
                /* XXX: adjust */
1056
0
                n += 10 + abs(mul_log2_radix(e - 1, radix));
1057
0
            }
1058
14.6k
        } else {
1059
            /* extra: sign, 1 dot and exponent "e-1000" */
1060
14.6k
            n += 1 + 1 + 6;
1061
14.6k
        }
1062
14.6k
    } else {
1063
0
        a = float64_as_uint64(d);
1064
0
        e = (a >> 52) & 0x7ff;
1065
0
        if (e == 0x7ff) {
1066
            /* NaN, Infinity */
1067
0
            n = 0;
1068
0
        } else {
1069
            /* high bound for the integer part */
1070
0
            e -= 1023;
1071
            /* x < 2^(e + 1) */
1072
0
            if (e < 0) {
1073
0
                n = 1;
1074
0
            } else {
1075
0
                n = 2 + mul_log2_radix(e - 1, radix);
1076
0
            }
1077
            /* sign, extra digit, 1 dot */
1078
0
            n += 1 + 1 + 1 + n_digits;
1079
0
        }
1080
0
    }
1081
14.6k
    return max_int(n, 9); /* also include NaN and [-]Infinity */
1082
14.6k
}
1083
1084
#if defined(__SANITIZE_ADDRESS__) && 0
1085
static void *dtoa_malloc(uint64_t **pptr, size_t size)
1086
{
1087
    return malloc(size);
1088
}
1089
static void dtoa_free(void *ptr)
1090
{
1091
    free(ptr);
1092
}
1093
#else
1094
static void *dtoa_malloc(uint64_t **pptr, size_t size)
1095
177k
{
1096
177k
    void *ret;
1097
177k
    ret = *pptr;
1098
177k
    *pptr += (size + 7) / 8;
1099
177k
    return ret;
1100
177k
}
1101
1102
static void dtoa_free(void *ptr)
1103
177k
{
1104
177k
}
1105
#endif
1106
1107
/* return the length */
1108
int js_dtoa(char *buf, double d, int radix, int n_digits, int flags,
1109
            JSDTOATempMem *tmp_mem)
1110
14.6k
{
1111
14.6k
    uint64_t a, m, *mptr = tmp_mem->mem;
1112
14.6k
    int e, sgn, l, E, P, i, E_max, radix1, radix_shift;
1113
14.6k
    char *q;
1114
14.6k
    mpb_t *tmp1, *mant_max;
1115
14.6k
    int fmt = flags & JS_DTOA_FORMAT_MASK;
1116
1117
14.6k
    tmp1 = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * DBIGNUM_LEN_MAX);
1118
14.6k
    mant_max = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * MANT_LEN_MAX);
1119
14.6k
    assert((mptr - tmp_mem->mem) <= sizeof(JSDTOATempMem) / sizeof(mptr[0]));
1120
1121
14.6k
    radix_shift = ctz32(radix);
1122
14.6k
    radix1 = radix >> radix_shift;
1123
14.6k
    a = float64_as_uint64(d);
1124
14.6k
    sgn = a >> 63;
1125
14.6k
    e = (a >> 52) & 0x7ff;
1126
14.6k
    m = a & (((uint64_t)1 << 52) - 1);
1127
14.6k
    q = buf;
1128
14.6k
    if (e == 0x7ff) {
1129
14.6k
        if (m == 0) {
1130
0
            if (sgn)
1131
0
                *q++ = '-';
1132
0
            memcpy(q, "Infinity", 8);
1133
0
            q += 8;
1134
14.6k
        } else {
1135
14.6k
            memcpy(q, "NaN", 3);
1136
14.6k
            q += 3;
1137
14.6k
        }
1138
14.6k
        goto done;
1139
14.6k
    } else if (e == 0) {
1140
0
        if (m == 0) {
1141
0
            tmp1->len = 1;
1142
0
            tmp1->tab[0] = 0;
1143
0
            E = 1;
1144
0
            if (fmt == JS_DTOA_FORMAT_FREE)
1145
0
                P = 1;
1146
0
            else if (fmt == JS_DTOA_FORMAT_FRAC)
1147
0
                P = n_digits + 1;
1148
0
            else
1149
0
                P = n_digits;
1150
            /* "-0" is displayed as "0" if JS_DTOA_MINUS_ZERO is not present */
1151
0
            if (sgn && (flags & JS_DTOA_MINUS_ZERO))
1152
0
                *q++ = '-';
1153
0
            goto output;
1154
0
        }
1155
        /* denormal number: convert to a normal number */
1156
0
        l = clz64(m) - 11;
1157
0
        e -= l - 1;
1158
0
        m <<= l;
1159
5
    } else {
1160
5
        m |= (uint64_t)1 << 52;
1161
5
    }
1162
5
    if (sgn)
1163
0
        *q++ = '-';
1164
    /* remove the bias */
1165
5
    e -= 1022;
1166
    /* d = 2^(e-53)*m */
1167
    //    printf("m=0x%016" PRIx64 " e=%d\n", m, e);
1168
5
#ifdef USE_FAST_INT
1169
5
    if (fmt == JS_DTOA_FORMAT_FREE &&
1170
5
        e >= 1 && e <= 53 &&
1171
5
        (m & (((uint64_t)1 << (53 - e)) - 1)) == 0 &&
1172
0
        (flags & JS_DTOA_EXP_MASK) != JS_DTOA_EXP_ENABLED) {
1173
0
        m >>= 53 - e;
1174
        /* 'm' is never zero */
1175
0
        q += u64toa_radix(q, m, radix);
1176
0
        goto done;
1177
0
    }
1178
5
#endif
1179
    
1180
    /* this choice of E implies F=round(x*B^(P-E) is such as: 
1181
       B^(P-1) <= F < 2.B^P. */
1182
5
    E = 1 + mul_log2_radix(e - 1, radix);
1183
    
1184
5
    if (fmt == JS_DTOA_FORMAT_FREE) {
1185
5
        int P_max, E0, e1, E_found, P_found;
1186
5
        uint64_t m1, mant_found, mant, mant_max1;
1187
        /* P_max is guarranteed to work by construction */
1188
5
        P_max = dtoa_max_digits_table[radix - 2];
1189
5
        E0 = E;
1190
5
        E_found = 0;
1191
5
        P_found = 0;
1192
5
        mant_found = 0;
1193
        /* find the minimum number of digits by successive tries */
1194
5
        P = P_max; /* P_max is guarateed to work */
1195
10
        for(;;) {
1196
            /* mant_max always fits on 64 bits */
1197
10
            mant_max1 = pow_ui(radix, P);
1198
            /* compute the mantissa in base B */
1199
10
            E = E0;
1200
20
            for(;;) {
1201
                /* XXX: add inexact flag */
1202
20
                mul_pow_round(tmp1, m, e - 53, radix1, radix_shift, P - E, JS_RNDN);
1203
20
                mant = mpb_get_u64(tmp1);
1204
20
                if (mant < mant_max1)
1205
10
                    break;
1206
10
                E++; /* at most one iteration is possible */
1207
10
            }
1208
            /* remove useless trailing zero digits */
1209
10
            while ((mant % radix) == 0) {
1210
0
                mant /= radix;
1211
0
                P--;
1212
0
            }
1213
            /* garanteed to work for P = P_max */
1214
10
            if (P_found == 0)
1215
5
                goto prec_found;
1216
            /* convert back to base 2 */
1217
5
            mpb_set_u64(tmp1, mant);
1218
5
            m1 = mul_pow_round_to_d(&e1, tmp1, radix1, radix_shift, E - P, JS_RNDN);
1219
            //            printf("P=%2d: m=0x%016" PRIx64 " e=%d m1=0x%016" PRIx64 " e1=%d\n", P, m, e, m1, e1);
1220
            /* Note: (m, e) is never zero here, so the exponent for m1
1221
               = 0 does not matter */
1222
5
            if (m1 == m && e1 == e) {
1223
5
            prec_found:
1224
5
                P_found = P;
1225
5
                E_found = E;
1226
5
                mant_found = mant;
1227
5
                if (P == 1)
1228
0
                    break;
1229
5
                P--; /* try lower exponent */
1230
5
            } else {
1231
5
                break;
1232
5
            }
1233
5
        }
1234
5
        P = P_found;
1235
5
        E = E_found;
1236
5
        mpb_set_u64(tmp1, mant_found);
1237
#ifdef JS_DTOA_DUMP_STATS
1238
        if (radix == 10) {
1239
            out_len_count[P - 1]++;
1240
        }
1241
#endif        
1242
5
    } else if (fmt == JS_DTOA_FORMAT_FRAC) {
1243
0
        int len;
1244
1245
0
        assert(n_digits >= 0 && n_digits <= JS_DTOA_MAX_DIGITS);
1246
        /* P = max_int(E, 1) + n_digits; */
1247
        /* frac is rounded using RNDNA */
1248
0
        mul_pow_round(tmp1, m, e - 53, radix1, radix_shift, n_digits, JS_RNDNA);
1249
1250
        /* we add one extra digit on the left and remove it if needed
1251
           to avoid testing if the result is < radix^P */
1252
0
        len = output_digits(q, tmp1, radix, max_int(E + 1, 1) + n_digits,
1253
0
                            max_int(E + 1, 1));
1254
0
        if (q[0] == '0' && len >= 2 && q[1] != '.') {
1255
0
            len--;
1256
0
            memmove(q, q + 1, len);
1257
0
        }
1258
0
        q += len;
1259
0
        goto done;
1260
0
    } else {
1261
0
        int pow_shift;
1262
0
        assert(n_digits >= 1 && n_digits <= JS_DTOA_MAX_DIGITS);
1263
0
        P = n_digits;
1264
        /* mant_max = radix^P */
1265
0
        mant_max->len = 1;
1266
0
        mant_max->tab[0] = 1;
1267
0
        pow_shift = mul_pow(mant_max, radix1, radix_shift, P, FALSE, 0);
1268
0
        mpb_shr_round(mant_max, pow_shift, JS_RNDZ);
1269
        
1270
0
        for(;;) {
1271
            /* fixed and frac are rounded using RNDNA */
1272
0
            mul_pow_round(tmp1, m, e - 53, radix1, radix_shift, P - E, JS_RNDNA);
1273
0
            if (mpb_cmp(tmp1, mant_max) < 0)
1274
0
                break;
1275
0
            E++; /* at most one iteration is possible */
1276
0
        }
1277
0
    }
1278
5
 output:
1279
5
    if (fmt == JS_DTOA_FORMAT_FIXED)
1280
0
        E_max = n_digits;
1281
5
    else
1282
5
        E_max = dtoa_max_digits_table[radix - 2] + 4;
1283
5
    if ((flags & JS_DTOA_EXP_MASK) == JS_DTOA_EXP_ENABLED ||
1284
5
        ((flags & JS_DTOA_EXP_MASK) == JS_DTOA_EXP_AUTO && (E <= -6 || E > E_max))) {
1285
0
        q += output_digits(q, tmp1, radix, P, 1);
1286
0
        E--;
1287
0
        if (radix == 10) {
1288
0
            *q++ = 'e';
1289
0
        } else if (radix1 == 1 && radix_shift <= 4) {
1290
0
            E *= radix_shift;
1291
0
            *q++ = 'p';
1292
0
        } else {
1293
0
            *q++ = '@';
1294
0
        }
1295
0
        if (E < 0) {
1296
0
            *q++ = '-';
1297
0
            E = -E;
1298
0
        } else {
1299
0
            *q++ = '+';
1300
0
        }
1301
0
        q += u32toa(q, E);
1302
5
    } else if (E <= 0) {
1303
0
        *q++ = '0';
1304
0
        *q++ = '.';
1305
0
        for(i = 0; i < -E; i++)
1306
0
            *q++ = '0';
1307
0
        q += output_digits(q, tmp1, radix, P, P);
1308
5
    } else {
1309
5
        q += output_digits(q, tmp1, radix, P, min_int(P, E));
1310
5
        for(i = 0; i < E - P; i++)
1311
0
            *q++ = '0';
1312
5
    }
1313
14.6k
 done:
1314
14.6k
    *q = '\0';
1315
14.6k
    dtoa_free(mant_max);
1316
14.6k
    dtoa_free(tmp1);
1317
14.6k
    return q - buf;
1318
5
}
1319
1320
static inline int to_digit(int c)
1321
8.04M
{
1322
8.04M
    if (c >= '0' && c <= '9')
1323
5.28M
        return c - '0';
1324
2.76M
    else if (c >= 'A' && c <= 'Z')
1325
13
        return c - 'A' + 10;
1326
2.76M
    else if (c >= 'a' && c <= 'z')
1327
2.61M
        return c - 'a' + 10;
1328
148k
    else
1329
148k
        return 36;
1330
8.04M
}
1331
1332
/* r = r * radix_base + a. radix_base = 0 means radix_base = 2^32 */
1333
static void mpb_mul1_base(mpb_t *r, limb_t radix_base, limb_t a)
1334
148k
{
1335
148k
    int i;
1336
148k
    if (r->tab[0] == 0 && r->len == 1) {
1337
148k
        r->tab[0] = a;
1338
148k
    } else {
1339
315
        if (radix_base == 0) {
1340
9
            for(i = r->len; i >= 0; i--) {
1341
6
                r->tab[i + 1] = r->tab[i];
1342
6
            }
1343
3
            r->tab[0] = a;
1344
312
        } else {
1345
312
            r->tab[r->len] = mp_mul1(r->tab, r->tab, r->len,
1346
312
                                     radix_base, a);
1347
312
        }
1348
315
        r->len++;
1349
315
        mpb_renorm(r);
1350
315
    }
1351
148k
}
1352
1353
/* XXX: add fast path for small integers */
1354
double js_atod(const char *str, const char **pnext, int radix, int flags,
1355
               JSATODTempMem *tmp_mem)
1356
148k
{
1357
148k
    uint64_t *mptr = tmp_mem->mem;
1358
148k
    const char *p, *p_start;
1359
148k
    limb_t cur_limb, radix_base, extra_digits;
1360
148k
    int is_neg, digit_count, limb_digit_count, digits_per_limb, sep, radix1, radix_shift;
1361
148k
    int radix_bits, expn, e, max_digits, expn_offset, dot_pos, sig_pos, pos;
1362
148k
    mpb_t *tmp0;
1363
148k
    double dval;
1364
148k
    BOOL is_bin_exp, is_zero, expn_overflow;
1365
148k
    uint64_t m, a;
1366
1367
148k
    tmp0 = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * DBIGNUM_LEN_MAX);
1368
148k
    assert((mptr - tmp_mem->mem) <= sizeof(JSATODTempMem) / sizeof(mptr[0]));
1369
    /* optional separator between digits */
1370
148k
    sep = (flags & JS_ATOD_ACCEPT_UNDERSCORES) ? '_' : 256;
1371
1372
148k
    p = str;
1373
148k
    is_neg = 0;
1374
148k
    if (p[0] == '+') {
1375
0
        p++;
1376
0
        p_start = p;
1377
148k
    } else if (p[0] == '-') {
1378
0
        is_neg = 1;
1379
0
        p++;
1380
0
        p_start = p;
1381
148k
    } else {
1382
148k
        p_start = p;
1383
148k
    }
1384
    
1385
148k
    if (p[0] == '0') {
1386
73.3k
        if ((p[1] == 'x' || p[1] == 'X') &&
1387
0
            (radix == 0 || radix == 16)) {
1388
0
            p += 2;
1389
0
            radix = 16;
1390
73.3k
        } else if ((p[1] == 'o' || p[1] == 'O') &&
1391
0
                   radix == 0 && (flags & JS_ATOD_ACCEPT_BIN_OCT)) {
1392
0
            p += 2;
1393
0
            radix = 8;
1394
73.3k
        } else if ((p[1] == 'b' || p[1] == 'B') &&
1395
0
                   radix == 0 && (flags & JS_ATOD_ACCEPT_BIN_OCT)) {
1396
0
            p += 2;
1397
0
            radix = 2;
1398
73.3k
        } else if ((p[1] >= '0' && p[1] <= '9') &&
1399
73.3k
                   radix == 0 && (flags & JS_ATOD_ACCEPT_LEGACY_OCTAL)) {
1400
0
            int i;
1401
0
            sep = 256;
1402
0
            for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++)
1403
0
                continue;
1404
0
            if (p[i] == '8' || p[i] == '9')
1405
0
                goto no_prefix;
1406
0
            p += 1;
1407
0
            radix = 8;
1408
73.3k
        } else {
1409
73.3k
            goto no_prefix;
1410
73.3k
        }
1411
        /* there must be a digit after the prefix */
1412
0
        if (to_digit((uint8_t)*p) >= radix)
1413
0
            goto fail;
1414
73.3k
    no_prefix: ;
1415
74.9k
    } else {
1416
74.9k
        if (!(flags & JS_ATOD_INT_ONLY) && strstart(p, "Infinity", &p))
1417
0
            goto overflow;
1418
74.9k
    }
1419
148k
    if (radix == 0)
1420
0
        radix = 10;
1421
1422
148k
    cur_limb = 0;
1423
148k
    expn_offset = 0;
1424
148k
    digit_count = 0;
1425
148k
    limb_digit_count = 0;
1426
148k
    max_digits = atod_max_digits_table[radix - 2];
1427
148k
    digits_per_limb = digits_per_limb_table[radix - 2];
1428
148k
    radix_base = radix_base_table[radix - 2];
1429
148k
    radix_shift = ctz32(radix);
1430
148k
    radix1 = radix >> radix_shift;
1431
148k
    if (radix1 == 1) {
1432
        /* radix = 2^radix_bits */
1433
4
        radix_bits = radix_shift;
1434
148k
    } else {
1435
148k
        radix_bits = 0;
1436
148k
    }
1437
148k
    tmp0->len = 1;
1438
148k
    tmp0->tab[0] = 0;
1439
148k
    extra_digits = 0;
1440
148k
    pos = 0;
1441
148k
    dot_pos = -1;
1442
    /* skip leading zeros */
1443
221k
    for(;;) {
1444
221k
        if (*p == '.' && (p > p_start || to_digit(p[1]) < radix) &&
1445
3
            !(flags & JS_ATOD_INT_ONLY)) {
1446
3
            if (*p == sep)
1447
0
                goto fail;
1448
3
            if (dot_pos >= 0)
1449
0
                break;
1450
3
            dot_pos = pos;
1451
3
            p++;
1452
3
        }
1453
221k
        if (*p == sep && p > p_start && p[1] == '0')
1454
0
            p++;
1455
221k
        if (*p != '0')
1456
148k
            break;
1457
73.3k
        p++;
1458
73.3k
        pos++;
1459
73.3k
    }
1460
    
1461
148k
    sig_pos = pos;
1462
8.04M
    for(;;) {
1463
8.04M
        limb_t c;
1464
8.04M
        if (*p == '.' && (p > p_start || to_digit(p[1]) < radix) &&
1465
70
            !(flags & JS_ATOD_INT_ONLY)) {
1466
70
            if (*p == sep)
1467
0
                goto fail;
1468
70
            if (dot_pos >= 0)
1469
0
                break;
1470
70
            dot_pos = pos;
1471
70
            p++;
1472
70
        }
1473
8.04M
        if (*p == sep && p > p_start && to_digit(p[1]) < radix)
1474
0
            p++;
1475
8.04M
        c = to_digit(*p);
1476
8.04M
        if (c >= radix)
1477
148k
            break;
1478
7.90M
        p++;
1479
7.90M
        pos++;
1480
7.90M
        if (digit_count < max_digits) {
1481
            /* XXX: could be faster when radix_bits != 0 */
1482
301k
            cur_limb = cur_limb * radix + c;
1483
301k
            limb_digit_count++;
1484
301k
            if (limb_digit_count == digits_per_limb) {
1485
319
                mpb_mul1_base(tmp0, radix_base, cur_limb);
1486
319
                cur_limb = 0;
1487
319
                limb_digit_count = 0;
1488
319
            }
1489
301k
            digit_count++;
1490
7.59M
        } else {
1491
7.59M
            extra_digits |= c;
1492
7.59M
        }
1493
7.90M
    }
1494
148k
    if (limb_digit_count != 0) {
1495
148k
        mpb_mul1_base(tmp0, pow_ui(radix, limb_digit_count), cur_limb);
1496
148k
    }
1497
148k
    if (digit_count == 0) {
1498
41
        is_zero = TRUE;
1499
41
        expn_offset = 0;
1500
148k
    } else {
1501
148k
        is_zero = FALSE;
1502
148k
        if (dot_pos < 0)
1503
148k
            dot_pos = pos;
1504
148k
        expn_offset = sig_pos + digit_count - dot_pos;
1505
148k
    }
1506
    
1507
    /* Use the extra digits for rounding if the base is a power of
1508
       two. Otherwise they are just truncated. */
1509
148k
    if (radix_bits != 0 && extra_digits != 0) {
1510
3
        tmp0->tab[0] |= 1;
1511
3
    }
1512
    
1513
    /* parse the exponent, if any */
1514
148k
    expn = 0;
1515
148k
    expn_overflow = FALSE;
1516
148k
    is_bin_exp = FALSE;
1517
148k
    if (!(flags & JS_ATOD_INT_ONLY) &&
1518
86
        ((radix == 10 && (*p == 'e' || *p == 'E')) ||
1519
73
         (radix != 10 && (*p == '@' ||
1520
0
                          (radix_bits >= 1 && radix_bits <= 4 && (*p == 'p' || *p == 'P'))))) &&
1521
13
        p > p_start) {
1522
13
        BOOL exp_is_neg;
1523
13
        int c;
1524
13
        is_bin_exp = (*p == 'p' || *p == 'P');
1525
13
        p++;
1526
13
        exp_is_neg = 0;
1527
13
        if (*p == '+') {
1528
0
            p++;
1529
13
        } else if (*p == '-') {
1530
3
            exp_is_neg = 1;
1531
3
            p++;
1532
3
        }
1533
13
        c = to_digit(*p);
1534
13
        if (c >= 10)
1535
0
            goto fail; /* XXX: could stop before the exponent part */
1536
13
        expn = c;
1537
13
        p++;
1538
52
        for(;;) {
1539
52
            if (*p == sep && to_digit(p[1]) < 10)
1540
0
                p++;
1541
52
            c = to_digit(*p);
1542
52
            if (c >= 10)
1543
13
                break;
1544
39
            if (!expn_overflow) {
1545
39
                if (unlikely(expn > ((INT32_MAX - 2 - 9) / 10))) {
1546
0
                    expn_overflow = TRUE;
1547
39
                } else {
1548
39
                    expn = expn * 10 + c;
1549
39
                }
1550
39
            }
1551
39
            p++;
1552
39
        }
1553
13
        if (exp_is_neg)
1554
3
            expn = -expn;
1555
        /* if zero result, the exponent can be arbitrarily large */
1556
13
        if (!is_zero && expn_overflow) {
1557
0
            if (exp_is_neg)
1558
0
                a = 0;
1559
0
            else
1560
0
                a = (uint64_t)0x7ff << 52; /* infinity */
1561
0
            goto done;
1562
0
        }
1563
13
    }
1564
1565
148k
    if (p == p_start)
1566
0
        goto fail;
1567
1568
148k
    if (is_zero) {
1569
41
        a = 0;
1570
148k
    } else {
1571
148k
        int expn1;
1572
148k
        if (radix_bits != 0) {
1573
3
            if (!is_bin_exp)
1574
3
                expn *= radix_bits;
1575
3
            expn -= expn_offset * radix_bits;
1576
3
            expn1 = expn + digit_count * radix_bits;
1577
3
            if (expn1 >= 1024 + radix_bits)
1578
3
                goto overflow;
1579
0
            else if (expn1 <= -1075)
1580
0
                goto underflow;
1581
0
            m = round_to_d(&e, tmp0, -expn, JS_RNDN);
1582
148k
        } else {
1583
148k
            expn -= expn_offset;
1584
148k
            expn1 = expn + digit_count;
1585
148k
            if (expn1 >= max_exponent[radix - 2] + 1)
1586
9
                goto overflow;
1587
148k
            else if (expn1 <= min_exponent[radix - 2])
1588
3
                goto underflow;
1589
148k
            m = mul_pow_round_to_d(&e, tmp0, radix1, radix_shift, expn, JS_RNDN);
1590
148k
        }
1591
148k
        if (m == 0) {
1592
3
        underflow:
1593
3
            a = 0;
1594
148k
        } else if (e > 1024) {
1595
12
        overflow:
1596
            /* overflow */
1597
12
            a = (uint64_t)0x7ff << 52;
1598
148k
        } else if (e < -1073) {
1599
            /* underflow */
1600
            /* XXX: check rounding */
1601
0
            a = 0;
1602
148k
        } else if (e < -1021) {
1603
            /* subnormal */
1604
0
            a = m >> (-e - 1021);
1605
148k
        } else {
1606
148k
            a = ((uint64_t)(e + 1022) << 52) | (m & (((uint64_t)1 << 52) - 1));
1607
148k
        }
1608
148k
    }
1609
148k
 done:
1610
148k
    a |= (uint64_t)is_neg << 63;
1611
148k
    dval = uint64_as_float64(a);
1612
148k
 done1:
1613
148k
    if (pnext)
1614
0
        *pnext = p;
1615
148k
    dtoa_free(tmp0);
1616
148k
    return dval;
1617
0
 fail:
1618
    dval = NAN;
1619
0
    goto done1;
1620
148k
}