Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
5705f06
chore: add xjb-as to util
JairusSW Jun 9, 2026
c778be9
chore: add liceses to NOTICE
JairusSW Jun 9, 2026
1fdc61d
chore: update changed tests
JairusSW Jun 9, 2026
09c3ef8
chore: simplify and use smaller tables
JairusSW Jun 16, 2026
7cd14a4
chore: use table from number instead
JairusSW Jun 16, 2026
e0646ff
chore: update notice
JairusSW Jun 16, 2026
650a7c3
chore: clean up
JairusSW Jun 16, 2026
759c01f
chore: clean up
JairusSW Jun 16, 2026
fa93c15
chore: rename to dtoa.ts and remove XJB_SIMD toggle
JairusSW Jun 17, 2026
d41ce13
Update std/assembly/util/dtoa.ts
JairusSW Jun 17, 2026
4aa4210
Update std/assembly/util/dtoa.ts
JairusSW Jun 17, 2026
48f3ee5
Update std/assembly/util/dtoa.ts
JairusSW Jun 17, 2026
5dd492b
Update std/assembly/util/dtoa.ts
JairusSW Jun 17, 2026
b1bcc18
Update std/assembly/util/dtoa.ts
JairusSW Jun 17, 2026
4bdb432
chore: update import and update test outputs
JairusSW Jun 17, 2026
76c4b11
Update std/assembly/util/dtoa.ts
JairusSW Jun 17, 2026
b9cf897
Update std/assembly/util/dtoa.ts
JairusSW Jun 17, 2026
87c12f1
Update std/assembly/util/dtoa.ts
JairusSW Jun 17, 2026
c97a0e9
Update std/assembly/util/dtoa.ts
JairusSW Jun 17, 2026
9721226
chore: add lazy decorators where needed, update styling, etc
JairusSW Jun 17, 2026
2dfdb0f
use let
MaxGraey Jun 18, 2026
f322f2d
Apply suggestion from @MaxGraey
MaxGraey Jun 18, 2026
422a611
chore: add some comments for more esoteric literals
JairusSW Jun 18, 2026
e7b2dd8
Merge branch 'jairus/switch-to-xjb' of github.com:JairusSW/assemblysc…
JairusSW Jun 18, 2026
795b262
chore: use named constants instead of esoteric literals
JairusSW Jun 18, 2026
209ed02
chore: dedupe constants
JairusSW Jun 18, 2026
fe03f90
chore: standardize naming convention
JairusSW Jun 18, 2026
29ac707
core: more styling stuff
JairusSW Jun 18, 2026
d5b0607
chore: remove dbl ternary
JairusSW Jun 18, 2026
8044b88
reformat
MaxGraey Jun 18, 2026
43dbf58
chore: use more descriptive names
JairusSW Jun 24, 2026
c5c6e07
Merge branch 'jairus/switch-to-xjb' of github.com:JairusSW/assemblysc…
JairusSW Jun 24, 2026
d93842f
fix: correct dtoa digit counts and shortest formatting
JairusSW Sep 21, 2026
644040a
Merge origin/main into jairus/switch-to-xjb
JairusSW Sep 21, 2026
a28f957
fix: finalize float formatting and review cleanup
JairusSW Sep 21, 2026
c13739d
Avoid emitting unused dtoa globals in debug output
JairusSW Sep 21, 2026
42ff464
Optimize float formatting fast paths and validate scalar/SIMD output
JairusSW Sep 21, 2026
859401d
Cover f32 exact-integer fast-path boundary
JairusSW Sep 21, 2026
cf6bad1
Optimize SIMD digit packing and normalized f64 formatting
JairusSW Sep 21, 2026
f516ed4
Use SIMD digit packing for long integer formatting
JairusSW Sep 21, 2026
c9f8b9c
Use full dtoa power cache in speed builds
JairusSW Sep 21, 2026
fdbc7ed
Speed up subnormal f32 digit scaling
JairusSW Sep 21, 2026
1079de4
Use compact power cache in all builds
JairusSW Sep 21, 2026
ed4390a
Reuse float power cache for common doubles
JairusSW Sep 21, 2026
055a82d
Share minor powers with float cache
JairusSW Sep 21, 2026
f39d7b7
Use one shared power table in every build
JairusSW Sep 21, 2026
dcab81e
Trim shared power table to common f64 range
JairusSW Sep 21, 2026
881a8ec
Use compact power cache outside common exponents
JairusSW Sep 21, 2026
84f5f2f
Test exact dtoa output and compact powers
JairusSW Sep 21, 2026
660bd25
Speed up exact-integer string formatting
JairusSW Sep 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use one shared power table in every build
  • Loading branch information
