json-as 1.4.0 → 1.5.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +50 -29
  2. package/README.md +84 -33
  3. package/assembly/custom/chars.ts +39 -78
  4. package/assembly/deserialize/index/arbitrary.ts +26 -8
  5. package/assembly/deserialize/index/float.ts +2 -4
  6. package/assembly/deserialize/index/integer.ts +2 -4
  7. package/assembly/deserialize/index/object.ts +6 -1
  8. package/assembly/deserialize/index/string.ts +2 -7
  9. package/assembly/deserialize/index/unsigned.ts +2 -4
  10. package/assembly/deserialize/naive/array/integer.ts +1 -1
  11. package/assembly/deserialize/naive/array/map.ts +1 -1
  12. package/assembly/deserialize/naive/array/object.ts +1 -1
  13. package/assembly/deserialize/naive/array/struct.ts +19 -1
  14. package/assembly/deserialize/naive/bool.ts +1 -5
  15. package/assembly/deserialize/naive/date.ts +1 -2
  16. package/assembly/deserialize/naive/float.ts +2 -7
  17. package/assembly/deserialize/naive/integer.ts +1 -2
  18. package/assembly/deserialize/naive/map.ts +5 -6
  19. package/assembly/deserialize/naive/object.ts +151 -13
  20. package/assembly/deserialize/naive/raw.ts +1 -5
  21. package/assembly/deserialize/naive/set.ts +2 -4
  22. package/assembly/deserialize/naive/staticarray.ts +1 -2
  23. package/assembly/deserialize/naive/string.ts +6 -9
  24. package/assembly/deserialize/naive/unsigned.ts +1 -2
  25. package/assembly/deserialize/simd/array/integer.ts +2 -7
  26. package/assembly/deserialize/simd/float.ts +3 -5
  27. package/assembly/deserialize/simd/integer.ts +2 -7
  28. package/assembly/deserialize/simd/string.ts +5 -22
  29. package/assembly/deserialize/swar/array/arbitrary.ts +1 -2
  30. package/assembly/deserialize/swar/array/array.ts +1 -2
  31. package/assembly/deserialize/swar/array/bool.ts +1 -2
  32. package/assembly/deserialize/swar/array/box.ts +1 -2
  33. package/assembly/deserialize/swar/array/float.ts +6 -18
  34. package/assembly/deserialize/swar/array/generic.ts +1 -2
  35. package/assembly/deserialize/swar/array/integer.ts +7 -16
  36. package/assembly/deserialize/swar/array/map.ts +1 -2
  37. package/assembly/deserialize/swar/array/object.ts +1 -2
  38. package/assembly/deserialize/swar/array/raw.ts +1 -2
  39. package/assembly/deserialize/swar/array/shared.ts +6 -13
  40. package/assembly/deserialize/swar/array/string.ts +3 -8
  41. package/assembly/deserialize/swar/array/struct.ts +2 -8
  42. package/assembly/deserialize/swar/array.ts +1 -3
  43. package/assembly/deserialize/swar/float.ts +4 -9
  44. package/assembly/deserialize/swar/integer.ts +2 -7
  45. package/assembly/deserialize/swar/string.ts +13 -15
  46. package/assembly/deserialize/swar/typedarray.ts +4 -4
  47. package/assembly/index.d.ts +29 -24
  48. package/assembly/index.ts +1362 -246
  49. package/assembly/serialize/index/arbitrary.ts +70 -4
  50. package/assembly/serialize/index/jsonarray.ts +51 -0
  51. package/assembly/serialize/index/object.ts +25 -3
  52. package/assembly/serialize/index/string.ts +1 -2
  53. package/assembly/serialize/index/typedarray.ts +1 -2
  54. package/assembly/serialize/index.ts +1 -0
  55. package/assembly/serialize/naive/array.ts +23 -34
  56. package/assembly/serialize/naive/bool.ts +0 -1
  57. package/assembly/serialize/naive/float.ts +16 -25
  58. package/assembly/serialize/naive/integer.ts +1 -5
  59. package/assembly/serialize/naive/raw.ts +1 -2
  60. package/assembly/serialize/naive/set.ts +0 -4
  61. package/assembly/serialize/naive/staticarray.ts +0 -5
  62. package/assembly/serialize/naive/string.ts +2 -5
  63. package/assembly/serialize/naive/typedarray.ts +0 -6
  64. package/assembly/serialize/simd/string.ts +1 -3
  65. package/assembly/serialize/swar/string.ts +1 -2
  66. package/assembly/util/atoi-fast.ts +4 -14
  67. package/assembly/util/bytes.ts +1 -2
  68. package/assembly/util/idofd.ts +1 -2
  69. package/assembly/util/isSpace.ts +1 -2
  70. package/assembly/util/itoa-fast.ts +6 -9
  71. package/assembly/util/nextPowerOf2.ts +1 -2
  72. package/assembly/util/parsefloat-fast.ts +3 -5
  73. package/assembly/util/ptrToStr.ts +1 -2
  74. package/assembly/util/scanValueEndSimd.ts +54 -16
  75. package/assembly/util/scanValueEndSwar.ts +67 -25
  76. package/assembly/util/scientific.ts +5 -8
  77. package/assembly/util/snp.ts +1 -2
  78. package/assembly/util/swar-int.ts +5 -10
  79. package/assembly/util/swar.ts +2 -4
  80. package/lib/as-bs.ts +23 -45
  81. package/package.json +14 -7
  82. package/transform/lib/index.js +108 -64
  83. package/transform/lib/types.d.ts +2 -1
  84. package/transform/lib/types.js +3 -0
  85. package/assembly/util/dragonbox-cache.ts +0 -445
  86. package/assembly/util/dragonbox.ts +0 -652
