Coverage Report

Created: 2025-10-13 07:07

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
10.4M
#define LIMB_LOG2_BITS 5
53
54
10.4M
#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
2.61M
#define DBIGNUM_LEN_MAX 52 /* ~ 2^(1072+53)*36^100 (dtoa) */
65
219k
#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
69.6k
{
77
69.6k
    size_t i;
78
69.6k
    limb_t k, a;
79
80
69.6k
    k=b;
81
139k
    for(i=0;i<n;i++) {
82
105k
        if (k == 0)
83
35.3k
            break;
84
70.2k
        a = tab[i] + k;
85
70.2k
        k = (a < k);
86
70.2k
        tab[i] = a;
87
70.2k
    }
88
69.6k
    return k;
89
69.6k
}
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
107k
{
95
107k
    limb_t i;
96
107k
    dlimb_t t;
97
98
319k
    for(i = 0; i < n; i++) {
99
212k
        t = (dlimb_t)taba[i] * (dlimb_t)b + l;
100
212k
        tabr[i] = t;
101
212k
        l = t >> LIMB_BITS;
102
212k
    }
103
107k
    return l;
104
107k
}
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
205k
{
120
205k
    limb_t n1m, n_adj, q, r, ah;
121
205k
    dlimb_t a;
122
205k
    n1m = ((slimb_t)a0 >> (LIMB_BITS - 1));
123
205k
    n_adj = a0 + (n1m & d);
124
205k
    a = (dlimb_t)d_inv * (a1 - n1m) + n_adj;
125
205k
    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
205k
    a = ((dlimb_t)a1 << LIMB_BITS) | a0;
129
205k
    a = a - (dlimb_t)q * d - d;
130
205k
    ah = a >> LIMB_BITS;
131
205k
    q += 1 + ah;
132
205k
    r = (limb_t)a + (ah & d);
133
205k
    *pr = r;
134
205k
    return q;
135
205k
}
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
33.6k
{
140
33.6k
    slimb_t i;
141
33.6k
    dlimb_t a1;
142
67.3k
    for(i = n - 1; i >= 0; i--) {
143
33.6k
        a1 = ((dlimb_t)r << LIMB_BITS) | taba[i];
144
33.6k
        tabr[i] = a1 / b;
145
33.6k
        r = a1 % b;
146
33.6k
    }
147
33.6k
    return r;
148
33.6k
}
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
104k
{
155
104k
    mp_size_t i;
156
104k
    limb_t l, a;
157
158
104k
    assert(shift >= 1 && shift < LIMB_BITS);
159
104k
    l = high;
160
415k
    for(i = n - 1; i >= 0; i--) {
161
310k
        a = tab[i];
162
310k
        tab_r[i] = (a >> shift) | (l << (LIMB_BITS - shift));
163
310k
        l = a;
164
310k
    }
165
104k
    return l & (((limb_t)1 << shift) - 1);
166
104k
}
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
1.54M
{
173
1.54M
    mp_size_t i;
174
1.54M
    limb_t l, a;
175
176
1.54M
    assert(shift >= 1 && shift < LIMB_BITS);
177
1.54M
    l = low;
178
3.23M
    for(i = 0; i < n; i++) {
179
1.68M
        a = tab[i];
180
1.68M
        tab_r[i] = (a << shift) | l;
181
1.68M
        l = (a >> (LIMB_BITS - shift)); 
182
1.68M
    }
183
1.54M
    return l;
184
1.54M
}
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
68.5k
{
189
68.5k
    slimb_t i;
190
191
68.5k
    if (shift != 0) {
192
68.5k
        r = (r << shift) | mp_shl(tabr, taba, n, shift, 0);
193
68.5k
    }
194
274k
    for(i = n - 1; i >= 0; i--) {
195
205k
        tabr[i] = udiv1norm(&r, r, taba[i], b, b_inv);
196
205k
    }
197
68.5k
    r >>= shift;
198
68.5k
    return r;
199
68.5k
}
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
1.69M
{
216
3.24M
    while (r->len > 1 && r->tab[r->len - 1] == 0)
217
1.54M
        r->len--;
218
1.69M
}
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
1.65M
{
244
1.65M
    int i, n_bits;
245
1.65M
    uint64_t r;
246
1.65M
    if (b == 0)
247
0
        return 1;
248
1.65M
    if (b == 1)
249
1.40M
        return a;
250
243k
#ifdef USE_POW5_TABLE
251
243k
    if ((a == 5 || a == 10) && b <= 17) {
252
243k
        r = pow5_table[b - 1];
253
243k
        if (b >= 14) {
254
67.3k
            r |= (uint64_t)pow5h_table[b - 14] << 32;
255
67.3k
        }
256
243k
        if (a == 10)
257
175k
            r <<= b;
258
243k
        return r;
259
243k
    }
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
243k
}
270
271
static uint32_t pow_ui_inv(uint32_t *pr_inv, int *pshift, uint32_t a, uint32_t b)
272
68.5k
{
273
68.5k
    uint32_t r_inv, r;
274
68.5k
    int shift;
275
68.5k
#ifdef USE_POW5_TABLE
276
68.5k
    if (a == 5 && b >= 1 && b <= 13) {
277
68.5k
        r = pow5_table[b - 1];
278
68.5k
        shift = clz32(r);
279
68.5k
        r <<= shift;
280
68.5k
        r_inv = pow5_inv_table[b - 1];
281
68.5k
    } 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
68.5k
    *pshift = shift;
290
68.5k
    *pr_inv = r_inv;
291
68.5k
    return r;
292
68.5k
}
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
171k
{
302
171k
    int l;
303
    
304
171k
    l = (unsigned)k / LIMB_BITS;
305
171k
    k = k & (LIMB_BITS - 1);
306
171k
    if (l >= r->len)
307
0
        return 0;
308
171k
    else
309
171k
        return (r->tab[l] >> k) & 1;
310
171k
}
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
1.68M
{
315
1.68M
    int l, i;
316
317
1.68M
    if (shift == 0)
318
52
        return;
319
1.68M
    if (shift < 0) {
320
1.51M
        shift = -shift;
321
1.51M
        l = (unsigned)shift / LIMB_BITS;
322
1.51M
        shift = shift & (LIMB_BITS - 1);
323
1.51M
        if (shift != 0) {
324
1.48M
            r->tab[r->len] = mp_shl(r->tab, r->tab, r->len, shift, 0);
325
1.48M
            r->len++;
326
1.48M
            mpb_renorm(r);
327
1.48M
        }
328
1.51M
        if (l > 0) {
329
3.06M
            for(i = r->len - 1; i >= 0; i--)
330
1.54M
                r->tab[i + l] = r->tab[i];
331
3.05M
            for(i = 0; i < l; i++)
332
1.54M
                r->tab[i] = 0;
333
1.51M
            r->len += l;
334
1.51M
        }
335
1.51M
    } else {
336
171k
        limb_t bit1, bit2;
337
171k
        int k, add_one;
338
        
339
171k
        switch(rnd_mode) {
340
0
        default:
341
0
        case JS_RNDZ:
342
0
            add_one = 0;
343
0
            break;
344
171k
        case JS_RNDN:
345
171k
        case JS_RNDNA:
346
171k
            bit1 = mpb_get_bit(r, shift - 1);
347
171k
            if (bit1) {
348
69.6k
                if (rnd_mode == JS_RNDNA) {
349
0
                    bit2 = 1;
350
69.6k
                } else {
351
                    /* bit2 = oring of all the bits after bit1 */
352
69.6k
                    bit2 = 0;
353
69.6k
                    if (shift >= 2) {
354
69.6k
                        k = shift - 1;
355
69.6k
                        l = (unsigned)k / LIMB_BITS;
356
69.6k
                        k = k & (LIMB_BITS - 1);
357
70.2k
                        for(i = 0; i < min_int(l, r->len); i++)
358
663
                            bit2 |= r->tab[i];
359
69.6k
                        if (l < r->len)
360
69.6k
                            bit2 |= r->tab[l] & (((limb_t)1 << k) - 1);
361
69.6k
                    }
362
69.6k
                }
363
69.6k
                if (bit2) {
364
69.6k
                    add_one = 1;
365
69.6k
                } else {
366
                    /* round to even */
367
0
                    add_one = mpb_get_bit(r, shift);
368
0
                }
369
102k
            } else {
370
102k
                add_one = 0;
371
102k
            }
372
171k
            break;
373
171k
        }
374
375
171k
        l = (unsigned)shift / LIMB_BITS;
376
171k
        shift = shift & (LIMB_BITS - 1);
377
171k
        if (l >= r->len) {
378
0
            r->len = 1;
379
0
            r->tab[0] = add_one;
380
171k
        } else {
381
171k
            if (l > 0) {
382
68.0k
                r->len -= l;
383
170k
                for(i = 0; i < r->len; i++)
384
102k
                    r->tab[i] = r->tab[i + l];
385
68.0k
            }
386
171k
            if (shift != 0) {
387
104k
                mp_shr(r->tab, r->tab, r->len, shift, 0);
388
104k
                mpb_renorm(r);
389
104k
            }
390
171k
            if (add_one) {
391
69.6k
                limb_t a;
392
69.6k
                a = mp_add_ui(r->tab, 1, r->len);
393
69.6k
                if (a)
394
0
                    r->tab[r->len++] = a;
395
69.6k
            }
396
171k
        }
397
171k
    }
398
1.68M
}
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
201k
{
421
#if LIMB_BITS == 64
422
    r->tab[0] = m;
423
    r->len = 1;
424
#else
425
201k
    r->tab[0] = m;
426
201k
    r->tab[1] = m >> LIMB_BITS;
427
201k
    if (r->tab[1] == 0)
428
100k
        r->len = 1;
429
100k
    else
430
100k
        r->len = 2;
431
201k
#endif
432
201k
}
433
434
static uint64_t mpb_get_u64(mpb_t *r)
435
1.61M
{
436
#if LIMB_BITS == 64
437
    return r->tab[0];
438
#else
439
1.61M
    if (r->len == 1) {
440
33.6k
        return r->tab[0];
441
1.58M
    } else {
442
1.58M
        return r->tab[0] | ((uint64_t)r->tab[1] << LIMB_BITS);
443
1.58M
    }
444
1.61M
#endif
445
1.61M
}
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
1.58M
{
450
1.58M
    limb_t v;
451
1.58M
    v = a->tab[a->len - 1];
452
1.58M
    if (v == 0)
453
0
        return -1;
454
1.58M
    else
455
1.58M
        return a->len * LIMB_BITS - 1 - clz32(v);
456
1.58M
}
457
458
33.6k
#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
33.6k
{
476
33.6k
    int radix_bits, mult;
477
478
33.6k
    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
33.6k
    } else {
485
33.6k
        mult = mul_log2_radix_table[radix - 2];
486
33.6k
        return ((int64_t)a * mult) >> MUL_LOG2_RADIX_BASE_LOG2;
487
33.6k
    }
