/** * mamba1_cpu.ts — exact CPU forward + backward for a Mamba-1 (S6) block. * * This is the REFERENCE implementation of the same maths the WGSL kernels run * (`rmsnorm_forward`, `linear_forward`, `conv1d_forward`, `silu_forward`, * `forward_scan` + `forward_reduce`). It exists so real per-parameter gradients * can be computed — and, crucially, PROVEN correct by finite differences — * without a WebGPU device. {@link MambaTrainer} consumes it as its gradient * engine: the optimizer (AdamW + trust region + NaN guard) stays on the GPU, * the gradients are exact. * * Every formula below is a line-for-line mirror of the corresponding kernel; if * a kernel changes, this file changes with it and `tests/backprop.test.ts` * catches the drift (the gradient check fails the moment forward and backward * disagree). * * Layout conventions (identical to the GPU buffers): * x (M, dModel) M = batch * seqLen, row r = b * seqLen + t * wInProj (2*dInner, dModel) row-major, Y = X @ W^T + b * wConv (dInner, dConv) depthwise, causal * wXProj (dtRank + 2*dState, dInner) * wDtProj (dInner, dtRank) * A_log (dInner, dState) * wOutProj (dModel, dInner) * hCache (B, L, dInner, dState) */ /** The 13 learnable tensors of a Mamba-1 block, keyed by the SAME names * {@link Mamba1Block.parameters} publishes. */ export interface Mamba1CpuWeights { wInProj: Float32Array; bInProj: Float32Array; wConv: Float32Array; bConv: Float32Array; wXProj: Float32Array; bXProj: Float32Array; wDtProj: Float32Array; bDtProj: Float32Array; A_log: Float32Array; D_vec: Float32Array; wOutProj: Float32Array; bOutProj: Float32Array; normWeight: Float32Array; } /** Parameter names of a Mamba-1 block, in `parameters()` order. */ export declare const MAMBA1_PARAM_NAMES: readonly ["wInProj", "bInProj", "wConv", "bConv", "wXProj", "bXProj", "wDtProj", "bDtProj", "A_log", "D_vec", "wOutProj", "bOutProj", "normWeight"]; export interface Mamba1CpuDims { dModel: number; dState: number; dConv: number; dInner: number; dtRank: number; batch: number; seqLen: number; } /** Everything the backward pass needs from the forward pass. */ export interface Mamba1CpuCache { x: Float32Array; normInv: Float32Array; normOut: Float32Array; xConvIn: Float32Array; z: Float32Array; convOut: Float32Array; u: Float32Array; dtRaw: Float32Array; bRaw: Float32Array; cRaw: Float32Array; deltaFull: Float32Array; dv: Float32Array; aCont: Float32Array; aBar: Float32Array; bBar: Float32Array; h: Float32Array; scanY: Float32Array; siluZ: Float32Array; gated: Float32Array; } export interface Mamba1CpuForwardResult { output: Float32Array; cache: Mamba1CpuCache; } /** Gradients for every Mamba-1 parameter, same keys as {@link Mamba1CpuWeights}. */ export type Mamba1CpuGrads = Record; /** * Clamp bounds on `A_log` applied by `discretise_A`/`discretise_B` in * `SELECTIVE_SCAN_FORWARD_WGSL`. Outside this range the kernel's output is * constant in `A_log`, so the gradient is exactly zero — mirrored here so the * analytic gradient matches the function the model actually computes. */ export declare const A_LOG_CLAMP_LO = -10; export declare const A_LOG_CLAMP_HI = 5; /** Allocate a zeroed gradient set matching `dims`. */ export declare function zeroMamba1Grads(dims: Mamba1CpuDims): Mamba1CpuGrads; /** * Exact CPU forward for one Mamba-1 block. * * Mirrors `Mamba1Block.forward` step for step: * RMSNorm → in_proj → split(x, z) → causal conv1d → SiLU → x_proj(Δ, B, C) * → dt_proj → selective scan → gate by SiLU(z) → out_proj → residual add. */ export declare function mamba1CpuForward(x: Float32Array, w: Mamba1CpuWeights, dims: Mamba1CpuDims): Mamba1CpuForwardResult; /** * Exact CPU backward for one Mamba-1 block. * * @param dOut dL/d(block output), (M, dModel) * @param grads accumulator — parameter gradients are ADDED into it * @returns dL/d(block input), (M, dModel) */ export declare function mamba1CpuBackward(dOut: Float32Array, w: Mamba1CpuWeights, cache: Mamba1CpuCache, dims: Mamba1CpuDims, grads: Mamba1CpuGrads): Float32Array; //# sourceMappingURL=mamba1_cpu.d.ts.map