import type { Value } from './program'; export declare const MAX_JOINT_SIZE = 300000; export declare const MAX_REPEAT_JOINT_SIZE = 300000; export declare const MAX_SORT_JOINT_SIZE = 500000; /** An array value carried through a SymDist (e.g. the result of `[d6, d6]`). */ export interface SymArray { readonly k: 'arr'; value: Value[]; } /** A record value carried through a SymDist (e.g. a structured-dice roll). */ export interface SymRecord { readonly k: 'rec'; value: { [key: string]: Value; }; } /** * Marker for a joint/marginal outcome whose value is undefined (e.g. division * by zero). Operator propagation in combineSymDist / mapSymDist / condSymDist * carries this through unchanged; the FieldStats builder peels its accumulated * mass off the distribution and surfaces it as `undefinedMass`. */ export interface SymUndefined { readonly k: 'undef'; } export type SymValue = number | boolean | string | SymArray | SymRecord | SymUndefined; export interface JointEntry { sourceVals: number[]; value: T; prob: number; } export interface SymDist { dist: Map; sourceIds: string[]; joint: JointEntry[]; } /** * Canonical, type-tagged dedup key for a SymValue. Scalars carry a one-letter * type prefix so e.g. the number `1`, the string `"1"`, and the boolean `true` * never collide; composites hash their structure via {@link stableStringify}. */ export declare function symValueKey(v: SymValue): string; /** * A `Map` whose keys are SymValues but which dedups * structurally: composite values (arrays, records) and the undefined marker * that are structurally equal merge into a single entry. Drop-in for the * `Map` interface the marginal distribution is typed as; the only * caller-visible difference is that lookups/inserts dedup structurally. * * Scalars (number/boolean/string) are keyed by their native value — a JS Map * already distinguishes `1`, `"1"`, and `true` — so the common numeric * dice-pool path pays no string-allocation cost. Only composites/undefined go * through {@link symValueKey}. Two backing maps also rule out any collision * between a composite's canonical key and a real DSL string value. */ export declare class SymValueMap implements Map { private readonly prims; private readonly comps; constructor(init?: Iterable | null); get size(): number; get(v: T): number | undefined; set(v: T, p: number): this; has(v: T): boolean; getOrInsert(key: T, value: number): number; getOrInsertComputed(key: T, compute: (key: T) => number): number; delete(v: T): boolean; clear(): void; forEach(cb: (value: number, key: T, map: Map) => void, thisArg?: unknown): void; keys(): MapIterator; values(): MapIterator; entries(): MapIterator<[T, number]>; [Symbol.iterator](): MapIterator<[T, number]>; get [Symbol.toStringTag](): string; } export interface SourceIdContext { nextSourceId: { value: number; }; } export declare function constSymDist(value: T): SymDist; export declare function fromDiceDistribution(sourceId: string, dist: Map): SymDist; export declare const MAX_COMPOSITION_COUNT = 1000000; /** * Distribution of `mapComposition(counts, values)` for a homogeneous * iid pool of N dice with face distribution `perDieDist`. The mapper * is invoked once per composition, where `values` are the deduplicated * ascending face values and `counts[i]` is the number of dice (out of * N) showing `values[i]`, with `sum(counts) === n`. * * Returns null if the composition count exceeds `MAX_COMPOSITION_COUNT`; * the caller should fall back to brute-force enumeration or Monte Carlo. * * Weights are computed in log space for numerical stability. */ export declare function distributeHomogeneousByComposition(perDieDist: Map, n: number, mapComposition: (counts: readonly number[], values: readonly number[]) => T): Map | null; export declare function mapSymDist(sd: SymDist, fn: (v: T) => U): SymDist; export declare function combineSymDist(a: SymDist, b: SymDist, fn: (av: A, bv: B) => C, cap?: number): SymDist | null; export declare function sharedMarginalCache(sd: SymDist, sharedIdx: number[]): Map; /** * Fold a list of field SymDists into a record-level joint distribution * keyed by stableStringify of the record value. Each pair of fields is * combined via `combineSymDist`, which handles source-id alignment and * probability arithmetic for shared random sources. * * Returns truncated=true if the cardinality during folding exceeds * `combineSymDist`'s internal cap (≈4× MAX_JOINT_SIZE, its default) or the * final marginal exceeds `cap`. */ export declare function combineFieldSymDistsAsJoint(fieldSymDists: { key: string; sd: SymDist; }[], cap: number): { joint: Map; truncated: boolean; }; export declare function combineFieldSymDistsAsJointSymDist(fieldSymDists: { key: string; sd: SymDist; }[], cap: number): { sd: SymDist | null; truncated: boolean; }; export declare function liftSymValueToValue(v: SymValue): Value; /** * Marker carried through SymDist when a sub-expression evaluated to an * undefined outcome (e.g. division by zero). Operator propagation in * combineSymDist / mapSymDist / condSymDist carries it through unchanged: when * any input is undefined, the output is undefined regardless of operator. The * FieldStats builder peels accumulated undefined mass off the distribution and * surfaces it as `undefinedMass` on a `partial-number` (or `undefined`) * variant. */ export declare const UNDEFINED_SENTINEL: SymUndefined; export declare function isUndefinedSentinel(v: SymValue): v is SymUndefined; export declare function encodeArrayValue(arr: Value[]): SymArray; export declare function decodeArrayValue(v: SymValue): Value[]; export declare function isEncodedArray(v: SymValue): v is SymArray; export declare function encodeRecordValue(rec: { [key: string]: Value; }): SymRecord; export declare function decodeRecordValue(v: SymValue): { [key: string]: Value; }; export declare function isEncodedRecord(v: SymValue): v is SymRecord; export declare function freshSourceId(ctx: SourceIdContext): string; export declare function cloneSymDistWithFreshSources(sd: SymDist, ctx: SourceIdContext): SymDist; export declare function condSymDist(cond: SymDist, thenD: SymDist, elseD: SymDist): SymDist | null; export declare function conditionalizeSymDist(d: SymDist, predicate: SymDist): SymDist | null;