diff --git a/conformance/vectors/INDEX_all_formats.json b/conformance/vectors/INDEX_all_formats.json index b6454b07c..2268829cd 100644 --- a/conformance/vectors/INDEX_all_formats.json +++ b/conformance/vectors/INDEX_all_formats.json @@ -5,8 +5,9 @@ "preprint": "https://arxiv.org/abs/2606.05017", "total_formats": 83, "total_packs": 83, - "bitexact_packs": 55, - "structural_packs": 22, + "bitexact_packs": 61, + "selfconsistent_packs": 6, + "structural_packs": 16, "packs": [ { "id": "binary16", @@ -51,26 +52,26 @@ { "id": "decimal32", "file": "decimal32_conformance_v0.json", - "kind": "structural", - "n_vectors": 0, + "kind": "bitexact", + "n_vectors": 7, "source": "generated by gen_all_formats.py", - "sha256": "cd43863397f911142eed1e8e5f2a8ef41ba97d344aa6b64f8f550b5b390bbcad" + "sha256": "e13bc9cd6bc33545ab55f575e23d2343418ded5eddf1395b61f31321dc7d272e" }, { "id": "decimal64", "file": "decimal64_conformance_v0.json", - "kind": "structural", - "n_vectors": 0, + "kind": "bitexact", + "n_vectors": 7, "source": "generated by gen_all_formats.py", - "sha256": "c42aabb5cf847a521698d9451f490ceb17c29ff1169e9c1147609ae737635a5b" + "sha256": "fedef68cfe1b910e737574bbe331dc19fbe1724edbd35ec8beac89b1595bea0d" }, { "id": "decimal128", "file": "decimal128_conformance_v0.json", - "kind": "structural", - "n_vectors": 0, + "kind": "bitexact", + "n_vectors": 8, "source": "generated by gen_all_formats.py", - "sha256": "0e3ab9f3bd6bc3525457c9cbbab1d99ecc801a5019dd92cc87f2c5468b0d471a" + "sha256": "84dbc594340717415385b3bd86eb20432f5430aba047557579f2e2a96de0dc2d" }, { "id": "x87_fp80", @@ -83,18 +84,18 @@ { "id": "double_double", "file": "double_double_conformance_v0.json", - "kind": "structural", - "n_vectors": 0, + "kind": "bitexact", + "n_vectors": 8, "source": "generated by gen_all_formats.py", - "sha256": "6bc6d15ba3258a125c591dedc63b4125b7ecc0d502bc1c3a2ecf65a76714c526" + "sha256": "f8dc9608093afada65df94852a9b78c3a4a5466415389c5ec359afd19d3b208c" }, { "id": "quad_double", "file": "quad_double_conformance_v0.json", - "kind": "structural", - "n_vectors": 0, + "kind": "bitexact", + "n_vectors": 8, "source": "generated by gen_all_formats.py", - "sha256": "d0d7b15d7d8d6c590437a1e9f2d215d63115448f4eb26fe479cc5999f7b21c03" + "sha256": "62ef8067fd1d70ef0abac77d4b0252a3686b9cd698ee4806e0bc1e01bcfe7cfa" }, { "id": "bfloat16", @@ -366,16 +367,15 @@ { "id": "gf10", "file": "gf10_conformance_v0.json", - "kind": "structural", - "n_vectors": 0, + "kind": "bitexact", + "n_vectors": 8, "source": "generated by gen_all_formats.py", - "sha256": "e7043494280dd9716f7e47ed2ef1b149872823514a9267cca5190599fc6b2102" + "sha256": "af62499491faf340d7940b0b10ab0208745e57faa97bbe19588fe1d879db485b" }, { "id": "gf14", "file": "gf14_conformance_v0.json", "kind": "bitexact_selfconsistent", - "n_vectors": 14, "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", "sha256": "e4e25a0cd32c4539e152569304b1ae6204b63de65fa4fa3d824b3d74d6d875c8" }, @@ -383,7 +383,6 @@ "id": "gf48", "file": "gf48_conformance_v0.json", "kind": "bitexact_selfconsistent", - "n_vectors": 15, "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", "sha256": "bf88f55076175dffe1fa108e0e6a526829e274f049c839e26a002a6ea6dd534e" }, @@ -391,7 +390,6 @@ "id": "gf96", "file": "gf96_conformance_v0.json", "kind": "bitexact_selfconsistent", - "n_vectors": 15, "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", "sha256": "2566ac9f2b9fb1950e4c52e09715c148f6d29d681aa37c70f0a7e6c0457a3dba" }, @@ -399,7 +397,6 @@ "id": "gf128", "file": "gf128_conformance_v0.json", "kind": "bitexact_selfconsistent", - "n_vectors": 15, "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", "sha256": "23a82862b0302585031b46ca75928c793f30297351ca84f806ee6497bc659264" }, @@ -415,7 +412,6 @@ "id": "gf512", "file": "gf512_conformance_v0.json", "kind": "bitexact_selfconsistent", - "n_vectors": 15, "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", "sha256": "87bd4d7cbf7fc0d653b7c3b5e5399154c7cb746a0fe668a983f767ad69b15b07" }, @@ -423,7 +419,6 @@ "id": "gf1024", "file": "gf1024_conformance_v0.json", "kind": "bitexact_selfconsistent", - "n_vectors": 15, "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", "sha256": "6ef1c5cbe76828bf0e587fa5c0bb0f40989a7d1056cb54ad45eed192e98b4f4e" }, @@ -667,6 +662,5 @@ "source": "generated by gen_all_formats.py", "sha256": "fc2a0a6dcce7bbb0eccc1e23ebdacb9abbd81cd54111796be6dc7e6a87a2071a" } - ], - "selfconsistent_packs": 6 -} + ] +} \ No newline at end of file diff --git a/conformance/vectors/README.md b/conformance/vectors/README.md index 367ffa6ad..47395c021 100644 --- a/conformance/vectors/README.md +++ b/conformance/vectors/README.md @@ -17,8 +17,9 @@ ships **83 conformance packs — one per format**, with no gaps: | Class | Packs | Meaning | |---|---|---| -| **Bit-precise** | **55** | Native bits decode to f64 exactly; `abs_error = 0` by construction for every representable value. Values not exactly representable in a format report a nonzero `abs_error` **honestly** (e.g. 0.1 in bf16) — nothing is hidden. | -| **Structural** | **28** | The format has no single fixed radix-2 S:E:M round-trip (parametric / lookup / open-R&D / multi-double composite). These packs carry full catalog metadata plus an explicit `structural_reason` and are marked `bitexact: false`. They are honest placeholders, **not** bit-exact claims. | +| **Bit-precise** | **61** | Native bits decode to f64 exactly; `abs_error = 0` by construction for every representable value. Values not exactly representable in a format report a nonzero `abs_error` **honestly** (e.g. 0.1 in bf16) — nothing is hidden. | +| **Self-consistent** | **6** | Wide GoldenFloat rungs (`gf14/48/96/128/512/1024`) that re-derive under a single dyadic-exact decode law but have **no independent second witness**, so they are deliberately **not** promoted to the stronger bit-precise label. | +| **Structural** | **16** | The format has no single fixed radix-2 S:E:M round-trip (parametric / lookup / open-R&D / multi-double composite). These packs carry full catalog metadata plus an explicit `structural_reason` and are marked `bitexact: false`. They are honest placeholders, **not** bit-exact claims. | | **Total** | **83** | One pack per catalog format. | Coverage policy (deterministic, reproducible): @@ -36,7 +37,7 @@ floats (`ibm_hfp32/64/128`), Intel `x87_fp80` (explicit integer bit), the NF4 explicit decoder + reference encoder and `abs_error = 0` for every recorded vector. -Of the 55 bit-precise packs, the IBM HFP and x87 packs hit the 3.0 anchor +Of the 61 bit-precise packs, the IBM HFP and x87 packs hit the 3.0 anchor **exactly** (3.0 = 0.1875 x 16^1 in HFP; 3.0 = 1.5 x 2^1 in x87). The packs that do **not** place 3.0 on a grid point — `lns8/16/32/64`, `gf4`, `mxgf4`, and now `gfternary` and `nf4` — are honest about it: log2(3) is not exactly @@ -46,10 +47,16 @@ phi^2 + phi^-2 = 3, not as a single code), and the NF4 table spans [-1, 1]. Each such pack records the nearest representable value (or a null anchor with a note) and its true `abs_error`. -## Index — bit-precise packs (55) +## Index — bit-precise packs (61) | Pack | Format | Vectors | Round-trip | |---|---|---|---| +| `gf10_conformance_v0.json` | GF10 | 8 | ✔ (GoldenFloat phi-aligned S1E3M6, bias 3 (rule e=round(9/phi^2)=3)) | +| `decimal32_conformance_v0.json` | DECIMAL32 | 7 | ✔ (IEEE 754-2008 BID decode (coeff*10^exp); 3.0 exact) | +| `decimal64_conformance_v0.json` | DECIMAL64 | 7 | ✔ (IEEE 754-2008 BID decode (coeff*10^exp); 3.0 exact) | +| `decimal128_conformance_v0.json` | DECIMAL128 | 8 | ✔ (IEEE 754-2008 BID decode (coeff*10^exp); 3.0 exact) | +| `double_double_conformance_v0.json` | DOUBLE_DOUBLE | 8 | ✔ (Bailey/Hida limb-sum decode (2x binary64); 3.0 exact) | +| `quad_double_conformance_v0.json` | QUAD_DOUBLE | 8 | ✔ (Bailey/Hida limb-sum decode (4x binary64); 3.0 exact) | | `bf16_golden_conformance_v0.json` | BFLOAT16 | 8+golden | ✔ (предсуществующий) | | `gfternary_conformance_v0.json` | GFTERNARY | 4 | ✔ (2-bit {-phi,0,+phi}, exhaustive) | | `ibm_hfp128_conformance_v0.json` | IBM_HFP128 | 8 | ✔ (base-16, named small values) | @@ -109,29 +116,32 @@ note) and its true `abs_error`. `+golden` denotes an attached `golden_accumulation` section (bf16 reduction reference for tt-mlir #6252). -## Index — structural packs (28) + +## Index — self-consistent packs (6) + +Wide GoldenFloat rungs: single dyadic-exact decode law, no independent +second witness (kind=`bitexact_selfconsistent` in the index). + +| Pack | Format | n_vec | Note | +|---|---|---|---| +| `gf14_conformance_v0.json` | GF14 | 14 | wide-rung GoldenFloat oracle (dyadic-exact, single decode law) | +| `gf48_conformance_v0.json` | GF48 | 15 | wide-rung GoldenFloat oracle (dyadic-exact, single decode law) | +| `gf96_conformance_v0.json` | GF96 | 15 | wide-rung GoldenFloat oracle (dyadic-exact, single decode law) | +| `gf128_conformance_v0.json` | GF128 | 15 | wide-rung GoldenFloat oracle (dyadic-exact, single decode law) | +| `gf512_conformance_v0.json` | GF512 | 15 | wide-rung GoldenFloat oracle (dyadic-exact, single decode law) | +| `gf1024_conformance_v0.json` | GF1024 | 15 | wide-rung GoldenFloat oracle (dyadic-exact, single decode law) | + +## Index — structural packs (16) | Pack | Format | Why structural (not bit-exact) | |---|---|---| | `afp_conformance_v0.json` | AFP | No fixed bit-precise round-trip is defined for this entry; recorded structurally with catalog metadata. | | `bcd_conformance_v0.json` | BCD | This format has no single fixed bit layout (parametric / technique / variable-width). | | `block_fp_conformance_v0.json` | BLOCK_FP | This format has no single fixed bit layout (parametric / technique / variable-width). | -| `decimal128_conformance_v0.json` | DECIMAL128 | IEEE 754 decimal (DPD/BID) encodes coefficients in a packed decimal field; round-trip is exact for decimal values but the bit layout is not a plain radix-2 S:E:M. | -| `decimal32_conformance_v0.json` | DECIMAL32 | IEEE 754 decimal (DPD/BID) encodes coefficients in a packed decimal field; round-trip is exact for decimal values but the bit layout is not a plain radix-2 S:E:M. | -| `decimal64_conformance_v0.json` | DECIMAL64 | IEEE 754 decimal (DPD/BID) encodes coefficients in a packed decimal field; round-trip is exact for decimal values but the bit layout is not a plain radix-2 S:E:M. | -| `double_double_conformance_v0.json` | DOUBLE_DOUBLE | Extended-precision layout (explicit integer bit / multi-double components) is not a single S:E:M field; recorded structurally. | -| `gf1024_conformance_v0.json` | GF1024 | No fixed bit-precise round-trip is defined for this entry; recorded structurally with catalog metadata. | -| `gf10_conformance_v0.json` | GF10 | No fixed bit-precise round-trip is defined for this entry; recorded structurally with catalog metadata. | -| `gf128_conformance_v0.json` | GF128 | Bias is an OPEN R&D parameter for this width (see catalog status Experimental); a bit-precise pack is deferred until the bias is fixed. | -| `gf14_conformance_v0.json` | GF14 | No fixed bit-precise round-trip is defined for this entry; recorded structurally with catalog metadata. | | `gf256_conformance_v0.json` | GF256 | Bias is an OPEN R&D parameter for this width (see catalog status Experimental); a bit-precise pack is deferred until the bias is fixed. | -| `gf48_conformance_v0.json` | GF48 | No fixed bit-precise round-trip is defined for this entry; recorded structurally with catalog metadata. | -| `gf512_conformance_v0.json` | GF512 | No fixed bit-precise round-trip is defined for this entry; recorded structurally with catalog metadata. | -| `gf96_conformance_v0.json` | GF96 | No fixed bit-precise round-trip is defined for this entry; recorded structurally with catalog metadata. | | `minifloat_conformance_v0.json` | MINIFLOAT | This format has no single fixed bit layout (parametric / technique / variable-width). | | `per_channel_scale_conformance_v0.json` | PER_CHANNEL_SCALE | INT8 payload with an external per-channel fp32 scale; the decoded value depends on the scale tensor, so a standalone round-trip table is not defined. | | `q_format_conformance_v0.json` | Q_FORMAT | This format has no single fixed bit layout (parametric / technique / variable-width). | -| `quad_double_conformance_v0.json` | QUAD_DOUBLE | Extended-precision layout (explicit integer bit / multi-double components) is not a single S:E:M field; recorded structurally. | | `shared_exp_conformance_v0.json` | SHARED_EXP | This format has no single fixed bit layout (parametric / technique / variable-width). | | `stochastic_rounding_conformance_v0.json` | STOCHASTIC_ROUNDING | This format has no single fixed bit layout (parametric / technique / variable-width). | | `takum16_conformance_v0.json` | TAKUM16 | Takum (Hunhold 2024) is a tapered LOGARITHMIC format; its decode is not a plain S:E:M field. | @@ -173,8 +183,8 @@ round-trips. ## Machine-readable index `INDEX_all_formats.json` lists all 83 packs with totals -(`total_formats: 83`, `total_packs: 83`, `bitexact_packs: 55`, -`structural_packs: 28`), the anchor identity, the SSOT path, and the preprint. +(`total_formats: 83`, `total_packs: 83`, `bitexact_packs: 61`, +`selfconsistent_packs: 6`, `structural_packs: 16`), the anchor identity, the SSOT path, and the preprint. ## SHA-256 @@ -189,33 +199,33 @@ round-trips. 1d3e3d6daee576ae3b2b4dca6f26560390535fb7441a54b389f98a4238e58bec binary64_conformance_v0.json 3129fa92145096e55527c2fc22d9e6bed23db1a6d88148e8b711a3b6641a43c1 block_fp_conformance_v0.json b1a8f6652112be3f49949bafe9f6cd7f46f0271e8f4e19cadb55c2a0e972f503 cray_float_conformance_v0.json -0e3ab9f3bd6bc3525457c9cbbab1d99ecc801a5019dd92cc87f2c5468b0d471a decimal128_conformance_v0.json -cd43863397f911142eed1e8e5f2a8ef41ba97d344aa6b64f8f550b5b390bbcad decimal32_conformance_v0.json -c42aabb5cf847a521698d9451f490ceb17c29ff1169e9c1147609ae737635a5b decimal64_conformance_v0.json -6bc6d15ba3258a125c591dedc63b4125b7ecc0d502bc1c3a2ecf65a76714c526 double_double_conformance_v0.json +84dbc594340717415385b3bd86eb20432f5430aba047557579f2e2a96de0dc2d decimal128_conformance_v0.json +e13bc9cd6bc33545ab55f575e23d2343418ded5eddf1395b61f31321dc7d272e decimal32_conformance_v0.json +fedef68cfe1b910e737574bbe331dc19fbe1724edbd35ec8beac89b1595bea0d decimal64_conformance_v0.json +f8dc9608093afada65df94852a9b78c3a4a5466415389c5ec359afd19d3b208c double_double_conformance_v0.json 8ded6625c4644139320dd89b2b7815d6ba27177c35b7d645b2d93b8cfdc63fd9 fp4_e2m1_conformance_v0.json de70d6aacf0ac2d47decae0866d14f126058176428315d4c767e460c0a9ae5e5 fp6_e2m3_conformance_v0.json 17a80f0a3b5b2495dbcd6de6062d8c1f8ce19b9746d1e370e6d16897ef5f9c02 fp6_e3m2_conformance_v0.json 7193ccd0d330d3e05154432abcec5da4a4c170e11004d4ffa44ff5cbbff9cba9 fp8_e4m3fn_conformance_v0.json 9c31fbd03923bd6555304848a092504dfbc02f72d2be82d2b80f49243e925a18 fp8_e5m2_conformance_v0.json -652fe39cee0023880091c79bb4b6def96950947da920fdf6f059a33ea1b7c405 gf1024_conformance_v0.json -e7043494280dd9716f7e47ed2ef1b149872823514a9267cca5190599fc6b2102 gf10_conformance_v0.json -322bfc28e4182878b476ae4e869b5a697ea2224895550ada1dd953fad0b110cc gf128_conformance_v0.json +6ef1c5cbe76828bf0e587fa5c0bb0f40989a7d1056cb54ad45eed192e98b4f4e gf1024_conformance_v0.json +af62499491faf340d7940b0b10ab0208745e57faa97bbe19588fe1d879db485b gf10_conformance_v0.json +23a82862b0302585031b46ca75928c793f30297351ca84f806ee6497bc659264 gf128_conformance_v0.json ea00efde4825931a421ec9feb5910f3ad9ab7ab5d38a77d2c364ea9fa49a7f96 gf12_conformance_v0.json -0ed0eb17a72fb959746fd86892a257a53a7191edb7889e26d59fd630922f54a9 gf14_conformance_v0.json -7aea5b9e86ea71a54ae0c1601cea13e2d90d95fecaf2ae969eac1349cf7a2b42 gf16_conformance_v0.json +e4e25a0cd32c4539e152569304b1ae6204b63de65fa4fa3d824b3d74d6d875c8 gf14_conformance_v0.json +d1c0eb5bd66247b3c5db9a00a95e29cf4359653aec56f2f9e6827f96898d1509 gf16_conformance_v0.json 76c7814558901d5633cb16ffead7468583de5577c4ccf0378c296c73ae08acc5 gf20_conformance_v0.json 983642c7aea54b7e6c5b6e41edcf20828bfc3a1f2707307eaa713ca5a45e612c gf24_conformance_v0.json 49875dcac61b316151064ce2f462fe732f37ce07c18e9024240cba4d707e2f9d gf256_conformance_v0.json f7222e2442f2c106e7f3590e5dbe8ed177603fc2324560987af138ae9abeceb4 gf32_conformance_v0.json -85550904fc58172e11862a11be4cdad7a769064b39f7f2b457224208e4018d16 gf48_conformance_v0.json +bf88f55076175dffe1fa108e0e6a526829e274f049c839e26a002a6ea6dd534e gf48_conformance_v0.json 25471b7a0e3dc3633118191e722ced2f450a3ed8a6228ad2492f92084f556f96 gf4_conformance_v0.json -f03fa45ee9e640c8d1fba1b176c7951de1409696bf0f4395380ba6f029944087 gf512_conformance_v0.json +87bd4d7cbf7fc0d653b7c3b5e5399154c7cb746a0fe668a983f767ad69b15b07 gf512_conformance_v0.json 887223d0bc8b00d76b70238ddbc8933e3a773ed6a9fbc10264d9fdbebca76cd3 gf64_conformance_v0.json 9c9fc955db5f6c9b185bdd5d88bd92f3f21a71ad4d784b944330d5cba85fb724 gf6_conformance_v0.json fe600234cab0e589b69d84e673d74729cff153f9e4e63e871e285fa82ad2cc70 gf8_bfp_conformance_v0.json 6dccbc6628cbc051e06a006a0731499970c1d99e65fc0d42d9007d8f0ed1402d gf8_conformance_v0.json -786f9d144243db2e6c4dba2ddbef4ae2975d045f1ad370cd462eb61cc70dd3d5 gf96_conformance_v0.json +2566ac9f2b9fb1950e4c52e09715c148f6d29d681aa37c70f0a7e6c0457a3dba gf96_conformance_v0.json eb7c946281fb6ed6fadd9c63c7e7fa186412480910c9fedcb25fbc056c1bd34a gf_lns_hybrid_conformance_v0.json 9f246d24511fbff6fb9e83e60e1bedfce401052537f7c8929fe205d0f6e57b81 gfternary_conformance_v0.json 2f02899d621a8a7aebfdf2a69a2484d7616c61ac7cebdc483f643e8109c4e31f ibm_hfp128_conformance_v0.json @@ -246,7 +256,7 @@ aee6cc72691a0ae211e39bf6315ac68a5fe74e87190e0c27088871c6ccc87f52 posit32_confor 66b14056938549c1aaa522097ee8744246581cf6d3bb6002cef3b2f3f6ea0ff6 posit64_conformance_v0.json 0c638ef95b6537e4dc0e256dc1ca2d9363152b3d5a800501472230ce98a84b76 posit8_conformance_v0.json 2bc0c114aecd1d0dbfa7925efe298cea80efd510022ee0734cf9450af8027b63 q_format_conformance_v0.json -d0d7b15d7d8d6c590437a1e9f2d215d63115448f4eb26fe479cc5999f7b21c03 quad_double_conformance_v0.json +62ef8067fd1d70ef0abac77d4b0252a3686b9cd698ee4806e0bc1e01bcfe7cfa quad_double_conformance_v0.json ca139ebd7bc5c139357c533bb0a6509e4edd05044d7869fcea57cf34d052c3c7 shared_exp_conformance_v0.json fc2a0a6dcce7bbb0eccc1e23ebdacb9abbd81cd54111796be6dc7e6a87a2071a stochastic_rounding_conformance_v0.json 631c574d46f1b2288ffddeab0b157c12a4f904b5bf7371128267f96db0b19c5c takum16_conformance_v0.json @@ -293,6 +303,28 @@ All packs are ASCII-only. Apache-2.0, consistent with the t27 repository. ## Changelog +- **2026-06-28** — promoted 6 packs from structural to **bit-precise** by adding + dedicated reference codecs to `gen_all_formats.py` + (bit-precise 55 -> 61, structural 22 -> 16; the self-consistent GF wide-rung + tier (6) is unchanged): + - `gf10` — GoldenFloat phi-aligned radix-2 `S1E3M6`, bias 3 (rule + e=round(9/phi^2)=3, bridge GF8-GF12). Decode reuses the proven GF radix-2 + law; 3.0 is exact at code 0x120. + - `decimal32/64/128` — IEEE 754-2008 **BID** (Binary Integer Decimal): the + significand is a plain binary integer built from the combination-field head + plus the trailing field; `value = coeff * 10^(exp-bias)`. Cross-checked vs + an exact-rational (`fractions.Fraction`) oracle; 3.0 is f64-exact. + - `double_double` / `quad_double` — Bailey/Hida multi-double: value = the + **exact sum** of 2 (resp. 4) IEEE-754 binary64 limbs (most-significant + first). This is a fixed 128/256-bit layout with an unambiguous decode law, + directly analogous to the earlier `x87_fp80` explicit-integer-bit promotion. + Named integer/dyadic values are f64-exact (low limbs 0). + Each promoted pack carries an explicit decoder + reference encoder and + `abs_error = 0` for every recorded vector (decode side). `takum8/16/32/64`, + `afp`, `per_channel_scale`, `gf256` (open bias) and the 9 zero-width + parametric entries (`minifloat`, `q_format`, `bcd`, `block_fp`, `shared_exp`, + `stochastic_rounding`, `tapered_fp`, `unum_i`, `unum_ii`) remain structural. + - **2026-06-14** — promoted 6 packs from structural to **bit-precise** by adding dedicated reference codecs to `gen_all_formats.py` (bit-precise 49 -> 55, structural 34 -> 28): diff --git a/conformance/vectors/decimal128_conformance_v0.json b/conformance/vectors/decimal128_conformance_v0.json index 9eb17842e..b2bc0baf8 100644 --- a/conformance/vectors/decimal128_conformance_v0.json +++ b/conformance/vectors/decimal128_conformance_v0.json @@ -2,8 +2,8 @@ "schema": "t27-conformance/v0.1", "format": "DECIMAL128", "format_name": "decimal128", - "bitexact": false, - "format_notes": "decimal128 -- IEEE 754-2008", + "bitexact": true, + "format_notes": "IEEE 754-2008 decimal128 (BID / Binary Integer Decimal): S1 : combination : trailing significand; significand is a plain binary integer, value = coeff * 10^(exp-bias). inf at combo head 11110; nan at 11111; named decimal values f64-exact", "catalog": { "id": "decimal128", "bits": 128, @@ -23,8 +23,103 @@ "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", - "structural_reason": "IEEE 754 decimal (DPD/BID) encodes coefficients in a packed decimal field; round-trip is exact for decimal values but the bit layout is not a plain radix-2 S:E:M. Recorded structurally with the exact decimal anchor 3.0.", - "anchor_note": "3.0 is exactly representable (decimal coefficient 3, exponent 0).", - "n_vectors": 0, - "vectors": [] + "anchor_check": { + "value": 3.0, + "expected": 3.0, + "ieee754_exact": true, + "decimal128_bits_hex": "0x22080000000000000000000000000003" + }, + "round_trip_policy": "decode: exact bits->f64 (curated_named). encode (reference): round-nearest-ties-even; overflow per format convention. abs_error 0 for representable values.", + "vector_mode": "curated_named", + "n_vectors": 8, + "vectors": [ + { + "name": "pos_zero", + "input_f64": 0.0, + "input_f64_hex": "0x0000000000000000", + "decimal128_bits_hex": "0x06080000000000000000000000000000", + "decimal128_bits_int": 8016906349577773858451086332315828224, + "decoded_f64": 0.0, + "decoded_f64_hex": "0x0000000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "pos_one", + "input_f64": 1.0, + "input_f64_hex": "0x3FF0000000000000", + "decimal128_bits_hex": "0x22080000000000000000000000000001", + "decimal128_bits_int": 45235290231555418299757684020165476353, + "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", + "decimal128_bits_hex": "0xA2080000000000000000000000000001", + "decimal128_bits_int": 215376473692024650031444987736049582081, + "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", + "decimal128_bits_hex": "0x22080000000000000000000000000002", + "decimal128_bits_int": 45235290231555418299757684020165476354, + "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", + "decimal128_bits_hex": "0x22080000000000000000000000000003", + "decimal128_bits_int": 45235290231555418299757684020165476355, + "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", + "decimal128_bits_hex": "0x2207C000000000000000000000000005", + "decimal128_bits_int": 45233992157340784592850551396083171333, + "decoded_f64": 0.5, + "decoded_f64_hex": "0x3FE0000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "pos_four", + "input_f64": 4.0, + "input_f64_hex": "0x4010000000000000", + "decimal128_bits_hex": "0x22080000000000000000000000000004", + "decimal128_bits_int": 45235290231555418299757684020165476356, + "decoded_f64": 4.0, + "decoded_f64_hex": "0x4010000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "neg_three", + "input_f64": -3.0, + "input_f64_hex": "0xC008000000000000", + "decimal128_bits_hex": "0xA2080000000000000000000000000003", + "decimal128_bits_int": 215376473692024650031444987736049582083, + "decoded_f64": -3.0, + "decoded_f64_hex": "0xC008000000000000", + "abs_error": 0.0, + "category": "normal" + } + ] } \ No newline at end of file diff --git a/conformance/vectors/decimal32_conformance_v0.json b/conformance/vectors/decimal32_conformance_v0.json index abf3d5685..52854d141 100644 --- a/conformance/vectors/decimal32_conformance_v0.json +++ b/conformance/vectors/decimal32_conformance_v0.json @@ -2,8 +2,8 @@ "schema": "t27-conformance/v0.1", "format": "DECIMAL32", "format_name": "decimal32", - "bitexact": false, - "format_notes": "decimal32 -- IEEE 754-2008 (DPD/BID)", + "bitexact": true, + "format_notes": "IEEE 754-2008 decimal32 (BID / Binary Integer Decimal): S1 : combination : trailing significand; significand is a plain binary integer, value = coeff * 10^(exp-bias). inf at combo head 11110; nan at 11111; named decimal values f64-exact", "catalog": { "id": "decimal32", "bits": 32, @@ -23,8 +23,92 @@ "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", - "structural_reason": "IEEE 754 decimal (DPD/BID) encodes coefficients in a packed decimal field; round-trip is exact for decimal values but the bit layout is not a plain radix-2 S:E:M. Recorded structurally with the exact decimal anchor 3.0.", - "anchor_note": "3.0 is exactly representable (decimal coefficient 3, exponent 0).", - "n_vectors": 0, - "vectors": [] + "anchor_check": { + "value": 3.0, + "expected": 3.0, + "ieee754_exact": true, + "decimal32_bits_hex": "0x22500003" + }, + "round_trip_policy": "decode: exact bits->f64 (curated_named). encode (reference): round-nearest-ties-even; overflow per format convention. abs_error 0 for representable values.", + "vector_mode": "curated_named", + "n_vectors": 7, + "vectors": [ + { + "name": "pos_one", + "input_f64": 1.0, + "input_f64_hex": "0x3FF0000000000000", + "decimal32_bits_hex": "0x22500001", + "decimal32_bits_int": 575668225, + "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", + "decimal32_bits_hex": "0xA2500001", + "decimal32_bits_int": 2723151873, + "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", + "decimal32_bits_hex": "0x22500002", + "decimal32_bits_int": 575668226, + "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", + "decimal32_bits_hex": "0x22500003", + "decimal32_bits_int": 575668227, + "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", + "decimal32_bits_hex": "0x22400005", + "decimal32_bits_int": 574619653, + "decoded_f64": 0.5, + "decoded_f64_hex": "0x3FE0000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "pos_four", + "input_f64": 4.0, + "input_f64_hex": "0x4010000000000000", + "decimal32_bits_hex": "0x22500004", + "decimal32_bits_int": 575668228, + "decoded_f64": 4.0, + "decoded_f64_hex": "0x4010000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "neg_three", + "input_f64": -3.0, + "input_f64_hex": "0xC008000000000000", + "decimal32_bits_hex": "0xA2500003", + "decimal32_bits_int": 2723151875, + "decoded_f64": -3.0, + "decoded_f64_hex": "0xC008000000000000", + "abs_error": 0.0, + "category": "normal" + } + ] } \ No newline at end of file diff --git a/conformance/vectors/decimal64_conformance_v0.json b/conformance/vectors/decimal64_conformance_v0.json index b9e5e8b90..527e87bb1 100644 --- a/conformance/vectors/decimal64_conformance_v0.json +++ b/conformance/vectors/decimal64_conformance_v0.json @@ -2,8 +2,8 @@ "schema": "t27-conformance/v0.1", "format": "DECIMAL64", "format_name": "decimal64", - "bitexact": false, - "format_notes": "decimal64 -- IEEE 754-2008", + "bitexact": true, + "format_notes": "IEEE 754-2008 decimal64 (BID / Binary Integer Decimal): S1 : combination : trailing significand; significand is a plain binary integer, value = coeff * 10^(exp-bias). inf at combo head 11110; nan at 11111; named decimal values f64-exact", "catalog": { "id": "decimal64", "bits": 64, @@ -23,8 +23,92 @@ "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", - "structural_reason": "IEEE 754 decimal (DPD/BID) encodes coefficients in a packed decimal field; round-trip is exact for decimal values but the bit layout is not a plain radix-2 S:E:M. Recorded structurally with the exact decimal anchor 3.0.", - "anchor_note": "3.0 is exactly representable (decimal coefficient 3, exponent 0).", - "n_vectors": 0, - "vectors": [] + "anchor_check": { + "value": 3.0, + "expected": 3.0, + "ieee754_exact": true, + "decimal64_bits_hex": "0x2238000000000003" + }, + "round_trip_policy": "decode: exact bits->f64 (curated_named). encode (reference): round-nearest-ties-even; overflow per format convention. abs_error 0 for representable values.", + "vector_mode": "curated_named", + "n_vectors": 7, + "vectors": [ + { + "name": "pos_one", + "input_f64": 1.0, + "input_f64_hex": "0x3FF0000000000000", + "decimal64_bits_hex": "0x2238000000000001", + "decimal64_bits_int": 2465720795985346561, + "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", + "decimal64_bits_hex": "0xA238000000000001", + "decimal64_bits_int": 11689092832840122369, + "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", + "decimal64_bits_hex": "0x2238000000000002", + "decimal64_bits_int": 2465720795985346562, + "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", + "decimal64_bits_hex": "0x2238000000000003", + "decimal64_bits_int": 2465720795985346563, + "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", + "decimal64_bits_hex": "0x2234000000000005", + "decimal64_bits_int": 2464594896078503941, + "decoded_f64": 0.5, + "decoded_f64_hex": "0x3FE0000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "pos_four", + "input_f64": 4.0, + "input_f64_hex": "0x4010000000000000", + "decimal64_bits_hex": "0x2238000000000004", + "decimal64_bits_int": 2465720795985346564, + "decoded_f64": 4.0, + "decoded_f64_hex": "0x4010000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "neg_three", + "input_f64": -3.0, + "input_f64_hex": "0xC008000000000000", + "decimal64_bits_hex": "0xA238000000000003", + "decimal64_bits_int": 11689092832840122371, + "decoded_f64": -3.0, + "decoded_f64_hex": "0xC008000000000000", + "abs_error": 0.0, + "category": "normal" + } + ] } \ No newline at end of file diff --git a/conformance/vectors/double_double_conformance_v0.json b/conformance/vectors/double_double_conformance_v0.json index c499e735a..c1a5afe49 100644 --- a/conformance/vectors/double_double_conformance_v0.json +++ b/conformance/vectors/double_double_conformance_v0.json @@ -2,8 +2,8 @@ "schema": "t27-conformance/v0.1", "format": "DOUBLE_DOUBLE", "format_name": "double-double", - "bitexact": false, - "format_notes": "double-double -- Bailey/Hida (software)", + "bitexact": true, + "format_notes": "double-double (Bailey/Hida): two IEEE-754 binary64 limbs, most-significant first; value = exact sum of the limbs. no separate inf/nan field; hi-limb specials propagate; named integer/dyadic values are f64-exact (low limb 0)", "catalog": { "id": "double_double", "bits": 128, @@ -23,8 +23,103 @@ "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", - "structural_reason": "Extended-precision layout (explicit integer bit / multi-double components) is not a single S:E:M field; recorded structurally.", - "anchor_note": "Anchor identity phi^2 + 1/phi^2 = 3 recorded per shared schema.", - "n_vectors": 0, - "vectors": [] + "anchor_check": { + "value": 3.0, + "expected": 3.0, + "ieee754_exact": true, + "double_double_bits_hex": "0x40080000000000000000000000000000" + }, + "round_trip_policy": "decode: exact bits->f64 (curated_named). encode (reference): round-nearest-ties-even; overflow per format convention. abs_error 0 for representable values.", + "vector_mode": "curated_named", + "n_vectors": 8, + "vectors": [ + { + "name": "pos_zero", + "input_f64": 0.0, + "input_f64_hex": "0x0000000000000000", + "double_double_bits_hex": "0x00000000000000000000000000000000", + "double_double_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", + "double_double_bits_hex": "0x3FF00000000000000000000000000000", + "double_double_bits_int": 84987514980498058623787163916674531328, + "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", + "double_double_bits_hex": "0xBFF00000000000000000000000000000", + "double_double_bits_int": 255128698440967290355474467632558637056, + "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", + "double_double_bits_hex": "0x40000000000000000000000000000000", + "double_double_bits_int": 85070591730234615865843651857942052864, + "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", + "double_double_bits_hex": "0x40080000000000000000000000000000", + "double_double_bits_int": 85112130105102894486871895828575813632, + "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", + "double_double_bits_hex": "0x3FE00000000000000000000000000000", + "double_double_bits_int": 84904438230761501381730675975407009792, + "decoded_f64": 0.5, + "decoded_f64_hex": "0x3FE0000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "pos_four", + "input_f64": 4.0, + "input_f64_hex": "0x4010000000000000", + "double_double_bits_hex": "0x40100000000000000000000000000000", + "double_double_bits_int": 85153668479971173107900139799209574400, + "decoded_f64": 4.0, + "decoded_f64_hex": "0x4010000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "neg_three", + "input_f64": -3.0, + "input_f64_hex": "0xC008000000000000", + "double_double_bits_hex": "0xC0080000000000000000000000000000", + "double_double_bits_int": 255253313565572126218559199544459919360, + "decoded_f64": -3.0, + "decoded_f64_hex": "0xC008000000000000", + "abs_error": 0.0, + "category": "normal" + } + ] } \ No newline at end of file diff --git a/conformance/vectors/gen_all_formats.py b/conformance/vectors/gen_all_formats.py index 3eaec1e5a..e64b20ba8 100644 --- a/conformance/vectors/gen_all_formats.py +++ b/conformance/vectors/gen_all_formats.py @@ -27,6 +27,7 @@ All output ASCII-only. Apache-2.0. """ import json, struct, math, hashlib, os, re +from fractions import Fraction HERE = os.path.dirname(os.path.abspath(__file__)) OUT = HERE # write packs next to the existing ones @@ -323,6 +324,143 @@ def decode(bits, total_bits): return (v, cat) return decode +# --------------------------------------------------------------------------- +# IEEE 754-2008 decimal (BID encoding -- Binary Integer Decimal, Intel form). +# Storage is a plain unsigned integer (u32/u64/u128). Layout: +# S(1) : combination(ncomb) : trailing-significand(t) +# The significand is a PLAIN BINARY INTEGER: implied high bits (from the 5-bit +# combination head) concatenated above the t-bit trailing field. The exponent +# continuation bits sit in the low (ncomb-5) bits of the combination field. +# value = (-1)^S * coeff * 10^(exp - bias). +# Decode returns a float (f64); curated_codes keeps only the named values that +# are f64-exact (abs_error == 0 by construction). 3.0 is f64-exact. +# Cross-checked vs an exact-rational (fractions.Fraction) oracle (probe_decoders.py). +# --------------------------------------------------------------------------- +DECIMAL_PARAMS = { + # id -> (ncomb combination bits, t trailing bits, bias, pmax decimal digits) + "decimal32": (11, 20, 101, 7), + "decimal64": (13, 50, 398, 16), + "decimal128": (17, 110, 6176, 34), +} +DECIMAL_TOTAL = {"decimal32": 32, "decimal64": 64, "decimal128": 128} + +def make_decimal_bid_decoder(name): + ncomb, t, bias, pmax = DECIMAL_PARAMS[name] + total = DECIMAL_TOTAL[name] + ec = ncomb - 5 # exponent-continuation bits in the combination field + def decode(bits, total_bits): + x = bits + sign = (x >> (total - 1)) & 1 + combo = (x >> t) & ((1 << ncomb) - 1) + trailing = x & ((1 << t) - 1) + g = combo >> ec # 5-bit combination head + if (g >> 3) == 0b11: # 11xxx -> special or 'large' significand form + if (g >> 1) == 0b1111: # 11110 -> inf, 11111 -> nan + if (g & 1) == 0: + return (math.inf if sign == 0 else -math.inf, "inf") + return (math.nan, "nan") + exp_msb = (g >> 1) & 0b11 + sig_hi = 0b100 | (g & 1) # implied 8 or 9 as the leading group + exp_low = combo & ((1 << ec) - 1) + exp = (exp_msb << ec) | exp_low + coeff = (sig_hi << t) | trailing + else: # normal form + exp_msb = g >> 3 + sig_hi = g & 0b111 + exp_low = combo & ((1 << ec) - 1) + exp = (exp_msb << ec) | exp_low + coeff = (sig_hi << t) | trailing + e = exp - bias + if coeff == 0: + return (-0.0 if sign else 0.0, "zero") + val = Fraction(coeff) * (Fraction(10) ** e if e >= 0 else Fraction(1, 10 ** (-e))) + f = float(-val if sign else val) + return (f, "normal") + return decode + +def make_decimal_bid_encoder(name): + """Encode an f64 target into a canonical BID code (normal form). Returns None + if the target is not exactly an integer*10^exp within pmax digits and normal + form, so curated_codes filters non-exact values.""" + ncomb, t, bias, pmax = DECIMAL_PARAMS[name] + total = DECIMAL_TOTAL[name] + ec = ncomb - 5 + def encode(target): + if not isinstance(target, (int, float)): + return None + if isinstance(target, float) and (math.isnan(target) or math.isinf(target)): + return None + fr = Fraction(target) + sign = 1 if fr < 0 else 0 + a = -fr if fr < 0 else fr + if a == 0: + biased = bias + return (sign << (total - 1)) | (biased << t) + for exp in range(0, -pmax - 1, -1): + scaled = a * (Fraction(10) ** (-exp)) + if scaled.denominator == 1: + coeff = scaled.numerator + if coeff < 10 ** pmax: + biased = exp + bias + if biased < 0 or biased >= (1 << (ec + 2)): + return None + sig_hi = coeff >> t + if sig_hi > 7: + continue + trailing = coeff & ((1 << t) - 1) + exp_msb = biased >> ec + exp_low = biased & ((1 << ec) - 1) + gh = (exp_msb << 3) | sig_hi + combo = (gh << ec) | exp_low + return (sign << (total - 1)) | (combo << t) | trailing + return None + return encode + +# --------------------------------------------------------------------------- +# double-double / quad-double (Bailey/Hida): the value is the EXACT SUM of +# 2 (resp. 4) IEEE-754 binary64 limbs stored most-significant first. Fixed +# 128-bit (resp. 256-bit) layout; the decode law (sum of limbs) is unambiguous +# -- analogous to x87's explicit-integer-bit promotion. Decode returns the f64 +# of the exact sum; for named integer/dyadic targets the low limbs are 0 and the +# value is f64-exact (abs_error == 0). +# --------------------------------------------------------------------------- +def make_multidouble_decoder(n_limbs): + def decode(bits, total_bits): + limbs = [] + for i in range(n_limbs): + shift = (n_limbs - 1 - i) * 64 + u = (bits >> shift) & ((1 << 64) - 1) + limbs.append(struct.unpack(">d", u.to_bytes(8, "big"))[0]) + hi = limbs[0] + if math.isnan(hi): + return (math.nan, "nan") + if math.isinf(hi): + return (hi, "inf") + total_fr = Fraction(0) + for v in limbs: + if math.isnan(v) or math.isinf(v): + return (math.nan, "nan") + total_fr += Fraction(v) + if total_fr == 0: + return (0.0, "zero") + return (float(total_fr), "normal") + return decode + +def make_multidouble_encoder(n_limbs): + def encode(target): + if not isinstance(target, (int, float)): + return None + if isinstance(target, float) and (math.isnan(target) or math.isinf(target)): + return None + hi = float(target) + if hi != target: + return None + u_hi = int.from_bytes(struct.pack(">d", hi), "big") + bits = u_hi << ((n_limbs - 1) * 64) # low limbs = +0.0 + return bits + return encode + + # --------------------------------------------------------------------------- # GFTernary: 2-bit discrete set {-phi, 0, +phi}. Four 2-bit codes; one is a # spare (we map it to the same +phi for completeness / documented as reserved). @@ -531,6 +669,28 @@ def build_decodable(rec): e, m, bias, bits = rec["e"], rec["m"], rec["bias"], rec["bits"] storage = rec["storage"] + # IEEE 754-2008 decimal (BID): fixed bit layout, exact decimal decode. + if cluster == "Ieee754Decimal" and cid in DECIMAL_PARAMS: + return (make_decimal_bid_decoder(cid), + f"IEEE 754-2008 {cid} (BID / Binary Integer Decimal): " + f"S1 : combination : trailing significand; significand is a plain " + f"binary integer, value = coeff * 10^(exp-bias)", + "inf at combo head 11110; nan at 11111; named decimal values f64-exact") + + # Extended-precision multi-double (Bailey/Hida): exact sum of binary64 limbs. + if cluster == "ExtendedFloat" and cid == "double_double": + return (make_multidouble_decoder(2), + "double-double (Bailey/Hida): two IEEE-754 binary64 limbs, " + "most-significant first; value = exact sum of the limbs", + "no separate inf/nan field; hi-limb specials propagate; " + "named integer/dyadic values are f64-exact (low limb 0)") + if cluster == "ExtendedFloat" and cid == "quad_double": + return (make_multidouble_decoder(4), + "quad-double (Bailey/Hida): four IEEE-754 binary64 limbs, " + "most-significant first; value = exact sum of the limbs", + "no separate inf/nan field; hi-limb specials propagate; " + "named integer/dyadic values are f64-exact (low limbs 0)") + # Integer / fixed two's complement if cluster == "IntegerFixed" and cid.startswith("int") and bits > 0: return (make_int_decoder(m, signed=True), @@ -553,7 +713,7 @@ def build_decodable(rec): "GFTernary 2-bit discrete set {-phi, 0, +phi}; codes 00=0, " "01=+phi, 10=-phi, 11=reserved (duplicate +phi)", "no inf/nan; discrete ternary levels") - if e > 0 and m > 0 and bits in (4, 6, 8, 12, 16, 20, 24, 32, 64): + if e > 0 and m > 0 and bits in (4, 6, 8, 10, 12, 16, 20, 24, 32, 64): dec = make_ieee_decoder(e, m, bias, has_inf=True, has_nan=True) return (dec, f"GoldenFloat phi-aligned radix-2 float S{1}E{e}M{m}, bias {bias}", "IEEE-style specials at top exponent") @@ -621,7 +781,7 @@ def build_decodable(rec): f"bit as MSB of the {m}-bit significand), bias {bias}: " f"value = (SIG/2^{m-1}) * 2^(E-{bias})", "inf at max exp (int=1, frac=0); nan otherwise at max exp") - return None # double_double / quad_double -> structural + # double_double / quad_double handled above (multi-double limb-sum decode) # QuantTuned: NF4 is a fixed 16-entry quantile table -> bit-exact lookup. if cluster == "QuantTuned" and cid == "nf4": @@ -767,6 +927,12 @@ def build_bitexact_pack(rec, decode, notes, specials_desc): encoder = make_posit_encoder(bits, es=2) elif cluster == "Lns": encoder = make_lns_encoder(bits) + elif cluster == "Ieee754Decimal" and cid in DECIMAL_PARAMS: + encoder = make_decimal_bid_encoder(cid) + elif cluster == "ExtendedFloat" and cid == "double_double": + encoder = make_multidouble_encoder(2) + elif cluster == "ExtendedFloat" and cid == "quad_double": + encoder = make_multidouble_encoder(4) vectors, mode = curated_codes(bits, decode, fmt_key, encoder=encoder) # anchor if bits <= 16: diff --git a/conformance/vectors/gf10_conformance_v0.json b/conformance/vectors/gf10_conformance_v0.json index 2ecaa49d8..c62932865 100644 --- a/conformance/vectors/gf10_conformance_v0.json +++ b/conformance/vectors/gf10_conformance_v0.json @@ -2,8 +2,8 @@ "schema": "t27-conformance/v0.1", "format": "GF10", "format_name": "GF10 (rule-derived)", - "bitexact": false, - "format_notes": "GF10 (rule-derived) -- this work; rule e=round(9/phi^2)=3; bridge GF8-GF12", + "bitexact": true, + "format_notes": "GoldenFloat phi-aligned radix-2 float S1E3M6, bias 3. IEEE-style specials at top exponent", "catalog": { "id": "gf10", "bits": 10, @@ -23,8 +23,103 @@ "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", - "structural_reason": "No fixed bit-precise round-trip is defined for this entry; recorded structurally with catalog metadata.", - "anchor_note": "Anchor identity phi^2 + 1/phi^2 = 3 recorded per shared schema.", - "n_vectors": 0, - "vectors": [] + "anchor_check": { + "value": 3.0, + "expected": 3.0, + "ieee754_exact": true, + "gf10_bits_hex": "0x120" + }, + "round_trip_policy": "decode: exact bits->f64 (curated_named). encode (reference): round-nearest-ties-even; overflow per format convention. abs_error 0 for representable values.", + "vector_mode": "curated_named", + "n_vectors": 8, + "vectors": [ + { + "name": "pos_zero", + "input_f64": 0.0, + "input_f64_hex": "0x0000000000000000", + "gf10_bits_hex": "0x000", + "gf10_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", + "gf10_bits_hex": "0x0C0", + "gf10_bits_int": 192, + "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", + "gf10_bits_hex": "0x2C0", + "gf10_bits_int": 704, + "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", + "gf10_bits_hex": "0x100", + "gf10_bits_int": 256, + "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", + "gf10_bits_hex": "0x120", + "gf10_bits_int": 288, + "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", + "gf10_bits_hex": "0x080", + "gf10_bits_int": 128, + "decoded_f64": 0.5, + "decoded_f64_hex": "0x3FE0000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "pos_four", + "input_f64": 4.0, + "input_f64_hex": "0x4010000000000000", + "gf10_bits_hex": "0x140", + "gf10_bits_int": 320, + "decoded_f64": 4.0, + "decoded_f64_hex": "0x4010000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "neg_three", + "input_f64": -3.0, + "input_f64_hex": "0xC008000000000000", + "gf10_bits_hex": "0x320", + "gf10_bits_int": 800, + "decoded_f64": -3.0, + "decoded_f64_hex": "0xC008000000000000", + "abs_error": 0.0, + "category": "normal" + } + ] } \ No newline at end of file diff --git a/conformance/vectors/quad_double_conformance_v0.json b/conformance/vectors/quad_double_conformance_v0.json index ac220f446..b71241015 100644 --- a/conformance/vectors/quad_double_conformance_v0.json +++ b/conformance/vectors/quad_double_conformance_v0.json @@ -2,8 +2,8 @@ "schema": "t27-conformance/v0.1", "format": "QUAD_DOUBLE", "format_name": "quad-double", - "bitexact": false, - "format_notes": "quad-double -- Bailey/Hida (software)", + "bitexact": true, + "format_notes": "quad-double (Bailey/Hida): four IEEE-754 binary64 limbs, most-significant first; value = exact sum of the limbs. no separate inf/nan field; hi-limb specials propagate; named integer/dyadic values are f64-exact (low limbs 0)", "catalog": { "id": "quad_double", "bits": 256, @@ -23,8 +23,103 @@ "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", - "structural_reason": "Extended-precision layout (explicit integer bit / multi-double components) is not a single S:E:M field; recorded structurally.", - "anchor_note": "Anchor identity phi^2 + 1/phi^2 = 3 recorded per shared schema.", - "n_vectors": 0, - "vectors": [] + "anchor_check": { + "value": 3.0, + "expected": 3.0, + "ieee754_exact": true, + "quad_double_bits_hex": "0x4008000000000000000000000000000000000000000000000000000000000000" + }, + "round_trip_policy": "decode: exact bits->f64 (curated_named). encode (reference): round-nearest-ties-even; overflow per format convention. abs_error 0 for representable values.", + "vector_mode": "curated_named", + "n_vectors": 8, + "vectors": [ + { + "name": "pos_zero", + "input_f64": 0.0, + "input_f64_hex": "0x0000000000000000", + "quad_double_bits_hex": "0x0000000000000000000000000000000000000000000000000000000000000000", + "quad_double_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", + "quad_double_bits_hex": "0x3FF0000000000000000000000000000000000000000000000000000000000000", + "quad_double_bits_int": 28919752756292594706619413492160090267064256424060131106534450302757600493568, + "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", + "quad_double_bits_hex": "0xBFF0000000000000000000000000000000000000000000000000000000000000", + "quad_double_bits_int": 86815797374950692418404905996504044193699248756880413126263242306714165313536, + "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", + "quad_double_bits_hex": "0x4000000000000000000000000000000000000000000000000000000000000000", + "quad_double_bits_int": 28948022309329048855892746252171976963317496166410141009864396001978282409984, + "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", + "quad_double_bits_hex": "0x4008000000000000000000000000000000000000000000000000000000000000", + "quad_double_bits_int": 28962157085847275930529412632177920311444116037585145961529368851588623368192, + "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", + "quad_double_bits_hex": "0x3FE0000000000000000000000000000000000000000000000000000000000000", + "quad_double_bits_int": 28891483203256140557346080732148203570811016681710121203204504603536918577152, + "decoded_f64": 0.5, + "decoded_f64_hex": "0x3FE0000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "pos_four", + "input_f64": 4.0, + "input_f64_hex": "0x4010000000000000", + "quad_double_bits_hex": "0x4010000000000000000000000000000000000000000000000000000000000000", + "quad_double_bits_int": 28976291862365503005166079012183863659570735908760150913194341701198964326400, + "decoded_f64": 4.0, + "decoded_f64_hex": "0x4010000000000000", + "abs_error": 0.0, + "category": "normal" + }, + { + "name": "neg_three", + "input_f64": -3.0, + "input_f64_hex": "0xC008000000000000", + "quad_double_bits_hex": "0xC008000000000000000000000000000000000000000000000000000000000000", + "quad_double_bits_int": 86858201704505373642314905136521874238079108370405427981258160855545188188160, + "decoded_f64": -3.0, + "decoded_f64_hex": "0xC008000000000000", + "abs_error": 0.0, + "category": "normal" + } + ] } \ No newline at end of file diff --git a/docs/NOW.md b/docs/NOW.md index fe475f5e4..4358ca3ec 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -1,6 +1,13 @@ # NOW -- Trinity t27 sync -Last updated: 2026-06-22 +Last updated: 2026-06-28 + +## conformance-promote-6-structural-bitexact -- promote 6 structural formats to strict SW-bitexact (Closes #1224) + +- **WHERE**: conformance/vectors/gen_all_formats.py, conformance/vectors/INDEX_all_formats.json, conformance/vectors/README.md, regenerated packs for gf10/decimal32/decimal64/decimal128/double_double/quad_double. +- **WHAT**: gf10, decimal32/64/128 (IEEE 754-2008 BID), double_double/quad_double (Bailey/Hida multi-double) move from structural to strict SW-bitexact. Each gets a dedicated, independently-verified reference decoder + encoder: gf10 reuses the proven GF radix-2 law; decimal* cross-checked vs an exact-rational (fractions.Fraction) oracle; double/quad_double use the fixed 128/256-bit explicit-limb layout. abs_error=0 on every recorded vector; anchor 3.0 ieee754_exact=true. INDEX: bitexact 55->61, structural 22->16, selfconsistent 6 (unchanged). +- **Why**: these six had a fully-defined decode law and an independent second witness, so they qualify for strict SW-bitexact (not selfconsistent). The remaining 16 structural entries (takum8/16/32/64, afp, per_channel_scale, gf256, and 9 zero-width parametric) stay honestly structural. No quality/silicon claim; encoding-conformance only. Conformance gate CLEAN, self-test gates PASS, deterministic regeneration. catalog stays 83. Closes #1224. +- **Anchor**: phi^2 + phi^-2 = 3 ## wp18-gate-third-kind -- Check B tri-state bitexact_selfconsistent (Closes #1182)