488
33.6k
}
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
45.3k
{
534
45.3k
    int digit, i;
535
420k
    for(i = len - 1; i >= 0; i--) {
536
374k
        digit = n % 10;
537
374k
        n = n / 10;
538
374k
        buf[i] = digit + '0';
539
374k
    }
540
45.3k
}
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
33.6k
{
563
33.6k
    int digit, i;
564
565
33.6k
    if (radix == 10) {
566
        /* specific case with constant divisor */
567
33.6k
#if LIMB_BITS == 32
568
33.6k
        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
33.6k
    } 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
33.6k
}
589
590
size_t u32toa(char *buf, uint32_t n)
591
2.21M
{
592
2.21M
    char buf1[10], *q;
593
2.21M
    size_t len;
594
    
595
2.21M
    q = buf1 + sizeof(buf1);
596
7.92M
    do {
597
7.92M
        *--q = n % 10 + '0';
598
7.92M
        n /= 10;
599
7.92M
    } while (n != 0);
600
2.21M
    len = buf1 + sizeof(buf1) - q;
601
2.21M
    memcpy(buf, q, len);
602
2.21M
    return len;
603
2.21M
}
604
605
size_t i32toa(char *buf, int32_t n)
606
438k
{
607
438k
    if (n >= 0) {
608
438k
        return u32toa(buf, n);
609
438k
    } else {
610
0
        buf[0] = '-';
611
0
        return u32toa(buf + 1, -(uint32_t)n) + 1;
612
0
    }
613
438k
}
614
615
#ifdef USE_FAST_INT
616
size_t u64toa(char *buf, uint64_t n)
617
992k
{
618
992k
    if (n < 0x100000000) {
619
980k
        return u32toa(buf, n);
620
980k
    } else {
621
11.7k
        uint64_t n1;
622
11.7k
        char *q = buf;
623
11.7k
        uint32_t n2;
624
        
625
11.7k
        n1 = n / 1000000000;
626
11.7k
        n %= 1000000000;
627
11.7k
        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
11.7k
        } else {
639
11.7k
            q += u32toa(q, n1);
640
11.7k
        }
641
11.7k
        u32toa_len(q, n, 9);
642
11.7k
        q += 9;
643
11.7k
        return q - buf;
644
11.7k
    }