JairusSW committed Sep 21, 2026
commit f39d7b78576c3d5ee63c62923b0f8e1b796d2306
72 changes: 24 additions & 48 deletions std/assembly/util/dtoa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,6 @@ import { DIGITS, MAX_DOUBLE_LENGTH } from "./number";
// Compact pow10 (Dougall Johnson's method, ported from vitaut/zmij)
// 10**i = top-128-bits(major[(i+10)/28] * minor[(i+10)%28]) minus a per-power round-down bit.

// 28 normalized exact powers 10**0..10**27 - the within-stride minor factors.
// @ts-ignore: decorator
@lazy @inline const POW10_MINOR = memory.data<u64>([
0x8000000000000000, 0xa000000000000000, 0xc800000000000000, 0xfa00000000000000,
0x9c40000000000000, 0xc350000000000000, 0xf424000000000000, 0x9896800000000000,
0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000, 0xba43b74000000000,
0xe8d4a51000000000, 0x9184e72a00000000, 0xb5e620f480000000, 0xe35fa931a0000000,
0x8e1bc9bf04000000, 0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000,
0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000, 0xa968163f0a57b400,
0xd3c21bcecceda100, 0x84595161401484a0, 0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a,
]);

// 23 full 128-bit anchors (hi, lo) spaced every 28 powers, covering 10**-303..10**313.
// @ts-ignore: decorator
@lazy @inline const POW10_MAJOR = memory.data<u64>([
Expand Down Expand Up @@ -74,11 +62,11 @@ import { DIGITS, MAX_DOUBLE_LENGTH } from "./number";
0x00000d0d, 0x14042400, 0x53713840, 0x11781db4, 0x00000000,
]);

