/** DECIMAL pure kernel — the FRAMEWORK-FREE Decimal contract, single-sourced. * * This module is the ONE authority for KERN's Decimal *meaning* — the canonical * literal grammar, the pinned arithmetic CONTEXT (precision 28, ROUND_HALF_EVEN, * modulo ROUND_DOWN), the canonical stringifier rules, the fail-close message * constants, and the guarded div/mod/pow LOGIC (incl. the `0**0 → 1` special * case). It depends ONLY on `decimal.js` — NO codegen, NO IR, NO `typescript` * package — so it is importable from BOTH: * - the codegen leg (`codegen/decimal-contract.ts`, which re-exports the pure * validators/messages it surfaces to the emitters — see that file), and * - the ReferenceRunner (`ir/semantics/`), which EXECUTES `Decimal.of/add/mul` * natively as a third "leg" of the decimal differential oracle, computing on a * LOCAL cloned `Decimal` constructor and rendering through {@link kernDecimalStr}. * * PRINCIPLE: own the meaning (this module's stringifier/context/fail-close), * borrow the calculator (decimal.js). The transpile paths are UNTOUCHED — the * emitters still lower `Decimal.*` to decimal.js (TS) / stdlib `decimal` (Python) * exactly as before; this kernel only adds a runtime-evaluable twin of the SAME * rules so the runner can be byte-identical to both emitted legs. * * BROWSER-SPINE PIN: this file MUST NOT import the `typescript` npm package, and * nothing it pulls in may either — it is reachable from `ir/semantics/`, which is * on the browser-safe spine. decimal.js is a small standalone arithmetic library * with no such dependency, so the pin (exactly 5 files importing `typescript`) * stays intact. */ /** The decimal.js CONSTRUCTOR type — the class, carrying both the `new` signature * and the static surface (`clone`, `ROUND_*`). A clone of this is what * {@link makeKDecimal} returns. */ export type KDecimalCtor = typeof import('decimal.js').Decimal; /** A live Decimal *instance* — the runner's in-flight Decimal value representation * during compute, rendered to a canonical STRING only at the output boundary. */ export type KDecimalValue = InstanceType; /** The pinned Decimal context the runner's local constructor is cloned with — * the runtime twin of the `precision: 28, rounding: ROUND_HALF_EVEN, * modulo: ROUND_DOWN` values `decimalImportLineTS()` writes into the TS leg. */ export declare const DECIMAL_CONTEXT: Readonly<{ readonly precision: 28; readonly rounding: 6; readonly modulo: 1; }>; /** Build a LOCAL Decimal constructor pinned to {@link DECIMAL_CONTEXT}. Cloning — * NEVER `Decimal.set(...)` on the global — keeps the runner's precision-28 context * isolated from the shared `Decimal` the codegen import line configures and from * any other decimal.js consumer in the process. Used by the runner's native * `Decimal.of/add/mul` evaluation. */ export declare function makeKDecimal(): KDecimalCtor; /** Diagnostic prefix for the Slice-1 Decimal scale/significance fail-close. */ export declare const DECIMAL_SCALE_FAILCLOSE = "Decimal literal carries non-canonical scale/significance"; /** The npm package the TS leg's Decimal lowering depends on. Surfaced into the TS * expression emitter's `imports` set so a caller can render the import line. */ export declare const DECIMAL_TS_PACKAGE = "decimal.js"; /** True iff `raw` is a portable KERN Decimal literal per the v1 canonical grammar * — i.e. decimal.js and Python `decimal` render it to the byte-identical string, * so binding it makes NO scale promise. Drives the symmetric fail-close on all * legs. `raw` is the literal's STRING value (the content of `Decimal.of("...")`). */ export declare function isPortableDecimalLiteral(raw: string): boolean; /** Build the (target-agnostic) compile-error for a non-canonical Decimal literal. * All legs throw this identical text — selected only by the offending literal — so * the refusal is observably symmetric across TS, Python, AND the runner. */ export declare function decimalScaleFailMessage(raw: string): string; /** Throw the symmetric scale fail-close if `raw` is not a portable Decimal literal. * Called by ALL legs at the `Decimal(...)` / `Decimal.of(...)` lowering / eval site. */ export declare function assertPortableDecimalLiteral(raw: string): void; /** The ONE byte-identical diagnostic a zero divisor raises (the text the emitted * helper throws on both legs), so a `Decimal.div(x, Decimal.of("0"))` fails closed * identically across targets. */ export declare const DECIMAL_DIV_ZERO_FAILCLOSE = "KERN Decimal division by zero"; /** The byte-identical diagnostic a zero modulus raises. */ export declare const DECIMAL_MOD_ZERO_FAILCLOSE = "KERN Decimal modulo by zero"; /** `0 ** negative` is a zero-divide in disguise; the pow helper preflights it to * this byte-identical zero-error so the surface never yields a non-finite value. */ export declare const DECIMAL_POW_ZERO_NEGATIVE_EXP_FAILCLOSE = "KERN Decimal 0 raised to a negative power (division by zero)"; /** Guarded division LOGIC: throws the byte-identical {@link DECIMAL_DIV_ZERO_FAILCLOSE} * on a zero divisor, else `a / b` under the caller's pinned constructor. The * executable twin of the emitted `__k_decimal_div` helper. */ export declare function kDecimalDiv(a: KDecimalValue, b: KDecimalValue): KDecimalValue; /** Guarded modulo LOGIC: throws {@link DECIMAL_MOD_ZERO_FAILCLOSE} on a zero * modulus, else `a % b` (truncated remainder under the pinned ROUND_DOWN modulo). * The executable twin of the emitted `__k_decimal_mod` helper. */ export declare function kDecimalMod(a: KDecimalValue, b: KDecimalValue): KDecimalValue; /** Integer-power LOGIC mirroring the emitted `__k_decimal_pow_int`: special-cases * `0**0 → 1` (so both legs agree even though Python's `**` raises that input under * the default context) and preflights `0**neg` to the byte-identical zero-divide * error. `KDecimal` is the local pinned constructor (so `new KDecimal(1)` carries * the same context). The compile-time fail-close already guarantees the exponent * is an integer literal and the base non-negative, so no further validation here. */ export declare function kDecimalPowInt(KDecimal: KDecimalCtor, a: KDecimalValue, b: KDecimalValue): KDecimalValue; /** Render a live Decimal value to its KERN-canonical STRING — the runtime twin of * the TS leg's `String(decimalResult)`: decimal.js `.toString()` under the pinned * context, with the one KERN rule that a ZERO value renders as unsigned `"0"` * (never `"-0"`), matching the Python `_kern_decimal_str` zero canonicalization * and the TS leg. (decimal.js `.toString()` already yields `"0"` for a literal * `new Decimal("-0")`, but a COMPUTED `-0` instance can stringify to `"-0"`, so * the explicit `isZero()` clamp closes that boundary.) */ export declare function kernDecimalStr(value: KDecimalValue): string;