2.3 KiB
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; returnsundefinedon overflow / underflow / inexact-precision.selectFloatWidth(value)picks float32 (4 bytes) whengetFloat32round- trips the value exactly, otherwise float64 (8 bytes). NaN is treated as float32-exact since both float32 and float64 represent NaN.
Usage: Basic Example
import { tryEncodeFloat16 } from "@suaveplan/cbor/encoder";
const bytes = tryEncodeFloat16(1.5); // Uint8Array(2) [0x3e, 0x00]
Usage: Advanced Example
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.