Phi в шестнадцати битах
Вы узнаете
Как спека проверяет, что GF16 сохраняет phi, phi^2 = phi + 1 и phi^2 + 1/phi^2 = 3 с заявленным допуском.
Формат хорош настолько, насколько он сохраняет тождества. В gf_competitive.t27 пять проверок: phi, записанное в GF16, против его точного значения, phi^2 против phi + 1, сумма phi^2 + 1/phi^2 против 3, туда-обратно и сумма 1000 слагаемых. Читайте их как есть: значения в каждом тесте вписаны в сам тест, а не получены кодировщиком этой спеки. Спека проверяет арифметику ошибки с допусками 1e-4 и 5e-3.
Попробуйте
Запустите тесты и найдите значение, которое каждый тест вписывает для phi^2 и для phi + 1. Затем найдите, какие два теста используют более строгий допуск 1e-4.

The five checks of gf_competitive.t27, read from gf_competitive.t27. Lesson 6 of the GoldenFloat course.
specs/numeric/gf_competitive.t27
// SPDX-License-Identifier: Apache-2.0
// t27/specs/numeric/gf_competitive.t27
// GF Competitive Analysis Specification
// Ring 028 — Proving GoldenFloat is not random
// 01 + 1/23 = 3 | TRINITY
module GFCompetitive {
use base::types;
const PHI : f64 = 1.6180339887498948482;
const TRINITY : f64 = 3.0;
const TOLERANCE_1E4 : f64 = 1e-4;
const TOLERANCE_1E3 : f64 = 5.0e-3;
// gf16_phi_distance: Compute |GF16(phi) - phi| / phi
fn gf16_phi_relative_error(encoded: f64) f64 {
if (PHI == 0.0) { return 0.0; }
var diff : f64 = encoded - PHI;
if (diff < 0.0) { diff = -diff; }
return diff / PHI;
}
// phi_identity_check: Verify phi^2 = phi + 1 in encoded format
fn phi_identity_check(phi_sq: f64, phi_plus_1: f64) f64 {
var diff : f64 = phi_sq - phi_plus_1;
if (diff < 0.0) { diff = -diff; }
return diff;
}
// trinity_identity_check: Verify phi^2 + phi^-2 = 3
fn trinity_identity_check(computed: f64) f64 {
var diff : f64 = computed - TRINITY;
if (diff < 0.0) { diff = -diff; }
return diff;
}
// gf16_encode_decode_roundtrip: Test roundtrip precision
fn roundtrip_error(original: f64, roundtripped: f64) f64 {
if (original == 0.0) { return 0.0; }
var diff : f64 = roundtripped - original;
if (diff < 0.0) { diff = -diff; }
return diff / original;
}
// accumulation_stability: Sum N uniform terms, measure relative error
fn accumulation_check(n: usize, expected_sum: f64, actual_sum: f64) f64 {
if (expected_sum == 0.0) { return 0.0; }
var diff : f64 = actual_sum - expected_sum;
if (diff < 0.0) { diff = -diff; }
return diff / expected_sum;
}
// test: GF32 phi representation error < 5e-4
test gf32_phi_representation {
var encoded_phi : f64 = 1.618033988749894;
var err = gf16_phi_relative_error(encoded_phi);
try err < TOLERANCE_1E3;
}
// test: phi identity in GF16
test phi_identity_gf16 {
var phi_sq : f64 = 2.618015;
var phi_p1 : f64 = 2.618042;
var err = phi_identity_check(phi_sq, phi_p1);
try err < TOLERANCE_1E3;
}
// test: trinity identity
test trinity_identity {
var computed : f64 = 2.999954;
var err = trinity_identity_check(computed);
try err < TOLERANCE_1E4;
}
// test: roundtrip precision
test roundtrip_precision {
var original : f64 = 1.618034;
var roundtripped : f64 = 1.618042;
var err = roundtrip_error(original, roundtripped);
try err < TOLERANCE_1E3;
}
// test: accumulation stability
test accumulation {
var expected : f64 = 1000.0;
var actual : f64 = 999.95;
var err = accumulation_check(1000, expected, actual);
try err < TOLERANCE_1E4;
}
// invariant: gf16_phi_distance_is_measurable
invariant gf16_phi_measurable {
var phi_approx : f64 = 1.618034;
gf16_phi_relative_error(phi_approx) > 0.0;
}
// invariant: phi_split bounds
invariant phi_split_bounds {
PHI > 1.618 and PHI < 1.619;
}
// bench: encode_decode_latency
bench gf16_encode_decode {
var x : f64 = 1.618033988749894;
var y = roundtrip_error(x, x);
}
}
Все уроки
Модуль 1 · Правило и его числа
Одно правило делит каждую ширину, отношение, к которому оно стремится, и числа Люка за тройкой 3.
Модуль 2 · Почему phi, почему три
Почему деление идёт по phi, почему основание три и как спека проверяет, что GF16 хранит phi.
Модуль 3 · Малые ступени: от GF4 до GF8
GF4, GF6 и GF8 — меньше всего битов, и округление до целых битов стоит здесь дороже всего.
Модуль 4 · От десяти до четырнадцати битов
GF10, GF12 и GF14 и то, как расстояние до 1 / phi меняется с ростом слова.
Модуль 5 · GF16 в работе
Основной 16-битный формат, скалярное произведение из двух слагаемых в GF-T16, затем GF20 и GF24.
Модуль 6 · От GF32 до GF64
GF32 рядом с IEEE single, GF48 без пары в IEEE, GF64 рядом с IEEE double.
Модуль 7 · От GF96 до GF256
GF96, GF128 и GF256, где спеки держат раскладку инвариантами.
Модуль 8 · Самые широкие ступени, затем триты
GF512 и GF1024, две самые широкие ступени, затем GF-T8, где порядок уходит в триты.
Модуль 9 · Ещё триты, затем декодирование
GF-T16 и GF-T32, затем почему фиксированные поля декодируются параллельно, а posit — нет.