# `half-float` (encoder side) ## Purpose Encodes a JavaScript `number` as IEEE 754 binary16 (CBOR major 7 / value 25) when the round-trip is exact, and otherwise indicates non-representability so the caller can pick a wider format. Also exports `selectFloatWidth`, which chooses between float32 and float64 based on exact-representability — the encoder's deterministic path uses this to skip half-float without giving up shortest-exact behaviour at the float32 / float64 boundary. ## Features - Full IEEE 754 binary16 coverage: ±0, ±Infinity, NaN, normal values, subnormals, smallest-normal / largest-normal boundaries. - `tryEncodeFloat16(value)` returns the 2-byte big-endian sequence on exact round-trip; returns `undefined` on overflow / underflow / inexact-precision. - `selectFloatWidth(value)` picks float32 (4 bytes) when `getFloat32` round- trips the value exactly, otherwise float64 (8 bytes). NaN is treated as float32-exact since both float32 and float64 represent NaN. ## Usage: Basic Example ```ts import { tryEncodeFloat16 } from "@suaveplan/cbor/encoder"; const bytes = tryEncodeFloat16(1.5); // Uint8Array(2) [0x3e, 0x00] ``` ## Usage: Advanced Example ```ts import { selectFloatWidth, tryEncodeFloat16 } from "@suaveplan/cbor/encoder"; function pickFloat(value: number): { tag: number; bytes: Uint8Array } { const f16 = tryEncodeFloat16(value); if (f16) return { tag: 0xf9, bytes: f16 }; const { width, bytes } = selectFloatWidth(value); return { tag: width === 4 ? 0xfa : 0xfb, bytes }; } ``` ## API Reference - `tryEncodeFloat16(value: number): Uint8Array | undefined` — exact-only. - `selectFloatWidth(value: number): { width: 4 | 8; bytes: Uint8Array }`. - `type FloatWidth = 4 | 8`. ## Implementation Notes The exact-only contract is critical for deterministic encoding: a lossy half-float emission would produce different bytes for inputs that look "close" but differ in the last bit of the mantissa. The implementation verifies round-trip via reconstruction (`(1 + mant/1024) * 2^(exp-15)` for normals, `mant * 2^-24` for subnormals) and rejects when the rebuild does not equal the input under `===`. NaN is hard-coded to `7e00` (the canonical quiet-NaN form) — RFC 8949 §3.3 explicitly permits losing NaN payload bits, which JavaScript would do anyway since `Number` collapses payloads.