645
992k
}
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
992k
{
660
992k
    int radix_bits, l;
661
992k
    if (likely(radix == 10))
662
992k
        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
992k
{
693
992k
    if (n >= 0) {
694
558k
        return u64toa_radix(buf, n, radix);
695
558k
    } else {
696
433k
        buf[0] = '-';
697
433k
        return u64toa_radix(buf + 1, -(uint64_t)n, radix) + 1;
698
433k
    }
699
992k
}
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
33.6k
{
851
33.6k
    int n_digits, digits_per_limb, radix_bits, n, len;
852
853
33.6k
    n_digits = n_digits1;
854
33.6k
    if ((radix & (radix - 1)) == 0) {
855
        /* radix = 2^radix_bits */
856
0
        radix_bits = 31 - clz32(radix);
857
33.6k
    } else {
858
33.6k
        radix_bits = 0;
859
33.6k
    }
860
33.6k
    digits_per_limb = digits_per_limb_table[radix - 2];
861
33.6k
    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
33.6k
    } else {
871
33.6k
        limb_t r;
872
67.3k
        while (n_digits != 0) {
873
33.6k
            n = min_int(n_digits, digits_per_limb);
874
33.6k
            n_digits -= n;
875
33.6k
            r = mp_div1(a->tab, a->tab, a->len, radix_base_table[radix - 2], 0);
876
33.6k
            mpb_renorm(a);
877
33.6k
            limb_to_a(buf + n_digits, r, radix, n);
878
33.6k
        }
879
33.6k
    }
880
881
    /* add the dot */
882
33.6k
    len = n_digits1;
883
33.6k
    if (dot_pos != n_digits1) {
884
33.6k
        memmove(buf + dot_pos + 1, buf + dot_pos, n_digits1 - dot_pos);
885
33.6k
        buf[dot_pos] = '.';
886
33.6k
        len++;
887
33.6k
    }
888
33.6k
    return len;
889
33.6k
}
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
1.61M
{
895
1.61M
    int e_offset, d, n, n0;
896
897
1.61M
    e_offset = -f * radix_shift;
898
1.61M
    if (radix1 != 1) {
899
1.61M
        d = digits_per_limb_table[radix1 - 2];
900
1.61M
        if (f >= 0) {
901
1.54M
            limb_t h, b;
902
            
903
1.54M
            b = 0;
904
1.54M
            n0 = 0;
905
1.65M
            while (f != 0) {
906
101k
                n = min_int(f, d);
907
101k
                if (n != n0) {
908
101k
                    b = pow_ui(radix1, n);
909
101k
                    n0 = n;
910
101k
                }
911
101k
                h = mp_mul1(a->tab, a->tab, a->len, b, 0);
912
101k
                if (h != 0) {
913
67.3k
                    a->tab[a->len++] = h;
914
67.3k
                }
915
101k
                f -= n;
916
101k
            }
917
1.54M
        } else {
918
68.5k
            int extra_bits, l, shift;
919
68.5k
            limb_t r, rem, b, b_inv;
920
            
921
68.5k
            f = -f;
922
68.5k
            l = (f + d - 1) / d; /* high bound for the number of limbs (XXX: make it better) */
923
68.5k
            e_offset += l * LIMB_BITS;
924
68.5k
            if (!is_int) {
925
                /* at least 'e' bits are needed in the final result for rounding */
926
68.5k
                extra_bits = max_int(e - mpb_floor_log2(a), 0);
927
68.5k
            } 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
68.5k
            e_offset += extra_bits;
933
68.5k
            mpb_shr_round(a, -(l * LIMB_BITS + extra_bits), JS_RNDZ);
934
            
935
68.5k
            b = 0;
936
68.5k
            b_inv = 0;
937
68.5k
            shift = 0;
938
68.5k
            n0 = 0;
939
68.5k
            rem = 0;
940
137k
            while (f != 0) {
941
68.5k
                n = min_int(f, d);
942
68.5k
                if (n != n0) {
943
68.5k
                    b = pow_ui_inv(&b_inv, &shift, radix1, n);
944
68.5k
                    n0 = n;
945
68.5k
                }
946
68.5k
                r = mp_div1norm(a->tab, a->tab, a->len, b, 0, b_inv, shift);
947
68.5k
                rem |= r;
948
68.5k
                mpb_renorm(a);
949
68.5k
                f -= n;
950
68.5k
            }
951
            /* if the remainder is non zero, use it for rounding */
952
68.5k
            a->tab[0] |= (rem != 0);
953
68.5k
        }
954
1.61M
    }
955
1.61M
    return e_offset;
956
1.61M
}
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
100k
{
962
100k
    int e_offset;
963
964
100k
    mpb_set_u64(tmp1, m);
965
100k
    e_offset = mul_pow(tmp1, radix1, radix_shift, f, TRUE, e);
966
100k
    mpb_shr_round(tmp1, -e + e_offset, rnd_mode);
967
100k
}
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
1.51M
{
972
1.51M
    int e;
973
1.51M
    uint64_t m;
974
975
1.51M
    if (a->tab[0] == 0 && a->len == 1) {
976
        /* zero result */
977
0
        m = 0;
978
0
        e = 0; /* don't care */
979
1.51M
    } else {
980
1.51M
        int prec, prec1, e_min;
981
1.51M
        e = mpb_floor_log2(a) + 1 - e_offset;
982
1.51M
        prec1 = 53;
983
1.51M
        e_min = -1021;
984
1.51M
        if (e < e_min) {
985
            /* subnormal result or zero */
986
0
            prec = prec1 - (e_min - e);
987
1.51M
        } else {
988
1.51M
            prec = prec1;
989
1.51M
        }
990
1.51M
        mpb_shr_round(a, e + e_offset - prec, rnd_mode);
991
1.51M
        m = mpb_get_u64(a);
992
1.51M
        m <<= (53 - prec);
993
        /* mantissa overflow due to rounding */
994
1.51M
        if (m >= (uint64_t)1 << 53) {
995
637
            m >>= 1;
996
637
            e++;
997
637
        }
998
1.51M
    }
999
1.51M
    *pe = e;
1000
1.51M
    return m;
1001
1.51M
}
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
1.51M
{
1009
1.51M
    int e_offset;
1010
1011
1.51M
    e_offset = mul_pow(a, radix1, radix_shift, f, FALSE, 55);
1012
1.51M
    return round_to_d(pe, a, e_offset, rnd_mode);
1013
1.51M
}
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
219k
{
1036
219k
    int fmt = flags & JS_DTOA_FORMAT_MASK;
1037
219k
    int n, e;
1038
219k
    uint64_t a;
1039
1040
219k
    if (fmt != JS_DTOA_FORMAT_FRAC) {
1041
219k
        if (fmt == JS_DTOA_FORMAT_FREE) {
1042
219k
            n = dtoa_max_digits_table[radix - 2];
1043
219k
        } else {
1044
0
            n = n_digits;
1045
0
        }
1046
219k
        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
219k
        } else {
1059
            /* extra: sign, 1 dot and exponent "e-1000" */
1060
219k
            n += 1 + 1 + 6;
1061
219k
        }
1062
219k
    } 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
