From 4af84543894ee364ed97686cff41efffc48b02bb Mon Sep 17 00:00:00 2001 From: Dmitrii Vasilev Date: Tue, 18 Aug 2026 12:18:15 +0700 Subject: [PATCH 1/2] Blog: the golden ratio in this format is a scale factor, not information Bilingual, and the first post to carry a diagram: adds a 'figure' block kind holding inline SVG, plus its renderer case. The SVG is authored in this repository's data files, never supplied by a reader, so no untrusted markup reaches that path. The post reports what was measured today: phi is not observable at all in the closed 2-bit format (1, 2, pi, 0.001 and 1e12 give identical tables), a GFTernary dot product is exactly phi^2 times the same codes read as balanced ternary, and the fp32 multiplier the board uses for that product costs 1654 cells against 13 for the exact unit -- 16/16 input pairs equivalent, on Yosys 0.65. The diagram is a difference diagram: the same constant in two placements, and the one edge that exists on the left and cannot exist on the right. --- .../bodies/phi-is-a-scale-not-information.ts | 303 ++++++++++++++++++ apps/website/src/data/blog/index.ts | 32 ++ apps/website/src/data/blog/posts.ts | 2 + apps/website/src/data/blog/types.ts | 1 + apps/website/src/pages/Blog.tsx | 21 ++ 5 files changed, 359 insertions(+) create mode 100644 apps/website/src/data/blog/bodies/phi-is-a-scale-not-information.ts diff --git a/apps/website/src/data/blog/bodies/phi-is-a-scale-not-information.ts b/apps/website/src/data/blog/bodies/phi-is-a-scale-not-information.ts new file mode 100644 index 0000000000..e92d744c12 --- /dev/null +++ b/apps/website/src/data/blog/bodies/phi-is-a-scale-not-information.ts @@ -0,0 +1,303 @@ +import type { Block } from '../types' + +export const body: Block[] = [ + { + "kind": "p", + "text": "A format called GoldenFloat has a golden ratio in its name. The question worth asking is not whether 1.618 is close to phi. It is whether the thing the format calls phi satisfies the property that defines phi, in the arithmetic the format actually uses." + }, + { + "kind": "p", + "text": "Three arithmetics here carry a phi, and they do not agree." + }, + { + "kind": "table", + "head": [ + "where", + "phi^2 = phi + 1 ?", + "notes" + ], + "rows": [ + [ + "the oracle, exact ring Z[phi]", + "yes, symbolically", + "14641/14641 sign decisions agree with 60-digit arithmetic; never touches a float" + ], + [ + "the closed 2-bit format", + "not measurable", + "see below" + ], + [ + "the RTL, fp32", + "no, off by 1 ulp", + "0x40278DDF against 0x40278DDE" + ] + ] + }, + { + "kind": "h", + "text": "phi is not observable in the closed format" + }, + { + "kind": "p", + "text": "Decode two codes, operate, quantise back by sign. Substituting 1, 2, pi, 0.001 or 10^12 for phi reproduces the identical 16 addition and 16 multiplication results. At two bits the format is observationally balanced ternary." + }, + { + "kind": "p", + "text": "In a dot product the same fact takes a sharper form. Every digit is phi*t with t in {-1, 0, +1}, so each product term is (phi*t)(phi*u) = phi^2*t*u, and by linearity:" + }, + { + "kind": "code", + "text": " = phi^2 * " + }, + { + "kind": "p", + "text": "where x~ and y~ are the same codes read as balanced ternary. Verified on 20000 random dot products as integer equality in Z[phi] — the accumulator is always (k, k). A first attempt measured this through a decimal phi, got 1e-47, and nearly reported it as exact. The ruler was the error, not the result." + }, + { + "kind": "figure", + "svg": "phi in the DIGIT ALPHABETGFTernary, 2 bits-phi0+phiweight111dot product<x, y>phi factors outphi^2 x <x~, y~>a per-tensor scalephi in the POSITIONAL WEIGHTSStakhov 2002, on Bergman 1957-10+1weightphi^0phi^2phi^4dot product<x, y>(no such edge)the weights differ, so phicannot be factored outcarriesinformation", + "caption": "The same constant, two placements, opposite outcomes. On the left every digit carries the same weight, so phi factors out of the sum and lands in a per-tensor scale. On the right the weights are powers of phi, so it cannot: the extra edge on the left is the whole difference." + }, + { + "kind": "h", + "text": "So what does phi cost?" + }, + { + "kind": "p", + "text": "phi^2 = 2.618034 is a constant every quantised pipeline already carries as a per-tensor scale. The fp32 constant implementing it, 0x3FCF1BBD, is the correctly-rounded phi — 0.138 ulp — and buys no representational power while costing rounding: 14 ulp on a dot product of length 4096, and phi^2 != phi + 1 in the hardware by 1 ulp." + }, + { + "kind": "p", + "text": "The board pays for that in area. It computes the product of two 2-bit codes by decoding both to fp32, running a full IEEE-shaped multiplier, and thresholding the 32-bit result back down to 2 bits." + }, + { + "kind": "table", + "head": [ + "unit", + "cells", + "wires", + "flops" + ], + "rows": [ + [ + "gf_mul_param, free 32-bit inputs", + "1654", + "1664", + "17" + ], + [ + "the exact unit, no multiplier and no phi", + "13", + "14", + "0" + ], + [ + "the fp32 path with only 2-bit inputs", + "14", + "63", + "2" + ] + ] + }, + { + "kind": "p", + "text": "Measured with Yosys 0.65. The version is part of the number: the same script on 0.33 reports different cell counts. All 16 input pairs agree between the two units, driven through the fp32 pipeline's handshake — equivalent, not merely smaller." + }, + { + "kind": "p", + "text": "The third row is not a design. It is yosys reaching the same conclusion by constant propagation: given only four input codes, the multiplier folds away. That fold is luck, not architecture. The design still asks for a general multiplier to compute a function of four bits, and a tool that does not fold it pays the first row." + }, + { + "kind": "h", + "text": "Where phi does carry information" + }, + { + "kind": "p", + "text": "None of this says phi is a bad choice. It says the digit alphabet is the placement where phi cannot do any work. Put it in the positional weights and it can: Stakhov's ternary mirror-symmetrical system uses digits {-1, 0, +1} with weights phi^(2i), building on Bergman's 1957 base-phi system. There a digit's position changes its value, so phi does not factor out." + }, + { + "kind": "p", + "text": "That system was reimplemented here and checked: every integer from 0 to 12 has a representation whose digit string is unchanged when read backwards. Stakhov built a self-checking adder on exactly that property — a fault breaks the symmetry, so the code detects its own errors." + }, + { + "kind": "quote", + "text": "Same constant, opposite outcome. The prior art chose the load-bearing placement in 2002." + }, + { + "kind": "h", + "text": "A check that cannot fail" + }, + { + "kind": "p", + "text": "The verifier behind all of this was mutation-tested, and it passed a mutation it should have failed: flipping one entry of its lookup table left every claim green, because the table sat on both sides of the identity being tested and cancelled with itself. An hour earlier, a workflow step written to catch a silently-ignored toolchain pin had read an 8-digit date out of a version string that contains no date, so its guard skipped and the step reported success without comparing anything." + }, + { + "kind": "p", + "text": "Both were vacuous. Neither was caught by reading; both were caught by changing a constant and noticing nothing went red. That became a command, and pointing it back at the verifier found a third: the substitution test above compared quantiser tables only against each other, so a degenerate quantiser would have made the whole inertness claim pass vacuously. It is pinned to the decode RTL now." + }, + { + "kind": "p", + "text": "A check that cannot fail is indistinguishable from one that passed." + }, + { + "kind": "h", + "text": "What none of this establishes" + }, + { + "kind": "p", + "text": "No frequency, no board, no power. The exact unit is combinational, so its zero flip-flops are a property of the unit and not a speed claim. Nothing here compares any design against a specification. And the measurement that would decide whether this format family is worth publishing at all — the block axis against MXFP4 — has not been made." + }, +] + +import type { Block } from '../types' + +export const ruBody: Block[] = [ + { + "kind": "p", + "text": "У формата под названием GoldenFloat золотое сечение стоит в имени. Спрашивать стоит не о том, близко ли 1.618 к φ, а о том, выполняется ли определяющее свойство φ в той арифметике, которой формат реально считает." + }, + { + "kind": "p", + "text": "Здесь φ живёт в трёх арифметиках, и они не согласны между собой." + }, + { + "kind": "table", + "head": [ + "где", + "φ² = φ + 1 ?", + "примечание" + ], + "rows": [ + [ + "оракул, точное кольцо ℤ[φ]", + "да, символьно", + "14641/14641 решений о знаке сходятся с 60-значной арифметикой, ни разу не касаясь float" + ], + [ + "замкнутый 2-битный формат", + "не измеримо", + "см. ниже" + ], + [ + "RTL, fp32", + "нет, расхождение 1 ulp", + "0x40278DDF против 0x40278DDE" + ] + ] + }, + { + "kind": "h", + "text": "В замкнутом формате φ не наблюдаем" + }, + { + "kind": "p", + "text": "Декодировать два кода, выполнить операцию, квантовать обратно по знаку. Подстановка 1, 2, π, 0.001 или 10¹² вместо φ даёт идентичные 16 таблиц сложения и 16 умножения. На двух битах формат наблюдательно неотличим от сбалансированной троичной." + }, + { + "kind": "p", + "text": "В скалярном произведении тот же факт принимает более резкую форму. Каждая цифра есть φ·t, где t ∈ {−1, 0, +1}, поэтому каждое слагаемое равно (φ·t)(φ·u) = φ²·t·u, и по линейности:" + }, + { + "kind": "code", + "text": " = φ² · " + }, + { + "kind": "p", + "text": "где x~ и y~ — те же коды, прочитанные как сбалансированная троичная. Проверено на 20000 случайных скалярных произведений как целочисленное равенство в ℤ[φ]: аккумулятор всегда равен (k, k). Первая попытка мерила это через десятичное приближение φ, дала 1e-47, и я чуть не записал результат как точный ноль. Ошибкой была линейка, а не результат." + }, + { + "kind": "figure", + "svg": "phi in the DIGIT ALPHABETGFTernary, 2 bits-phi0+phiweight111dot product<x, y>phi factors outphi^2 x <x~, y~>a per-tensor scalephi in the POSITIONAL WEIGHTSStakhov 2002, on Bergman 1957-10+1weightphi^0phi^2phi^4dot product<x, y>(no such edge)the weights differ, so phicannot be factored outcarriesinformation", + "caption": "Одна и та же константа, два места, противоположный итог. Слева все цифры имеют одинаковый вес, поэтому φ выносится из суммы и оседает в per-tensor scale. Справа веса — степени φ, и вынести его нельзя: лишнее ребро слева и есть вся разница." + }, + { + "kind": "h", + "text": "Во что обходится φ" + }, + { + "kind": "p", + "text": "φ² = 2.618034 — константа, которую любой квантованный конвейер уже несёт как per-tensor scale. Реализующая её константа fp32 `0x3FCF1BBD` — корректно округлённый φ (0.138 ulp), и она не добавляет представимости, но стоит округления: 14 ulp на скалярном произведении длины 4096, и φ² ≠ φ + 1 в железе с расхождением в 1 ulp." + }, + { + "kind": "p", + "text": "Плата за это — площадь. Произведение двух 2-битных кодов вычисляется так: оба декодируются в fp32, запускается полноразмерный умножитель формы IEEE, и 32-битный результат порогами сводится обратно к двум битам." + }, + { + "kind": "table", + "head": [ + "блок", + "ячеек", + "проводов", + "триггеров" + ], + "rows": [ + [ + "gf_mul_param, свободные 32-битные входы", + "1654", + "1664", + "17" + ], + [ + "точный блок, без умножителя и без φ", + "13", + "14", + "0" + ], + [ + "fp32-путь с 2-битными входами", + "14", + "63", + "2" + ] + ] + }, + { + "kind": "p", + "text": "Измерено на Yosys 0.65. Версия — часть числа: тот же скрипт на 0.33 даёт другие счётчики ячеек. Все 16 пар входов совпадают между двумя блоками, прогнанные через рукопожатие fp32-конвейера: это эквивалентность, а не просто уменьшение." + }, + { + "kind": "p", + "text": "Третья строка — не проект. Это yosys приходит к тому же выводу распространением констант: когда входов всего четыре кода, умножитель сворачивается. Такое сворачивание — везение, а не архитектура. Проект по-прежнему запрашивает общий умножитель ради функции от четырёх бит, и инструмент, который не свернёт, заплатит первую строку." + }, + { + "kind": "h", + "text": "Где φ всё-таки несёт информацию" + }, + { + "kind": "p", + "text": "Ничто из этого не говорит, что φ — плохой выбор. Оно говорит, что алфавит цифр — то самое место, где φ не может сделать никакой работы. Поставьте его в позиционные веса, и он сможет: тернарная зеркально-симметричная система Стахова использует цифры {−1, 0, +1} с весами φ^(2i), опираясь на систему Бергмана с основанием φ (1957). Там позиция цифры меняет её значение, поэтому φ не выносится." + }, + { + "kind": "p", + "text": "Эта система была здесь переписана и проверена: у каждого целого от 0 до 12 есть представление, чья строка цифр не меняется при чтении задом наперёд. Именно на этом свойстве Стахов построил самопроверяющийся сумматор: сбой ломает симметрию, и код обнаруживает собственную ошибку." + }, + { + "kind": "quote", + "text": "Та же константа, противоположный итог. Предшествующая работа выбрала несущее место ещё в 2002-м." + }, + { + "kind": "h", + "text": "Проверка, которая не может провалиться" + }, + { + "kind": "p", + "text": "Верификатор, стоящий за всем этим, прошёл мутационное тестирование — и пережил мутацию, которую обязан был поймать: подмена одной записи в таблице оставила все утверждения зелёными, потому что таблица стояла по обе стороны проверяемого тождества и сократилась сама с собой. Часом раньше шаг воркфлоу, написанный чтобы поймать молча игнорируемый пин тулчейна, читал 8-значную дату из строки версии, где даты нет, — охрана пропускала сравнение, и шаг рапортовал успех, ничего не сравнив." + }, + { + "kind": "p", + "text": "Оба были вакуумными. Ни один не был найден чтением; оба нашлись, когда меняешь константу и замечаешь, что ничего не покраснело. Из этого выросла команда, и наведённая обратно на верификатор она нашла третью дыру: тест подстановки сравнивал таблицы квантователя только друг с другом, поэтому вырожденный квантователь сделал бы всё утверждение об инертности вакуумно истинным. Теперь таблица привязана к декодеру RTL." + }, + { + "kind": "p", + "text": "Проверка, которая не может провалиться, неотличима от проверки, которая прошла." + }, + { + "kind": "h", + "text": "Чего всё это не устанавливает" + }, + { + "kind": "p", + "text": "Ни частоты, ни платы, ни энергопотребления. Точный блок комбинационный, поэтому ноль триггеров — свойство блока, а не заявка на скорость. Ничто здесь не сверяет проект со спецификацией. И измерение, которое решает, стоит ли вообще публиковать это семейство форматов — блочная ось против MXFP4 — не сделано." + }, +] diff --git a/apps/website/src/data/blog/index.ts b/apps/website/src/data/blog/index.ts index da52c86044..7170b0bdf9 100644 --- a/apps/website/src/data/blog/index.ts +++ b/apps/website/src/data/blog/index.ts @@ -2,6 +2,38 @@ import type { PostMeta } from './types' /** Индекс блога: список и метаданные без тяжёлых тел публикаций. */ export const postsIndex: PostMeta[] = [ + { + slug: 'phi-is-a-scale-not-information', + title: 'The golden ratio in this format is a scale factor, not information', + summary: 'A format with phi in its name. Measured: in the two-bit digit alphabet phi is not observable at all, and a dot product of GFTernary vectors is exactly phi-squared times the same codes read as balanced ternary. The prior art put phi where it does carry information — in 2002.', + date: '2026-08-18', + readingMinutes: 8, + tags: ['Number formats', 'Measurement', 'Self-critique', 'FPGA'], + receipts: [ + { label: 'gHashTag/trinity-fpga #582 — the native phi check, mutation-tested', href: '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/gHashTag/trinity-fpga/pull/582' }, + { label: 'gHashTag/trinity-fpga #584 — 1654 cells against 13, and 16/16 equivalent', href: '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/gHashTag/trinity-fpga/pull/584' }, + { label: 'gHashTag/t27 #2177 — tri mutate, the command that found the third vacuous check', href: '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/gHashTag/t27/pull/2177' }, + { label: 'Stakhov, The Computer Journal 45(2):221-236 (2002) — phi in the positional weights', href: 'https://doi.org/10.1093/comjnl/45.2.221' }, + { label: 'Bergman, Mathematics Magazine 31:98-110 (1957) — the base-phi system underneath it', href: 'https://doi.org/10.2307/3029218' } + ], + openQuestions: [ + 'The area comparison is one multiplier on Yosys 0.65. Whether a board-level synthesis folds the fp32 path or pays for it has not been measured, and that is the number that decides whether this matters in practice.', + 'The RTL quantiser has an asymmetric dead zone (+0.25 against 0.5) where the oracle documents a pure sign rule. They agree on every reachable input today. Nothing checks that they still agree if the input set widens.', + 'The mirror-symmetric prior art was reproduced for N = 0..12 by exhaustive search. No claim is made about larger N, and no adder was built.', + 'Whether phi as an exponent base would beat base 2 on a real workload is untested. It is not used as a base anywhere in this codebase — the ladders are base 2, and one is base 3.' + ], + published: true, + ru: { + title: 'Золотое сечение в этом формате — масштаб, а не информация', + summary: 'Формат, у которого φ в названии. Измерено: в двухбитном алфавите цифр φ вообще не наблюдаем, а скалярное произведение векторов GFTernary точно равно φ² на те же коды, прочитанные как сбалансированная троичная. Предшествующая работа поставила φ туда, где он несёт информацию, ещё в 2002-м.', + openQuestions: [ + 'Сравнение площади — один умножитель на Yosys 0.65. Свернёт ли fp32-путь синтез на уровне платы или заплатит за него, не измерено, а именно это решает, важно ли всё на практике.', + 'У квантователя RTL несимметричная мёртвая зона (+0.25 против 0.5), тогда как оракул документирует чистое правило знака. Сегодня они совпадают на всех достижимых входах. Ничто не проверяет, что они совпадут при расширении множества входов.', + 'Зеркально-симметричная предшествующая система воспроизведена для N = 0..12 полным перебором. Про большие N ничего не утверждается, сумматор не построен.', + 'Побьёт ли φ как основание экспоненты основание 2 на реальной нагрузке — не проверено. В этой кодовой базе φ основанием не используется нигде: лестницы на основании 2, одна на основании 3.' + ] + } + }, { slug: 'an-inert-filter-is-safest-until-it-works', title: 'An inert filter is safest until it works', diff --git a/apps/website/src/data/blog/posts.ts b/apps/website/src/data/blog/posts.ts index 5897945598..8de44cf593 100644 --- a/apps/website/src/data/blog/posts.ts +++ b/apps/website/src/data/blog/posts.ts @@ -1,6 +1,7 @@ import { postsIndex } from './index' import { body as body_a_health_snapshot_changed_its_denominator, ruBody as ruBody_a_health_snapshot_changed_its_denominator } from './bodies/a-health-snapshot-changed-its-denominator' import type { Post, PostBody } from './types' +import { body as body_phi_is_a_scale_not_information, ruBody as ruBody_phi_is_a_scale_not_information } from './bodies/phi-is-a-scale-not-information' import { body as body_an_inert_filter_is_safest_until_it_works, ruBody as ruBody_an_inert_filter_is_safest_until_it_works } from './bodies/an-inert-filter-is-safest-until-it-works' import { body as body_a_gate_that_rejected_its_own_users, ruBody as ruBody_a_gate_that_rejected_its_own_users } from './bodies/a-gate-that-rejected-its-own-users' import { body as body_a_broken_reference_looks_exactly_like_broken_code, ruBody as ruBody_a_broken_reference_looks_exactly_like_broken_code } from './bodies/a-broken-reference-looks-exactly-like-broken-code' @@ -21,6 +22,7 @@ import { body as body_open_gigabit_ethernet_artix7, ruBody as ruBody_open_gigabi import { body as body_a_multiplicity_correction_changed_the_deployment_reading, ruBody as ruBody_a_multiplicity_correction_changed_the_deployment_reading } from './bodies/a-multiplicity-correction-changed-the-deployment-reading' const bodies: Record = { + 'phi-is-a-scale-not-information': { body: body_phi_is_a_scale_not_information, ruBody: ruBody_phi_is_a_scale_not_information }, 'an-inert-filter-is-safest-until-it-works': { body: body_an_inert_filter_is_safest_until_it_works, ruBody: ruBody_an_inert_filter_is_safest_until_it_works }, 'a-gate-that-rejected-its-own-users': { body: body_a_gate_that_rejected_its_own_users, ruBody: ruBody_a_gate_that_rejected_its_own_users }, 'a-health-snapshot-changed-its-denominator': { body: body_a_health_snapshot_changed_its_denominator, ruBody: ruBody_a_health_snapshot_changed_its_denominator }, diff --git a/apps/website/src/data/blog/types.ts b/apps/website/src/data/blog/types.ts index 3fb3805c12..452fdbc8df 100644 --- a/apps/website/src/data/blog/types.ts +++ b/apps/website/src/data/blog/types.ts @@ -6,6 +6,7 @@ export type Block = | { kind: 'quote'; text: string } | { kind: 'code'; text: string } | { kind: 'table'; head: string[]; rows: string[][] } + | { kind: 'figure'; svg: string; caption: string } export interface PostRuMeta { title: string diff --git a/apps/website/src/pages/Blog.tsx b/apps/website/src/pages/Blog.tsx index dcfd141347..fea44e555f 100644 --- a/apps/website/src/pages/Blog.tsx +++ b/apps/website/src/pages/Blog.tsx @@ -201,6 +201,27 @@ function renderBlock(b: Block, i: number) { {b.text} ) + case 'figure': + // The SVG here is authored in this repository's own data files, never + // supplied by a reader, so no untrusted markup reaches this path. + return ( +
+
+
+ {b.caption} +
+
+ ) case 'table': return (
From c1fd33a21e7cc8d179bf053ff381b77b20998fff Mon Sep 17 00:00:00 2001 From: Dmitrii Vasilev Date: Tue, 18 Aug 2026 12:25:08 +0700 Subject: [PATCH 2/2] Fix a duplicate type import the ratchet caught The body file was generated by concatenating two blocks that each carried the import line, so 'Block' was declared twice. My own check missed it: I ran tsc --noEmit -p tsconfig.json, and the project's typecheck is tsc -b, which is what the ratchet runs. Ratchet now: 179 errors across 26 files against a baseline of 184 across 27, and no file gained. --- .../src/data/blog/bodies/phi-is-a-scale-not-information.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/website/src/data/blog/bodies/phi-is-a-scale-not-information.ts b/apps/website/src/data/blog/bodies/phi-is-a-scale-not-information.ts index e92d744c12..0e9ff07fec 100644 --- a/apps/website/src/data/blog/bodies/phi-is-a-scale-not-information.ts +++ b/apps/website/src/data/blog/bodies/phi-is-a-scale-not-information.ts @@ -150,7 +150,6 @@ export const body: Block[] = [ }, ] -import type { Block } from '../types' export const ruBody: Block[] = [ {