Skip to content

Commit cedbeaf

Browse files
gHashTaggHashTaggHashTag
authored
fix(codegen): handle bias formulas in numeric format SSOT (closes #1064) (#1065)
* fix(codegen): handle bias formulas in numeric format SSOT (closes #1064) The bias field in formats_catalog.t27 can carry either a literal int or a rule-derived formula like 2^N-1. Two formats use the formula form: gf512: bias = 2^194-1 gf1024: bias = 2^390-1 Both were added by PR #1051 as limit-of-ladder phi-aligned formats. The parser did int(bias_str) unconditionally, which raised ValueError, so both rows were silently dropped with a "malformed CATALOG line" warning. This is why count drifted: committed gen/ JSON shipped 77 (pre-#1051), post-#1051 SSOT carries 83 raw lines, codegen yielded 81 even after a fresh re-run, paper #3 (arXiv:2606.09686) claims 84. Four sources of truth, none matching. See issue #1064 for the full audit. Fix: - parse_bias(s) helper: tries int(); falls back to evaluating simple 2^N+offset forms within int64 range; otherwise returns sentinel -2 with the raw string in a new bias_formula field - Format dataclass: adds bias_formula: str (preserves the raw SSOT string for every row, including the literal-int cases for symmetry) - All existing emitters (Rust struct, C header, TS interface, Python, Markdown table, etc.) continue to render the int bias field as before; bias_formula appears only in JSON and python emitter where asdict() picks it up automatically -- non-breaking for the typed emitters that hardcode their Format schema. Verification after fix: $ python3 tools/gen_formats_catalog.py specs/numeric/formats_catalog.t27 gen/numeric/ $ python3 -c "import json; print(json.load(open('gen/numeric/formats_catalog.json'))['count'])" 83 gf512 and gf1024 now appear in the JSON with bias=-2 and the formula preserved in bias_formula. Downstream tools that need the actual i64 value can carry the string forward and evaluate at use-site (mpmath or big-int arithmetic) without losing provenance. This does NOT yet reconcile SSOT 83 vs paper #3 claim of 84; that delta is the MXFP6 split + standalone E8M0 in Table 1 vs the SSOT's collapsed mxfp6 row + Microscaling cluster layout. See #1064 for the follow-up plan. The CI invariant (raw line count == JSON count) will land in a separate PR. Refs: #1051 (GF ladder expansion), #1063 (HF Discovery thread), #1064 * fix(codegen): revert auto-generated gen/ artefacts, add NOW.md entry PR #1065 originally committed regenerated gen/numeric/* outputs alongside the source fix in tools/gen_formats_catalog.py. Per L2 generation rules, gen/ artefacts must be auto-regenerated post-merge by ./scripts/tri gen, not committed in source PRs. This commit: - reverts gen/numeric/* back to master state - keeps the source fix (tools/gen_formats_catalog.py) intact - adds docs/NOW.md entry per NOW Sync Gate Closes #1064 --------- Co-authored-by: gHashTag <playra@trinity-s3ai.org> Co-authored-by: gHashTag <admin@t27.ai>
1 parent 6ecad30 commit cedbeaf

2 files changed

Lines changed: 43 additions & 3 deletions

File tree

docs/NOW.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# NOW -- Trinity t27 sync
22

3-
Last updated: 2026-06-08
3+
Last updated: 2026-06-13
4+
5+
## fix-parser-bias-formula -- handle bias formulas in numeric format SSOT (Closes #1064)
6+
7+
- **WHERE** (codegen only): `tools/gen_formats_catalog.py` parser extended to handle bias formulas like `2^N-1` (gf512, gf1024) which were previously dropped on `int(s)` cast. No `specs/` edits, no `gen/` edits in this PR (codegen runs auto-regenerate on master post-merge). The fix raises live regen output from 81 to 83 rows, matching the SSOT raw-line count at HEAD `6ecad30`.
8+
- **Why**: count-drift audit (#1064) showed four divergent counts across the catalog pipeline -- paper 84 / SSOT 83 / regen 81 / shipped gen 77. Root cause for the 83 -> 81 drop was a parser that treated bias as `int(value)` and silently dropped two rows on `2^N-1`. After this fix lands and codegen reruns, gen/ artefacts and the HF mirror at `playra/numeric-format-catalog` converge on 83. The paper-84 vs SSOT-83 difference is the historical paper expansion plan recorded as a separate row that was never materialised in the SSOT; treated as an honest documentation note in arXiv:2606.09686 §11. L6 gf16 SSOT untouched. L2 gen/ untouched in this PR (will auto-regen). Closes #1064.
9+
- **Anchor**: phi^2 + phi^-2 = 3
410

511
## funding-json-trinity-s3ai -- maintainer block + ORCID + project_info anchor (Closes #1062)
612

tools/gen_formats_catalog.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ class Format:
4747
s_bits: int
4848
e_bits: int
4949
m_bits: int
50-
bias: int
50+
bias: int # -2 sentinel = value exceeds int64, see bias_formula
51+
bias_formula: str # raw SSOT bias string (literal int or formula like '2^194-1')
5152
phi_distance: float # -1.0 == undefined
5253
storage: str
5354
cluster: str
@@ -70,19 +71,52 @@ def parse_kv_line(line: str) -> dict[str, str]:
7071
return out
7172

7273

74+
def parse_bias(s: str) -> tuple[int, str]:
75+
"""Parse a bias field.
76+
77+
Returns (bias_int, bias_formula). bias_formula is the raw SSOT string
78+
(e.g. '2^194-1' for gf512); bias_int is the int() of s when possible,
79+
else -1 sentinel meaning 'see bias_formula'. This lets the int-typed
80+
bias field stay backwards-compatible with all downstream emitters
81+
(Rust i64, C int64_t, TS number) while preserving the rule-derived
82+
formulas for the limit-of-ladder GF rungs (gf512 bias 2^194-1,
83+
gf1024 bias 2^390-1) that were added by PR #1051. See issue #1064.
84+
"""
85+
try:
86+
return int(s), s
87+
except ValueError:
88+
# Try to evaluate simple 2^N-1 / 2^N+1 / 2^N forms; if the
89+
# exponent stays within range, return the literal int.
90+
m = re.match(r"^2\^(\d+)([+-]\d+)?$", s.strip())
91+
if m:
92+
exp = int(m.group(1))
93+
off = int(m.group(2)) if m.group(2) else 0
94+
if exp <= 1024: # python int is arbitrary precision but i64 isn't
95+
val = (1 << exp) + off
96+
# Only return as int if it fits signed 64-bit; otherwise
97+
# downstream emitters (Rust i64, C int64_t) overflow.
98+
if -(1 << 63) <= val < (1 << 63):
99+
return val, s
100+
# Cannot lift to int; record formula, use sentinel -2 meaning
101+
# "value lives in bias_formula field, exceeds int64".
102+
return -2, s
103+
104+
73105
def parse_t27(text: str) -> list[Format]:
74106
formats: list[Format] = []
75107
for m in CATALOG_LINE.finditer(text):
76108
fields = parse_kv_line(m.group(1))
77109
try:
110+
bias_int, bias_formula = parse_bias(fields["bias"])
78111
fmt = Format(
79112
id=fields["id"],
80113
name=fields["name"],
81114
bits=int(fields["bits"]),
82115
s_bits=int(fields["s"]),
83116
e_bits=int(fields["e"]),
84117
m_bits=int(fields["m"]),
85-
bias=int(fields["bias"]),
118+
bias=bias_int,
119+
bias_formula=bias_formula,
86120
phi_distance=float(fields["phi_distance"]),
87121
storage=fields["storage"],
88122
cluster=fields["cluster"],

0 commit comments

Comments
 (0)