219k
    return max_int(n, 9); /* also include NaN and [-]Infinity */
1082
219k
}
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
2.83M
{
1096
2.83M
    void *ret;
1097
2.83M
    ret = *pptr;
1098
2.83M
    *pptr += (size + 7) / 8;
1099
2.83M
    return ret;
1100
2.83M
}
1101
1102
static void dtoa_free(void *ptr)
1103
2.83M
{
1104
2.83M
}
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
219k
{
1111
219k
    uint64_t a, m, *mptr = tmp_mem->mem;
1112
219k
    int e, sgn, l, E, P, i, E_max, radix1, radix_shift;
1113
219k
    char *q;
1114
219k
    mpb_t *tmp1, *mant_max;
1115
219k
    int fmt = flags & JS_DTOA_FORMAT_MASK;
1116
1117
219k
    tmp1 = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * DBIGNUM_LEN_MAX);
1118
219k
    mant_max = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * MANT_LEN_MAX);
1119
219k
    assert((mptr - tmp_mem->mem) <= sizeof(JSDTOATempMem) / sizeof(mptr[0]));
1120
1121
219k
    radix_shift = ctz32(radix);
1122
219k
    radix1 = radix >> radix_shift;
1123
219k
    a = float64_as_uint64(d);
1124
219k
    sgn = a >> 63;
