quickjs 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1626 @@
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
+ #define LIMB_LOG2_BITS 5
53
+
54
+ #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
+ #define DBIGNUM_LEN_MAX 52 /* ~ 2^(1072+53)*36^100 (dtoa) */
65
+ #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
+ {
77
+ size_t i;
78
+ limb_t k, a;
79
+
80
+ k=b;
81
+ for(i=0;i<n;i++) {
82
+ if (k == 0)
83
+ break;
84
+ a = tab[i] + k;
85
+ k = (a < k);
86
+ tab[i] = a;
87
+ }
88
+ return k;
89
+ }
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
+ {
95
+ limb_t i;
96
+ dlimb_t t;
97
+
98
+ for(i = 0; i < n; i++) {
99
+ t = (dlimb_t)taba[i] * (dlimb_t)b + l;
100
+ tabr[i] = t;
101
+ l = t >> LIMB_BITS;
102
+ }
103
+ return l;
104
+ }
105
+
106
+ /* WARNING: d must be >= 2^(LIMB_BITS-1) */
107
+ static inline limb_t udiv1norm_init(limb_t d)
108
+ {
109
+ limb_t a0, a1;
110
+ a1 = -d - 1;
111
+ a0 = -1;
112
+ return (((dlimb_t)a1 << LIMB_BITS) | a0) / d;
113
+ }
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
+ {
120
+ limb_t n1m, n_adj, q, r, ah;
121
+ dlimb_t a;
122
+ n1m = ((slimb_t)a0 >> (LIMB_BITS - 1));
123
+ n_adj = a0 + (n1m & d);
124
+ a = (dlimb_t)d_inv * (a1 - n1m) + n_adj;
125
+ 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
+ a = ((dlimb_t)a1 << LIMB_BITS) | a0;
129
+ a = a - (dlimb_t)q * d - d;
130
+ ah = a >> LIMB_BITS;
131
+ q += 1 + ah;
132
+ r = (limb_t)a + (ah & d);
133
+ *pr = r;
134
+ return q;
135
+ }
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
+ {
140
+ slimb_t i;
141
+ dlimb_t a1;
142
+ for(i = n - 1; i >= 0; i--) {
143
+ a1 = ((dlimb_t)r << LIMB_BITS) | taba[i];
144
+ tabr[i] = a1 / b;
145
+ r = a1 % b;
146
+ }
147
+ return r;
148
+ }
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
+ {
155
+ mp_size_t i;
156
+ limb_t l, a;
157
+
158
+ assert(shift >= 1 && shift < LIMB_BITS);
159
+ l = high;
160
+ for(i = n - 1; i >= 0; i--) {
161
+ a = tab[i];
162
+ tab_r[i] = (a >> shift) | (l << (LIMB_BITS - shift));
163
+ l = a;
164
+ }
165
+ return l & (((limb_t)1 << shift) - 1);
166
+ }
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
+ {
173
+ mp_size_t i;
174
+ limb_t l, a;
175
+
176
+ assert(shift >= 1 && shift < LIMB_BITS);
177
+ l = low;
178
+ for(i = 0; i < n; i++) {
179
+ a = tab[i];
180
+ tab_r[i] = (a << shift) | l;
181
+ l = (a >> (LIMB_BITS - shift));
182
+ }
183
+ return l;
184
+ }
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
+ {
189
+ slimb_t i;
190
+
191
+ if (shift != 0) {
192
+ r = (r << shift) | mp_shl(tabr, taba, n, shift, 0);
193
+ }
194
+ for(i = n - 1; i >= 0; i--) {
195
+ tabr[i] = udiv1norm(&r, r, taba[i], b, b_inv);
196
+ }
197
+ r >>= shift;
198
+ return r;
199
+ }
200
+
201
+ static __maybe_unused void mpb_dump(const char *str, const mpb_t *a)
202
+ {
203
+ int i;
204
+
205
+ printf("%s= 0x", str);
206
+ for(i = a->len - 1; i >= 0; i--) {
207
+ printf("%08x", a->tab[i]);
208
+ if (i != 0)
209
+ printf("_");
210
+ }
211
+ printf("\n");
212
+ }
213
+
214
+ static void mpb_renorm(mpb_t *r)
215
+ {
216
+ while (r->len > 1 && r->tab[r->len - 1] == 0)
217
+ r->len--;
218
+ }
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
+ {
244
+ int i, n_bits;
245
+ uint64_t r;
246
+ if (b == 0)
247
+ return 1;
248
+ if (b == 1)
249
+ return a;
250
+ #ifdef USE_POW5_TABLE
251
+ if ((a == 5 || a == 10) && b <= 17) {
252
+ r = pow5_table[b - 1];
253
+ if (b >= 14) {
254
+ r |= (uint64_t)pow5h_table[b - 14] << 32;
255
+ }
256
+ if (a == 10)
257
+ r <<= b;
258
+ return r;
259
+ }
260
+ #endif
261
+ r = a;
262
+ n_bits = 32 - clz32(b);
263
+ for(i = n_bits - 2; i >= 0; i--) {
264
+ r *= r;
265
+ if ((b >> i) & 1)
266
+ r *= a;
267
+ }
268
+ return r;
269
+ }
270
+
271
+ static uint32_t pow_ui_inv(uint32_t *pr_inv, int *pshift, uint32_t a, uint32_t b)
272
+ {
273
+ uint32_t r_inv, r;
274
+ int shift;
275
+ #ifdef USE_POW5_TABLE
276
+ if (a == 5 && b >= 1 && b <= 13) {
277
+ r = pow5_table[b - 1];
278
+ shift = clz32(r);
279
+ r <<= shift;
280
+ r_inv = pow5_inv_table[b - 1];
281
+ } else
282
+ #endif
283
+ {
284
+ r = pow_ui(a, b);
285
+ shift = clz32(r);
286
+ r <<= shift;
287
+ r_inv = udiv1norm_init(r);
288
+ }
289
+ *pshift = shift;
290
+ *pr_inv = r_inv;
291
+ return r;
292
+ }
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
+ {
302
+ int l;
303
+
304
+ l = (unsigned)k / LIMB_BITS;
305
+ k = k & (LIMB_BITS - 1);
306
+ if (l >= r->len)
307
+ return 0;
308
+ else
309
+ return (r->tab[l] >> k) & 1;
310
+ }
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
+ {
315
+ int l, i;
316
+
317
+ if (shift == 0)
318
+ return;
319
+ if (shift < 0) {
320
+ shift = -shift;
321
+ l = (unsigned)shift / LIMB_BITS;
322
+ shift = shift & (LIMB_BITS - 1);
323
+ if (shift != 0) {
324
+ r->tab[r->len] = mp_shl(r->tab, r->tab, r->len, shift, 0);
325
+ r->len++;
326
+ mpb_renorm(r);
327
+ }
328
+ if (l > 0) {
329
+ for(i = r->len - 1; i >= 0; i--)
330
+ r->tab[i + l] = r->tab[i];
331
+ for(i = 0; i < l; i++)
332
+ r->tab[i] = 0;
333
+ r->len += l;
334
+ }
335
+ } else {
336
+ limb_t bit1, bit2;
337
+ int k, add_one;
338
+
339
+ switch(rnd_mode) {
340
+ default:
341
+ case JS_RNDZ:
342
+ add_one = 0;
343
+ break;
344
+ case JS_RNDN:
345
+ case JS_RNDNA:
346
+ bit1 = mpb_get_bit(r, shift - 1);
347
+ if (bit1) {
348
+ if (rnd_mode == JS_RNDNA) {
349
+ bit2 = 1;
350
+ } else {
351
+ /* bit2 = oring of all the bits after bit1 */
352
+ bit2 = 0;
353
+ if (shift >= 2) {
354
+ k = shift - 1;
355
+ l = (unsigned)k / LIMB_BITS;
356
+ k = k & (LIMB_BITS - 1);
357
+ for(i = 0; i < min_int(l, r->len); i++)
358
+ bit2 |= r->tab[i];
359
+ if (l < r->len)
360
+ bit2 |= r->tab[l] & (((limb_t)1 << k) - 1);
361
+ }
362
+ }
363
+ if (bit2) {
364
+ add_one = 1;
365
+ } else {
366
+ /* round to even */
367
+ add_one = mpb_get_bit(r, shift);
368
+ }
369
+ } else {
370
+ add_one = 0;
371
+ }
372
+ break;
373
+ }
374
+
375
+ l = (unsigned)shift / LIMB_BITS;
376
+ shift = shift & (LIMB_BITS - 1);
377
+ if (l >= r->len) {
378
+ r->len = 1;
379
+ r->tab[0] = add_one;
380
+ } else {
381
+ if (l > 0) {
382
+ r->len -= l;
383
+ for(i = 0; i < r->len; i++)
384
+ r->tab[i] = r->tab[i + l];
385
+ }
386
+ if (shift != 0) {
387
+ mp_shr(r->tab, r->tab, r->len, shift, 0);
388
+ mpb_renorm(r);
389
+ }
390
+ if (add_one) {
391
+ limb_t a;
392
+ a = mp_add_ui(r->tab, 1, r->len);
393
+ if (a)
394
+ r->tab[r->len++] = a;
395
+ }
396
+ }
397
+ }
398
+ }
399
+
400
+ /* return -1, 0 or 1 */
401
+ static int mpb_cmp(const mpb_t *a, const mpb_t *b)
402
+ {
403
+ mp_size_t i;
404
+ if (a->len < b->len)
405
+ return -1;
406
+ else if (a->len > b->len)
407
+ return 1;
408
+ for(i = a->len - 1; i >= 0; i--) {
409
+ if (a->tab[i] != b->tab[i]) {
410
+ if (a->tab[i] < b->tab[i])
411
+ return -1;
412
+ else
413
+ return 1;
414
+ }
415
+ }
416
+ return 0;
417
+ }
418
+
419
+ static void mpb_set_u64(mpb_t *r, uint64_t m)
420
+ {
421
+ #if LIMB_BITS == 64
422
+ r->tab[0] = m;
423
+ r->len = 1;
424
+ #else
425
+ r->tab[0] = m;
426
+ r->tab[1] = m >> LIMB_BITS;
427
+ if (r->tab[1] == 0)
428
+ r->len = 1;
429
+ else
430
+ r->len = 2;
431
+ #endif
432
+ }
433
+
434
+ static uint64_t mpb_get_u64(mpb_t *r)
435
+ {
436
+ #if LIMB_BITS == 64
437
+ return r->tab[0];
438
+ #else
439
+ if (r->len == 1) {
440
+ return r->tab[0];
441
+ } else {
442
+ return r->tab[0] | ((uint64_t)r->tab[1] << LIMB_BITS);
443
+ }
444
+ #endif
445
+ }
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
+ {
450
+ limb_t v;
451
+ v = a->tab[a->len - 1];
452
+ if (v == 0)
453
+ return -1;
454
+ else
455
+ return a->len * LIMB_BITS - 1 - clz32(v);
456
+ }
457
+
458
+ #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
+ {
476
+ int radix_bits, mult;
477
+
478
+ if ((radix & (radix - 1)) == 0) {
479
+ /* if the radix is a power of two better to do it exactly */
480
+ radix_bits = 31 - clz32(radix);
481
+ if (a < 0)
482
+ a -= radix_bits - 1;
483
+ return a / radix_bits;
484
+ } else {
485
+ mult = mul_log2_radix_table[radix - 2];
486
+ return ((int64_t)a * mult) >> MUL_LOG2_RADIX_BASE_LOG2;
487
+ }
488
+ }
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
+ {
534
+ int digit, i;
535
+ for(i = len - 1; i >= 0; i--) {
536
+ digit = n % 10;
537
+ n = n / 10;
538
+ buf[i] = digit + '0';
539
+ }
540
+ }
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
+ {
545
+ int digit, i;
546
+ unsigned int mask;
547
+
548
+ mask = (1 << radix_bits) - 1;
549
+ for(i = len - 1; i >= 0; i--) {
550
+ digit = n & mask;
551
+ n >>= radix_bits;
552
+ if (digit < 10)
553
+ digit += '0';
554
+ else
555
+ digit += 'a' - 10;
556
+ buf[i] = digit;
557
+ }
558
+ }
559
+
560
+ /* len >= 1. 2 <= radix <= 36 */
561
+ static void limb_to_a(char *buf, limb_t n, unsigned int radix, int len)
562
+ {
563
+ int digit, i;
564
+
565
+ if (radix == 10) {
566
+ /* specific case with constant divisor */
567
+ #if LIMB_BITS == 32
568
+ 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
+ } else {
578
+ for(i = len - 1; i >= 0; i--) {
579
+ digit = (limb_t)n % radix;
580
+ n = (limb_t)n / radix;
581
+ if (digit < 10)
582
+ digit += '0';
583
+ else
584
+ digit += 'a' - 10;
585
+ buf[i] = digit;
586
+ }
587
+ }
588
+ }
589
+
590
+ size_t u32toa(char *buf, uint32_t n)
591
+ {
592
+ char buf1[10], *q;
593
+ size_t len;
594
+
595
+ q = buf1 + sizeof(buf1);
596
+ do {
597
+ *--q = n % 10 + '0';
598
+ n /= 10;
599
+ } while (n != 0);
600
+ len = buf1 + sizeof(buf1) - q;
601
+ memcpy(buf, q, len);
602
+ return len;
603
+ }
604
+
605
+ size_t i32toa(char *buf, int32_t n)
606
+ {
607
+ if (n >= 0) {
608
+ return u32toa(buf, n);
609
+ } else {
610
+ buf[0] = '-';
611
+ return u32toa(buf + 1, -(uint32_t)n) + 1;
612
+ }
613
+ }
614
+
615
+ #ifdef USE_FAST_INT
616
+ size_t u64toa(char *buf, uint64_t n)
617
+ {
618
+ if (n < 0x100000000) {
619
+ return u32toa(buf, n);
620
+ } else {
621
+ uint64_t n1;
622
+ char *q = buf;
623
+ uint32_t n2;
624
+
625
+ n1 = n / 1000000000;
626
+ n %= 1000000000;
627
+ if (n1 >= 0x100000000) {
628
+ n2 = n1 / 1000000000;
629
+ n1 = n1 % 1000000000;
630
+ /* at most two digits */
631
+ if (n2 >= 10) {
632
+ *q++ = n2 / 10 + '0';
633
+ n2 %= 10;
634
+ }
635
+ *q++ = n2 + '0';
636
+ u32toa_len(q, n1, 9);
637
+ q += 9;
638
+ } else {
639
+ q += u32toa(q, n1);
640
+ }
641
+ u32toa_len(q, n, 9);
642
+ q += 9;
643
+ return q - buf;
644
+ }
645
+ }
646
+
647
+ size_t i64toa(char *buf, int64_t n)
648
+ {
649
+ if (n >= 0) {
650
+ return u64toa(buf, n);
651
+ } else {
652
+ buf[0] = '-';
653
+ return u64toa(buf + 1, -(uint64_t)n) + 1;
654
+ }
655
+ }
656
+
657
+ /* XXX: only tested for 1 <= n < 2^53 */
658
+ size_t u64toa_radix(char *buf, uint64_t n, unsigned int radix)
659
+ {
660
+ int radix_bits, l;
661
+ if (likely(radix == 10))
662
+ return u64toa(buf, n);
663
+ if ((radix & (radix - 1)) == 0) {
664
+ radix_bits = 31 - clz32(radix);
665
+ if (n == 0)
666
+ l = 1;
667
+ else
668
+ l = (64 - clz64(n) + radix_bits - 1) / radix_bits;
669
+ u64toa_bin_len(buf, n, radix_bits, l);
670
+ return l;
671
+ } else {
672
+ char buf1[41], *q; /* maximum length for radix = 3 */
673
+ size_t len;
674
+ int digit;
675
+ q = buf1 + sizeof(buf1);
676
+ do {
677
+ digit = n % radix;
678
+ n /= radix;
679
+ if (digit < 10)
680
+ digit += '0';
681
+ else
682
+ digit += 'a' - 10;
683
+ *--q = digit;
684
+ } while (n != 0);
685
+ len = buf1 + sizeof(buf1) - q;
686
+ memcpy(buf, q, len);
687
+ return len;
688
+ }
689
+ }
690
+
691
+ size_t i64toa_radix(char *buf, int64_t n, unsigned int radix)
692
+ {
693
+ if (n >= 0) {
694
+ return u64toa_radix(buf, n, radix);
695
+ } else {
696
+ buf[0] = '-';
697
+ return u64toa_radix(buf + 1, -(uint64_t)n, radix) + 1;
698
+ }
699
+ }
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
+ {
851
+ int n_digits, digits_per_limb, radix_bits, n, len;
852
+
853
+ n_digits = n_digits1;
854
+ if ((radix & (radix - 1)) == 0) {
855
+ /* radix = 2^radix_bits */
856
+ radix_bits = 31 - clz32(radix);
857
+ } else {
858
+ radix_bits = 0;
859
+ }
860
+ digits_per_limb = digits_per_limb_table[radix - 2];
861
+ if (radix_bits != 0) {
862
+ for(;;) {
863
+ n = min_int(n_digits, digits_per_limb);
864
+ n_digits -= n;
865
+ u64toa_bin_len(buf + n_digits, a->tab[0], radix_bits, n);
866
+ if (n_digits == 0)
867
+ break;
868
+ mpb_shr_round(a, digits_per_limb * radix_bits, JS_RNDZ);
869
+ }
870
+ } else {
871
+ limb_t r;
872
+ while (n_digits != 0) {
873
+ n = min_int(n_digits, digits_per_limb);
874
+ n_digits -= n;
875
+ r = mp_div1(a->tab, a->tab, a->len, radix_base_table[radix - 2], 0);
876
+ mpb_renorm(a);
877
+ limb_to_a(buf + n_digits, r, radix, n);
878
+ }
879
+ }
880
+
881
+ /* add the dot */
882
+ len = n_digits1;
883
+ if (dot_pos != n_digits1) {
884
+ memmove(buf + dot_pos + 1, buf + dot_pos, n_digits1 - dot_pos);
885
+ buf[dot_pos] = '.';
886
+ len++;
887
+ }
888
+ return len;
889
+ }
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
+ {
895
+ int e_offset, d, n, n0;
896
+
897
+ e_offset = -f * radix_shift;
898
+ if (radix1 != 1) {
899
+ d = digits_per_limb_table[radix1 - 2];
900
+ if (f >= 0) {
901
+ limb_t h, b;
902
+
903
+ b = 0;
904
+ n0 = 0;
905
+ while (f != 0) {
906
+ n = min_int(f, d);
907
+ if (n != n0) {
908
+ b = pow_ui(radix1, n);
909
+ n0 = n;
910
+ }
911
+ h = mp_mul1(a->tab, a->tab, a->len, b, 0);
912
+ if (h != 0) {
913
+ a->tab[a->len++] = h;
914
+ }
915
+ f -= n;
916
+ }
917
+ } else {
918
+ int extra_bits, l, shift;
919
+ limb_t r, rem, b, b_inv;
920
+
921
+ f = -f;
922
+ l = (f + d - 1) / d; /* high bound for the number of limbs (XXX: make it better) */
923
+ e_offset += l * LIMB_BITS;
924
+ if (!is_int) {
925
+ /* at least 'e' bits are needed in the final result for rounding */
926
+ extra_bits = max_int(e - mpb_floor_log2(a), 0);
927
+ } else {
928
+ /* at least two extra bits are needed in the final result
929
+ for rounding */
930
+ extra_bits = max_int(2 + e - e_offset, 0);
931
+ }
932
+ e_offset += extra_bits;
933
+ mpb_shr_round(a, -(l * LIMB_BITS + extra_bits), JS_RNDZ);
934
+
935
+ b = 0;
936
+ b_inv = 0;
937
+ shift = 0;
938
+ n0 = 0;
939
+ rem = 0;
940
+ while (f != 0) {
941
+ n = min_int(f, d);
942
+ if (n != n0) {
943
+ b = pow_ui_inv(&b_inv, &shift, radix1, n);
944
+ n0 = n;
945
+ }
946
+ r = mp_div1norm(a->tab, a->tab, a->len, b, 0, b_inv, shift);
947
+ rem |= r;
948
+ mpb_renorm(a);
949
+ f -= n;
950
+ }
951
+ /* if the remainder is non zero, use it for rounding */
952
+ a->tab[0] |= (rem != 0);
953
+ }
954
+ }
955
+ return e_offset;
956
+ }
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
+ {
962
+ int e_offset;
963
+
964
+ mpb_set_u64(tmp1, m);
965
+ e_offset = mul_pow(tmp1, radix1, radix_shift, f, TRUE, e);
966
+ mpb_shr_round(tmp1, -e + e_offset, rnd_mode);
967
+ }
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
+ {
972
+ int e;
973
+ uint64_t m;
974
+
975
+ if (a->tab[0] == 0 && a->len == 1) {
976
+ /* zero result */
977
+ m = 0;
978
+ e = 0; /* don't care */
979
+ } else {
980
+ int prec, prec1, e_min;
981
+ e = mpb_floor_log2(a) + 1 - e_offset;
982
+ prec1 = 53;
983
+ e_min = -1021;
984
+ if (e < e_min) {
985
+ /* subnormal result or zero */
986
+ prec = prec1 - (e_min - e);
987
+ } else {
988
+ prec = prec1;
989
+ }
990
+ mpb_shr_round(a, e + e_offset - prec, rnd_mode);
991
+ m = mpb_get_u64(a);
992
+ m <<= (53 - prec);
993
+ /* mantissa overflow due to rounding */
994
+ if (m >= (uint64_t)1 << 53) {
995
+ m >>= 1;
996
+ e++;
997
+ }
998
+ }
999
+ *pe = e;
1000
+ return m;
1001
+ }
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
+ {
1009
+ int e_offset;
1010
+
1011
+ e_offset = mul_pow(a, radix1, radix_shift, f, FALSE, 55);
1012
+ return round_to_d(pe, a, e_offset, rnd_mode);
1013
+ }
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
+ {
1036
+ int fmt = flags & JS_DTOA_FORMAT_MASK;
1037
+ int n, e;
1038
+ uint64_t a;
1039
+
1040
+ if (fmt != JS_DTOA_FORMAT_FRAC) {
1041
+ if (fmt == JS_DTOA_FORMAT_FREE) {
1042
+ n = dtoa_max_digits_table[radix - 2];
1043
+ } else {
1044
+ n = n_digits;
1045
+ }
1046
+ if ((flags & JS_DTOA_EXP_MASK) == JS_DTOA_EXP_DISABLED) {
1047
+ /* no exponential */
1048
+ a = float64_as_uint64(d);
1049
+ e = (a >> 52) & 0x7ff;
1050
+ if (e == 0x7ff) {
1051
+ /* NaN, Infinity */
1052
+ n = 0;
1053
+ } else {
1054
+ e -= 1023;
1055
+ /* XXX: adjust */
1056
+ n += 10 + abs(mul_log2_radix(e - 1, radix));
1057
+ }
1058
+ } else {
1059
+ /* extra: sign, 1 dot and exponent "e-1000" */
1060
+ n += 1 + 1 + 6;
1061
+ }
1062
+ } else {
1063
+ a = float64_as_uint64(d);
1064
+ e = (a >> 52) & 0x7ff;
1065
+ if (e == 0x7ff) {
1066
+ /* NaN, Infinity */
1067
+ n = 0;
1068
+ } else {
1069
+ /* high bound for the integer part */
1070
+ e -= 1023;
1071
+ /* x < 2^(e + 1) */
1072
+ if (e < 0) {
1073
+ n = 1;
1074
+ } else {
1075
+ n = 2 + mul_log2_radix(e - 1, radix);
1076
+ }
1077
+ /* sign, extra digit, 1 dot */
1078
+ n += 1 + 1 + 1 + n_digits;
1079
+ }
1080
+ }
1081
+ return max_int(n, 9); /* also include NaN and [-]Infinity */
1082
+ }
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
+ {
1096
+ void *ret;
1097
+ ret = *pptr;
1098
+ *pptr += (size + 7) / 8;
1099
+ return ret;
1100
+ }
1101
+
1102
+ static void dtoa_free(void *ptr)
1103
+ {
1104
+ }
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
+ {
1111
+ uint64_t a, m, *mptr = tmp_mem->mem;
1112
+ int e, sgn, l, E, P, i, E_max, radix1, radix_shift;
1113
+ char *q;
1114
+ mpb_t *tmp1, *mant_max;
1115
+ int fmt = flags & JS_DTOA_FORMAT_MASK;
1116
+
1117
+ tmp1 = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * DBIGNUM_LEN_MAX);
1118
+ mant_max = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * MANT_LEN_MAX);
1119
+ assert((mptr - tmp_mem->mem) <= sizeof(JSDTOATempMem) / sizeof(mptr[0]));
1120
+
1121
+ radix_shift = ctz32(radix);
1122
+ radix1 = radix >> radix_shift;
1123
+ a = float64_as_uint64(d);
1124
+ sgn = a >> 63;
1125
+ e = (a >> 52) & 0x7ff;
1126
+ m = a & (((uint64_t)1 << 52) - 1);
1127
+ q = buf;
1128
+ if (e == 0x7ff) {
1129
+ if (m == 0) {
1130
+ if (sgn)
1131
+ *q++ = '-';
1132
+ memcpy(q, "Infinity", 8);
1133
+ q += 8;
1134
+ } else {
1135
+ memcpy(q, "NaN", 3);
1136
+ q += 3;
1137
+ }
1138
+ goto done;
1139
+ } else if (e == 0) {
1140
+ if (m == 0) {
1141
+ tmp1->len = 1;
1142
+ tmp1->tab[0] = 0;
1143
+ E = 1;
1144
+ if (fmt == JS_DTOA_FORMAT_FREE)
1145
+ P = 1;
1146
+ else if (fmt == JS_DTOA_FORMAT_FRAC)
1147
+ P = n_digits + 1;
1148
+ else
1149
+ P = n_digits;
1150
+ goto output;
1151
+ }
1152
+ /* denormal number: convert to a normal number */
1153
+ l = clz64(m) - 11;
1154
+ e -= l - 1;
1155
+ m <<= l;
1156
+ } else {
1157
+ m |= (uint64_t)1 << 52;
1158
+ }
1159
+ /* remove the bias */
1160
+ e -= 1022;
1161
+ /* d = 2^(e-53)*m */
1162
+ // printf("m=0x%016" PRIx64 " e=%d\n", m, e);
1163
+ #ifdef USE_FAST_INT
1164
+ if (fmt == JS_DTOA_FORMAT_FREE &&
1165
+ e >= 1 && e <= 53 &&
1166
+ (m & (((uint64_t)1 << (53 - e)) - 1)) == 0 &&
1167
+ (flags & JS_DTOA_EXP_MASK) != JS_DTOA_EXP_ENABLED) {
1168
+ m >>= 53 - e;
1169
+ /* 'm' is never zero */
1170
+ if (sgn)
1171
+ *q++ = '-';
1172
+ q += u64toa_radix(q, m, radix);
1173
+ goto done;
1174
+ }
1175
+ #endif
1176
+
1177
+ /* this choice of E implies F=round(x*B^(P-E) is such as:
1178
+ B^(P-1) <= F < 2.B^P. */
1179
+ E = 1 + mul_log2_radix(e - 1, radix);
1180
+
1181
+ if (fmt == JS_DTOA_FORMAT_FREE) {
1182
+ int P_max, E0, e1, E_found, P_found;
1183
+ uint64_t m1, mant_found, mant, mant_max1;
1184
+ /* P_max is guarranteed to work by construction */
1185
+ P_max = dtoa_max_digits_table[radix - 2];
1186
+ E0 = E;
1187
+ E_found = 0;
1188
+ P_found = 0;
1189
+ mant_found = 0;
1190
+ /* find the minimum number of digits by successive tries */
1191
+ P = P_max; /* P_max is guarateed to work */
1192
+ for(;;) {
1193
+ /* mant_max always fits on 64 bits */
1194
+ mant_max1 = pow_ui(radix, P);
1195
+ /* compute the mantissa in base B */
1196
+ E = E0;
1197
+ for(;;) {
1198
+ /* XXX: add inexact flag */
1199
+ mul_pow_round(tmp1, m, e - 53, radix1, radix_shift, P - E, JS_RNDN);
1200
+ mant = mpb_get_u64(tmp1);
1201
+ if (mant < mant_max1)
1202
+ break;
1203
+ E++; /* at most one iteration is possible */
1204
+ }
1205
+ /* remove useless trailing zero digits */
1206
+ while ((mant % radix) == 0) {
1207
+ mant /= radix;
1208
+ P--;
1209
+ }
1210
+ /* garanteed to work for P = P_max */
1211
+ if (P_found == 0)
1212
+ goto prec_found;
1213
+ /* convert back to base 2 */
1214
+ mpb_set_u64(tmp1, mant);
1215
+ m1 = mul_pow_round_to_d(&e1, tmp1, radix1, radix_shift, E - P, JS_RNDN);
1216
+ // printf("P=%2d: m=0x%016" PRIx64 " e=%d m1=0x%016" PRIx64 " e1=%d\n", P, m, e, m1, e1);
1217
+ /* Note: (m, e) is never zero here, so the exponent for m1
1218
+ = 0 does not matter */
1219
+ if (m1 == m && e1 == e) {
1220
+ prec_found:
1221
+ P_found = P;
1222
+ E_found = E;
1223
+ mant_found = mant;
1224
+ if (P == 1)
1225
+ break;
1226
+ P--; /* try lower exponent */
1227
+ } else {
1228
+ break;
1229
+ }
1230
+ }
1231
+ P = P_found;
1232
+ E = E_found;
1233
+ mpb_set_u64(tmp1, mant_found);
1234
+ #ifdef JS_DTOA_DUMP_STATS
1235
+ if (radix == 10) {
1236
+ out_len_count[P - 1]++;
1237
+ }
1238
+ #endif
1239
+ } else if (fmt == JS_DTOA_FORMAT_FRAC) {
1240
+ int len;
1241
+
1242
+ assert(n_digits >= 0 && n_digits <= JS_DTOA_MAX_DIGITS);
1243
+ /* P = max_int(E, 1) + n_digits; */
1244
+ /* frac is rounded using RNDNA */
1245
+ mul_pow_round(tmp1, m, e - 53, radix1, radix_shift, n_digits, JS_RNDNA);
1246
+
1247
+ /* "-0" is displayed as "0" */
1248
+ if (sgn && !(tmp1->tab[0] == 0 && tmp1->len == 1)) {
1249
+ *q++ = '-';
1250
+ }
1251
+ /* we add one extra digit on the left and remove it if needed
1252
+ to avoid testing if the result is < radix^P */
1253
+ len = output_digits(q, tmp1, radix, max_int(E + 1, 1) + n_digits,
1254
+ max_int(E + 1, 1));
1255
+ if (q[0] == '0' && len >= 2 && q[1] != '.') {
1256
+ len--;
1257
+ memmove(q, q + 1, len);
1258
+ }
1259
+ q += len;
1260
+ goto done;
1261
+ } else {
1262
+ int pow_shift;
1263
+ assert(n_digits >= 1 && n_digits <= JS_DTOA_MAX_DIGITS);
1264
+ P = n_digits;
1265
+ /* mant_max = radix^P */
1266
+ mant_max->len = 1;
1267
+ mant_max->tab[0] = 1;
1268
+ pow_shift = mul_pow(mant_max, radix1, radix_shift, P, FALSE, 0);
1269
+ mpb_shr_round(mant_max, pow_shift, JS_RNDZ);
1270
+
1271
+ for(;;) {
1272
+ /* fixed and frac are rounded using RNDNA */
1273
+ mul_pow_round(tmp1, m, e - 53, radix1, radix_shift, P - E, JS_RNDNA);
1274
+ if (mpb_cmp(tmp1, mant_max) < 0)
1275
+ break;
1276
+ E++; /* at most one iteration is possible */
1277
+ }
1278
+ }
1279
+ output:
1280
+ /* "-0" is displayed as "0" if JS_DTOA_MINUS_ZERO is not present */
1281
+ if (sgn && ((flags & JS_DTOA_MINUS_ZERO) ||
1282
+ !(tmp1->tab[0] == 0 && tmp1->len == 1))) {
1283
+ *q++ = '-';
1284
+ }
1285
+ if (fmt == JS_DTOA_FORMAT_FIXED)
1286
+ E_max = n_digits;
1287
+ else
1288
+ E_max = dtoa_max_digits_table[radix - 2] + 4;
1289
+ if ((flags & JS_DTOA_EXP_MASK) == JS_DTOA_EXP_ENABLED ||
1290
+ ((flags & JS_DTOA_EXP_MASK) == JS_DTOA_EXP_AUTO && (E <= -6 || E > E_max))) {
1291
+ q += output_digits(q, tmp1, radix, P, 1);
1292
+ E--;
1293
+ if (radix == 10) {
1294
+ *q++ = 'e';
1295
+ } else if (radix1 == 1 && radix_shift <= 4) {
1296
+ E *= radix_shift;
1297
+ *q++ = 'p';
1298
+ } else {
1299
+ *q++ = '@';
1300
+ }
1301
+ if (E < 0) {
1302
+ *q++ = '-';
1303
+ E = -E;
1304
+ } else {
1305
+ *q++ = '+';
1306
+ }
1307
+ q += u32toa(q, E);
1308
+ } else if (E <= 0) {
1309
+ *q++ = '0';
1310
+ *q++ = '.';
1311
+ for(i = 0; i < -E; i++)
1312
+ *q++ = '0';
1313
+ q += output_digits(q, tmp1, radix, P, P);
1314
+ } else {
1315
+ q += output_digits(q, tmp1, radix, P, min_int(P, E));
1316
+ for(i = 0; i < E - P; i++)
1317
+ *q++ = '0';
1318
+ }
1319
+ done:
1320
+ *q = '\0';
1321
+ dtoa_free(mant_max);
1322
+ dtoa_free(tmp1);
1323
+ return q - buf;
1324
+ }
1325
+
1326
+ static inline int to_digit(int c)
1327
+ {
1328
+ if (c >= '0' && c <= '9')
1329
+ return c - '0';
1330
+ else if (c >= 'A' && c <= 'Z')
1331
+ return c - 'A' + 10;
1332
+ else if (c >= 'a' && c <= 'z')
1333
+ return c - 'a' + 10;
1334
+ else
1335
+ return 36;
1336
+ }
1337
+
1338
+ /* r = r * radix_base + a. radix_base = 0 means radix_base = 2^32 */
1339
+ static void mpb_mul1_base(mpb_t *r, limb_t radix_base, limb_t a)
1340
+ {
1341
+ int i;
1342
+ if (r->tab[0] == 0 && r->len == 1) {
1343
+ r->tab[0] = a;
1344
+ } else {
1345
+ if (radix_base == 0) {
1346
+ for(i = r->len; i >= 0; i--) {
1347
+ r->tab[i + 1] = r->tab[i];
1348
+ }
1349
+ r->tab[0] = a;
1350
+ } else {
1351
+ r->tab[r->len] = mp_mul1(r->tab, r->tab, r->len,
1352
+ radix_base, a);
1353
+ }
1354
+ r->len++;
1355
+ mpb_renorm(r);
1356
+ }
1357
+ }
1358
+
1359
+ /* XXX: add fast path for small integers */
1360
+ double js_atod(const char *str, const char **pnext, int radix, int flags,
1361
+ JSATODTempMem *tmp_mem)
1362
+ {
1363
+ uint64_t *mptr = tmp_mem->mem;
1364
+ const char *p, *p_start;
1365
+ limb_t cur_limb, radix_base, extra_digits;
1366
+ int is_neg, digit_count, limb_digit_count, digits_per_limb, sep, radix1, radix_shift;
1367
+ int radix_bits, expn, e, max_digits, expn_offset, dot_pos, sig_pos, pos;
1368
+ mpb_t *tmp0;
1369
+ double dval;
1370
+ BOOL is_bin_exp, is_zero, expn_overflow;
1371
+ uint64_t m, a;
1372
+
1373
+ tmp0 = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * DBIGNUM_LEN_MAX);
1374
+ assert((mptr - tmp_mem->mem) <= sizeof(JSATODTempMem) / sizeof(mptr[0]));
1375
+ /* optional separator between digits */
1376
+ sep = (flags & JS_ATOD_ACCEPT_UNDERSCORES) ? '_' : 256;
1377
+
1378
+ p = str;
1379
+ is_neg = 0;
1380
+ if (p[0] == '+') {
1381
+ p++;
1382
+ p_start = p;
1383
+ } else if (p[0] == '-') {
1384
+ is_neg = 1;
1385
+ p++;
1386
+ p_start = p;
1387
+ } else {
1388
+ p_start = p;
1389
+ }
1390
+
1391
+ if (p[0] == '0') {
1392
+ if ((p[1] == 'x' || p[1] == 'X') &&
1393
+ (radix == 0 || radix == 16)) {
1394
+ p += 2;
1395
+ radix = 16;
1396
+ } else if ((p[1] == 'o' || p[1] == 'O') &&
1397
+ radix == 0 && (flags & JS_ATOD_ACCEPT_BIN_OCT)) {
1398
+ p += 2;
1399
+ radix = 8;
1400
+ } else if ((p[1] == 'b' || p[1] == 'B') &&
1401
+ radix == 0 && (flags & JS_ATOD_ACCEPT_BIN_OCT)) {
1402
+ p += 2;
1403
+ radix = 2;
1404
+ } else if ((p[1] >= '0' && p[1] <= '9') &&
1405
+ radix == 0 && (flags & JS_ATOD_ACCEPT_LEGACY_OCTAL)) {
1406
+ int i;
1407
+ sep = 256;
1408
+ for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++)
1409
+ continue;
1410
+ if (p[i] == '8' || p[i] == '9')
1411
+ goto no_prefix;
1412
+ p += 1;
1413
+ radix = 8;
1414
+ } else {
1415
+ goto no_prefix;
1416
+ }
1417
+ /* there must be a digit after the prefix */
1418
+ if (to_digit((uint8_t)*p) >= radix)
1419
+ goto fail;
1420
+ no_prefix: ;
1421
+ } else {
1422
+ if (!(flags & JS_ATOD_INT_ONLY) && strstart(p, "Infinity", &p))
1423
+ goto overflow;
1424
+ }
1425
+ if (radix == 0)
1426
+ radix = 10;
1427
+
1428
+ cur_limb = 0;
1429
+ expn_offset = 0;
1430
+ digit_count = 0;
1431
+ limb_digit_count = 0;
1432
+ max_digits = atod_max_digits_table[radix - 2];
1433
+ digits_per_limb = digits_per_limb_table[radix - 2];
1434
+ radix_base = radix_base_table[radix - 2];
1435
+ radix_shift = ctz32(radix);
1436
+ radix1 = radix >> radix_shift;
1437
+ if (radix1 == 1) {
1438
+ /* radix = 2^radix_bits */
1439
+ radix_bits = radix_shift;
1440
+ } else {
1441
+ radix_bits = 0;
1442
+ }
1443
+ tmp0->len = 1;
1444
+ tmp0->tab[0] = 0;
1445
+ extra_digits = 0;
1446
+ pos = 0;
1447
+ dot_pos = -1;
1448
+ /* skip leading zeros */
1449
+ for(;;) {
1450
+ if (*p == '.' && (p > p_start || to_digit(p[1]) < radix) &&
1451
+ !(flags & JS_ATOD_INT_ONLY)) {
1452
+ if (*p == sep)
1453
+ goto fail;
1454
+ if (dot_pos >= 0)
1455
+ break;
1456
+ dot_pos = pos;
1457
+ p++;
1458
+ }
1459
+ if (*p == sep && p > p_start && p[1] == '0')
1460
+ p++;
1461
+ if (*p != '0')
1462
+ break;
1463
+ p++;
1464
+ pos++;
1465
+ }
1466
+
1467
+ sig_pos = pos;
1468
+ for(;;) {
1469
+ limb_t c;
1470
+ if (*p == '.' && (p > p_start || to_digit(p[1]) < radix) &&
1471
+ !(flags & JS_ATOD_INT_ONLY)) {
1472
+ if (*p == sep)
1473
+ goto fail;
1474
+ if (dot_pos >= 0)
1475
+ break;
1476
+ dot_pos = pos;
1477
+ p++;
1478
+ }
1479
+ if (*p == sep && p > p_start && to_digit(p[1]) < radix)
1480
+ p++;
1481
+ c = to_digit(*p);
1482
+ if (c >= radix)
1483
+ break;
1484
+ p++;
1485
+ pos++;
1486
+ if (digit_count < max_digits) {
1487
+ /* XXX: could be faster when radix_bits != 0 */
1488
+ cur_limb = cur_limb * radix + c;
1489
+ limb_digit_count++;
1490
+ if (limb_digit_count == digits_per_limb) {
1491
+ mpb_mul1_base(tmp0, radix_base, cur_limb);
1492
+ cur_limb = 0;
1493
+ limb_digit_count = 0;
1494
+ }
1495
+ digit_count++;
1496
+ } else {
1497
+ extra_digits |= c;
1498
+ }
1499
+ }
1500
+ if (limb_digit_count != 0) {
1501
+ mpb_mul1_base(tmp0, pow_ui(radix, limb_digit_count), cur_limb);
1502
+ }
1503
+ if (digit_count == 0) {
1504
+ is_zero = TRUE;
1505
+ expn_offset = 0;
1506
+ } else {
1507
+ is_zero = FALSE;
1508
+ if (dot_pos < 0)
1509
+ dot_pos = pos;
1510
+ expn_offset = sig_pos + digit_count - dot_pos;
1511
+ }
1512
+
1513
+ /* Use the extra digits for rounding if the base is a power of
1514
+ two. Otherwise they are just truncated. */
1515
+ if (radix_bits != 0 && extra_digits != 0) {
1516
+ tmp0->tab[0] |= 1;
1517
+ }
1518
+
1519
+ /* parse the exponent, if any */
1520
+ expn = 0;
1521
+ expn_overflow = FALSE;
1522
+ is_bin_exp = FALSE;
1523
+ if (!(flags & JS_ATOD_INT_ONLY) &&
1524
+ ((radix == 10 && (*p == 'e' || *p == 'E')) ||
1525
+ (radix != 10 && (*p == '@' ||
1526
+ (radix_bits >= 1 && radix_bits <= 4 && (*p == 'p' || *p == 'P'))))) &&
1527
+ p > p_start) {
1528
+ BOOL exp_is_neg;
1529
+ int c;
1530
+ is_bin_exp = (*p == 'p' || *p == 'P');
1531
+ p++;
1532
+ exp_is_neg = 0;
1533
+ if (*p == '+') {
1534
+ p++;
1535
+ } else if (*p == '-') {
1536
+ exp_is_neg = 1;
1537
+ p++;
1538
+ }
1539
+ c = to_digit(*p);
1540
+ if (c >= 10)
1541
+ goto fail; /* XXX: could stop before the exponent part */
1542
+ expn = c;
1543
+ p++;
1544
+ for(;;) {
1545
+ if (*p == sep && to_digit(p[1]) < 10)
1546
+ p++;
1547
+ c = to_digit(*p);
1548
+ if (c >= 10)
1549
+ break;
1550
+ if (!expn_overflow) {
1551
+ if (unlikely(expn > ((INT32_MAX - 2 - 9) / 10))) {
1552
+ expn_overflow = TRUE;
1553
+ } else {
1554
+ expn = expn * 10 + c;
1555
+ }
1556
+ }
1557
+ p++;
1558
+ }
1559
+ if (exp_is_neg)
1560
+ expn = -expn;
1561
+ /* if zero result, the exponent can be arbitrarily large */
1562
+ if (!is_zero && expn_overflow) {
1563
+ if (exp_is_neg)
1564
+ a = 0;
1565
+ else
1566
+ a = (uint64_t)0x7ff << 52; /* infinity */
1567
+ goto done;
1568
+ }
1569
+ }
1570
+
1571
+ if (p == p_start)
1572
+ goto fail;
1573
+
1574
+ if (is_zero) {
1575
+ a = 0;
1576
+ } else {
1577
+ int expn1;
1578
+ if (radix_bits != 0) {
1579
+ if (!is_bin_exp)
1580
+ expn *= radix_bits;
1581
+ expn -= expn_offset * radix_bits;
1582
+ expn1 = expn + digit_count * radix_bits;
1583
+ if (expn1 >= 1024 + radix_bits)
1584
+ goto overflow;
1585
+ else if (expn1 <= -1075)
1586
+ goto underflow;
1587
+ m = round_to_d(&e, tmp0, -expn, JS_RNDN);
1588
+ } else {
1589
+ expn -= expn_offset;
1590
+ expn1 = expn + digit_count;
1591
+ if (expn1 >= max_exponent[radix - 2] + 1)
1592
+ goto overflow;
1593
+ else if (expn1 <= min_exponent[radix - 2])
1594
+ goto underflow;
1595
+ m = mul_pow_round_to_d(&e, tmp0, radix1, radix_shift, expn, JS_RNDN);
1596
+ }
1597
+ if (m == 0) {
1598
+ underflow:
1599
+ a = 0;
1600
+ } else if (e > 1024) {
1601
+ overflow:
1602
+ /* overflow */
1603
+ a = (uint64_t)0x7ff << 52;
1604
+ } else if (e < -1073) {
1605
+ /* underflow */
1606
+ /* XXX: check rounding */
1607
+ a = 0;
1608
+ } else if (e < -1021) {
1609
+ /* subnormal */
1610
+ a = m >> (-e - 1021);
1611
+ } else {
1612
+ a = ((uint64_t)(e + 1022) << 52) | (m & (((uint64_t)1 << 52) - 1));
1613
+ }
1614
+ }
1615
+ done:
1616
+ a |= (uint64_t)is_neg << 63;
1617
+ dval = uint64_as_float64(a);
1618
+ done1:
1619
+ if (pnext)
1620
+ *pnext = p;
1621
+ dtoa_free(tmp0);
1622
+ return dval;
1623
+ fail:
1624
+ dval = NAN;
1625
+ goto done1;
1626
+ }