Optionalvalidity: ValidityBitmapReadonlyallSafety contract. true MUST mean "every defined cell is
finite — no NaN, no ±Infinity" (missing cells, tracked by
validity, are irrelevant). It is a promise the producer makes
so reducers can skip the per-element Number.isFinite guard that
the reducer non-finite policy (docs/notes/reducer-nan-policy.md)
otherwise requires on every numeric reduceColumn.
A wrongly-true flag makes reduceColumn take the unguarded fast
path and silently include a non-finite cell → wrong result. So the
default is false (conservative: guarded path, correct-but-
slower) and a producer sets true ONLY where finiteness is proven
— either data-derived by inspecting every cell, validated upstream
(strict intake), or propagated from a source column that was
itself allFinite. When unsure, leave it false: a missed true
is slower, never wrong.
ReadonlykindReadonlylengthLogical row count (number of cells), independent of buffer capacity.
ReadonlystorageSee ColumnStorage. Plain variants are 'packed'; chunked are 'chunked'.
Optional ReadonlyvalidityOptional validity bitmap. Absent ⇒ "every cell is defined." Build
code only allocates a bitmap when at least one cell is undefined.
Chunked columns surface an aggregate bitmap computed eagerly
at construction from per-chunk validity — kept in sync with this
convention so col.validity === undefined reliably means "all
cells defined."
Index-bucketed reduction. See docs/rfcs/column-api.md §7.3
and §8 worked example.
Returns a fresh Float64Array(bins) for scalar reducers,
or { lo: Float64Array(bins); hi: Float64Array(bins) } for
'minMax'. An earlier revision exposed an optional
{ out } parameter for buffer reuse; the
chart-experiment M2.3 measurement showed it contributed
nothing on top of the chart-side Y-from-bin-output
reorganization, so the option was reverted to keep the
surface small. Per-frame chart allocation pressure
(6 × Float64Array(W=1024) ≈ 48 KB/frame) is well within
V8 nursery GC budget.
Count of defined cells (validity-bitmap-aware). NOT the
event count — diverges from series.length when the column
has any undefined cells. For an all-defined column equals
col.length. Matches the data-frame count idiom (Polars /
Pandas / numpy all use count for non-null counting on a
column).
Reads cell i. Out-of-range or invalid → undefined.
Linear scan with callback. skipInvalid defaults to true. The
callback receives the cell value and the row index; row indices
are always relative to this column, not the source it may have
been sliced from.
Optionaloptions: ScanOptionsReturns a column whose row i is this column's row indices[i].
Always materializes — gather cannot be expressed as a view over a
single typed array. For zero-copy index projection at the store
level use withRowSelection (lands in sub-step 1f).
Returns a column covering the half-open range [start, end).
For Float64Column the underlying buffer is a subarray view
(zero-copy); other column kinds may repack.
Storage-agnostic typed-array gather. Returns a
Float64Array of length exactly this.length,
identity-when-possible:
Float64Column), exact-sized buffer (the
typical case where _values.length === length): returns
this._values exactly — same reference, no allocation._values.length > length
— capacity-grown columns from ColumnarRingBuffer or
similar): returns this._values.subarray(0, length) — a
bounded view over the same backing buffer (no copy, but
a fresh Float64Array view object).ChunkedFloat64Column): allocates a fresh
Float64Array(this.length) and gathers the chunks into
it via the substrate's materializeChunkedFloat64. One
linear pass.The returned buffer shares the column's storage and inherits its read-only-by-convention contract (writes through the buffer corrupt trusted-construction invariants).
Motivating use case: chart adapters that want raw typed- array access for inline canvas draw without caring about storage. Replaces the awkward storage guard
if (col.storage !== 'packed') throw ...;
const values = col._values; // substrate-internal handle
with
const values = col.toFloat64Array();
Validity is not encoded — toFloat64Array returns the
raw value buffer including any undefined-marked slots.
Callers that need gap-aware iteration check
col.hasMissing() / col.validity separately, or use
col.scan(fn) for the storage-agnostic skip-undefined
walk.
Cross-kind note: this method is intentionally scoped to
the numeric column today. A symmetric method on other
kinds isn't a guaranteed fit because their .values
shapes diverge — BooleanColumn.values is bit-packed
(one bit per row), so a hypothetical
BooleanColumn.toUint8Array() wouldn't be identity on
packed. Each kind earns its own gather API on its own
merits; v1 ships only the numeric version.
Numeric value column backed by a
Float64Array. The underlying_valuesbuffer is dense — undefined / missing cells are tracked solely by thevaliditybitmap. Buffer slots corresponding to invalid cells hold an arbitrary value (typically0); callers must consultvaliditybefore treating a slot as meaningful._valuesis substrate-internal: it's the raw buffer handle that reducers, builders, and other substrate-level code reach for in their hot paths. The class permitslength <= _values.length(capacity-grown columns fromColumnarRingBuffer.toColumnetc.), so_values.lengthis NOT the row count; substrate consumers must walk withthis.lengthas the bound. Consumer-style code that wants aFloat64Arrayof exactlythis.lengthshould usetoFloat64Array()from the public column-API surface (src/column.ts).