1125
219k
    e = (a >> 52) & 0x7ff;
1126
219k
    m = a & (((uint64_t)1 << 52) - 1);
1127
219k
    q = buf;
1128
219k
    if (e == 0x7ff) {
1129
185k
        if (m == 0) {
1130
0
            if (sgn)
1131
0
                *q++ = '-';
1132
0
            memcpy(q, "Infinity", 8);
1133
0
            q += 8;
1134
185k
        } else {
1135
185k
            memcpy(q, "NaN", 3);
1136
185k
            q += 3;
1137
185k
        }
1138
185k
        goto done;
1139
185k
    } 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
33.6k
    } else {
1160
33.6k
        m |= (uint64_t)1 << 52;
1161
33.6k
    }
1162
33.6k
    if (sgn)
1163
0
        *q++ = '-';
1164
    /* remove the bias */
1165
33.6k
    e -= 1022;
1166
    /* d = 2^(e-53)*m */
1167
    //    printf("m=0x%016" PRIx64 " e=%d\n", m, e);
1168
33.6k
#ifdef USE_FAST_INT
1169
33.6k
    if (fmt == JS_DTOA_FORMAT_FREE &&
1170
33.6k
        e >= 1 && e <= 53 &&
1171
33.6k
        (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
33.6k
#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
33.6k
    E = 1 + mul_log2_radix(e - 1, radix);
1183
    
1184
33.6k
    if (fmt == JS_DTOA_FORMAT_FREE) {
1185
33.6k
        int P_max, E0, e1, E_found, P_found;
1186
33.6k
        uint64_t m1, mant_found, mant, mant_max1;
1187
        /* P_max is guarranteed to work by construction */
1188
33.6k
        P_max = dtoa_max_digits_table[radix - 2];
1189
33.6k
        E0 = E;
1190
33.6k
        E_found = 0;
1191
33.6k
        P_found = 0;
1192
33.6k
        mant_found = 0;
1193
        /* find the minimum number of digits by successive tries */
1194
33.6k
        P = P_max; /* P_max is guarateed to work */
1195
100k
        for(;;) {
1196
            /* mant_max always fits on 64 bits */
1197
100k
            mant_max1 = pow_ui(radix, P);
1198
            /* compute the mantissa in base B */
1199
100k
            E = E0;
1200
100k
            for(;;) {
1201
                /* XXX: add inexact flag */
1202
100k
                mul_pow_round(tmp1, m, e - 53, radix1, radix_shift, P - E, JS_RNDN);
1203
100k
                mant = mpb_get_u64(tmp1);
1204
100k
                if (mant < mant_max1)
1205
100k
                    break;
1206
4
                E++; /* at most one iteration is possible */
1207
4
            }
1208
            /* remove useless trailing zero digits */
1209
370k
            while ((mant % radix) == 0) {
1210
269k
                mant /= radix;
1211
269k
                P--;
1212
269k
            }
1213
            /* garanteed to work for P = P_max */
1214
100k
            if (P_found == 0)
1215
33.6k
                goto prec_found;
1216
            /* convert back to base 2 */
1217
67.2k
            mpb_set_u64(tmp1, mant);
1218
67.2k
            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
67.2k
            if (m1 == m && e1 == e) {
1223
67.2k
            prec_found:
1224
67.2k
                P_found = P;
1225
67.2k
                E_found = E;
1226
67.2k
                mant_found = mant;
1227
67.2k
                if (P == 1)
1228
0
                    break;
1229
67.2k
                P--; /* try lower exponent */
1230
67.2k
            } else {
1231
33.6k
                break;
1232
33.6k
            }
1233
67.2k
        }
1234
33.6k
        P = P_found;
1235
33.6k
        E = E_found;
1236
33.6k
        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
33.6k
    } 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
33.6k
 output:
1279
33.6k
    if (fmt == JS_DTOA_FORMAT_FIXED)
1280
0
        E_max = n_digits;
1281
33.6k
    else
1282
33.6k
        E_max = dtoa_max_digits_table[radix - 2] + 4;
1283
33.6k
    if ((flags & JS_DTOA_EXP_MASK) == JS_DTOA_EXP_ENABLED ||
1284
33.6k
        ((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
33.6k
    } 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
33.6k
    } else {
1309
33.6k
        q += output_digits(q, tmp1, radix, P, min_int(P, E));
1310
33.6k
        for(i = 0; i < E - P; i++)
1311
0
            *q++ = '0';
1312
33.6k
    }
1313
219k
 done:
1314
219k
    *q = '\0';
1315
219k
    dtoa_free(mant_max);
1316
219k
    dtoa_free(tmp1);
1317
219k
    return q - buf;
1318
33.6k
}
1319
1320
static inline int to_digit(int c)
1321
7.93M
{
1322
7.93M
    if (c >= '0' && c <= '9')
1323
4.49M
        return c - '0';
1324
3.44M
    else if (c >= 'A' && c <= 'Z')
1325
1.37k
        return c - 'A' + 10;
1326
3.44M
    else if (c >= 'a' && c <= 'z')
1327
1.04M
        return c - 'a' + 10;
1328
2.39M
    else
1329
2.39M
        return 36;
1330
7.93M
}
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
1.45M
{
1335
1.45M
    int i;
1336
1.45M
    if (r->tab[0] == 0 && r->len == 1) {
1337
1.44M
        r->tab[0] = a;
1338
1.44M
    } else {
1339
6.13k
        if (radix_base == 0) {
1340
27
            for(i = r->len; i >= 0; i--) {
1341
18
                r->tab[i + 1] = r->tab[i];
1342
18
            }
1343
9
            r->tab[0] = a;
1344
6.12k
        } else {
1345
6.12k
            r->tab[r->len] = mp_mul1(r->tab, r->tab, r->len,
1346
6.12k
                                     radix_base, a);
1347
6.12k
        }
1348
6.13k
        r->len++;
1349
6.13k
        mpb_renorm(r);
1350
6.13k
    }
1351
1.45M
}
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
2.39M
{
1357
2.39M
    uint64_t *mptr = tmp_mem->mem;
1358
2.39M
    const char *p, *p_start;
1359
2.39M
    limb_t cur_limb, radix_base, extra_digits;
1360
2.39M
    int is_neg, digit_count, limb_digit_count, digits_per_limb, sep, radix1, radix_shift;
1361
2.39M
    int radix_bits, expn, e, max_digits, expn_offset, dot_pos, sig_pos, pos;
1362
2.39M
    mpb_t *tmp0;
1363
2.39M
    double dval;
1364
2.39M
    BOOL is_bin_exp, is_zero, expn_overflow;
1365
2.39M
    uint64_t m, a;
1366
1367
2.39M
    tmp0 = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * DBIGNUM_LEN_MAX);
1368
2.39M
    assert((mptr - tmp_mem->mem) <= sizeof(JSATODTempMem) / sizeof(mptr[0]));
1369
    /* optional separator between digits */
1370
2.39M
    sep = (flags & JS_ATOD_ACCEPT_UNDERSCORES) ? '_' : 256;
1371
1372
2.39M
    p = str;
1373
2.39M
    is_neg = 0;
1374
2.39M
    if (p[0] == '+') {
1375
0
        p++;
1376
0
        p_start = p;
1377
2.39M
    } else if (p[0] == '-') {
1378
0
        is_neg = 1;
1379
0
        p++;
1380
0
        p_start = p;
1381
2.39M
    } else {
1382
2.39M
        p_start = p;
1383
2.39M
    }
1384
    
1385
2.39M
    if (p[0] == '0') {
1386
1.04M
        if ((p[1] == 'x' || p[1] == 'X') &&
1387
0
            (radix == 0 || radix == 16)) {
1388
0
            p += 2;
1389
0
            radix = 16;
1390
1.04M
        } 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
1.04M
        } 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
1.04M
        } else if ((p[1] >= '0' && p[1] <= '9') &&
1399
96.6k
                   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
1.04M
        } else {
1409
1.04M
            goto no_prefix;
1410
1.04M
        }
1411
        /* there must be a digit after the prefix */
1412
0
        if (to_digit((uint8_t)*p) >= radix)
1413
0
            goto fail;
1414
1.04M
    no_prefix: ;
1415
1.35M
    } else {
1416
1.35M
        if (!(flags & JS_ATOD_INT_ONLY) && strstart(p, "Infinity", &p))
1417
0
            goto overflow;
1418
1.35M
    }
