/** * `accumulate=` — a running total inside one record's `repeat` list. * * A cell holding `100,150,150` becomes `100,250,400`. That is the shape most * "I need a running total" questions actually have: a receipt's subtotal, the * elapsed time of a session, the odometer over the legs of a trip. The * accumulation lives inside ONE record, which is why it costs nothing — a * record is computed whole anyway, so rows stay independent and streaming, * `--jobs` and `getAt` are untouched. * * The one decision worth defending is the arithmetic. Five implementations have * to produce the same bytes, and floating point does not: `0.1 + 0.2` prints * differently in JavaScript, Python, Java, C# and Rust. So the sum is done on * SCALED INTEGERS. Every element is read as a fixed-point number, the widest * fraction in the list sets the scale, and the total is formatted back at that * scale by hand. No float ever touches the value, and `19.99 + 0.01` is `20.00` * everywhere rather than `20.000000000000004` in one of them. * * `min` and `max` are different in a useful way: their result IS one of the * inputs, so the winning element's own text is returned unchanged. A value that * arrived as `007` stays `007`. */ /** What a running accumulation can do. Each keeps a value that only ever moves one way. */ export type AccumulateOp = 'sum' | 'min' | 'max'; export declare const ACCUMULATE_OPS: readonly AccumulateOp[]; export declare class AccumulateError extends Error { readonly name = "AccumulateError"; } /** * Read `accumulate=` where an unknown op simply means "none". * * The engine path uses this one. By the time a value is drawn the validator has * already refused a misspelled op (TDC238), so throwing here would only turn a * reported problem into a crash — the same "the validator already said so" * contract the rest of the engine runs on. */ export declare function readAccumulate(attrs: Record): AccumulateOp | undefined; /** The same, but strict — the validator's copy, which turns a bad op into a diagnostic. */ export declare function parseAccumulate(attrs: Record): AccumulateOp | undefined; /** * Turn a list into its running accumulation. * * An EMPTY element stays empty and leaves the accumulator alone. That is what * `missing=` produces, and "no reading that day" should not reset a meter or * count as a zero-value transaction. */ export declare function accumulateParts(parts: readonly string[], op: AccumulateOp): string[]; /** * The same fold, but down a COLUMN instead of across a list. * * `` is this: row i's value is the accumulation of every row * up to it. Reusing {@link accumulateParts} rather than writing a second fold is * deliberate — the arithmetic, the scale rule and the treatment of an empty cell * then cannot drift apart between the two features. * * `base` is prepended and its result dropped, which is exactly "start from an * opening balance": it joins the scale pool, so an opening `1000.00` widens the * whole column to two decimals the way a reader would expect. * * `resetAt` splits the column into segments. When it is given, each segment is * accumulated on its own — one running balance per account rather than one for * the file. */ export declare function accumulateColumn(values: readonly (string | undefined)[], op: AccumulateOp, base: string | undefined, resetAt: readonly (string | undefined)[] | undefined): (string | undefined)[]; //# sourceMappingURL=accumulate.d.ts.map