first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
# `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.