floating_vs_decmial_x tutorial
This tutorial shows how to compare moonbitlang/x/decimal (X) and floating’s
decimal_gda (GDA) under each of the two semantic groups, check them against
the oracle, run a small Mare Mark measurement, and reproduce the published
benchmark. Why the groups and precisions are chosen this way is on the
design page.
Quick start
The repository is not published on mooncakes; clone it and work inside the
module or a moon.work workspace that contains it:
git clone https://github.com/Luna-Flow/diff_bench.git
cd diff_bench
moon test --target native
Import the package in the moon.pkg of a package in the module:
import {
"Luna-Flow/diff_bench/floating_vs_decmial_x",
}
The smallest useful program divides by under X’s policy in both libraries:
test "quick start" {
let one = @floating_vs_decmial_x.parse_decimal_value("1")
let three = @floating_vs_decmial_x.parse_decimal_value("3")
let fixture = @floating_vs_decmial_x.prepare_fixture(Divide, one, three, semantics=XCompatible)
let show = (o : @floating_vs_decmial_x.DecimalObservation) => {
@floating_vs_decmial_x.canonical_string(@floating_vs_decmial_x.canonical_observation(o))
}
inspect(show(@floating_vs_decmial_x.run_x(fixture)), content="0.3333333333333333333333333333")
inspect(show(@floating_vs_decmial_x.run_gda(fixture)), content="0.3333333333333333333333333333")
}
Both return the quotient truncated to 28 fractional digits; GDA gets there with
a divide followed by a quantize.
Everyday tasks
Choose a semantic group
ExactOverlap is for inputs whose exact result both libraries represent. GDA
then runs one operation and must return the exact value:
test "exact overlap" {
let a = @floating_vs_decmial_x.parse_decimal_value("12345.6789")
let b = @floating_vs_decmial_x.parse_decimal_value("8")
let fixture = @floating_vs_decmial_x.prepare_fixture(Divide, a, b, semantics=ExactOverlap)
let gda = @floating_vs_decmial_x.canonical_observation(@floating_vs_decmial_x.run_gda(fixture))
inspect(@floating_vs_decmial_x.canonical_string(gda), content="1543.2098625")
inspect(@floating_vs_decmial_x.working_precision(Divide, a, b, semantics=ExactOverlap), content="12")
}
XCompatible reproduces X’s 28-digit truncation. A product with 36
fractional digits is cut to 28 on both sides:
test "x-compatible product" {
let a : @floating_vs_decmial_x.DecimalValue = { coefficient: 123456789N, scale: 18 }
let b : @floating_vs_decmial_x.DecimalValue = { coefficient: 987654321N, scale: 18 }
let fixture = @floating_vs_decmial_x.prepare_fixture(Multiply, a, b, semantics=XCompatible)
let show = (o : @floating_vs_decmial_x.DecimalObservation) => {
@floating_vs_decmial_x.canonical_string(@floating_vs_decmial_x.canonical_observation(o))
}
inspect(show(@floating_vs_decmial_x.run_x(fixture)), content="0.0000000000000000001219326311")
inspect(show(@floating_vs_decmial_x.run_gda(fixture)), content="0.0000000000000000001219326311")
}
The exact product is ; truncation keeps the digits up to .
Check a corpus against the oracle
oracle_operation implements X’s policy, so it is the reference for both
groups:
test "corpus against the oracle" {
let ops : Array[@floating_vs_decmial_x.Operation] = [Add, Subtract, Multiply, Divide, Compare]
let mut checked = 0
for op in ops {
for case in @floating_vs_decmial_x.generate_cases(73, 20, op) {
let left = @floating_vs_decmial_x.parse_decimal_value(case.left)
let right = @floating_vs_decmial_x.parse_decimal_value(case.right)
let expected = @floating_vs_decmial_x.oracle_operation(op, left, right).canonical
let fixture = @floating_vs_decmial_x.prepare_fixture(op, left, right)
for observation in [
@floating_vs_decmial_x.run_x(fixture),
@floating_vs_decmial_x.run_gda(fixture),
] {
let got = @floating_vs_decmial_x.canonical_observation(observation)
assert_eq(@floating_vs_decmial_x.canonical_string(got), expected)
}
checked += 1
}
}
inspect(checked, content="100")
}
Generated cases have at most 24 digits, below every division precision, so the operand-rounding limitation does not apply to them.
Run a small Mare Mark measurement
async test "smoke measurement" {
let report = @floating_vs_decmial_x.run_mare_benchmark(
[Add, Multiply],
ExactOverlap,
[4, 16],
@floating_vs_decmial_x.smoke_protocol(),
42UL,
)
inspect(report.failed_count, content="0")
inspect(report.validation_count, content="8")
inspect(report.results[0].timing_scope, content="arithmetic_only")
}
Run it on native or js; the function is async. Each result row holds the
X and GDA medians in microseconds and x_speedup_vs_gda, the GDA median over
the X median.
Reproduce the published benchmark
From the repository root:
moon run --release src/floating_vs_decmial_x/bench --target native \
> artifacts/floating_vs_decmial_x/scaling.jsonl
moon run --release src/floating_vs_decmial_x/bench_common --target native \
> artifacts/floating_vs_decmial_x/common_digits.jsonl
The first command measures 1 to 4,096 digits, the second 1, 4, 8, 16, 18 and 28
digits. Both write an HTML report next to the JSONL (see the
bench page). Set MARE_CPU, MARE_OS,
MARE_BUILD_MODE and the other MARE_* variables to record the host; unset
facts are written as unknown or unspecified. Then render the figure:
python3 tools/layout_x_decimal.py
Read the records by timing scope: arithmetic_only is one public operation,
semantic_equivalent_pipeline is the full sequence that reproduces X’s policy
in GDA. Results from different targets are never combined.
Going further
Precision for your own inputs. For XCompatible division
working_precision depends on the digit difference of the operands, not on
their length. Inputs longer than that precision are rounded when the fixture
is built (see the design page).
Keep both operands at most digits long when you need a guaranteed match.
Interpreting a speedup. x_speedup_vs_gda is a ratio of medians from
paired samples; decision applies a 3 % practical threshold to the median
paired difference. Neither is a confidence interval. The
statistics section of
the sibling benchmark gives the formulas.
Sibling package. dzmingli_vs_floating applies
the same method with an exact oracle, a second timing scope with parsing, and
19 operations.
Common pitfalls
prepare_fixtureandworking_precisiondefault toXCompatible. Passsemantics=ExactOverlapexplicitly when you want the exact group.- In
XCompatibledivision, operands with more significant digits than the precision are rounded before GDA divides them: GDA can then return where X returns , and the timing compares shorter GDA operands with full X operands. x_from_neutralaborts for scales above 28; X cannot hold such values.- The HTML summary line is correct only for runs without failures; read
validation_countandfailed_countfrom the report instead. BigInt::from_stringis wrong for long strings onwasm-gcin the currentmoonbitlang/core. The testdivision precision follows the requested semantic contractbuilds a 4,096-nines operand with it and expects4097, the value produced by that wrong parse; the correct working precision is . The test therefore passes onwasm-gcand fails onnativeandjs. Build long test values withparse_decimal_valueorBigIntarithmetic instead.- The published numbers for X were measured with
moonbitlang/x@0.4.46; the module now depends on0.5.5, and the JSONL implementation record still names0.4.46.
Next steps
- API reference for every item.
- Design for the semantic groups and the precision proofs.
- Performance analysis for the measured results.
- Benchmark executables and the common-digit executable.