t27.aiРусский

A float whose exponent is four trits

You will learn

How TNF17e packs a sign, a ternary exponent and a mantissa into 17 bits, and why 17 and not 16.

The name TNF covers two different things. In the sieve, TNF(k, b) is an alphabet of weights with 3 or 9 levels. TNF17e in tnf17.t27 is a Ternary Network Float, which the spec calls the signed accumulator format: a sign bit, a 7-bit offset and a 9-bit mantissa, worth (-1)^s x (1 + m/512) x 2^(offset - 40). Its trits are in the exponent, not in the weights: the offset takes 81 values, exactly 3^4, so the exponent is four balanced trits, from -40 to +40. Four trits cost 7 bits on a binary chip, so the rung is 17 bits, not 16; the spec records that its source counted positions, and a trit is not a bit. The browser runs 20 of its 44 checks, all 10 invariants among them, and names the cast behind each skip.

Try it

Read the reason on one skipped test; then find the invariant that says four trits span 81 values. In the spec frame, tnf16 has four exponent trits too and sums to 16: find width_rule and read whether that 16 counts bits or positions.

Open the interactive lesson →

tnf17.t27, a 17-bit ternary-exponent float, compiled inside the post
tnf17.t27, a 17-bit ternary-exponent float, compiled inside the post ↗

TNF17e as a t27 spec: a sign, a 7-bit offset holding four balanced trits, a 9-bit mantissa, compiled by t27c in your browser. Seven backends; every test the page cannot run says why.

specs/numeric/tnf16.t27

// SPDX-License-Identifier: Apache-2.0
// tnf16.t27 -- TNF16: Ternary Network Float.
//
// A fixed-field GoldenFloat whose EXPONENT is a balanced-ternary number, built to
// beat tekum16 on a ternary fabric: no regime decode (tekum16's main cost), the
// exponent is added natively in balanced ternary, and the mantissa keeps GF16's
// phi-optimal uniform 9-bit precision (vs tekum16 tapering to ~4 bits at extremes).
//
//   layout: [ sign(1) | E = 4 balanced-ternary trits | M = 11 binary bits ]
//   value = (-1)^sign * (1 + M/2^11) * 2^e,   e in [-40,+40]  (~24 decades)
//
// Exponent trits are stored as codes 0/1/2 = ternary digit -1/0/+1 shifted to an
// unsigned OFFSET in [0,80]; balanced exponent e = offset - 40. Measured (session
// 2026-08-05): beats tekum16 3x at mid range and 5.5x at far range, 0 clipping.
// phi^2 + 1/phi^2 = 3 | TRINITY

module triformat_tnf16 {
    use base::types;

    const SIGN_BITS: u32 = 1;
    const EXP_TRITS: u32 = 4;      // 3^4 = 81 exponent values
    const MANT_BITS: u32 = 11;     // 1 + E_t + M = 16, the ladder's width rule
    const EXP_OFFSET: u32 = 40;    // (3^EXP_TRITS - 1) / 2  -- the balanced zero point
    const OFFSET_MAX: u32 = 80;    // 3^EXP_TRITS - 1

    // Decode the 4-trit exponent field (each 2-bit code in {0,1,2}) into its
    // unsigned offset in [0,80]: offset = t0 + 3*t1 + 9*t2 + 27*t3.
    fn exp_offset(t0: u32, t1: u32, t2: u32, t3: u32) -> u32 {
        return t0 + (3 * t1) + (9 * t2) + (27 * t3);
    }

    // The balanced exponent value is (offset - EXP_OFFSET), kept as a biased u32
    // (add EXP_OFFSET back so it stays unsigned): biased_exp == offset.
    // Reserved: offset == OFFSET_MAX is the special (inf/nan) row.
    fn is_finite(offset: u32) -> bool {
        return offset != OFFSET_MAX;
    }

    // Number of representable exponent steps (3^EXP_TRITS).
    fn exp_values() -> u32 {
        return 81;
    }

    // ---- Tests / invariants ----

    // The rung now spends every position it names. This is why the change was
    // made, and the guard against it regressing.
    test width_rule {
        assert(SIGN_BITS + EXP_TRITS + MANT_BITS == 16, "1 + E_t + M = N, one position per trit");
    }

    // The all-max trit word is the top of the offset range (= +40 before reserve).
    test offset_range {
        assert(exp_offset(0, 0, 0, 0) == 0, "min offset (exponent -40)");
        assert(exp_offset(2, 2, 2, 2) == 80, "max offset (reserved special)");
        assert(exp_offset(1, 1, 1, 1) == 40, "center offset = exponent 0 (unity)");
    }

    // Radix-3 economy: 4 trits carry 81 exponent values (~24 decades) with no
    // regime decode -- more range per digit than a 4-bit binary exponent (16).
    test radix3_economy {
        assert(exp_values() == 81, "3^4 exponent values");
        assert(exp_values() > 16, "4 trits > 4 binary bits of exponent range");
    }

    // The special (inf/nan) row is the top offset; everything below is finite.
    test finiteness {
        assert(is_finite(40) == true, "unity exponent is finite");
        assert(is_finite(79) == true, "near-top finite");
        assert(is_finite(80) == false, "offset 80 is the reserved special row");
    }
}

Open the lesson's spec in the player ↗

All lessons