/** * Order of iso-ssbg1-v1 FEC blocks on the 32-bit SS_ID (ISO/IEC 23008-1:2023 * C.5.2/C.5.3; RFC 1982 serial arithmetic, SERIAL_BITS = 32; BLO-35597 iso:5). * The K-stride (SBN * K) order of the retired k-padded-v1 profile is gone. */ const SPAN = 0x1_0000_0000; const HALF = 0x8000_0000; // --- iso-ssbg1-v1 (ISO/IEC 23008-1 C.3.3 ssbg_mode1; C.5.2/C.5.3) --------- // // Under the ISO profile SS_ID increments by one per FEC source packet and // wraps at 2^32, and a block is the SSB_length consecutive SS_IDs // `[SS_Start, SS_Start + SSB_length)`. Blocks are keyed and ordered by their // SS_Start, never by an SBN derived from K: the catalog K is only the maximum // block length (kMax). The canonical helpers are @blockcast/mmt-base // `serial32Distance` / `serial32Precedes` / `isoBlockContains` / // `isoBlocksBehindLowerBound`; this bundle carries its own copies (it does not // depend on mmt-base), and block-order.test.ts pins them to the same vectors. /** Forward RFC 1982 distance from `from` to `to` on the 32-bit SS_ID, in 0..2^32-1. */ export function serialDistance(from: number, to: number): number { return (to - from + SPAN) % SPAN; } /** Whether `a` precedes `b` under RFC 1982 serial comparison (SERIAL_BITS = 32). */ export function serialPrecedes(a: number, b: number): boolean { const distance = serialDistance(a, b); return distance !== 0 && distance < HALF; } /** Whether `ssId` is one of the `ssbLength` consecutive SS_IDs starting at `ssStart`, mod 2^32. */ export function isoBlockContains(ssStart: number, ssbLength: number, ssId: number): boolean { return serialDistance(ssStart, ssId) < ssbLength; } /** Whether two SS_ID ranges `[start, start + length)` share any SS_ID, mod 2^32. */ export function isoBlocksOverlap( aStart: number, aLength: number, bStart: number, bLength: number, ): boolean { return isoBlockContains(aStart, aLength, bStart) || isoBlockContains(bStart, bLength, aStart); } /** * How many blocks SS_ID `a` lies behind SS_ID `b` (0 unless `a` precedes `b`): * a lower bound, because an iso-ssbg1-v1 block holds at most `kMax` source * symbols, so `n * kMax` SS_IDs always span at least `n` blocks. This is the * one interleave-horizon metric every ISO receiver layer shares (decoder * retention, worker retirement, ordered-relay settlement). */ export function isoBlocksBehind(a: number, b: number, kMax: number): number { if (!Number.isSafeInteger(kMax) || kMax <= 0) { throw new Error(`iso-ssbg1-v1 block horizon needs a positive maximum K (got ${kMax})`); } return serialPrecedes(a, b) ? Math.floor(serialDistance(a, b) / kMax) : 0; }