Skip to content

fix: canonicalize double rendering#999

Open
He-Pin wants to merge 1 commit into
databricks:masterfrom
He-Pin:worktree-fix-render-double-format
Open

fix: canonicalize double rendering#999
He-Pin wants to merge 1 commit into
databricks:masterfrom
He-Pin:worktree-fix-render-double-format

Conversation

@He-Pin

@He-Pin He-Pin commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Motivation

Double rendering was split across five renderer implementations
(BaseByteRenderer, BaseCharRenderer, BaseRenderer, ByteRenderer,
Renderer + TomlRenderer), depended on platform defaults (JVM emits
uppercase 1.0E-6, Scala.js/Wasm emit lowercase 1e-7), and large whole
doubles exposed exact binary64 noise via new BigDecimal(d).

Modification

  • Consolidate all double rendering into RenderUtils.renderDouble.
  • Canonicalize scientific notation to lowercase e with explicit sign
    and 2-digit exponent padding.
  • Use BigDecimal.valueOf(d) instead of new BigDecimal(d) for
    out-of-Long whole doubles, eliminating binary64 noise.
  • Align TomlRenderer with the shared helper.
  • Adopt the ECMAScript Number.prototype.toString convention for the
    [1e-6, 1e21) fixed-decimal window.

Result

Stable, canonical double rendering across JVM / JS / Wasm / Graal:

  • 0.000001 -> 0.000001
  • 0.0000001 -> 1e-07
  • 1e100 -> 1 + 100 zeros

All tests pass on JVM/JS/Wasm/Native/Graal.

References

None — double rendering canonicalization.

@He-Pin He-Pin force-pushed the worktree-fix-render-double-format branch 2 times, most recently from 4bee239 to 30e0ecc Compare June 19, 2026 17:44
@He-Pin

He-Pin commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

Scala.js has different Double.tostring, fixing

@He-Pin He-Pin force-pushed the worktree-fix-render-double-format branch from 659f40a to 457a0a9 Compare June 19, 2026 18:59
@He-Pin He-Pin changed the title fix: normalize scientific notation format in double rendering (E→e) fix: canonicalize double rendering Jun 19, 2026
@He-Pin He-Pin marked this pull request as draft June 19, 2026 19:04
@He-Pin He-Pin marked this pull request as ready for review June 19, 2026 19:17
@He-Pin He-Pin force-pushed the worktree-fix-render-double-format branch from 457a0a9 to eb9397f Compare June 19, 2026 19:28
Motivation:
Double rendering was split across renderer implementations and depended
on platform defaults. JVM emitted uppercase scientific notation,
Scala.js/Wasm used different fixed/scientific thresholds, and large
whole doubles could expose exact binary64 noise in some manifestation
paths.

Modification:
Route renderers through RenderUtils.renderDouble. Canonicalize double
strings by keeping common JSON-range values in fixed decimal form,
normalizing smaller scientific notation, and rendering out-of-Long-range
whole doubles from BigDecimal.valueOf instead of the exact binary
constructor. Keep TOML in sync and update directional/golden tests.
Document two design choices that otherwise read as arbitrary:
- The [1e-6, 1e21) fixed-decimal window is ECMAScript's
  Number.prototype.toString convention, which JSON/Java/Scala.js all
  follow.
- HALF_EVEN on BigDecimal.valueOf(d) is equivalent to any other
  tie-breaking rule in this branch, because doubles that reach it
  have |d| >= 2^53 where ULP >= 1 and no representable value is an
  exact .5 tie.

Result:
sjsonnet now renders representative doubles consistently across JVM, JS,
Wasm, and Graal without claiming Go/C++ exact-digit compatibility.
- 0.000001 -> 0.000001
- 0.0000001 -> 1e-07
- 1e100 -> 1 followed by 100 zeros (no binary64 noise)

Tests:
- scalafmt on changed files
- ./mill __.checkFormat
- ./mill sjsonnet.jvm[2.13.18].test  (all pass)
- ./mill sjsonnet.js[2.13.18].test   (all pass)
- ./mill sjsonnet.wasm[2.13.18].test (all pass)
- sjsonnet/test/graalvm/run_test_suites.py

References:
None - double rendering canonicalization.
@He-Pin He-Pin force-pushed the worktree-fix-render-double-format branch from eb9397f to b1bdb3b Compare June 19, 2026 19:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant