Coverage Report

Created: 2026-04-12 07:07

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