Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
106 changes: 106 additions & 0 deletions conformance/vectors/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# t27 numeric-format conformance vector packs (v0)

Bit-precise conformance vectors for a family of low-precision numeric formats,
in a single shared row schema so one differ runs across all packs.

- SSOT: https://github.com/gHashTag/t27/blob/master/conformance/FORMAT-SPEC-001.json
- Anchor identity (ASCII): `phi^2 + 1/phi^2 = 3`
- Context preprint: https://arxiv.org/abs/2606.05017
- Schema tag: `t27-conformance/v0.1`

Every pack decodes its native bits to f64 exactly (`abs_error = 0` by
construction for representable values). Values that are NOT exactly
representable in a format report a nonzero `abs_error` honestly (for example
0.1 in bf16) -- nothing is hidden.

## Index

| Pack | Format | Bits | Vectors | 3.0 anchor bits | Max finite | Inf | NaN | Has golden | tt-mlir issue |
|---|---|---|---|---|---|---|---|---|---|
| `gf16_conformance_v0.json` | GF16 | 16 | 21 | `0x4100` | n/a | yes | no | no | sibling (SSOT anchor pack) |
| `fp8_e4m3fn_conformance_v0.json` | FP8 E4M3FN | 8 | 14 | `0x44` | 448.0 (`0x7E`) | no | single (`0x7F`/`0xFF`) | no | [#8549](https://github.com/tenstorrent/tt-mlir/issues/8549) |
| `fp8_e5m2_conformance_v0.json` | FP8 E5M2 | 8 | 16 | `0x42` | 57344.0 (`0x7B`) | yes (`0x7C`/`0xFC`) | yes (E=11111,M!=0) | no | [#8549](https://github.com/tenstorrent/tt-mlir/issues/8549) |
| `mxfp4_e2m1_conformance_v0.json` | MXFP4 E2M1 | 4 | 16 | `0x5` | 6.0 (`0x7`) | no | no | no | [#7085](https://github.com/tenstorrent/tt-mlir/issues/7085) |
| `bf16_golden_conformance_v0.json` | bfloat16 | 16 | 8 + golden | `0x4040` | n/a | yes | yes | yes | [#6252](https://github.com/tenstorrent/tt-mlir/issues/6252) |

## SHA-256

```
7aea5b9e86ea71a54ae0c1601cea13e2d90d95fecaf2ae969eac1349cf7a2b42 gf16_conformance_v0.json
7193ccd0d330d3e05154432abcec5da4a4c170e11004d4ffa44ff5cbbff9cba9 fp8_e4m3fn_conformance_v0.json
9c31fbd03923bd6555304848a092504dfbc02f72d2be82d2b80f49243e925a18 fp8_e5m2_conformance_v0.json
b5795fed0c0f2b580174b443d2c54519c4953916525237bb7ea7d6831f14fde7 mxfp4_e2m1_conformance_v0.json
98bbddcbb8a520dc45a6dfed7209c50a0acc0fabc4d3b430359969467eee4e13 bf16_golden_conformance_v0.json
```

## Shared row schema

Each vector row carries:

```
name short label
input_f64 the f64 value (or "NaN" / "Inf" / "-Inf" for specials)
input_f64_hex big-endian IEEE-754 double hex of input
<fmt>_bits_hex the native format bit pattern, hex
<fmt>_bits_int the native format bit pattern, integer
decoded_f64 value after decode back to f64
decoded_f64_hex big-endian double hex of decoded
abs_error |input_f64 - decoded_f64| (0 for representable values)
category one of: zero, subnormal, normal, inf, nan, phi_anchor
```

The bits field is named per format: `gf16_bits_*`, `fp8_bits_*`,
`mxfp4_bits_*`, `bf16_bits_*`. All other keys are identical across packs.

## Per-format notes (the round-trip decision in each)

### GF16 (16-bit)
The original anchor pack. Carries `phi`, `inv_phi`, `phi^2`, `inv_phi^2`, and
the identity sum `phi^2 + 1/phi^2 = 3` (vector `identity_sum`, bits `0x4100`).
Categories include `phi_anchor`. Sibling to the FP8/MXFP4/bf16 packs via the
shared row schema.

### FP8 E4M3FN (`torch.float8_e4m3fn`)
1s4e3m, bias 7. No inf. Single NaN at `S.1111.111`. Max finite 448.0 at `0x7E`
(mantissa 110, since all-ones mantissa at max exponent is reserved for NaN).
Min subnormal 2^-9, min normal 2^-6.
Encode policy (reference): round-nearest-ties-even; overflow SATURATES to
448.0, not NaN. That saturate-vs-NaN choice is the round-trip decision in
tt-mlir #8549.

### FP8 E5M2 (`torch.float8_e5m2`)
1s5e2m, bias 15. HAS inf at `0x7C`/`0xFC` (E=11111, M=00); NaN at E=11111,
M!=00. Max finite 57344.0 at `0x7B`. Min subnormal 2^-16, min normal 2^-14.
Encode policy (reference): round-nearest-ties-even; overflow goes to +/-Inf
(true IEEE), NOT saturate. The saturate (E4M3FN) vs overflow-to-Inf (E5M2)
split is the practical round-trip gotcha across the two FP8 variants.

### MXFP4 E2M1 (OCP Microscaling element format)
1s2e1m, bias 1. Only 16 codes; no inf, no NaN. Full positive grid
`{0, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0}`. Max finite 6.0 at `0x7`.
tt-mlir #7085 clamps to +/-7, which is one step ABOVE the format max:
values in (6, 7] still round to the 6.0 grid point. The clamp bound and the
representable max are different numbers; the pack enumerates all 16 codes so
that relationship is explicit. Anchor 3.0 is an exact grid point at `0x5`.

### bfloat16 (golden accumulation)
1s8e7m, bias 127 (top 16 bits of fp32). HAS inf and NaN. Decode exact into f64.
Element table plus a `golden_accumulation` section targeting tt-mlir #6252:
the all-close gap in depth-31 fused reduction trees comes from accumulation
ORDER, not single-op rounding. The section gives an f64 golden reference and
compares sequential vs pairwise bf16 reductions; pairwise stays near the golden
while sequential drifts. A reproducible all-close test needs a clamped
deterministic input set plus an f64 golden -- both are supplied.

## Provenance

Generators (re-run to reproduce byte-identical packs):

```
gen_fp8_e4m3.py -> fp8_e4m3fn_conformance_v0.json
gen_fp8_e5m2.py -> fp8_e5m2_conformance_v0.json
gen_mxfp4_e2m1.py -> mxfp4_e2m1_conformance_v0.json
gen_bf16_golden.py -> bf16_golden_conformance_v0.json
```

All packs are ASCII-only. Apache-2.0, consistent with the t27 repository.
169 changes: 169 additions & 0 deletions conformance/vectors/bf16_golden_conformance_v0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
{
"schema": "t27-conformance/v0.1",
"format": "BFLOAT16",
"format_notes": "1s8e7m, bias 127, same exponent range as fp32 (top 16 bits of fp32). HAS inf and NaN. Decode exact into f64.",
"ssot": "https://github.com/gHashTag/t27/blob/master/conformance/FORMAT-SPEC-001.json",
"preprint": "https://arxiv.org/abs/2606.05017",
"anchor_identity": "phi^2 + 1/phi^2 = 3",
"anchor_check": {
"value": 3.0,
"expected": 3.0,
"ieee754_exact": true,
"bf16_bits_hex": "0x4040"
},
"issue_6252_note": "Rounding-error accumulation in depth-31 fused trees. The all-close gap comes from accumulation ORDER, not single-op rounding. The golden_accumulation section gives an f64 golden reference plus sequential vs pairwise bf16 reductions; pairwise reduces the accumulated error. A reproducible all-close test needs (a) a clamped deterministic input set and (b) an f64 golden, both supplied here.",
"round_trip_policy": "decode: bf16 bits -> f64 exact. encode: fp32->bf16 round-nearest-ties-even on the 16-bit truncation boundary. abs_error is nonzero only for inputs not representable in bf16 (e.g. 0.1) -- stated honestly, not hidden.",
"n_vectors": 8,
"vectors": [
{
"name": "pos_zero",
"input_f64": 0.0,
"input_f64_hex": "0x0000000000000000",
"bf16_bits_hex": "0x0000",
"bf16_bits_int": 0,
"decoded_f64": 0.0,
"decoded_f64_hex": "0x0000000000000000",
"abs_error": 0.0,
"category": "zero"
},
{
"name": "pos_one",
"input_f64": 1.0,
"input_f64_hex": "0x3FF0000000000000",
"bf16_bits_hex": "0x3F80",
"bf16_bits_int": 16256,
"decoded_f64": 1.0,
"decoded_f64_hex": "0x3FF0000000000000",
"abs_error": 0.0,
"category": "normal"
},
{
"name": "neg_one",
"input_f64": -1.0,
"input_f64_hex": "0xBFF0000000000000",
"bf16_bits_hex": "0xBF80",
"bf16_bits_int": 49024,
"decoded_f64": -1.0,
"decoded_f64_hex": "0xBFF0000000000000",
"abs_error": 0.0,
"category": "normal"
},
{
"name": "pos_two",
"input_f64": 2.0,
"input_f64_hex": "0x4000000000000000",
"bf16_bits_hex": "0x4000",
"bf16_bits_int": 16384,
"decoded_f64": 2.0,
"decoded_f64_hex": "0x4000000000000000",
"abs_error": 0.0,
"category": "normal"
},
{
"name": "pos_three",
"input_f64": 3.0,
"input_f64_hex": "0x4008000000000000",
"bf16_bits_hex": "0x4040",
"bf16_bits_int": 16448,
"decoded_f64": 3.0,
"decoded_f64_hex": "0x4008000000000000",
"abs_error": 0.0,
"category": "normal"
},
{
"name": "pos_half",
"input_f64": 0.5,
"input_f64_hex": "0x3FE0000000000000",
"bf16_bits_hex": "0x3F00",
"bf16_bits_int": 16128,
"decoded_f64": 0.5,
"decoded_f64_hex": "0x3FE0000000000000",
"abs_error": 0.0,
"category": "normal"
},
{
"name": "pos_quarter",
"input_f64": 0.25,
"input_f64_hex": "0x3FD0000000000000",
"bf16_bits_hex": "0x3E80",
"bf16_bits_int": 16000,
"decoded_f64": 0.25,
"decoded_f64_hex": "0x3FD0000000000000",
"abs_error": 0.0,
"category": "normal"
},
{
"name": "pos_0p1",
"input_f64": 0.1,
"input_f64_hex": "0x3FB999999999999A",
"bf16_bits_hex": "0x3DCD",
"bf16_bits_int": 15821,
"decoded_f64": 0.10009765625,
"decoded_f64_hex": "0x3FB9A00000000000",
"abs_error": 9.765624999999445e-05,
"category": "normal"
}
],
"golden_accumulation": [
{
"element_f64": 0.1,
"element_f64_hex": "0x3FB999999999999A",
"element_bf16_hex": "0x3DCD",
"n_terms": 1024,
"golden_f64": 102.4,
"golden_f64_hex": "0x405999999999999A",
"sequential_bf16": 32.0,
"pairwise_bf16": 102.5,
"abs_err_sequential": 70.4,
"abs_err_pairwise": 0.09999999999999432,
"rel_err_sequential": 0.6875,
"rel_err_pairwise": 0.0009765624999999445,
"pairwise_better": true
},
{
"element_f64": 3.0,
"element_f64_hex": "0x4008000000000000",
"element_bf16_hex": "0x4040",
"n_terms": 1024,
"golden_f64": 3072.0,
"golden_f64_hex": "0x40A8000000000000",
"sequential_bf16": 1024.0,
"pairwise_bf16": 3072.0,
"abs_err_sequential": 2048.0,
"abs_err_pairwise": 0.0,
"rel_err_sequential": 0.6666666666666666,
"rel_err_pairwise": 0.0,
"pairwise_better": true
},
{
"element_f64": 0.1,
"element_f64_hex": "0x3FB999999999999A",
"element_bf16_hex": "0x3DCD",
"n_terms": 4096,
"golden_f64": 409.6,
"golden_f64_hex": "0x407999999999999A",
"sequential_bf16": 32.0,
"pairwise_bf16": 410.0,
"abs_err_sequential": 377.6,
"abs_err_pairwise": 0.39999999999997726,
"rel_err_sequential": 0.921875,
"rel_err_pairwise": 0.0009765624999999445,
"pairwise_better": true
},
{
"element_f64": 0.3333333333333333,
"element_f64_hex": "0x3FD5555555555555",
"element_bf16_hex": "0x3EAB",
"n_terms": 2048,
"golden_f64": 682.6666666666666,
"golden_f64_hex": "0x4085555555555555",
"sequential_bf16": 128.0,
"pairwise_bf16": 684.0,
"abs_err_sequential": 554.6666666666666,
"abs_err_pairwise": 1.3333333333333712,
"rel_err_sequential": 0.8125,
"rel_err_pairwise": 0.0019531250000000555,
"pairwise_better": true
}
]
}
Loading
Loading