json-as 1.3.1 → 1.3.3

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