1419
2.39M
    if (radix == 0)
1420
0
        radix = 10;
1421
1422
2.39M
    cur_limb = 0;
1423
2.39M
    expn_offset = 0;
1424
2.39M
    digit_count = 0;
1425
2.39M
    limb_digit_count = 0;
1426
2.39M
    max_digits = atod_max_digits_table[radix - 2];
1427
2.39M
    digits_per_limb = digits_per_limb_table[radix - 2];
1428
2.39M
    radix_base = radix_base_table[radix - 2];
1429
2.39M
    radix_shift = ctz32(radix);
1430
2.39M
    radix1 = radix >> radix_shift;
1431
2.39M
    if (radix1 == 1) {
1432
        /* radix = 2^radix_bits */
1433
10
        radix_bits = radix_shift;
1434
2.39M
    } else {
1435
2.39M
        radix_bits = 0;
1436
2.39M
    }
1437
2.39M
    tmp0->len = 1;
1438
2.39M
    tmp0->tab[0] = 0;
1439
2.39M
    extra_digits = 0;
1440
2.39M
    pos = 0;
1441
2.39M
    dot_pos = -1;
1442
    /* skip leading zeros */
1443
3.78M
    for(;;) {
1444
3.78M
        if (*p == '.' && (p > p_start || to_digit(p[1]) < radix) &&
1445
104
            !(flags & JS_ATOD_INT_ONLY)) {
1446
104
            if (*p == sep)
1447
0
                goto fail;
1448
104
            if (dot_pos >= 0)
1449
0
                break;
1450
104
            dot_pos = pos;
1451
104
            p++;
1452
104
        }
1453
3.78M
        if (*p == sep && p > p_start && p[1] == '0')
1454
0
            p++;
1455
3.78M
        if (*p != '0')
1456
2.39M
            break;
1457
1.38M
        p++;
1458
1.38M
        pos++;
1459
1.38M
    }