@@ -1,652 +0,0 @@
1
- import { DRAGONBOX_F32_CACHE, DRAGONBOX_F64_CACHE } from "./dragonbox-cache";
2
- import { decimalCount32, utoa32_dec_core } from "util/number";
3
- import { ensureItoaPairs, itoaU32, itoaU64 } from "./itoa-fast";
4
-
5
- const CHAR_MINUS: u16 = 45;
6
- const CHAR_DOT: u16 = 46;
7
- const CHAR_0: u16 = 48;
8
- const CHAR_E: u16 = 101;
9
- const CHAR_PLUS: u16 = 43;
10
-
11
- let _dbK: i32 = 0;
12
- let _dbMulInteger32: u32 = 0;
13
- let _dbMulInteger64: u64 = 0;
14
- let _dbMulIsInteger: bool = false;
15
- let _dbParity: bool = false;
16
- let _dbRemovedExponent: i32 = 0;
17
-
18
-
19
- @inline
20
- function rotr32(n: u32, r: i32): u32 {
21
- const s = r & 31;
22
- return (n >>> s) | (n << ((32 - s) & 31));
23
- }
24
-
25
-
26
- @inline
27
- function rotr64(n: u64, r: i32): u64 {
28
- const s = r & 63;
29
- return (n >>> s) | (n << ((64 - s) & 63));
30
- }
31
-
32
-
33
- @inline
34
- function floor_log10_pow2(e: i32): i32 {
35
- return (e * 315653) >> 20;
36
- }
37
-
38
-
39
- @inline
40
- function floor_log2_pow10(e: i32): i32 {
41
- return (e * 1741647) >> 19;
42
- }
43
-
44
-
45
- @inline
46
- function floor_log10_pow2_minus_log10_4_over_3(e: i32): i32 {
47
- return (e * 631305 - 261663) >> 21;
48
- }
49
-
50
-
51
- @inline
52
- function floor_log5_pow2(e: i32): i32 {
53
- return (e * 225799) >> 19;
54
- }
55
-
56
-
57
- @inline
58
- function floor_log5_pow2_minus_log5_3(e: i32): i32 {
59
- return (e * 451597 - 715764) >> 20;
60
- }
61
-
62
-
63
- @inline
64
- function umul128_upper64(x: u64, y: u64): u64 {
65
- const a = <u32>(x >>> 32);
66
- const b = <u32>x;
67
- const c = <u32>(y >>> 32);
68
- const d = <u32>y;
69
- const ac = <u64>a * c;
70
- const bc = <u64>b * c;
71
- const ad = <u64>a * d;
72
- const bd = <u64>b * d;
73
- const intermediate = (bd >>> 32) + <u32>ad + <u32>bc;
74
- return ac + (intermediate >>> 32) + (ad >>> 32) + (bc >>> 32);
75
- }
76
-
77
-
78
- @inline
79
- function umul96_upper64(x: u32, y: u64): u64 {
80
- const yh = <u32>(y >>> 32);
81
- const yl = <u32>y;
82
- const xyh = <u64>x * yh;
83
- const xyl = <u64>x * yl;
84
- return xyh + (xyl >>> 32);
85
- }
86
-
87
-
88
- @inline
89
- function computeMul32(u: u32, cache: u64): void {
90
- const r = umul96_upper64(u, cache);
91
- _dbMulInteger32 = <u32>(r >>> 32);
92
- _dbMulIsInteger = <u32>r == 0;
93
- }
94
-
95
-
96
- @inline
97
- function computeMulParity32(twoF: u32, cache: u64, beta: i32): void {
98
- const r = <u64>twoF * cache;
99
- _dbParity = ((r >>> (64 - beta)) & 1) != 0;
100
- _dbMulIsInteger = <u32>(r >>> (32 - beta)) == 0;
101
- }
102
-
103
-
104
- @inline
105
- function computeLeftEndpointShorter32(cache: u64, beta: i32): u32 {
106
- return <u32>((cache - (cache >>> 25)) >>> (40 - beta));
107
- }
108
-
109
-
110
- @inline
111
- function computeRightEndpointShorter32(cache: u64, beta: i32): u32 {
112
- return <u32>((cache + (cache >>> 24)) >>> (40 - beta));
113
- }
114
-
115
-
116
- @inline
117
- function computeRoundUpShorter32(cache: u64, beta: i32): u32 {
118
- return (<u32>(cache >>> (39 - beta)) + 1) >>> 1;
119
- }
120
-
121
- function removeTrailingZeros32(significand: u32): u32 {
122
- let exponent = 0;
123
- let r = rotr32(significand * 184254097, 4);
124
- let b = r < 429497;
125
- let s: u32 = b ? 1 : 0;
126
- if (b) significand = r;
127
-
128
- r = rotr32(significand * 42949673, 2);
129
- b = r < 42949673;
130
- s = s * 2 + (b ? 1 : 0);
131
- if (b) significand = r;
132
-
133
- r = rotr32(significand * 1288490189, 1);
134
- b = r < 429496730;
135
- s = s * 2 + (b ? 1 : 0);
136
- if (b) significand = r;
137
-
138
- exponent += s;
139
- _dbRemovedExponent = exponent;
140
- return significand;
141
- }
142
-
143
-
144
- @inline
145
- function divideByPow10_32_1(n: u32): u32 {
146
- return <u32>((<u64>n * 429496730) >>> 32);
147
- }
148
-
149
-
150
- @inline
151
- function divideByPow10_32_2(n: u32): u32 {
152
- return <u32>((<u64>n * 1374389535) >>> 37);
153
- }
154
-
155
-
156
- @inline
157
- function checkDivisibilityAndDivideByPow10_32_1(n: u32): u64 {
158
- const prod = <u32>(n * 6554);
159
- return ((<u64>(prod >>> 16)) << 32) | ((prod & 0xffff) < 6554 ? 1 : 0);
160
- }
161
-
162
- function computeMul64(u: u64, cacheHigh: u64, cacheLow: u64): void {
163
- const high = umul128_upper64(u, cacheHigh);
164
-
165
- const a = <u32>(u >>> 32);
166
- const b = <u32>u;
167
- const c = <u32>(cacheHigh >>> 32);
168
- const d = <u32>cacheHigh;
169
- const ac = <u64>a * c;
170
- const bc = <u64>b * c;
171
- const ad = <u64>a * d;
172
- const bd = <u64>b * d;
173
- let intermediate = (bd >>> 32) + <u32>ad + <u32>bc;
174
- let rHigh = ac + (intermediate >>> 32) + (ad >>> 32) + (bc >>> 32);
175
- let rLow = (intermediate << 32) + <u32>bd;
176
-
177
- const add = umul128_upper64(u, cacheLow);
178
- const sumLow = rLow + add;
179
- rHigh += sumLow < rLow ? 1 : 0;
180
- rLow = sumLow;
181
-
182
- _dbMulInteger64 = rHigh;
183
- _dbMulIsInteger = rLow == 0;
184
- }
185
-
186
- function computeMulParity64(
187
- twoF: u64,
188
- cacheHigh: u64,
189
- cacheLow: u64,
190
- beta: i32,
191
- ): void {
192
- const high = twoF * cacheHigh;
193
-
194
- const a = <u32>(twoF >>> 32);
195
- const b = <u32>twoF;
196
- const c = <u32>(cacheLow >>> 32);
197
- const d = <u32>cacheLow;
198
- const ac = <u64>a * c;
199
- const bc = <u64>b * c;
200
- const ad = <u64>a * d;
201
- const bd = <u64>b * d;
202
- const intermediate = (bd >>> 32) + <u32>ad + <u32>bc;
203
- const lowHigh = ac + (intermediate >>> 32) + (ad >>> 32) + (bc >>> 32);
204
- const lowLow = (intermediate << 32) + <u32>bd;
205
-
206
- const rHigh = high + lowHigh;
207
- _dbParity = ((rHigh >>> (64 - beta)) & 1) != 0;
208
- _dbMulIsInteger =
209
- (((rHigh << beta) & 0xffffffffffffffff) | (lowLow >>> (64 - beta))) == 0;
210
- }
211
-
212
-
213
- @inline
214
- function computeLeftEndpointShorter64(cacheHigh: u64, beta: i32): u64 {
215
- return (cacheHigh - (cacheHigh >>> 54)) >>> (11 - beta);
216
- }
217
-
218
-
219
- @inline
220
- function computeRightEndpointShorter64(cacheHigh: u64, beta: i32): u64 {
221
- return (cacheHigh + (cacheHigh >>> 53)) >>> (11 - beta);
222
- }
223
-
224
-
225
- @inline
226
- function computeRoundUpShorter64(cacheHigh: u64, beta: i32): u64 {
227
- return ((cacheHigh >>> (10 - beta)) + 1) >>> 1;
228
- }
229
-
230
- function removeTrailingZeros64(significand: u64): u64 {
231
- let exponent = 0;
232
- let r = rotr64(significand * 28999941890838049, 8);
233
- let b = r < 184467440738;
234
- let s: u32 = b ? 1 : 0;
235
- if (b) significand = r;
236
-
237
- r = rotr64(significand * 182622766329724561, 4);
238
- b = r < 1844674407370956;
239
- s = s * 2 + (b ? 1 : 0);
240
- if (b) significand = r;
241
-
242
- r = rotr64(significand * 10330176681277348905, 2);
243
- b = r < 184467440737095517;
244
- s = s * 2 + (b ? 1 : 0);
245
- if (b) significand = r;
246
-
247
- r = rotr64(significand * 14757395258967641293, 1);
248
- b = r < 1844674407370955162;
249
- s = s * 2 + (b ? 1 : 0);
250
- if (b) significand = r;
251
-
252
- exponent += s;
253
- _dbRemovedExponent = exponent;
254
- return significand;
255
- }
256
-
257
-
258
- @inline
259
- function divideByPow10_64_1(n: u64): u64 {
260
- return umul128_upper64(n, 1844674407370955162);
261
- }
262
-
263
-
264
- @inline
265
- function divideByPow10_64_3(n: u64): u64 {
266
- return umul128_upper64(n, 4722366482869645214) >>> 8;
267
- }
268
-
269
-
270
- @inline
271
- function checkDivisibilityAndDivideByPow10_64_2(n: u64): u64 {
272
- const prod = <u32>(n * 656);
273
- return ((<u64>(prod >>> 16)) << 32) | ((prod & 0xffff) < 656 ? 1 : 0);
274
- }
275
-
276
-
277
- @inline
278
- function genExponent(buffer: usize, k: i32): i32 {
279
- let negative = k < 0;
280
- if (negative) k = -k;
281
- let decimals = decimalCount32(<u32>k) + 1;
282
- utoa32_dec_core(buffer, <u32>k, <usize>decimals);
283
- store<u16>(buffer, negative ? CHAR_MINUS : CHAR_PLUS);
284
- return decimals;
285
- }
286
-
287
- function prettify(buffer: usize, length: i32, k: i32): i32 {
288
- const fast = prettifyFast(buffer, length, k);
289
- if (fast >= 0) return fast;
290
-
291
- if (!k) {
292
- const tail = buffer + ((<usize>length) << 1);
293
- store<u16>(tail, CHAR_DOT);
294
- store<u16>(tail, CHAR_0, 2);
295
- return length + 2;
296
- }
297
-
298
- const kk = length + k;
299
- if (length <= kk && kk <= 21) {
300
- for (let i = length; i < kk; ++i)
301
- store<u16>(buffer + ((<usize>i) << 1), CHAR_0);
302
- const tail = buffer + ((<usize>kk) << 1);
303
- store<u16>(tail, CHAR_DOT);
304
- store<u16>(tail, CHAR_0, 2);
305
- return kk + 2;
306
- } else if (kk > 0 && kk <= 21) {
307
- const ptr = buffer + ((<usize>kk) << 1);
308
- memory.copy(ptr + 2, ptr, (<usize>-k) << 1);
309
- store<u16>(buffer + ((<usize>kk) << 1), CHAR_DOT);
310
- return length + 1;
311
- } else if (-6 < kk && kk <= 0) {
312
- const offset = 2 - kk;
313
- memory.copy(buffer + ((<usize>offset) << 1), buffer, (<usize>length) << 1);
314
- store<u16>(buffer, CHAR_0);
315
- store<u16>(buffer, CHAR_DOT, 2);
316
- for (let i = 2; i < offset; ++i)
317
- store<u16>(buffer + ((<usize>i) << 1), CHAR_0);
318
- return length + offset;
319
- } else if (length == 1) {
320
- store<u16>(buffer, CHAR_E, 2);
321
- length = genExponent(buffer + 4, kk - 1);
322
- return length + 2;
323
- } else {
324
- const len = (<usize>length) << 1;
325
- memory.copy(buffer + 4, buffer + 2, len - 2);
326
- store<u16>(buffer, CHAR_DOT, 2);
327
- store<u16>(buffer + len, CHAR_E, 2);
328
- length += genExponent(buffer + len + 4, kk - 1);
329
- return length + 2;
330
- }
331
- }
332
-
333
- function prettifyFast(buffer: usize, length: i32, k: i32): i32 {
334
- if (k == 0) {
335
- const tail = buffer + ((<usize>length) << 1);
336
- store<u16>(tail, CHAR_DOT);
337
- store<u16>(tail, CHAR_0, 2);
338
- return length + 2;
339
- }
340
-
341
- const kk = length + k;
342
- if (length <= kk && kk <= 21) {
343
- for (let i = length; i < kk; ++i) {
344
- store<u16>(buffer + ((<usize>i) << 1), CHAR_0);
345
- }
346
- const tail = buffer + ((<usize>kk) << 1);
347
- store<u16>(tail, CHAR_DOT);
348
- store<u16>(tail, CHAR_0, 2);
349
- return kk + 2;
350
- } else if (kk > 0 && kk <= 21) {
351
- const ptr = buffer + ((<usize>kk) << 1);
352
- memory.copy(ptr + 2, ptr, (<usize>(length - kk)) << 1);
353
- store<u16>(buffer + ((<usize>kk) << 1), CHAR_DOT);
354
- return length + 1;
355
- } else if (-6 < kk && kk <= 0) {
356
- const offset = 2 - kk;
357
- memory.copy(buffer + ((<usize>offset) << 1), buffer, (<usize>length) << 1);
358
- store<u16>(buffer, CHAR_0);
359
- store<u16>(buffer, CHAR_DOT, 2);
360
- for (let i = 2; i < offset; ++i) {
361
- store<u16>(buffer + ((<usize>i) << 1), CHAR_0);
362
- }
363
- return length + offset;
364
- }
365
-
366
- return -1;
367
- }
368
-
369
- function dragonboxToDecimalF32(
370
- binarySignificand: u32,
371
- binaryExponent: i32,
372
- ): u32 {
373
- const isEven = (binarySignificand & 1) == 0;
374
- let twoFc = binarySignificand << 1;
375
-
376
- if (binaryExponent != 0) {
377
- binaryExponent += -150;
378
- if (twoFc == 0) {
379
- const minusK = floor_log10_pow2_minus_log10_4_over_3(binaryExponent);
380
- const beta = binaryExponent + floor_log2_pow10(-minusK);
381
- const cache = load<u64>(
382
- DRAGONBOX_F32_CACHE + ((<usize>(31 - minusK)) << 3),
383
- );
384
- let xi = computeLeftEndpointShorter32(cache, beta);
385
- const zi = computeRightEndpointShorter32(cache, beta);
386
- if (!(binaryExponent >= 2 && binaryExponent <= 3)) ++xi;
387
- let decimalSignificand = divideByPow10_32_1(zi);
388
- if (decimalSignificand * 10 >= xi) {
389
- let decimalExponent = minusK + 1;
390
- decimalSignificand = removeTrailingZeros32(decimalSignificand);
391
- decimalExponent += _dbRemovedExponent;
392
- _dbK = decimalExponent;
393
- return decimalSignificand;
394
- }
395
- decimalSignificand = computeRoundUpShorter32(cache, beta);
396
- if ((decimalSignificand & 1) != 0 && binaryExponent == -35)
397
- --decimalSignificand;
398
- else if (decimalSignificand < xi) ++decimalSignificand;
399
- _dbK = minusK;
400
- return decimalSignificand;
401
- }
402
- twoFc |= 1 << 24;
403
- } else {
404
- binaryExponent = -149;
405
- }
406
-
407
- const minusK = floor_log10_pow2(binaryExponent) - 1;
408
- const cache = load<u64>(DRAGONBOX_F32_CACHE + ((<usize>(31 - minusK)) << 3));
409
- const beta = binaryExponent + floor_log2_pow10(-minusK);
410
- const deltai = <u32>(cache >>> (63 - beta));
411
-
412
- computeMul32(<u32>((twoFc | 1) << beta), cache);
413
- let decimalSignificand = divideByPow10_32_2(_dbMulInteger32);
414
- let r = _dbMulInteger32 - decimalSignificand * 100;
415
-
416
- if (r < deltai) {
417
- if ((r | (_dbMulIsInteger ? 0 : 1) | (isEven ? 1 : 0)) == 0) {
418
- --decimalSignificand;
419
- r = 100;
420
- } else {
421
- let decimalExponent = minusK + 2;
422
- decimalSignificand = removeTrailingZeros32(decimalSignificand);
423
- decimalExponent += _dbRemovedExponent;
424
- _dbK = decimalExponent;
425
- return decimalSignificand;
426
- }
427
- } else if (r == deltai) {
428
- computeMulParity32(twoFc - 1, cache, beta);
429
- if (_dbParity || (_dbMulIsInteger && isEven)) {
430
- let decimalExponent = minusK + 2;
431
- decimalSignificand = removeTrailingZeros32(decimalSignificand);
432
- decimalExponent += _dbRemovedExponent;
433
- _dbK = decimalExponent;
434
- return decimalSignificand;
435
- }
436
- } else if (r < deltai) {
437
- let decimalExponent = minusK + 2;
438
- decimalSignificand = removeTrailingZeros32(decimalSignificand);
439
- decimalExponent += _dbRemovedExponent;
440
- _dbK = decimalExponent;
441
- return decimalSignificand;
442
- }
443
-
444
- decimalSignificand *= 10;
445
- let dist = r - (deltai >>> 1) + 5;
446
- const approxYParity = ((dist ^ 5) & 1) != 0;
447
- let packedDiv = checkDivisibilityAndDivideByPow10_32_1(dist);
448
- dist = <u32>(packedDiv >>> 32);
449
- decimalSignificand += dist;
450
-
451
- if ((packedDiv & 1) != 0) {
452
- computeMulParity32(twoFc, cache, beta);
453
- if (_dbParity != approxYParity) --decimalSignificand;
454
- else if ((decimalSignificand & 1) != 0 && _dbMulIsInteger)
455
- --decimalSignificand;
456
- }
457
-
458
- _dbK = minusK + 1;
459
- return decimalSignificand;
460
- }
461
-
462
- function dragonboxToDecimalF64(
463
- binarySignificand: u64,
464
- binaryExponent: i32,
465
- ): u64 {
466
- const isEven = (binarySignificand & 1) == 0;
467
- let twoFc = binarySignificand << 1;
468
-
469
- if (binaryExponent != 0) {
470
- binaryExponent += -1075;
471
- if (twoFc == 0) {
472
- const minusK = floor_log10_pow2_minus_log10_4_over_3(binaryExponent);
473
- const beta = binaryExponent + floor_log2_pow10(-minusK);
474
- const idx = (<usize>(292 - minusK)) << 4;
475
- const cacheHigh = load<u64>(DRAGONBOX_F64_CACHE + idx);
476
- const cacheLow = load<u64>(DRAGONBOX_F64_CACHE + idx + 8);
477
- let xi = computeLeftEndpointShorter64(cacheHigh, beta);
478
- const zi = computeRightEndpointShorter64(cacheHigh, beta);
479
- if (!(binaryExponent >= 2 && binaryExponent <= 3)) ++xi;
480
- let decimalSignificand = divideByPow10_64_1(zi);
481
- if (decimalSignificand * 10 >= xi) {
482
- let decimalExponent = minusK + 1;
483
- decimalSignificand = removeTrailingZeros64(decimalSignificand);
484
- decimalExponent += _dbRemovedExponent;
485
- _dbK = decimalExponent;
486
- return decimalSignificand;
487
- }
488
- decimalSignificand = computeRoundUpShorter64(cacheHigh, beta);
489
- if ((decimalSignificand & 1) != 0 && binaryExponent == -77)
490
- --decimalSignificand;
491
- else if (decimalSignificand < xi) ++decimalSignificand;
492
- _dbK = minusK;
493
- return decimalSignificand;
494
- }
495
- twoFc |= (<u64>1) << 53;
496
- } else {
497
- binaryExponent = -1074;
498
- }
499
-
500
- const minusK = floor_log10_pow2(binaryExponent) - 2;
501
- const idx = (<usize>(292 - minusK)) << 4;
502
- const cacheHigh = load<u64>(DRAGONBOX_F64_CACHE + idx);
503
- const cacheLow = load<u64>(DRAGONBOX_F64_CACHE + idx + 8);
504
- const beta = binaryExponent + floor_log2_pow10(-minusK);
505
- const deltai = cacheHigh >>> (63 - beta);
506
-
507
- computeMul64((twoFc | 1) << beta, cacheHigh, cacheLow);
508
- let decimalSignificand = divideByPow10_64_3(_dbMulInteger64);
509
- let r = _dbMulInteger64 - decimalSignificand * 1000;
510
-
511
- if (r < deltai) {
512
- if ((r | (_dbMulIsInteger ? 0 : 1) | (isEven ? 1 : 0)) == 0) {
513
- --decimalSignificand;
514
- r = 1000;
515
- } else {
516
- let decimalExponent = minusK + 3;
517
- decimalSignificand = removeTrailingZeros64(decimalSignificand);
518
- decimalExponent += _dbRemovedExponent;
519
- _dbK = decimalExponent;
520
- return decimalSignificand;
521
- }
522
- } else if (r == deltai) {
523
- computeMulParity64(twoFc - 1, cacheHigh, cacheLow, beta);
524
- if (_dbParity || (_dbMulIsInteger && isEven)) {
525
- let decimalExponent = minusK + 3;
526
- decimalSignificand = removeTrailingZeros64(decimalSignificand);
527
- decimalExponent += _dbRemovedExponent;
528
- _dbK = decimalExponent;
529
- return decimalSignificand;
530
- }
531
- } else if (r < deltai) {
532
- let decimalExponent = minusK + 3;
533
- decimalSignificand = removeTrailingZeros64(decimalSignificand);
534
- decimalExponent += _dbRemovedExponent;
535
- _dbK = decimalExponent;
536
- return decimalSignificand;
537
- }
538
-
539
- decimalSignificand *= 10;
540
- let dist = r - (deltai >>> 1) + 50;
541
- const approxYParity = ((dist ^ 50) & 1) != 0;
542
- let packedDiv = checkDivisibilityAndDivideByPow10_64_2(dist);
543
- dist = packedDiv >>> 32;
544
- decimalSignificand += dist;
545
-
546
- if ((packedDiv & 1) != 0) {
547
- computeMulParity64(twoFc, cacheHigh, cacheLow, beta);
548
- if (_dbParity != approxYParity) --decimalSignificand;
549
- else if ((decimalSignificand & 1) != 0 && _dbMulIsInteger)
550
- --decimalSignificand;
551
- }
552
-
553
- _dbK = minusK + 2;
554
- return decimalSignificand;
555
- }
556
-
557
- function dragonboxCoreF32(buffer: usize, value: f32): u32 {
558
- let sign = 0;
559
- if (value < 0) {
560
- sign = 1;
561
- value = -value;
562
- store<u16>(buffer, CHAR_MINUS);
563
- }
564
- const digits = dragonboxToDecimalF32(
565
- reinterpret<u32>(value) & 0x7fffff,
566
- (reinterpret<u32>(value) >>> 23) & 0xff,
567
- );
568
- // Use the jeaiii-style itoa (forward write + 2-digit-pair LUT) instead
569
- // of AS stdlib's `itoa_buffered`, which runs a separate width classifier
570
- // + backward div-by-10000 loop. Saves a function call and ~half the
571
- // per-digit work for the typical 7-17 digit dragonbox output.
572
- let len = itoaU32(buffer + ((<usize>sign) << 1), digits);
573
- return <u32>(prettify(buffer + ((<usize>sign) << 1), len, _dbK) + sign);
574
- }
575
-
576
- function dragonboxCoreF64(buffer: usize, value: f64): u32 {
577
- let sign = 0;
578
- if (value < 0) {
579
- sign = 1;
580
- value = -value;
581
- store<u16>(buffer, CHAR_MINUS);
582
- }
583
- const bits = reinterpret<u64>(value);
584
- const digits = dragonboxToDecimalF64(
585
- bits & 0x000fffffffffffff,
586
- <i32>((bits >>> 52) & 0x7ff),
587
- );
588
- let len = itoaU64(buffer + ((<usize>sign) << 1), digits);
589
- return <u32>(prettify(buffer + ((<usize>sign) << 1), len, _dbK) + sign);
590
- }
591
-
592
- export function dragonbox_f32_buffered(buffer: usize, value: f32): u32 {
593
- if (value == 0) {
594
- store<u16>(buffer, CHAR_0);
595
- store<u16>(buffer, CHAR_DOT, 2);
596
- store<u16>(buffer, CHAR_0, 4);
597
- return 3;
598
- }
599
- if (!isFinite(value)) {
600
- if (isNaN(value)) {
601
- store<u16>(buffer, 78);
602
- store<u16>(buffer, 97, 2);
603
- store<u16>(buffer, 78, 4);
604
- return 3;
605
- }
606
- let sign = value < 0;
607
- if (sign) {
608
- store<u16>(buffer, CHAR_MINUS);
609
- buffer += 2;
610
- }
611
- store<u64>(buffer, 0x690066006e0049);
612
- store<u64>(buffer + 8, 0x7900740069006e);
613
- return 8 + (sign ? 1 : 0);
614
- }
615
- ensureItoaPairs();
616
- return dragonboxCoreF32(buffer, value);
617
- }
618
-
619
- export function dragonbox_f64_buffered(buffer: usize, value: f64): u32 {
620
- if (value == 0) {
621
- store<u16>(buffer, CHAR_0);
622
- store<u16>(buffer, CHAR_DOT, 2);
623
- store<u16>(buffer, CHAR_0, 4);
624
- return 3;
625
- }
626
- if (!isFinite(value)) {
627
- if (isNaN(value)) {
628
- store<u16>(buffer, 78);
629
- store<u16>(buffer, 97, 2);
630
- store<u16>(buffer, 78, 4);
631
- return 3;
632
- }
633
- let sign = value < 0;
634
- if (sign) {
635
- store<u16>(buffer, CHAR_MINUS);
636
- buffer += 2;
637
- }
638
- store<u64>(buffer, 0x690066006e0049);
639
- store<u64>(buffer + 8, 0x7900740069006e);
640
- return 8 + (sign ? 1 : 0);
641
- }
642
- ensureItoaPairs();
643
- return dragonboxCoreF64(buffer, value);
644
- }
645
-
646
- export function dragonbox_buffered<T extends number>(
647
- buffer: usize,
648
- value: T,
649
- ): u32 {
650
- if (sizeof<T>() == 4) return dragonbox_f32_buffered(buffer, <f32>value);
651
- return dragonbox_f64_buffered(buffer, <f64>value);
652
- }