// hi-only significand of 10**i, 77 entries (index = 45 + k, k in [-45,31]) with
// the xjb64 +1 low-limb rounding folded in. One hi-only multiply covers both the
// regular and power-of-two paths.
// Shared normalized powers for f32 and common f64 exponents. The first 77
// limbs are high, and the next 77 are low. Entry t is power index 337 - t.
// The high limb is rounded up exactly when its low limb is nonzero.
// @ts-ignore: decorator
@lazy @inline const POW10_FLOAT_HI = memory.data<u64>([
@lazy @inline const POW10_SHARED = memory.data<u64>([
0x8f7e32ce7bea5c70, 0xe596b7b0c643c71a, 0xb7abc627050305ae, 0x92efd1b8d0cf37bf,
0xeb194f8e1ae525fe, 0xbc143fa4e250eb32, 0x96769950b50d88f5, 0xf0bdc21abb48db21,
0xc097ce7bc90715b4, 0x9a130b963a6c115d, 0xf684df56c3e01bc7, 0xc5371912364ce306,
Expand All @@ -98,33 +86,26 @@ import { DIGITS, MAX_DOUBLE_LENGTH } from "./number";
0xbce5086492111aeb, 0x971da05074da7bef, 0xf1c90080baf72cb2, 0xc16d9a0095928a28,
0x9abe14cd44753b53, 0xf79687aed3eec552, 0xc612062576589ddb, 0x9e74d1b791e07e49,
0xfd87b5f28300ca0e, 0xcad2f7f5359a3b3f, 0xa2425ff75e14fc32, 0x81ceb32c4b43fcf5,
0xcfb11ead453994bb,
]);

// Low limbs shared with the f32 power range (entry t is power index 337 - t).
// f32's high limb is rounded up exactly when the corresponding low limb is nonzero.
// @ts-ignore: decorator
@lazy @inline const POW10_FLOAT_LO = memory.data<u64>([
0xe4820023a2000000, 0x6d9ccd05d0000000, 0xf14a3d9e40000000, 0x5aa1cae500000000,
0x5dcfab0800000000, 0x17d955a000000000, 0x1314448000000000, 0x1e86d40000000000,
0x4b9f100000000000, 0x3c7f400000000000, 0xc732000000000000, 0x6c28000000000000,
0xf020000000000000, 0x4d00000000000000, 0xa400000000000000, 0x5000000000000000,
0x4000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0xcfb11ead453994bb, 0xe4820023a2000000, 0x6d9ccd05d0000000, 0xf14a3d9e40000000,
0x5aa1cae500000000, 0x5dcfab0800000000, 0x17d955a000000000, 0x1314448000000000,
0x1e86d40000000000, 0x4b9f100000000000, 0x3c7f400000000000, 0xc732000000000000,
0x6c28000000000000, 0xf020000000000000, 0x4d00000000000000, 0xa400000000000000,
0x5000000000000000, 0x4000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0xcccccccccccccccc, 0x3d70a3d70a3d70a3, 0x645a1cac083126e9,
0xd3c36113404ea4a8, 0x0fcf80dc33721d53, 0xa63f9a49c2c1b10f, 0x3d32907604691b4c,
0xfdc20d2b36ba7c3d, 0x31680a88f8953030, 0xb573440e5a884d1b, 0xf78f69a51539d748,
0xf93f87b7442e45d3, 0x2865a5f206b06fb9, 0x538484c19ef38c94, 0x0f9d37014bf60a10,
0x4c2ebe687989a9b3, 0x09befeb9fad487c2, 0x3aff322e62439fcf, 0x2b31e9e3d06c32e5,
0x88f4bb1ca6bcf584, 0xd3f6fc16ebca5e03, 0x5324c68b12dd6338, 0x75b7053c0f178293,
0xc4926a9672793542, 0x3a83ddbd83f52204, 0x95364afe032a819d, 0x775ea264cf55347d,
0x8bca9d6e188853fc, 0x096ee45813a04330, 0xa1258379a94d028d, 0x80eacf948770ced7,
0x67de18eda5814af2
0x0000000000000000, 0x0000000000000000, 0xcccccccccccccccc, 0x3d70a3d70a3d70a3,
0x645a1cac083126e9, 0xd3c36113404ea4a8, 0x0fcf80dc33721d53, 0xa63f9a49c2c1b10f,
0x3d32907604691b4c, 0xfdc20d2b36ba7c3d, 0x31680a88f8953030, 0xb573440e5a884d1b,
0xf78f69a51539d748, 0xf93f87b7442e45d3, 0x2865a5f206b06fb9, 0x538484c19ef38c94,
0x0f9d37014bf60a10, 0x4c2ebe687989a9b3, 0x09befeb9fad487c2, 0x3aff322e62439fcf,
0x2b31e9e3d06c32e5, 0x88f4bb1ca6bcf584, 0xd3f6fc16ebca5e03, 0x5324c68b12dd6338,
0x75b7053c0f178293, 0xc4926a9672793542, 0x3a83ddbd83f52204, 0x95364afe032a819d,
0x775ea264cf55347d, 0x8bca9d6e188853fc, 0x096ee45813a04330, 0xa1258379a94d028d,
0x80eacf948770ced7, 0x67de18eda5814af2
]);

@lazy @inline const FLOAT_EXP_OFFSET = 150; // exp_bias(127) + num_sig_bits(23)
Expand Down Expand Up @@ -197,22 +178,17 @@ import { DIGITS, MAX_DOUBLE_LENGTH } from "./number";
// then the per-power fixup bit subtracted off the low limb.
// @ts-ignore: decorator
@inline function computePow10(i: i32): u64 {
if (ASC_OPTIMIZE_LEVEL >= 3 && ASC_SHRINK_LEVEL == 0 && i >= 261 && i <= 337) {
if (i >= 261 && i <= 337) {
let t = 337 - i;
let lo = load<u64>(POW10_FLOAT_LO + (<usize>t << 3));
gPow10Hi = load<u64>(POW10_FLOAT_HI + (<usize>t << 3)) - u64(lo != 0);
let lo = load<u64>(POW10_SHARED + (<usize>(t + 77) << 3));
gPow10Hi = load<u64>(POW10_SHARED + (<usize>t << 3)) - u64(lo != 0);
return lo;
}
let j = i + 10;
let major = (j * 293) >>> 13; // exact j / 28 for j in [10,627]
let minor = j - major * 28;
let m: u64;
if (ASC_OPTIMIZE_LEVEL >= 3 && ASC_SHRINK_LEVEL == 0) {
// The minor factors are POW10_FLOAT_HI[44..17] in reverse order.
m = load<u64>(POW10_FLOAT_HI + (<usize>(44 - minor) << 3));
} else {
m = load<u64>(POW10_MINOR + (<usize>minor << 3));
}
// The minor factors are POW10_SHARED[44..17] in reverse order.
let m = load<u64>(POW10_SHARED + (<usize>(44 - minor) << 3));
let hoff = POW10_MAJOR + (<usize>major << 4);
let hHi = load<u64>(hoff);
let hLo = load<u64>(hoff, 8);
Expand Down Expand Up @@ -980,7 +956,7 @@ export function dtoa_buffered(buffer: usize, value: f64): u32 {
k = (expBin * 1233 - 512) >> 12;
h = 37 + expBin + ((k * -1701 + (-1701)) >> 9);
}
let pow10Hi = load<u64>(POW10_FLOAT_HI + ((45 + k) << 3));
let pow10Hi = load<u64>(POW10_SHARED + ((45 + k) << 3));

// hi64 = (binSig * pow10Hi) >> (64 - h), split as >> 24 (folded into the
// partial-product combine; exact since 64 - h >= 24) then >> (40 - h).
Expand Down
Loading
Loading