/** * How the in-memory engine derives a column the way the streaming engine does. * * The two engines were built on different ideas of randomness. Engine 1 threaded * one PRNG through every sequence in declaration order, so a column's values * depended on how many draws the columns before it had made; engines 2 and 3 * derive each cell from `(seed, streamId, row)` and are independent of one * another. Two architectures, and no seed could ever make them agree. * * This module is engine 1 adopting the second scheme. It holds the three pieces * that decide how: which generators may be built row by row, what a column is * called on the wire, and the exact layout a list of values gets. */ import type { SequenceBuildContext } from './context.js'; import type { GenSpec } from './types.js'; /** * The same context, told which column it is building. * * Independent generators derive from `(seed, streamId, row)` so this engine and * the streaming one agree; everything else ignores it. A fresh object rather * than a mutable field — two columns must never see each other's name. * * The mask, when the column has one, records the ABSOLUTE row each drawn * position belongs to. See `rows` on the context for why that matters. */ export declare function forStreamOf(ctx: SequenceBuildContext, streamId: string, mask?: readonly boolean[]): SequenceBuildContext; /** * The seed and column name this build draws under, when it has both. * * An inline generator or a nested build has no column of its own, so there is * nothing to key by and the caller falls back to the shared PRNG. */ export declare function keyedDraws(ctx: SequenceBuildContext): { seed: string; streamId: string; } | undefined; /** * The absolute row a drawn position belongs to. * * Index-dependent generators — counters, timeseries, a pattern stretched over * the run — read the POSITION for their value, and the streaming engine does * the same. Their random draws are keyed by the row instead, which is why the * two numbers have to be told apart. */ export declare function absoluteRow(ctx: SequenceBuildContext, position: number): number; /** * The context for a column whose drawn positions are known rows outright. * * A `` case is the reason this exists: its rows are not a contiguous run * and not a mask over the whole set either — they are whichever rows the * percentage layout gave that case. */ export declare function withRows(ctx: SequenceBuildContext, streamId: string, rows: readonly number[]): SequenceBuildContext; /** * Can this generator be built row by row? * * The recursion stops on `ctx.perRow`, not on the count. The per-row loop builds * each row by calling the generator again with a count of one, and that inner * call must take the ordinary path or the loop never ends. It used to stop on * `count <= 1` instead, which refused a GENUINE one-row column along with it — * a run of `count="1"`, or a `` case whose quota came to a single row. * Those fell back to the threaded PRNG while engines 2 and 3 drew from the * seekable stream, so one config produced two different datasets depending on * which engine ran it. A one-row build is one row either way; what tells the * two apart is whether we are already inside one. */ export declare function perRowBuildable(gen: GenSpec, count: number, ctx: SequenceBuildContext, locale: string): boolean; /** * The context a REDRAW runs under: one row, no column name of its own. * * A `` repair asks a generator for another value, and the streaming * engine asks with a context like this — so no whole-column layout can kick in * on a build of one row and hand back the same value it was trying to replace. * The caller supplies the stream through the PRNG it passes. */ export declare function redrawCtx(ctx: SequenceBuildContext): SequenceBuildContext; /** * Types the streaming engine builds INLINE — it reads the row's position rather * than deriving a value from the row — and whose `anomaly=`/`missing=` draws it * therefore takes from dedicated `#anom` and `#miss` streams instead of from * the generator's own. The in-memory engine has to key those two the same way. */ export declare const INLINE_ANOMALY_TYPES: ReadonlySet; /** * The value list and the shares a column lays out, when its values are LISTED * rather than drawn: a `text` list, a weighted file column, a weighted pack. * * These are the three the streaming engine sends down one path — it has no * separate uniform case, so an unweighted `text` list arrives here too, with * equal shares. Anything else returns undefined and is drawn per row. */ export declare function listedValues(gen: GenSpec, ctx: SequenceBuildContext, locale: string): { values: readonly string[]; percents: readonly number[]; } | undefined; /** * A list of values laid out exactly, the way the streaming engine lays it out. * * `computeCountsPerValue` turns the shares into a whole number of slots per * value; `permute` scatters those slots over the rows with a key derived from * the column's name. Row i gets the value whose slot range contains * `permute(i)`. Both halves are keyed by `(seed, streamId)`, so the in-memory * and the streaming engine land on the same arrangement. * * `percents` may be given directly — a weighted file column or a pack that * declares shares arrives with its own — otherwise `percentAttr` is expanded, * and an absent one means equal shares. The streaming engine has no separate * uniform path, so neither does this: uniform IS the exact layout, evenly cut. * * Returns undefined when this run cannot do it — no seed or no column name (an * inline generator, or a nested build) — and the caller keeps the old draw. */ /** * `exactTextLayout` with equal shares, guarded against one-row builds — the * same `perRow && count === 1` test the pack-generator body uses for its row * salt. A keyed `` branch builds each of its rows separately WITH the * column's seed, and a layout planned over one row hands its single slot to * one value: measured, a branch's whole 40,000 rows came out as one diagnosis. * One row of a run has no column to lay out; the caller keeps its keyed pick. */ export declare function plainListLayout(values: readonly string[], count: number, ctx: SequenceBuildContext): string[] | undefined; export declare function exactTextLayout(values: readonly string[], percentAttr: string | undefined, count: number, ctx: SequenceBuildContext, percents?: readonly number[]): string[] | undefined; /** * What a column's exact layout gave each row — kept so a child can be ordered * the way the streaming engine orders it. See `orderedRows` in assemble.ts. */ export interface ExactLayout { readonly values: readonly string[]; readonly counts: readonly number[]; /** Cumulative upper bound per value: value v owns slots [cumHi[v-1], cumHi[v]). */ readonly cumHi: readonly number[]; readonly slotByRow: ReadonlyMap; } //# sourceMappingURL=per-row.d.ts.map