1460
    
1461
2.39M
    sig_pos = pos;
1462
7.93M
    for(;;) {
1463
7.93M
        limb_t c;
1464
7.93M
        if (*p == '.' && (p > p_start || to_digit(p[1]) < radix) &&
1465
1.37k
            !(flags & JS_ATOD_INT_ONLY)) {
1466
1.37k
            if (*p == sep)
1467
0
                goto fail;
1468
1.37k
            if (dot_pos >= 0)
1469
0
                break;
1470
1.37k
            dot_pos = pos;
1471
1.37k
            p++;
1472
1.37k
        }
1473
7.93M
        if (*p == sep && p > p_start && to_digit(p[1]) < radix)
1474
0
            p++;
1475
7.93M
        c = to_digit(*p);
1476
7.93M
        if (c >= radix)
1477
2.39M
            break;
1478
5.53M
        p++;
1479
5.53M
        pos++;
1480
5.53M
        if (digit_count < max_digits) {
1481
            /* XXX: could be faster when radix_bits != 0 */
1482
1.68M
            cur_limb = cur_limb * radix + c;
1483
1.68M
            limb_digit_count++;
1484
1.68M
            if (limb_digit_count == digits_per_limb) {
1485
6.67k
                mpb_mul1_base(tmp0, radix_base, cur_limb);
1486
6.67k
                cur_limb = 0;
1487
6.67k
                limb_digit_count = 0;
1488
6.67k
            }
1489
1.68M
            digit_count++;
1490
3.85M
        } else {
1491
3.85M
            extra_digits |= c;
1492
3.85M
        }
1493
5.53M
    }
1494
2.39M
    if (limb_digit_count != 0) {
1495
1.44M
        mpb_mul1_base(tmp0, pow_ui(radix, limb_digit_count), cur_limb);
1496
1.44M
    }
1497
2.39M
    if (digit_count == 0) {
1498
947k
        is_zero = TRUE;
1499
947k
        expn_offset = 0;
1500
1.44M
    } else {
1501
1.44M
        is_zero = FALSE;
1502
1.44M
        if (dot_pos < 0)
1503
1.44M
            dot_pos = pos;
1504
1.44M
        expn_offset = sig_pos + digit_count - dot_pos;
1505
1.44M
    }
1506
    
1507
    /* Use the extra digits for rounding if the base is a power of
1508
       two. Otherwise they are just truncated. */
1509
2.39M
    if (radix_bits != 0 && extra_digits != 0) {
1510
9
        tmp0->tab[0] |= 1;
1511
9
    }
1512
    
1513
    /* parse the exponent, if any */
1514
2.39M
    expn = 0;
1515
2.39M
    expn_overflow = FALSE;
1516
2.39M
    is_bin_exp = FALSE;
1517
2.39M
    if (!(flags & JS_ATOD_INT_ONLY) &&
1518
3.25k
        ((radix == 10 && (*p == 'e' || *p == 'E')) ||
1519
1.48k
         (radix != 10 && (*p == '@' ||
1520
0
                          (radix_bits >= 1 && radix_bits <= 4 && (*p == 'p' || *p == 'P'))))) &&
1521
1.77k
        p > p_start) {
1522
1.77k
        BOOL exp_is_neg;
1523
1.77k
        int c;
1524
1.77k
        is_bin_exp = (*p == 'p' || *p == 'P');
1525
1.77k
        p++;
1526
1.77k
        exp_is_neg = 0;
1527
1.77k
        if (*p == '+') {
1528
398
            p++;
1529
1.37k
        } else if (*p == '-') {
1530
840
            exp_is_neg = 1;
1531
840
            p++;
1532
840
        }
1533
1.77k
        c = to_digit(*p);
1534
1.77k
        if (c >= 10)
1535
0
            goto fail; /* XXX: could stop before the exponent part */
1536
1.77k
        expn = c;
1537
1.77k
        p++;
1538
3.49k
        for(;;) {
1539
3.49k
            if (*p == sep && to_digit(p[1]) < 10)
1540
0
                p++;
1541
3.49k
            c = to_digit(*p);
1542
3.49k
            if (c >= 10)
1543
1.77k
                break;
1544
1.71k
            if (!expn_overflow) {
1545
1.71k
                if (unlikely(expn > ((INT32_MAX - 2 - 9) / 10))) {
1546
0
                    expn_overflow = TRUE;
1547
1.71k
                } else {
1548
1.71k
                    expn = expn * 10 + c;
1549
1.71k
                }
1550
1.71k
            }
1551
1.71k
            p++;
1552
1.71k
        }
1553
1.77k
        if (exp_is_neg)
1554
840
            expn = -expn;
1555
        /* if zero result, the exponent can be arbitrarily large */
1556
1.77k
        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
1.77k
    }
1564
1565
2.39M
    if (p == p_start)
1566
0
        goto fail;
1567
1568
2.39M
    if (is_zero) {
1569
947k
        a = 0;
1570
1.44M
    } else {
1571
1.44M
        int expn1;
1572
1.44M
        if (radix_bits != 0) {
1573
9
            if (!is_bin_exp)
1574
9
                expn *= radix_bits;
1575
9
            expn -= expn_offset * radix_bits;
1576
9
            expn1 = expn + digit_count * radix_bits;
1577
9
            if (expn1 >= 1024 + radix_bits)
1578
1
                goto overflow;
1579
8
            else if (expn1 <= -1075)
1580
0
                goto underflow;
1581
8
            m = round_to_d(&e, tmp0, -expn, JS_RNDN);
1582
1.44M
        } else {
1583
1.44M
            expn -= expn_offset;
1584
1.44M
            expn1 = expn + digit_count;
1585
1.44M
            if (expn1 >= max_exponent[radix - 2] + 1)
1586
7
                goto overflow;
1587
1.44M
            else if (expn1 <= min_exponent[radix - 2])
1588
840
                goto underflow;
1589
1.44M
            m = mul_pow_round_to_d(&e, tmp0, radix1, radix_shift, expn, JS_RNDN);
1590
1.44M
        }
1591
1.44M
        if (m == 0) {
1592
840
        underflow:
1593
840
            a = 0;
1594
1.44M
        } else if (e > 1024) {
1595
8
        overflow:
1596
            /* overflow */
1597
8
            a = (uint64_t)0x7ff << 52;
1598
1.44M
        } else if (e < -1073) {
1599
            /* underflow */
1600
            /* XXX: check rounding */
1601
0
            a = 0;
1602
1.44M
        } else if (e < -1021) {
1603
            /* subnormal */
1604
0
            a = m >> (-e - 1021);
1605
1.44M
        } else {
1606
1.44M
            a = ((uint64_t)(e + 1022) << 52) | (m & (((uint64_t)1 << 52) - 1));
1607
1.44M
        }
1608
1.44M
    }
1609
2.39M
 done:
1610
2.39M
    a |= (uint64_t)is_neg << 63;
1611
2.39M
    dval = uint64_as_float64(a);
1612
2.39M
 done1:
1613
2.39M
    if (pnext)
1614
0
        *pnext = p;
1615
2.39M
    dtoa_free(tmp0);
1616
2.39M
    return dval;
1617
0
 fail:
1618
    dval = NAN;
1619
0
    goto done1;
1620
2.39M
}