Skip to main content

gam_math/
jet_scalar.rs

1//! Order-specific Taylor-jet SCALAR algebras (#932 cutover, doc §A).
2//!
3//! [`crate::jet_tower::Tower4`] carries the full value/gradient/Hessian/`t3`/`t4`
4//! tensor stack: it answers EVERY channel a `gam_models::row_kernel::RowKernel`
5//! consumer can ask for, but at `K = 9` that is a ~50 KiB per-row object whose
6//! by-value copies overflowed the stack and timed out the location-scale fit.
7//! The cutover therefore does NOT instantiate the dense `Tower4<9>` per row; it
8//! carries, per consumer, only the one channel that consumer serves:
9//!
10//! | consumer | channel | scalar here | K=9 size |
11//! |---|---|---|---|
12//! | inner Newton / `row_kernel` | `(v, g, H)` | [`Order2`] | 728 B |
13//! | `row_third_contracted(dir)` | `Σ_c ℓ_{abc} dir_c` | [`OneSeed`] | 1.46 KiB |
14//! | `row_fourth_contracted(u, v)` | `Σ_{cd} ℓ_{abcd} u_c v_d` | [`TwoSeed`] | 2.8 KiB |
15//!
16//! Each is built on [`Order2`] (value/grad/Hessian), which is the production
17//! [`crate::jet_tower::Tower2`] re-expressed behind a generic interface: a row
18//! loss written ONCE against [`JetScalar`] re-instantiates at whatever order /
19//! representation a consumer needs, with the contraction folded INTO the
20//! differentiation (the nilpotent ε / δ directions), so `t3` / `t4` are never
21//! materialised. The single source of truth is the same one expression — the
22//! genus of #736 cross-block drift cannot reappear because there is no separate
23//! channel to forget.
24//!
25//! # Why each scalar is exact (doc §A.1–A.3)
26//!
27//! * [`Order2`] is the order-≤2 truncation of the Leibniz / Faà di Bruno rules.
28//!   Those order-2 terms read ONLY the order-≤2 channels of their inputs (see
29//!   [`crate::jet_tower::Tower4::mul`]: `out.h[i][j]` never touches `t3`/`t4`),
30//!   so its `(v, g, H)` is BIT-IDENTICAL to a full `Tower4<K>` — and identical
31//!   to [`crate::jet_tower::Tower2`], over which it is a thin newtype.
32//! * [`OneSeed`] carries an [`Order2`] base plus one nilpotent ε (`ε² = 0`)
33//!   holding another [`Order2`]. Seeding ε with the fixed direction `u` makes the
34//!   ε-component of the Hessian channel the contracted third `Σ_c ℓ_{abc} u_c`
35//!   (the nilpotent implements `d/dτ|₀` of `ℓ_{ab}(p + τu)` exactly).
36//! * [`TwoSeed`] carries an [`Order2`] base plus ε, δ (`ε² = δ² = 0`, `εδ`
37//!   retained) — four [`Order2`] parts. Seeding ε, δ with `u, v` makes the
38//!   εδ-component of the Hessian channel the contracted fourth
39//!   `Σ_{cd} ℓ_{abcd} u_c v_d` (the single mixed `∂_σ∂_ρ|₀` term, no `σ²`/`ρ²`
40//!   contamination).
41//!
42//! # Stability discipline
43//!
44//! As in [`crate::jet_tower`], humans own primitive stability and the algebra
45//! owns combinatorics: tail-critical special functions enter ONLY as
46//! hand-certified `[f64; 5]` derivative stacks through [`crate::nested_dual::JetField::compose_unary`]
47//! (each scalar consumes the leading entries its order needs), never by
48//! differentiating an unstable primal.
49//!
50//! # Production scalars and the test-only all-channels oracle
51//!
52//! The `JetScalar` trait below is production: it is the bound on the canonical
53//! [`crate::jet_tower::RowProgram::eval`] seam a family row loss is written
54//! against. The order-specific scalars that *consume* it —
55//! [`Order2`] (value/grad/Hessian), [`OneSeed`] (contracted third) and
56//! [`TwoSeed`] (contracted fourth) — are production: the survival location-scale
57//! `RowKernel<9>` builds its joint Hessian / directional derivatives through them
58//! (`survival::location_scale::row_kernel`), paying only the small packed scalar
59//! per row instead of the ~50 KiB dense [`crate::jet_tower::Tower4`].
60//!
61//! The [`crate::jet_tower::Tower4`] all-channels `JetScalar` impl is test-only: it
62//! is the oracle that pins the contracted scalars against the dense
63//! value/grad/Hessian/`t3`/`t4` truth, so it lives in the `#[cfg(test)]` module.
64
65/// Symmetric coefficient operator used by the universal quadratic-form jet
66/// primitive.
67///
68/// Implementations own representation-specific matrix access (diagonal,
69/// dense, low rank, structured, or matrix free). Jet scalars own the one
70/// derivative rule for `x' A x`; callers never spell its chain rule.
71pub trait SymmetricQuadraticCoefficients {
72    /// Input-space dimension of the symmetric operator.
73    fn dimension(&self) -> usize;
74
75    /// Compute `output = A * input` without materializing `A`.
76    fn multiply(&self, input: &[f64], output: &mut [f64]);
77
78    /// One symmetric coefficient `A[row, column]`.
79    fn coefficient(&self, row: usize, column: usize) -> f64;
80
81    /// Visit the operator's input-space upper triangle without materializing a
82    /// dense matrix. The default probes one basis direction at a time through
83    /// [`Self::multiply`], preserving matrix-free operators. Representations
84    /// with direct structure should override this hook so a packed curvature
85    /// lowering is O(K), O(K²), or O(K²R) as appropriate instead of performing
86    /// K full operator applications.
87    ///
88    /// `direction` and `projected` are caller-owned scratch of exact length
89    /// [`Self::dimension`]. Every `(row, column)` with `row <= column` is
90    /// visited exactly once, including structural zeros.
91    fn visit_upper_triangle(
92        &self,
93        direction: &mut [f64],
94        projected: &mut [f64],
95        mut visit: impl FnMut(usize, usize, f64),
96    ) {
97        let dimension = self.dimension();
98        assert_eq!(direction.len(), dimension);
99        assert_eq!(projected.len(), dimension);
100        direction.fill(0.0);
101        for column in 0..dimension {
102            direction[column] = 1.0;
103            self.multiply(direction, projected);
104            direction[column] = 0.0;
105            for row in 0..=column {
106                visit(row, column, projected[row]);
107            }
108        }
109    }
110
111    /// Evaluate the primal quadratic form without materializing the input as a
112    /// separate `f64` vector. Structured operators should override this to
113    /// preserve their representation's natural complexity (for example O(KR)
114    /// for a K-by-R low-rank factor).
115    fn quadratic_value<T, F>(&self, inputs: &[T], value: F) -> f64
116    where
117        F: Fn(&T) -> f64,
118    {
119        assert_eq!(
120            inputs.len(),
121            self.dimension(),
122            "symmetric quadratic-form dimension mismatch"
123        );
124        let mut out = 0.0;
125        for row in 0..inputs.len() {
126            let row_value = value(&inputs[row]);
127            out += self.coefficient(row, row) * row_value * row_value;
128            for column in row + 1..inputs.len() {
129                out += 2.0 * self.coefficient(row, column) * row_value * value(&inputs[column]);
130            }
131        }
132        out
133    }
134}
135
136fn symmetric_quadratic_form_default<T, C>(
137    inputs: &[T],
138    coefficients: &C,
139    constant: impl Fn(f64) -> T,
140    add: impl Fn(&T, &T) -> T,
141    mul: impl Fn(&T, &T) -> T,
142    scale: impl Fn(&T, f64) -> T,
143) -> T
144where
145    C: SymmetricQuadraticCoefficients,
146{
147    assert_eq!(
148        inputs.len(),
149        coefficients.dimension(),
150        "symmetric quadratic-form dimension mismatch"
151    );
152    let mut out = constant(0.0);
153    for row in 0..inputs.len() {
154        let diagonal = mul(&inputs[row], &inputs[row]);
155        out = add(&out, &scale(&diagonal, coefficients.coefficient(row, row)));
156        for column in row + 1..inputs.len() {
157            let cross = mul(&inputs[row], &inputs[column]);
158            out = add(
159                &out,
160                &scale(&cross, 2.0 * coefficients.coefficient(row, column)),
161            );
162        }
163    }
164    out
165}
166
167fn linear_combination_default<T>(
168    inputs: &[T],
169    weights: &[f64],
170    constant: impl Fn(f64) -> T,
171    add: impl Fn(&T, &T) -> T,
172    scale: impl Fn(&T, f64) -> T,
173) -> T {
174    assert_eq!(
175        inputs.len(),
176        weights.len(),
177        "linear-combination dimension mismatch"
178    );
179    inputs
180        .iter()
181        .zip(weights)
182        .fold(constant(0.0), |sum, (input, &weight)| {
183            add(&sum, &scale(input, weight))
184        })
185}
186
187fn multiply_add_default<T>(
188    left: &T,
189    right: &T,
190    addend: &T,
191    mul: impl Fn(&T, &T) -> T,
192    add: impl Fn(&T, &T) -> T,
193) -> T {
194    add(&mul(left, right), addend)
195}
196
197fn composed_sum_default<T>(
198    inputs: &[T],
199    derivative_stacks: &[[f64; 5]],
200    constant: impl Fn(f64) -> T,
201    add: impl Fn(&T, &T) -> T,
202    compose: impl Fn(&T, [f64; 5]) -> T,
203) -> T {
204    assert_eq!(
205        inputs.len(),
206        derivative_stacks.len(),
207        "composed-sum term-count mismatch"
208    );
209    inputs
210        .iter()
211        .zip(derivative_stacks)
212        .fold(constant(0.0), |sum, (input, &stack)| {
213            add(&sum, &compose(input, stack))
214        })
215}
216
217fn affine_compose_default<T>(
218    input: &T,
219    input_scale: f64,
220    input_shift: f64,
221    derivative_stack: [f64; 5],
222    scale: impl Fn(&T, f64) -> T,
223    add_constant: impl Fn(&T, f64) -> T,
224    compose: impl Fn(&T, [f64; 5]) -> T,
225) -> T {
226    compose(
227        &add_constant(&scale(input, input_scale), input_shift),
228        derivative_stack,
229    )
230}
231
232fn affine_composed_sum_default<T>(
233    inputs: &[T],
234    input_scales: &[f64],
235    derivative_stacks: &[[f64; 5]],
236    constant: impl Fn(f64) -> T,
237    add: impl Fn(&T, &T) -> T,
238    scale: impl Fn(&T, f64) -> T,
239    add_constant: impl Fn(&T, f64) -> T,
240    compose: impl Fn(&T, [f64; 5]) -> T,
241) -> T {
242    assert_eq!(inputs.len(), input_scales.len());
243    assert_eq!(inputs.len(), derivative_stacks.len());
244    inputs.iter().zip(input_scales).zip(derivative_stacks).fold(
245        constant(0.0),
246        |sum, ((input, &input_scale), &stack)| {
247            add(
248                &sum,
249                &affine_compose_default(
250                    input,
251                    input_scale,
252                    0.0,
253                    stack,
254                    &scale,
255                    &add_constant,
256                    &compose,
257                ),
258            )
259        },
260    )
261}
262
263fn shared_multiply_add_affine_composed_sum_default<T, const N: usize>(
264    lefts: &[&T; N],
265    right: &T,
266    addend: &T,
267    addend_scales: &[f64; N],
268    input_scales: &[f64; N],
269    derivative_stacks: &[[f64; 5]; N],
270    constant: impl Fn(f64) -> T,
271    add: impl Fn(&T, &T) -> T,
272    mul: impl Fn(&T, &T) -> T,
273    scale: impl Fn(&T, f64) -> T,
274    multiply_add: impl Fn(&T, &T, &T) -> T,
275    affine_compose: impl Fn(&T, f64, f64, [f64; 5]) -> T,
276) -> T {
277    let (representatives, term_sources, source_count) =
278        canonical_shared_source_schedule(|term, representative| {
279            std::ptr::eq(lefts[term], lefts[representative])
280                && addend_scales[term] == addend_scales[representative]
281        });
282    let (value, source_derivatives) =
283        aggregate_shared_source_derivatives(&term_sources, input_scales, derivative_stacks);
284    (0..source_count).fold(constant(value), |sum, source| {
285        let term = representatives[source];
286        let inner = if addend_scales[term] == 0.0 {
287            mul(lefts[term], right)
288        } else if addend_scales[term] == 1.0 {
289            multiply_add(lefts[term], right, addend)
290        } else {
291            multiply_add(lefts[term], right, &scale(addend, addend_scales[term]))
292        };
293        let composed = affine_compose(&inner, 1.0, 0.0, source_derivatives[source]);
294        add(&sum, &composed)
295    })
296}
297
298/// Canonical representatives for repeated inner sources in a shared composed sum.
299///
300/// Backends define source identity at their representation boundary: eager jets
301/// use reference identity, while compiled graphs use node identity. Terms are
302/// equivalent only when their left operand and structural addend coefficient
303/// name the same inner expression. The returned term-to-source map lets every
304/// backend sum outer first/second coefficients before propagating that source.
305#[inline(always)]
306pub(crate) fn canonical_shared_source_schedule<const N: usize>(
307    mut equivalent: impl FnMut(usize, usize) -> bool,
308) -> ([usize; N], [usize; N], usize) {
309    let mut representatives = [0; N];
310    let mut term_sources = [0; N];
311    let mut source_count = 0;
312    for term in 0..N {
313        let mut source = 0;
314        while source < source_count && !equivalent(term, representatives[source]) {
315            source += 1;
316        }
317        if source == source_count {
318            representatives[source] = term;
319            source_count += 1;
320        }
321        term_sources[term] = source;
322    }
323    (representatives, term_sources, source_count)
324}
325
326/// Sum each source's affine-scaled derivative stack through fourth order.
327///
328/// For a term `f(s*x)`, derivative order `r` contributes `f^(r) * s^r`.
329/// The primal value is accumulated once in original term order, while source
330/// stacks deliberately keep a zero value channel so adding their composed jets
331/// cannot perturb that authoritative primal sum.
332#[inline(always)]
333pub(crate) fn aggregate_shared_source_derivatives<const N: usize>(
334    term_sources: &[usize; N],
335    input_scales: &[f64; N],
336    derivative_stacks: &[[f64; 5]; N],
337) -> (f64, [[f64; 5]; N]) {
338    let mut value = 0.0;
339    let mut source_derivatives = [[0.0; 5]; N];
340    for term in 0..N {
341        value += derivative_stacks[term][0];
342        let source = term_sources[term];
343        let mut scale_power = input_scales[term];
344        for order in 1..5 {
345            source_derivatives[source][order] += derivative_stacks[term][order] * scale_power;
346            scale_power *= input_scales[term];
347        }
348    }
349    (value, source_derivatives)
350}
351
352/// A truncated-Taylor scalar carrying derivatives in `K` primaries.
353///
354/// All concrete scalars here ([`Order2`], [`OneSeed`], [`TwoSeed`]) and the full
355/// [`crate::jet_tower::Tower4`] implement the SAME algebra; only the carried
356/// channel set differs. A row loss written once against this interface yields a
357/// different channel set per instantiation, all exact for the channel they serve
358/// (doc §A.0).
359pub trait JetScalar<const K: usize>: crate::nested_dual::JetField + Copy {
360    /// A constant: value `c`, every derivative channel zero.
361    fn constant(c: f64) -> Self;
362
363    /// The seeded variable `p_axis` at value `x`: unit first derivative in slot
364    /// `axis`, all higher channels zero. (The nilpotent / cross channels of the
365    /// directional scalars are seeded zero — callers set ε/δ directions through
366    /// the scalar-specific [`OneSeed::seed_direction`] / [`TwoSeed::seed`].)
367    fn variable(x: f64, axis: usize) -> Self;
368
369    /// Evaluate `inputs' A inputs` from one universal semantic primitive.
370    /// Order-specific scalars may lower the mechanically derived channels
371    /// directly; the default is the exact scalar program over `mul/add/scale`.
372    fn symmetric_quadratic_form<C: SymmetricQuadraticCoefficients>(
373        inputs: &[Self],
374        coefficients: &C,
375    ) -> Self {
376        symmetric_quadratic_form_default(
377            inputs,
378            coefficients,
379            Self::constant,
380            crate::nested_dual::JetField::add,
381            crate::nested_dual::JetField::mul,
382            crate::nested_dual::JetField::scale,
383        )
384    }
385
386    /// Evaluate `sum_i weights[i] * inputs[i]` in one semantic primitive.
387    fn linear_combination(inputs: &[Self], weights: &[f64]) -> Self {
388        linear_combination_default(
389            inputs,
390            weights,
391            Self::constant,
392            crate::nested_dual::JetField::add,
393            crate::nested_dual::JetField::scale,
394        )
395    }
396
397    /// Add a primal constant without changing derivative channels.
398    fn add_constant(&self, constant: f64) -> Self {
399        self.add(&Self::constant(constant))
400    }
401
402    /// Evaluate `self * right + addend` in one semantic primitive.
403    fn multiply_add(&self, right: &Self, addend: &Self) -> Self {
404        multiply_add_default(
405            self,
406            right,
407            addend,
408            crate::nested_dual::JetField::mul,
409            crate::nested_dual::JetField::add,
410        )
411    }
412
413    /// Sum unary compositions directly from certified derivative stacks.
414    fn composed_sum(inputs: &[Self], derivative_stacks: &[[f64; 5]]) -> Self {
415        composed_sum_default(
416            inputs,
417            derivative_stacks,
418            Self::constant,
419            crate::nested_dual::JetField::add,
420            crate::nested_dual::JetField::compose_unary,
421        )
422    }
423
424    /// Exact product as an explicit compiled graph node.
425    fn product(&self, right: &Self) -> Self {
426        self.mul(right)
427    }
428
429    /// Compose a certified outer stack after the affine map
430    /// `u = input_scale * self + input_shift`.
431    fn affine_compose(
432        &self,
433        input_scale: f64,
434        input_shift: f64,
435        derivative_stack: [f64; 5],
436    ) -> Self {
437        affine_compose_default(
438            self,
439            input_scale,
440            input_shift,
441            derivative_stack,
442            crate::nested_dual::JetField::scale,
443            Self::add_constant,
444            crate::nested_dual::JetField::compose_unary,
445        )
446    }
447
448    /// Sum unary compositions whose inputs each carry an affine scale.
449    fn affine_composed_sum(
450        inputs: &[Self],
451        input_scales: &[f64],
452        derivative_stacks: &[[f64; 5]],
453    ) -> Self {
454        affine_composed_sum_default(
455            inputs,
456            input_scales,
457            derivative_stacks,
458            Self::constant,
459            crate::nested_dual::JetField::add,
460            crate::nested_dual::JetField::scale,
461            Self::add_constant,
462            crate::nested_dual::JetField::compose_unary,
463        )
464    }
465
466    /// Evaluate
467    /// `Σ_i f_i(input_scale_i · (left_i · right + addend_scale_i · addend))`
468    /// from the certified derivative stack of each `f_i`. The shared operands
469    /// make expression-level common subexpressions explicit, so optimized
470    /// backends apply their inherited derivative channels once. Expression
471    /// arity is part of the type, and borrowed operands never copy a full tower.
472    /// An exact-zero addend scale (either sign of IEEE zero) removes that addend
473    /// from the corresponding term entirely.
474    fn shared_multiply_add_affine_composed_sum<const N: usize>(
475        lefts: &[&Self; N],
476        right: &Self,
477        addend: &Self,
478        addend_scales: &[f64; N],
479        input_scales: &[f64; N],
480        derivative_stacks: &[[f64; 5]; N],
481    ) -> Self {
482        shared_multiply_add_affine_composed_sum_default(
483            lefts,
484            right,
485            addend,
486            addend_scales,
487            input_scales,
488            derivative_stacks,
489            Self::constant,
490            crate::nested_dual::JetField::add,
491            crate::nested_dual::JetField::mul,
492            crate::nested_dual::JetField::scale,
493            Self::multiply_add,
494            Self::affine_compose,
495        )
496    }
497
498    // The scalar-field algebra — `value`, `add`, `sub`, `mul`, `neg`, `scale`,
499    // and the single Faà di Bruno `compose_unary([f64; 5])` — is declared ONCE on
500    // the shared [`crate::nested_dual::JetField`] supertrait (which the runtime-`p`
501    // flex jets also extend), so it is not re-declared here. The value/composition
502    // convention is identical (`u = self.value()`, the `[f64; 5]` stack shape
503    // [`crate::jet_tower::Tower4`] consumes). The helpers below build on it.
504
505    /// Compose with a unary special-function whose derivative stack is built from
506    /// the scalar base value through `stack_fn`. This evaluates
507    /// `stack_fn(self.value())` once and forwards to
508    /// [`compose_unary`](crate::nested_dual::JetField::compose_unary), so it is bit-identical to the
509    /// explicit `self.compose_unary(stack_fn(self.value()))` form.
510    fn compose_unary_with(&self, stack_fn: impl Fn(f64) -> [f64; 5]) -> Self {
511        self.compose_unary(stack_fn(self.value()))
512    }
513
514    /// `e^self`. Convenience for tame arguments (see module stability note).
515    fn exp(&self) -> Self {
516        let e = self.value().exp();
517        self.compose_unary([e, e, e, e, e])
518    }
519
520    /// `√self`. Caller guarantees positivity.
521    fn sqrt(&self) -> Self {
522        let u = self.value();
523        let s = u.sqrt();
524        self.compose_unary([
525            s,
526            0.5 / s,
527            -0.25 / (u * s),
528            0.375 / (u * u * s),
529            -0.9375 / (u * u * u * s),
530        ])
531    }
532
533    /// `ln(self)`. Caller guarantees positivity. Same derivative stack
534    /// [`crate::jet_tower::Tower4::ln`] uses, so any program written over both
535    /// matches term-for-term.
536    fn ln(&self) -> Self {
537        let u = self.value();
538        let r = 1.0 / u;
539        self.compose_unary([u.ln(), r, -r * r, 2.0 * r * r * r, -6.0 * r * r * r * r])
540    }
541
542    /// `1/self`.
543    fn recip(&self) -> Self {
544        let r = 1.0 / self.value();
545        let r2 = r * r;
546        self.compose_unary([r, -r2, 2.0 * r2 * r, -6.0 * r2 * r2, 24.0 * r2 * r2 * r])
547    }
548
549    /// `self^a` for real exponent `a`. Caller guarantees a positive base.
550    /// Mirrors [`crate::jet_tower::Tower4::powf`] (falling-factorial stack).
551    fn powf(&self, a: f64) -> Self {
552        let u = self.value();
553        self.compose_unary([
554            u.powf(a),
555            a * u.powf(a - 1.0),
556            a * (a - 1.0) * u.powf(a - 2.0),
557            a * (a - 1.0) * (a - 2.0) * u.powf(a - 3.0),
558            a * (a - 1.0) * (a - 2.0) * (a - 3.0) * u.powf(a - 4.0),
559        ])
560    }
561
562    /// `ln Γ(self)`. Caller guarantees a positive argument. Uses the SAME
563    /// hand-certified derivative stack [`crate::jet_tower::Tower4::ln_gamma`]
564    /// consumes ([`crate::jet_tower::ln_gamma_derivative_stack`]), so any
565    /// program written over both matches term-for-term.
566    fn ln_gamma(&self) -> Self {
567        self.compose_unary(crate::jet_tower::ln_gamma_derivative_stack(self.value()))
568    }
569
570    /// `ψ(self) = d/dx ln Γ(x)` (digamma). Caller guarantees a positive
571    /// argument. Same hand-certified stack
572    /// [`crate::jet_tower::digamma_derivative_stack`].
573    fn digamma(&self) -> Self {
574        self.compose_unary(crate::jet_tower::digamma_derivative_stack(self.value()))
575    }
576}
577
578/// Lift a fixed-width primary jet through an independent second-order
579/// direction. Primary variables live in the inner scalar; constructing one
580/// must not seed the outer direction, which is reserved for a family or
581/// hyperparameter derivative selected by the caller.
582impl<S, const K: usize> JetScalar<K> for crate::nested_dual::Dual2<S>
583where
584    S: JetScalar<K>,
585{
586    #[inline]
587    fn constant(c: f64) -> Self {
588        Self {
589            v: S::constant(c),
590            g: S::constant(0.0),
591            h: S::constant(0.0),
592        }
593    }
594
595    #[inline]
596    fn variable(x: f64, axis: usize) -> Self {
597        Self {
598            v: S::variable(x, axis),
599            g: S::constant(0.0),
600            h: S::constant(0.0),
601        }
602    }
603}
604
605/// A Taylor-jet scalar whose primary dimension is selected at runtime.
606///
607/// This is the dimensioned counterpart of [`JetScalar`].  Its algebra is the
608/// same; only the constructors receive the row's actual primary count.  The
609/// fixed-size scalar implementations below bridge to this trait as well, which
610/// lets one row program serve both the const-generic derivative oracles and the
611/// runtime-sized production backends without duplicating the expression.
612pub trait RuntimeJetScalar<'arena>: Clone {
613    /// Storage arena used by runtime-backed scalars. Fixed derivative oracles
614    /// use the unit type because their storage is inline.
615    type Workspace: ?Sized;
616
617    /// A constant in a `dimension`-primary algebra.
618    fn constant(c: f64, dimension: usize, workspace: &'arena Self::Workspace) -> Self;
619    /// A seeded variable in a `dimension`-primary algebra.
620    fn variable(x: f64, axis: usize, dimension: usize, workspace: &'arena Self::Workspace) -> Self;
621    /// A constant in the same runtime algebra as `self`.
622    ///
623    /// Implementations must construct the constant directly, with every
624    /// derivative channel exactly zero. A shaped constant is an algebra
625    /// primitive: synthesizing one through [`Self::compose_unary`] needlessly
626    /// traverses every live derivative channel.
627    fn constant_like(&self, c: f64) -> Self;
628    /// Replace only the primal value, preserving every derivative channel.
629    fn with_value(&self, value: f64) -> Self;
630
631    /// Evaluate `inputs' A inputs` from the same universal semantic primitive
632    /// as [`JetScalar::symmetric_quadratic_form`].
633    fn symmetric_quadratic_form<C: SymmetricQuadraticCoefficients>(
634        inputs: &[Self],
635        coefficients: &C,
636        dimension: usize,
637        workspace: &'arena Self::Workspace,
638    ) -> Self {
639        symmetric_quadratic_form_default(
640            inputs,
641            coefficients,
642            |value| Self::constant(value, dimension, workspace),
643            Self::add,
644            Self::mul,
645            Self::scale,
646        )
647    }
648
649    /// Evaluate `sum_i weights[i] * inputs[i]` in one semantic primitive.
650    fn linear_combination(
651        inputs: &[Self],
652        weights: &[f64],
653        dimension: usize,
654        workspace: &'arena Self::Workspace,
655    ) -> Self {
656        linear_combination_default(
657            inputs,
658            weights,
659            |value| Self::constant(value, dimension, workspace),
660            Self::add,
661            Self::scale,
662        )
663    }
664
665    /// Add a primal constant without changing derivative channels.
666    fn add_constant(&self, constant: f64) -> Self {
667        self.with_value(self.value() + constant)
668    }
669
670    /// Evaluate `self * right + addend` in one semantic primitive.
671    fn multiply_add(&self, right: &Self, addend: &Self) -> Self {
672        multiply_add_default(self, right, addend, Self::mul, Self::add)
673    }
674
675    /// `addend + Sum_i lefts[i] * f_i(right)` from certified derivative stacks,
676    /// with ONE shared composition point.
677    ///
678    /// This is the shape a warp or deviation basis takes: a fixed inner index
679    /// `right`, one basis function per coefficient, and the coefficient jets as
680    /// the left factors. Written as a loop of `compose_unary` and `multiply_add`
681    /// it allocates and streams `2N` derivative blocks for a result that is one
682    /// block, and every one of those blocks re-reads the SAME `right.h` and
683    /// `right.g` - the composition point does not move with `i`. A runtime jet
684    /// that overrides this writes the single output block instead (gam#979: the
685    /// flexible marginal-slope row's link-deviation loop is `2*|w|` such blocks
686    /// per calibration node, per lift iteration, per row).
687    ///
688    /// The default is exactly the loop it replaces, so a representation that
689    /// does not override it computes what it computed, in the order it did.
690    fn weighted_compose_sum(
691        lefts: &[Self],
692        right: &Self,
693        derivative_stacks: &[[f64; 5]],
694        addend: &Self,
695    ) -> Self {
696        assert_eq!(
697            lefts.len(),
698            derivative_stacks.len(),
699            "weighted compose sum needs one derivative stack per left factor"
700        );
701        let mut sum = addend.clone();
702        for (left, stack) in lefts.iter().zip(derivative_stacks) {
703            let composed = right.compose_unary(*stack);
704            let accumulated = left.multiply_add(&composed, &sum);
705            sum = accumulated;
706        }
707        sum
708    }
709
710    /// Sum unary compositions directly from certified derivative stacks.
711    fn composed_sum(
712        inputs: &[Self],
713        derivative_stacks: &[[f64; 5]],
714        dimension: usize,
715        workspace: &'arena Self::Workspace,
716    ) -> Self {
717        composed_sum_default(
718            inputs,
719            derivative_stacks,
720            |value| Self::constant(value, dimension, workspace),
721            Self::add,
722            Self::compose_unary,
723        )
724    }
725
726    /// Exact product as an explicit compiled graph node.
727    fn product(&self, right: &Self) -> Self {
728        self.mul(right)
729    }
730
731    /// Compose a certified outer stack after an affine input map.
732    fn affine_compose(
733        &self,
734        input_scale: f64,
735        input_shift: f64,
736        derivative_stack: [f64; 5],
737    ) -> Self {
738        affine_compose_default(
739            self,
740            input_scale,
741            input_shift,
742            derivative_stack,
743            Self::scale,
744            |value, constant| value.add_constant(constant),
745            Self::compose_unary,
746        )
747    }
748
749    /// Sum unary compositions whose inputs each carry an affine scale.
750    fn affine_composed_sum(
751        inputs: &[Self],
752        input_scales: &[f64],
753        derivative_stacks: &[[f64; 5]],
754        dimension: usize,
755        workspace: &'arena Self::Workspace,
756    ) -> Self {
757        affine_composed_sum_default(
758            inputs,
759            input_scales,
760            derivative_stacks,
761            |value| Self::constant(value, dimension, workspace),
762            Self::add,
763            Self::scale,
764            |value, constant| value.add_constant(constant),
765            Self::compose_unary,
766        )
767    }
768
769    /// Runtime-dimension lowering of
770    /// `Σ_i f_i(input_scale_i · (left_i · right + addend_scale_i · addend))`
771    /// from certified derivative stacks. Const expression arity replaces an
772    /// implementation-specific term cap, while shared operands expose universal
773    /// common-subexpression elimination. If every addend scale is exact zero
774    /// (including `-0.0`), the addend has no dimension, workspace, or
775    /// derivative-channel obligations.
776    fn shared_multiply_add_affine_composed_sum<const N: usize>(
777        lefts: &[&Self; N],
778        right: &Self,
779        addend: &Self,
780        addend_scales: &[f64; N],
781        input_scales: &[f64; N],
782        derivative_stacks: &[[f64; 5]; N],
783        dimension: usize,
784        workspace: &'arena Self::Workspace,
785    ) -> Self {
786        shared_multiply_add_affine_composed_sum_default(
787            lefts,
788            right,
789            addend,
790            addend_scales,
791            input_scales,
792            derivative_stacks,
793            |value| Self::constant(value, dimension, workspace),
794            Self::add,
795            Self::mul,
796            Self::scale,
797            Self::multiply_add,
798            |input, scale, shift, stack| input.affine_compose(scale, shift, stack),
799        )
800    }
801    /// Number of primary derivative axes carried by this scalar.
802    fn dimension(&self) -> usize;
803    /// Value channel.
804    fn value(&self) -> f64;
805    /// Exact truncated sum.
806    fn add(&self, o: &Self) -> Self;
807    /// Exact truncated difference.
808    fn sub(&self, o: &Self) -> Self;
809    /// Exact truncated product.
810    fn mul(&self, o: &Self) -> Self;
811    /// Negate every channel.
812    fn neg(&self) -> Self;
813    /// Scale every channel.
814    fn scale(&self, s: f64) -> Self;
815    /// Exact unary composition from the certified derivative stack.
816    fn compose_unary(&self, d: [f64; 5]) -> Self;
817
818    /// `e^self`.
819    fn exp(&self) -> Self {
820        let e = self.value().exp();
821        self.compose_unary([e, e, e, e, e])
822    }
823
824    /// `ln(self)`. Caller guarantees positivity. This is the runtime-width
825    /// counterpart of [`JetScalar::ln`] and uses the identical certified
826    /// derivative stack.
827    fn ln(&self) -> Self {
828        let u = self.value();
829        let r = 1.0 / u;
830        self.compose_unary([u.ln(), r, -r * r, 2.0 * r * r * r, -6.0 * r * r * r * r])
831    }
832
833    /// `1/self`.
834    fn recip(&self) -> Self {
835        let r = 1.0 / self.value();
836        let r2 = r * r;
837        self.compose_unary([r, -r2, 2.0 * r2 * r, -6.0 * r2 * r2, 24.0 * r2 * r2 * r])
838    }
839}
840
841/// Zero-order runtime scalar for evaluating the primal value of a canonical
842/// runtime-width row program without constructing derivative channels.
843///
844/// The primary dimension remains part of the scalar so it obeys the same
845/// runtime algebra contract as derivative-carrying implementations. Unary
846/// derivative stacks contribute only their value entry, while structured
847/// quadratic operators retain their representation-specific primal lowering.
848#[derive(Clone, Copy, Debug, PartialEq)]
849pub struct RuntimeValue {
850    value: f64,
851    dimension: usize,
852}
853
854impl<'arena> RuntimeJetScalar<'arena> for RuntimeValue {
855    type Workspace = ();
856
857    #[inline(always)]
858    fn constant(c: f64, dimension: usize, &(): &'arena Self::Workspace) -> Self {
859        Self {
860            value: c,
861            dimension,
862        }
863    }
864
865    #[inline(always)]
866    fn variable(x: f64, axis: usize, dimension: usize, &(): &'arena Self::Workspace) -> Self {
867        assert!(
868            axis < dimension,
869            "runtime value variable axis out of bounds"
870        );
871        Self {
872            value: x,
873            dimension,
874        }
875    }
876
877    #[inline(always)]
878    fn constant_like(&self, c: f64) -> Self {
879        Self {
880            value: c,
881            dimension: self.dimension,
882        }
883    }
884
885    #[inline(always)]
886    fn with_value(&self, value: f64) -> Self {
887        Self {
888            value,
889            dimension: self.dimension,
890        }
891    }
892
893    #[inline(always)]
894    fn symmetric_quadratic_form<C: SymmetricQuadraticCoefficients>(
895        inputs: &[Self],
896        coefficients: &C,
897        dimension: usize,
898        &(): &'arena Self::Workspace,
899    ) -> Self {
900        assert_eq!(inputs.len(), coefficients.dimension());
901        assert!(inputs.iter().all(|input| input.dimension == dimension));
902        Self {
903            value: coefficients.quadratic_value(inputs, |input| input.value),
904            dimension,
905        }
906    }
907
908    #[inline(always)]
909    fn linear_combination(
910        inputs: &[Self],
911        weights: &[f64],
912        dimension: usize,
913        &(): &'arena Self::Workspace,
914    ) -> Self {
915        assert_eq!(inputs.len(), weights.len());
916        assert!(inputs.iter().all(|input| input.dimension == dimension));
917        let value = inputs
918            .iter()
919            .zip(weights)
920            .map(|(input, &weight)| input.value * weight)
921            .sum();
922        Self { value, dimension }
923    }
924
925    #[inline(always)]
926    fn multiply_add(&self, right: &Self, addend: &Self) -> Self {
927        self.assert_same_dimension(right);
928        self.assert_same_dimension(addend);
929        Self {
930            value: self.value * right.value + addend.value,
931            dimension: self.dimension,
932        }
933    }
934
935    #[inline(always)]
936    fn composed_sum(
937        inputs: &[Self],
938        derivative_stacks: &[[f64; 5]],
939        dimension: usize,
940        &(): &'arena Self::Workspace,
941    ) -> Self {
942        assert_eq!(inputs.len(), derivative_stacks.len());
943        assert!(inputs.iter().all(|input| input.dimension == dimension));
944        Self {
945            value: derivative_stacks.iter().map(|stack| stack[0]).sum(),
946            dimension,
947        }
948    }
949
950    #[inline(always)]
951    fn product(&self, right: &Self) -> Self {
952        self.mul(right)
953    }
954
955    #[inline(always)]
956    fn affine_compose(
957        &self,
958        input_scale: f64,
959        input_shift: f64,
960        derivative_stack: [f64; 5],
961    ) -> Self {
962        // Route the affine pre-composition through the shared default instead
963        // of hand-rolling the zero-order shortcut: `compose_unary` already
964        // reduces to `derivative_stack[0]` for this scalar, so the result is
965        // unchanged, but the scale and shift now travel the same path every
966        // other implementation uses rather than being dropped on the floor.
967        affine_compose_default(
968            self,
969            input_scale,
970            input_shift,
971            derivative_stack,
972            Self::scale,
973            |value, constant| value.add_constant(constant),
974            Self::compose_unary,
975        )
976    }
977
978    #[inline(always)]
979    fn affine_composed_sum(
980        inputs: &[Self],
981        input_scales: &[f64],
982        derivative_stacks: &[[f64; 5]],
983        dimension: usize,
984        &(): &'arena Self::Workspace,
985    ) -> Self {
986        assert_eq!(inputs.len(), input_scales.len());
987        assert_eq!(inputs.len(), derivative_stacks.len());
988        assert!(inputs.iter().all(|input| input.dimension == dimension));
989        Self {
990            value: derivative_stacks.iter().map(|stack| stack[0]).sum(),
991            dimension,
992        }
993    }
994
995    #[inline(always)]
996    fn dimension(&self) -> usize {
997        self.dimension
998    }
999
1000    #[inline(always)]
1001    fn value(&self) -> f64 {
1002        self.value
1003    }
1004
1005    #[inline(always)]
1006    fn add(&self, other: &Self) -> Self {
1007        self.assert_same_dimension(other);
1008        Self {
1009            value: self.value + other.value,
1010            dimension: self.dimension,
1011        }
1012    }
1013
1014    #[inline(always)]
1015    fn sub(&self, other: &Self) -> Self {
1016        self.assert_same_dimension(other);
1017        Self {
1018            value: self.value - other.value,
1019            dimension: self.dimension,
1020        }
1021    }
1022
1023    #[inline(always)]
1024    fn mul(&self, other: &Self) -> Self {
1025        self.assert_same_dimension(other);
1026        Self {
1027            value: self.value * other.value,
1028            dimension: self.dimension,
1029        }
1030    }
1031
1032    #[inline(always)]
1033    fn neg(&self) -> Self {
1034        Self {
1035            value: -self.value,
1036            dimension: self.dimension,
1037        }
1038    }
1039
1040    #[inline(always)]
1041    fn scale(&self, scale: f64) -> Self {
1042        Self {
1043            value: self.value * scale,
1044            dimension: self.dimension,
1045        }
1046    }
1047
1048    #[inline(always)]
1049    fn compose_unary(&self, derivative_stack: [f64; 5]) -> Self {
1050        Self {
1051            value: derivative_stack[0],
1052            dimension: self.dimension,
1053        }
1054    }
1055}
1056
1057impl RuntimeValue {
1058    #[inline(always)]
1059    fn assert_same_dimension(&self, other: &Self) {
1060        assert_eq!(self.dimension, other.dimension);
1061    }
1062}
1063
1064/// Adapter that presents any const-generic [`JetScalar<K>`] through the
1065/// runtime-dimension interface.  It is used by derivative oracles so the same
1066/// row program can be instantiated at a fixed tower and at a dynamic packed
1067/// scalar; production code unwraps the inner fixed tower after evaluation.
1068#[derive(Clone, Copy, Debug)]
1069#[repr(transparent)]
1070pub struct FixedRuntimeJet<S, const K: usize> {
1071    inner: S,
1072}
1073
1074impl<S, const K: usize> FixedRuntimeJet<S, K> {
1075    /// Wrap a fixed-dimension scalar so a runtime-dimension row expression can
1076    /// evaluate it without authoring a second const-generic body.
1077    #[inline(always)]
1078    #[must_use]
1079    pub fn from_inner(inner: S) -> Self {
1080        Self { inner }
1081    }
1082
1083    /// Recover the wrapped const-generic scalar.
1084    #[inline(always)]
1085    #[must_use]
1086    pub fn into_inner(self) -> S {
1087        self.inner
1088    }
1089}
1090
1091impl<'arena, S: JetScalar<K>, const K: usize> RuntimeJetScalar<'arena> for FixedRuntimeJet<S, K> {
1092    type Workspace = ();
1093
1094    #[inline(always)]
1095    fn constant(c: f64, dimension: usize, &(): &'arena Self::Workspace) -> Self {
1096        assert_eq!(dimension, K, "fixed jet dimension mismatch");
1097        Self {
1098            inner: S::constant(c),
1099        }
1100    }
1101
1102    #[inline(always)]
1103    fn variable(x: f64, axis: usize, dimension: usize, &(): &'arena Self::Workspace) -> Self {
1104        assert_eq!(dimension, K, "fixed jet dimension mismatch");
1105        Self {
1106            inner: S::variable(x, axis),
1107        }
1108    }
1109
1110    #[inline(always)]
1111    fn constant_like(&self, c: f64) -> Self {
1112        Self {
1113            inner: S::constant(c),
1114        }
1115    }
1116
1117    #[inline(always)]
1118    fn with_value(&self, value: f64) -> Self {
1119        Self {
1120            inner: self.inner.compose_unary([value, 1.0, 0.0, 0.0, 0.0]),
1121        }
1122    }
1123
1124    #[inline(always)]
1125    fn symmetric_quadratic_form<C: SymmetricQuadraticCoefficients>(
1126        inputs: &[Self],
1127        coefficients: &C,
1128        dimension: usize,
1129        &(): &'arena Self::Workspace,
1130    ) -> Self {
1131        assert_eq!(dimension, K, "fixed jet dimension mismatch");
1132        assert_eq!(inputs.len(), coefficients.dimension());
1133        // SAFETY: `FixedRuntimeJet<S, K>` is `repr(transparent)` with exactly one
1134        // non-zero-sized field of type `S`. Therefore each element has the same
1135        // layout and alignment as `S`; the cast preserves the allocation,
1136        // provenance, element count, and shared lifetime of `inputs`, and no
1137        // mutable reference is created while the original slice is borrowed.
1138        let inner =
1139            unsafe { std::slice::from_raw_parts(inputs.as_ptr().cast::<S>(), inputs.len()) };
1140        Self {
1141            inner: S::symmetric_quadratic_form(inner, coefficients),
1142        }
1143    }
1144
1145    #[inline(always)]
1146    fn linear_combination(
1147        inputs: &[Self],
1148        weights: &[f64],
1149        dimension: usize,
1150        &(): &'arena Self::Workspace,
1151    ) -> Self {
1152        assert_eq!(dimension, K, "fixed jet dimension mismatch");
1153        assert_eq!(inputs.len(), weights.len());
1154        // SAFETY: `FixedRuntimeJet<S, K>` is `repr(transparent)` over its sole
1155        // non-zero-sized `S` field, so the shared slice has identical element
1156        // layout, alignment, provenance, length, and lifetime after the cast.
1157        let inner =
1158            unsafe { std::slice::from_raw_parts(inputs.as_ptr().cast::<S>(), inputs.len()) };
1159        Self {
1160            inner: S::linear_combination(inner, weights),
1161        }
1162    }
1163
1164    #[inline(always)]
1165    fn add_constant(&self, constant: f64) -> Self {
1166        Self {
1167            inner: self.inner.add_constant(constant),
1168        }
1169    }
1170
1171    #[inline(always)]
1172    fn multiply_add(&self, right: &Self, addend: &Self) -> Self {
1173        Self {
1174            inner: self.inner.multiply_add(&right.inner, &addend.inner),
1175        }
1176    }
1177
1178    #[inline(always)]
1179    fn composed_sum(
1180        inputs: &[Self],
1181        derivative_stacks: &[[f64; 5]],
1182        dimension: usize,
1183        &(): &'arena Self::Workspace,
1184    ) -> Self {
1185        assert_eq!(dimension, K, "fixed jet dimension mismatch");
1186        // SAFETY: `FixedRuntimeJet<S, K>` is `repr(transparent)` over its sole
1187        // non-zero-sized `S` field, so the shared slice has identical element
1188        // layout, alignment, provenance, length, and lifetime after the cast.
1189        let inner =
1190            unsafe { std::slice::from_raw_parts(inputs.as_ptr().cast::<S>(), inputs.len()) };
1191        Self {
1192            inner: S::composed_sum(inner, derivative_stacks),
1193        }
1194    }
1195
1196    #[inline(always)]
1197    fn product(&self, right: &Self) -> Self {
1198        Self {
1199            inner: self.inner.product(&right.inner),
1200        }
1201    }
1202
1203    #[inline(always)]
1204    fn affine_compose(
1205        &self,
1206        input_scale: f64,
1207        input_shift: f64,
1208        derivative_stack: [f64; 5],
1209    ) -> Self {
1210        Self {
1211            inner: self
1212                .inner
1213                .affine_compose(input_scale, input_shift, derivative_stack),
1214        }
1215    }
1216
1217    #[inline(always)]
1218    fn affine_composed_sum(
1219        inputs: &[Self],
1220        input_scales: &[f64],
1221        derivative_stacks: &[[f64; 5]],
1222        dimension: usize,
1223        &(): &'arena Self::Workspace,
1224    ) -> Self {
1225        assert_eq!(dimension, K, "fixed jet dimension mismatch");
1226        // SAFETY: `FixedRuntimeJet<S, K>` is `repr(transparent)` over its sole
1227        // non-zero-sized `S` field, so the shared slice has identical element
1228        // layout, alignment, provenance, length, and lifetime after the cast.
1229        let inner =
1230            unsafe { std::slice::from_raw_parts(inputs.as_ptr().cast::<S>(), inputs.len()) };
1231        Self {
1232            inner: S::affine_composed_sum(inner, input_scales, derivative_stacks),
1233        }
1234    }
1235
1236    #[inline(always)]
1237    fn shared_multiply_add_affine_composed_sum<const N: usize>(
1238        lefts: &[&Self; N],
1239        right: &Self,
1240        addend: &Self,
1241        addend_scales: &[f64; N],
1242        input_scales: &[f64; N],
1243        derivative_stacks: &[[f64; 5]; N],
1244        dimension: usize,
1245        &(): &'arena Self::Workspace,
1246    ) -> Self {
1247        assert_eq!(dimension, K, "fixed jet dimension mismatch");
1248        let left_inner: [&S; N] = std::array::from_fn(|term| &lefts[term].inner);
1249        Self {
1250            inner: S::shared_multiply_add_affine_composed_sum(
1251                &left_inner,
1252                &right.inner,
1253                &addend.inner,
1254                addend_scales,
1255                input_scales,
1256                derivative_stacks,
1257            ),
1258        }
1259    }
1260
1261    #[inline(always)]
1262    fn dimension(&self) -> usize {
1263        K
1264    }
1265
1266    #[inline(always)]
1267    fn value(&self) -> f64 {
1268        self.inner.value()
1269    }
1270
1271    #[inline(always)]
1272    fn add(&self, o: &Self) -> Self {
1273        Self {
1274            inner: self.inner.add(&o.inner),
1275        }
1276    }
1277
1278    #[inline(always)]
1279    fn sub(&self, o: &Self) -> Self {
1280        Self {
1281            inner: self.inner.sub(&o.inner),
1282        }
1283    }
1284
1285    #[inline(always)]
1286    fn mul(&self, o: &Self) -> Self {
1287        Self {
1288            inner: self.inner.mul(&o.inner),
1289        }
1290    }
1291
1292    #[inline(always)]
1293    fn neg(&self) -> Self {
1294        Self {
1295            inner: self.inner.neg(),
1296        }
1297    }
1298
1299    #[inline(always)]
1300    fn scale(&self, s: f64) -> Self {
1301        Self {
1302            inner: self.inner.scale(s),
1303        }
1304    }
1305
1306    #[inline(always)]
1307    fn compose_unary(&self, d: [f64; 5]) -> Self {
1308        Self {
1309            inner: self.inner.compose_unary(d),
1310        }
1311    }
1312}
1313
1314/// Reusable storage for runtime-sized packed jets. Scalar primitives write
1315/// into this bump arena, so arithmetic performs no heap allocation. Callers
1316/// reserve once per worker/chunk and [`reset`](Self::reset) between rows.
1317#[derive(Debug)]
1318pub struct DynamicJetArena {
1319    bump: bumpalo::Bump,
1320}
1321
1322impl DynamicJetArena {
1323    /// Create an arena with the allocator's default initial chunk.
1324    #[must_use]
1325    pub fn new() -> Self {
1326        Self {
1327            bump: bumpalo::Bump::new(),
1328        }
1329    }
1330
1331    /// Create an arena with a row-program-selected initial byte capacity.
1332    #[must_use]
1333    pub fn with_capacity(bytes: usize) -> Self {
1334        Self {
1335            bump: bumpalo::Bump::with_capacity(bytes),
1336        }
1337    }
1338
1339    /// Reclaim all scalar outputs and compact a fragmented high-water mark
1340    /// into one retained chunk.
1341    ///
1342    /// `bumpalo::Bump::reset` keeps only its newest chunk and returns every
1343    /// older chunk to the global allocator. Runtime jet tapes routinely span
1344    /// several geometrically-grown chunks, so a bare reset would allocate
1345    /// those discarded chunks again on every row. When reset exposes that
1346    /// fragmentation, replace the empty arena once with a single chunk large
1347    /// enough for the complete prior tape. Later equal-or-smaller rows reuse
1348    /// that chunk without allocator traffic.
1349    pub fn reset(&mut self) {
1350        let high_water = self.bump.allocated_bytes();
1351        self.bump.reset();
1352        if self.bump.allocated_bytes() < high_water {
1353            self.bump = bumpalo::Bump::with_capacity(high_water);
1354        }
1355    }
1356
1357    /// Bytes currently reserved from the global allocator. A warm-reset-warm
1358    /// benchmark uses this to prove the second row requires no arena growth.
1359    #[must_use]
1360    pub fn allocated_bytes(&self) -> usize {
1361        self.bump.allocated_bytes()
1362    }
1363
1364    #[inline(always)]
1365    fn zeros(&self, len: usize) -> &mut [f64] {
1366        self.bump.alloc_slice_fill_copy(len, 0.0)
1367    }
1368
1369    /// Allocate and initialize a runtime-sized slice in the arena. Row programs
1370    /// use this for their primary-scalar arrays so those arrays share the same
1371    /// reusable workspace as derivative channels.
1372    #[inline(always)]
1373    pub fn alloc_slice_fill_with<T>(&self, len: usize, fill: impl FnMut(usize) -> T) -> &mut [T] {
1374        self.bump.alloc_slice_fill_with(len, fill)
1375    }
1376}
1377
1378impl Default for DynamicJetArena {
1379    fn default() -> Self {
1380        Self::new()
1381    }
1382}
1383
1384/// Runtime-sized packed first-order scalar: value plus arena-backed gradient.
1385#[derive(Clone, Copy, Debug)]
1386pub struct DynamicOrder1<'arena> {
1387    arena: &'arena DynamicJetArena,
1388    /// Value channel.
1389    pub v: f64,
1390    /// Gradient channel, length [`Self::dimension`].
1391    pub g: &'arena [f64],
1392}
1393
1394impl DynamicOrder1<'_> {
1395    /// Gradient channel.
1396    #[inline]
1397    #[must_use]
1398    pub fn g(&self) -> &[f64] {
1399        self.g
1400    }
1401
1402    #[inline]
1403    fn assert_compatible(&self, o: &Self) {
1404        assert_eq!(
1405            self.g.len(),
1406            o.g.len(),
1407            "dynamic first-order jet dimension mismatch"
1408        );
1409        assert!(
1410            std::ptr::eq(self.arena, o.arena),
1411            "dynamic jets belong to different arenas"
1412        );
1413    }
1414}
1415
1416impl<'arena> RuntimeJetScalar<'arena> for DynamicOrder1<'arena> {
1417    type Workspace = DynamicJetArena;
1418
1419    fn constant(c: f64, dimension: usize, arena: &'arena DynamicJetArena) -> Self {
1420        Self {
1421            arena,
1422            v: c,
1423            g: arena.zeros(dimension),
1424        }
1425    }
1426
1427    fn variable(x: f64, axis: usize, dimension: usize, arena: &'arena DynamicJetArena) -> Self {
1428        assert!(
1429            axis < dimension,
1430            "dynamic first-order jet axis out of bounds"
1431        );
1432        let g = arena_vector(arena, dimension, |i| if i == axis { 1.0 } else { 0.0 });
1433        Self { arena, v: x, g }
1434    }
1435
1436    #[inline(always)]
1437    fn constant_like(&self, c: f64) -> Self {
1438        Self {
1439            arena: self.arena,
1440            v: c,
1441            g: self.arena.zeros(self.dimension()),
1442        }
1443    }
1444
1445    #[inline(always)]
1446    fn with_value(&self, value: f64) -> Self {
1447        Self {
1448            arena: self.arena,
1449            v: value,
1450            g: self.g,
1451        }
1452    }
1453
1454    fn dimension(&self) -> usize {
1455        self.g.len()
1456    }
1457    fn value(&self) -> f64 {
1458        self.v
1459    }
1460
1461    fn add(&self, o: &Self) -> Self {
1462        self.assert_compatible(o);
1463        let g = arena_vector(self.arena, self.dimension(), |i| self.g[i] + o.g[i]);
1464        Self {
1465            arena: self.arena,
1466            v: self.v + o.v,
1467            g,
1468        }
1469    }
1470
1471    fn sub(&self, o: &Self) -> Self {
1472        self.assert_compatible(o);
1473        let g = arena_vector(self.arena, self.dimension(), |i| self.g[i] - o.g[i]);
1474        Self {
1475            arena: self.arena,
1476            v: self.v - o.v,
1477            g,
1478        }
1479    }
1480
1481    fn mul(&self, o: &Self) -> Self {
1482        self.assert_compatible(o);
1483        let g = arena_vector(self.arena, self.dimension(), |i| self.v * o.g[i] + self.g[i] * o.v);
1484        Self {
1485            arena: self.arena,
1486            v: self.v * o.v,
1487            g,
1488        }
1489    }
1490
1491    fn neg(&self) -> Self {
1492        self.scale(-1.0)
1493    }
1494
1495    fn scale(&self, s: f64) -> Self {
1496        let g = arena_vector(self.arena, self.dimension(), |i| self.g[i] * s);
1497        Self {
1498            arena: self.arena,
1499            v: self.v * s,
1500            g,
1501        }
1502    }
1503
1504    fn compose_unary(&self, d: [f64; 5]) -> Self {
1505        let g = arena_vector(self.arena, self.dimension(), |i| d[1] * self.g[i]);
1506        Self {
1507            arena: self.arena,
1508            v: d[0],
1509            g,
1510        }
1511    }
1512}
1513
1514/// Runtime-sized packed second-order scalar: value, gradient, and a row-major
1515/// Hessian. Storage is `O(K^2)` in the row's actual primary dimension and comes
1516/// from the row's reusable [`DynamicJetArena`].
1517#[derive(Clone, Copy, Debug)]
1518pub struct DynamicOrder2<'arena> {
1519    arena: &'arena DynamicJetArena,
1520    /// Value channel.
1521    pub v: f64,
1522    /// Gradient channel.
1523    pub g: &'arena [f64],
1524    /// Row-major Hessian channel.
1525    pub h: &'arena [f64],
1526}
1527
1528impl DynamicOrder2<'_> {
1529    /// Construct an arena-backed second-order scalar from channel functions.
1530    ///
1531    /// This is the allocation-free extension seam for exact projected products
1532    /// whose channel law is not ordinary scalar multiplication. Each channel is
1533    /// written directly into the row arena, so downstream runtime-jet programs
1534    /// can keep their specialized algebra without materializing temporary
1535    /// `Vec`s or exposing the arena pointer stored by [`DynamicOrder2`]. The
1536    /// Hessian function is evaluated on the upper triangle and mirrored because
1537    /// a scalar Hessian is symmetric.
1538    #[inline]
1539    #[must_use]
1540    pub fn from_channel_functions<'arena>(
1541        value: f64,
1542        dimension: usize,
1543        arena: &'arena DynamicJetArena,
1544        mut gradient: impl FnMut(usize) -> f64,
1545        mut hessian: impl FnMut(usize, usize) -> f64,
1546    ) -> DynamicOrder2<'arena> {
1547        let g = arena.alloc_slice_fill_with(dimension, |axis| gradient(axis));
1548        let h = arena.zeros(dimension * dimension);
1549        for row in 0..dimension {
1550            for column in row..dimension {
1551                let channel = hessian(row, column);
1552                h[row * dimension + column] = channel;
1553                h[column * dimension + row] = channel;
1554            }
1555        }
1556        DynamicOrder2 {
1557            arena,
1558            v: value,
1559            g,
1560            h,
1561        }
1562    }
1563
1564    /// Gradient channel.
1565    #[inline]
1566    #[must_use]
1567    pub fn g(&self) -> &[f64] {
1568        self.g
1569    }
1570
1571    /// Row-major Hessian channel.
1572    #[inline]
1573    #[must_use]
1574    pub fn h(&self) -> &[f64] {
1575        self.h
1576    }
1577
1578    #[inline(always)]
1579    fn assert_compatible(&self, o: &Self) {
1580        assert_eq!(
1581            self.g.len(),
1582            o.g.len(),
1583            "dynamic second-order jet dimension mismatch"
1584        );
1585        assert_eq!(
1586            self.h.len(),
1587            o.h.len(),
1588            "dynamic second-order jet Hessian mismatch"
1589        );
1590        assert!(
1591            std::ptr::eq(self.arena, o.arena),
1592            "dynamic jets belong to different arenas"
1593        );
1594    }
1595}
1596
1597/// Fill a fresh arena vector of `n` entries from a formula, writing every entry
1598/// exactly once.
1599///
1600/// Every jet operation below builds its result this way rather than zeroing a
1601/// buffer and overwriting it. On the flex row programs the zero pass was the
1602/// single largest cost measured (54% of samples in `memset`): each operation
1603/// writes a fresh `(1 + lanes)·(d + d²)` block of arena memory, and streaming
1604/// it twice doubles the memory traffic of the whole evaluation.
1605#[inline(always)]
1606fn arena_vector<'arena>(
1607    arena: &'arena DynamicJetArena,
1608    n: usize,
1609    entry: impl FnMut(usize) -> f64,
1610) -> &'arena mut [f64] {
1611    arena.alloc_slice_fill_with(n, entry)
1612}
1613
1614/// Fill a fresh `n × n` row-major arena matrix from a formula in `(row, column,
1615/// flat index)`, writing every entry exactly once. Every formula this file
1616/// passes is symmetric in `(row, column)`, so the full matrix is produced
1617/// directly instead of filling one triangle and mirroring it.
1618#[inline(always)]
1619fn arena_square<'arena>(
1620    arena: &'arena DynamicJetArena,
1621    n: usize,
1622    mut entry: impl FnMut(usize, usize, usize) -> f64,
1623) -> &'arena mut [f64] {
1624    let mut row = 0usize;
1625    let mut column = 0usize;
1626    arena.alloc_slice_fill_with(n * n, |index| {
1627        let value = entry(row, column, index);
1628        column += 1;
1629        if column == n {
1630            column = 0;
1631            row += 1;
1632        }
1633        value
1634    })
1635}
1636
1637impl<'arena> DynamicOrder2<'arena> {
1638    /// `Σ_k scales[k] · lefts[k] · rights[k]` in one pass over the result.
1639    ///
1640    /// The one-seed batch's epsilon lanes are sums of products of order-two
1641    /// jets; forming each product and each partial sum as its own jet would
1642    /// allocate and stream `2k − 1` intermediate blocks for a result that is
1643    /// one block.
1644    #[inline(always)]
1645    #[must_use]
1646    pub fn scaled_product_sum(scales: &[f64], lefts: &[Self], rights: &[Self]) -> Self {
1647        assert!(
1648            !lefts.is_empty() && lefts.len() == rights.len() && lefts.len() == scales.len(),
1649            "dynamic product sum needs matching non-empty term lists"
1650        );
1651        let arena = lefts[0].arena;
1652        let n = lefts[0].dimension();
1653        for (left, right) in lefts.iter().zip(rights) {
1654            left.assert_compatible(right);
1655            assert!(
1656                left.dimension() == n && std::ptr::eq(left.arena, arena),
1657                "dynamic product sum jets must share dimension and arena"
1658            );
1659        }
1660        let mut v = 0.0;
1661        for ((left, right), &scale) in lefts.iter().zip(rights).zip(scales) {
1662            v += scale * left.v * right.v;
1663        }
1664        let g = arena_vector(arena, n, |i| {
1665            let mut total = 0.0;
1666            for ((left, right), &scale) in lefts.iter().zip(rights).zip(scales) {
1667                total += scale * (left.v * right.g[i] + left.g[i] * right.v);
1668            }
1669            total
1670        });
1671        let h = arena_square(arena, n, |i, j, ij| {
1672            let mut total = 0.0;
1673            for ((left, right), &scale) in lefts.iter().zip(rights).zip(scales) {
1674                total += scale
1675                    * (left.v * right.h[ij]
1676                        + left.g[i] * right.g[j]
1677                        + left.g[j] * right.g[i]
1678                        + left.h[ij] * right.v);
1679            }
1680            total
1681        });
1682        Self { arena, v, g, h }
1683    }
1684
1685    /// `a·b + c·d + e` in one pass over the result.
1686    #[inline(always)]
1687    #[must_use]
1688    pub fn product_pair_sum_plus(a: &Self, b: &Self, c: &Self, d: &Self, e: &Self) -> Self {
1689        a.assert_compatible(b);
1690        a.assert_compatible(c);
1691        a.assert_compatible(d);
1692        a.assert_compatible(e);
1693        let arena = a.arena;
1694        let n = a.dimension();
1695        let g = arena_vector(arena, n, |i| {
1696            a.v * b.g[i] + a.g[i] * b.v + c.v * d.g[i] + c.g[i] * d.v + e.g[i]
1697        });
1698        let h = arena_square(arena, n, |i, j, ij| {
1699            a.v * b.h[ij]
1700                + a.g[i] * b.g[j]
1701                + a.g[j] * b.g[i]
1702                + a.h[ij] * b.v
1703                + c.v * d.h[ij]
1704                + c.g[i] * d.g[j]
1705                + c.g[j] * d.g[i]
1706                + c.h[ij] * d.v
1707                + e.h[ij]
1708        });
1709        Self {
1710            arena,
1711            v: a.v * b.v + c.v * d.v + e.v,
1712            g,
1713            h,
1714        }
1715    }
1716}
1717
1718impl<'arena> RuntimeJetScalar<'arena> for DynamicOrder2<'arena> {
1719    type Workspace = DynamicJetArena;
1720
1721    #[inline(always)]
1722    fn constant(c: f64, dimension: usize, arena: &'arena DynamicJetArena) -> Self {
1723        Self {
1724            arena,
1725            v: c,
1726            g: arena.zeros(dimension),
1727            h: arena.zeros(dimension * dimension),
1728        }
1729    }
1730
1731    #[inline(always)]
1732    fn variable(x: f64, axis: usize, dimension: usize, arena: &'arena DynamicJetArena) -> Self {
1733        assert!(
1734            axis < dimension,
1735            "dynamic second-order jet axis out of bounds"
1736        );
1737        let g = arena.zeros(dimension);
1738        g[axis] = 1.0;
1739        Self {
1740            arena,
1741            v: x,
1742            g,
1743            h: arena.zeros(dimension * dimension),
1744        }
1745    }
1746
1747    #[inline(always)]
1748    fn constant_like(&self, c: f64) -> Self {
1749        let dimension = self.dimension();
1750        Self {
1751            arena: self.arena,
1752            v: c,
1753            g: self.arena.zeros(dimension),
1754            h: self.arena.zeros(dimension * dimension),
1755        }
1756    }
1757
1758    #[inline(always)]
1759    fn with_value(&self, value: f64) -> Self {
1760        Self {
1761            arena: self.arena,
1762            v: value,
1763            g: self.g,
1764            h: self.h,
1765        }
1766    }
1767
1768    #[inline(always)]
1769    fn symmetric_quadratic_form<C: SymmetricQuadraticCoefficients>(
1770        inputs: &[Self],
1771        coefficients: &C,
1772        dimension: usize,
1773        arena: &'arena DynamicJetArena,
1774    ) -> Self {
1775        assert_eq!(inputs.len(), coefficients.dimension());
1776        assert!(
1777            inputs.iter().all(|input| {
1778                input.dimension() == dimension && std::ptr::eq(input.arena, arena)
1779            }),
1780            "dynamic quadratic-form jets must share dimension and arena"
1781        );
1782        let input_dimension = inputs.len();
1783        let values = arena.zeros(input_dimension);
1784        for (value, input) in values.iter_mut().zip(inputs) {
1785            *value = input.v;
1786        }
1787        let projected = arena.zeros(input_dimension);
1788        coefficients.multiply(values, projected);
1789
1790        let mut value = 0.0;
1791        for axis in 0..input_dimension {
1792            value += values[axis] * projected[axis];
1793        }
1794        let gradient = arena.zeros(dimension);
1795        for primary in 0..dimension {
1796            let mut channel = 0.0;
1797            for axis in 0..input_dimension {
1798                channel += projected[axis] * inputs[axis].g[primary];
1799            }
1800            gradient[primary] = 2.0 * channel;
1801        }
1802        let hessian = arena.zeros(dimension * dimension);
1803        let input_gradient = arena.zeros(input_dimension);
1804        let projected_gradient = arena.zeros(input_dimension);
1805        for primary_b in 0..dimension {
1806            for row in 0..input_dimension {
1807                input_gradient[row] = inputs[row].g[primary_b];
1808            }
1809            coefficients.multiply(input_gradient, projected_gradient);
1810            for primary_a in 0..=primary_b {
1811                let mut inherited = 0.0;
1812                let mut curvature = 0.0;
1813                for row in 0..input_dimension {
1814                    inherited += projected[row] * inputs[row].h[primary_a * dimension + primary_b];
1815                    curvature += inputs[row].g[primary_a] * projected_gradient[row];
1816                }
1817                let channel = 2.0 * (inherited + curvature);
1818                hessian[primary_a * dimension + primary_b] = channel;
1819                hessian[primary_b * dimension + primary_a] = channel;
1820            }
1821        }
1822        Self {
1823            arena,
1824            v: value,
1825            g: gradient,
1826            h: hessian,
1827        }
1828    }
1829
1830    #[inline(always)]
1831    fn product(&self, right: &Self) -> Self {
1832        self.mul(right)
1833    }
1834
1835    #[inline(always)]
1836    fn affine_compose(
1837        &self,
1838        input_scale: f64,
1839        input_shift: f64,
1840        derivative_stack: [f64; 5],
1841    ) -> Self {
1842        assert!(input_shift.is_finite(), "affine input shift must be finite");
1843        let arena = self.arena;
1844        let dimension = self.dimension();
1845        let first = derivative_stack[1] * input_scale;
1846        let second = derivative_stack[2] * input_scale * input_scale;
1847        let gradient = arena_vector(arena, dimension, |i| first * self.g[i]);
1848        let hessian = arena_square(arena, dimension, |i, j, ij| {
1849            first * self.h[ij] + second * self.g[i] * self.g[j]
1850        });
1851        Self {
1852            arena,
1853            v: derivative_stack[0],
1854            g: gradient,
1855            h: hessian,
1856        }
1857    }
1858
1859    #[inline(always)]
1860    fn affine_composed_sum(
1861        inputs: &[Self],
1862        input_scales: &[f64],
1863        derivative_stacks: &[[f64; 5]],
1864        dimension: usize,
1865        arena: &'arena DynamicJetArena,
1866    ) -> Self {
1867        assert_eq!(inputs.len(), input_scales.len());
1868        assert_eq!(inputs.len(), derivative_stacks.len());
1869        assert!(
1870            inputs.iter().all(|input| {
1871                input.dimension() == dimension && std::ptr::eq(input.arena, arena)
1872            }),
1873            "dynamic affine-composed-sum jets must share dimension and arena"
1874        );
1875        let mut value = 0.0;
1876        for stack in derivative_stacks {
1877            value += stack[0];
1878        }
1879        let gradient = arena_vector(arena, dimension, |i| {
1880            let mut total = 0.0;
1881            for ((input, &input_scale), stack) in
1882                inputs.iter().zip(input_scales).zip(derivative_stacks)
1883            {
1884                total += stack[1] * input_scale * input.g[i];
1885            }
1886            total
1887        });
1888        let hessian = arena_square(arena, dimension, |i, j, ij| {
1889            let mut total = 0.0;
1890            for ((input, &input_scale), stack) in
1891                inputs.iter().zip(input_scales).zip(derivative_stacks)
1892            {
1893                let first = stack[1] * input_scale;
1894                let second = stack[2] * input_scale * input_scale;
1895                total += first * input.h[ij] + second * input.g[i] * input.g[j];
1896            }
1897            total
1898        });
1899        Self {
1900            arena,
1901            v: value,
1902            g: gradient,
1903            h: hessian,
1904        }
1905    }
1906
1907    #[inline(always)]
1908    fn shared_multiply_add_affine_composed_sum<const N: usize>(
1909        lefts: &[&Self; N],
1910        right: &Self,
1911        addend: &Self,
1912        addend_scales: &[f64; N],
1913        input_scales: &[f64; N],
1914        derivative_stacks: &[[f64; 5]; N],
1915        dimension: usize,
1916        arena: &'arena DynamicJetArena,
1917    ) -> Self {
1918        assert!(
1919            lefts.iter().all(|input| {
1920                input.dimension() == dimension && std::ptr::eq(input.arena, arena)
1921            }) && (N == 0 || (right.dimension() == dimension && std::ptr::eq(right.arena, arena))),
1922            "dynamic fused product-composition jets must share dimension and arena"
1923        );
1924        let addend_live = addend_scales.iter().any(|&scale| scale != 0.0);
1925        assert!(
1926            !addend_live || (addend.dimension() == dimension && std::ptr::eq(addend.arena, arena)),
1927            "live dynamic fused addends must share dimension and arena"
1928        );
1929        let (representatives, term_sources, source_count) =
1930            canonical_shared_source_schedule::<N>(|term, representative| {
1931                std::ptr::eq(lefts[term], lefts[representative])
1932                    && addend_scales[term] == addend_scales[representative]
1933            });
1934        let (value, source_derivatives) =
1935            aggregate_shared_source_derivatives(&term_sources, input_scales, derivative_stacks);
1936        let source_gradients = arena.zeros(source_count * dimension);
1937        let gradient = arena.zeros(dimension);
1938        let hessian = arena.zeros(dimension * dimension);
1939        let mut right_first = 0.0;
1940        let mut addend_first = 0.0;
1941        for source in 0..source_count {
1942            let term = representatives[source];
1943            let first = source_derivatives[source][1];
1944            right_first += first * lefts[term].v;
1945            addend_first += first * addend_scales[term];
1946            for primary in 0..dimension {
1947                let product_gradient =
1948                    lefts[term].v * right.g[primary] + lefts[term].g[primary] * right.v;
1949                let inner_gradient = if addend_scales[term] == 0.0 {
1950                    product_gradient
1951                } else if addend_scales[term] == 1.0 {
1952                    product_gradient + addend.g[primary]
1953                } else {
1954                    product_gradient + addend_scales[term] * addend.g[primary]
1955                };
1956                source_gradients[source * dimension + primary] = inner_gradient;
1957                gradient[primary] += first * lefts[term].g[primary] * right.v;
1958            }
1959        }
1960        if N != 0 {
1961            for primary in 0..dimension {
1962                gradient[primary] += right_first * right.g[primary];
1963            }
1964        }
1965        if addend_live {
1966            for primary in 0..dimension {
1967                gradient[primary] += addend_first * addend.g[primary];
1968            }
1969        }
1970        for primary in 0..dimension {
1971            for other in primary..dimension {
1972                let index = primary * dimension + other;
1973                let mut channel = if N == 0 {
1974                    0.0
1975                } else {
1976                    right_first * right.h[index]
1977                };
1978                if addend_live {
1979                    channel += addend_first * addend.h[index];
1980                }
1981                for source in 0..source_count {
1982                    let term = representatives[source];
1983                    let local_product_hessian = lefts[term].g[primary] * right.g[other]
1984                        + lefts[term].g[other] * right.g[primary]
1985                        + lefts[term].h[index] * right.v;
1986                    channel += source_derivatives[source][1] * local_product_hessian
1987                        + source_derivatives[source][2]
1988                            * source_gradients[source * dimension + primary]
1989                            * source_gradients[source * dimension + other];
1990                }
1991                hessian[index] = channel;
1992                hessian[other * dimension + primary] = channel;
1993            }
1994        }
1995        Self {
1996            arena,
1997            v: value,
1998            g: gradient,
1999            h: hessian,
2000        }
2001    }
2002
2003    #[inline(always)]
2004    fn multiply_add(&self, right: &Self, addend: &Self) -> Self {
2005        self.assert_compatible(right);
2006        self.assert_compatible(addend);
2007        let dimension = self.dimension();
2008        let gradient = arena_vector(self.arena, dimension, |i| {
2009            self.v * right.g[i] + self.g[i] * right.v + addend.g[i]
2010        });
2011        let hessian = arena_square(self.arena, dimension, |i, j, ij| {
2012            self.v * right.h[ij]
2013                + self.g[i] * right.g[j]
2014                + self.g[j] * right.g[i]
2015                + self.h[ij] * right.v
2016                + addend.h[ij]
2017        });
2018        Self {
2019            arena: self.arena,
2020            v: self.v * right.v + addend.v,
2021            g: gradient,
2022            h: hessian,
2023        }
2024    }
2025
2026    #[inline(always)]
2027    fn composed_sum(
2028        inputs: &[Self],
2029        derivative_stacks: &[[f64; 5]],
2030        dimension: usize,
2031        arena: &'arena DynamicJetArena,
2032    ) -> Self {
2033        assert_eq!(inputs.len(), derivative_stacks.len());
2034        assert!(
2035            inputs.iter().all(|input| {
2036                input.dimension() == dimension && std::ptr::eq(input.arena, arena)
2037            }),
2038            "dynamic composed-sum jets must share dimension and arena"
2039        );
2040        let mut value = 0.0;
2041        for stack in derivative_stacks {
2042            value += stack[0];
2043        }
2044        let gradient = arena_vector(arena, dimension, |i| {
2045            let mut total = 0.0;
2046            for (input, stack) in inputs.iter().zip(derivative_stacks) {
2047                total += stack[1] * input.g[i];
2048            }
2049            total
2050        });
2051        let hessian = arena_square(arena, dimension, |i, j, ij| {
2052            let mut total = 0.0;
2053            for (input, stack) in inputs.iter().zip(derivative_stacks) {
2054                total += stack[1] * input.h[ij] + stack[2] * input.g[i] * input.g[j];
2055            }
2056            total
2057        });
2058        Self {
2059            arena,
2060            v: value,
2061            g: gradient,
2062            h: hessian,
2063        }
2064    }
2065
2066    #[inline(always)]
2067    fn linear_combination(
2068        inputs: &[Self],
2069        weights: &[f64],
2070        dimension: usize,
2071        arena: &'arena DynamicJetArena,
2072    ) -> Self {
2073        assert_eq!(inputs.len(), weights.len());
2074        assert!(
2075            inputs.iter().all(|input| {
2076                input.dimension() == dimension && std::ptr::eq(input.arena, arena)
2077            }),
2078            "dynamic linear-combination jets must share dimension and arena"
2079        );
2080        let mut value = 0.0;
2081        for (input, &weight) in inputs.iter().zip(weights) {
2082            value += input.v * weight;
2083        }
2084        let gradient = arena_vector(arena, dimension, |i| {
2085            let mut total = 0.0;
2086            for (input, &weight) in inputs.iter().zip(weights) {
2087                total += input.g[i] * weight;
2088            }
2089            total
2090        });
2091        let hessian = arena_square(arena, dimension, |_, _, ij| {
2092            let mut total = 0.0;
2093            for (input, &weight) in inputs.iter().zip(weights) {
2094                total += input.h[ij] * weight;
2095            }
2096            total
2097        });
2098        Self {
2099            arena,
2100            v: value,
2101            g: gradient,
2102            h: hessian,
2103        }
2104    }
2105
2106    #[inline(always)]
2107    fn dimension(&self) -> usize {
2108        self.g.len()
2109    }
2110
2111    #[inline(always)]
2112    fn value(&self) -> f64 {
2113        self.v
2114    }
2115
2116    #[inline(always)]
2117    fn add(&self, o: &Self) -> Self {
2118        self.assert_compatible(o);
2119        let dimension = self.dimension();
2120        let g = arena_vector(self.arena, dimension, |i| self.g[i] + o.g[i]);
2121        let h = arena_square(self.arena, dimension, |_, _, ij| self.h[ij] + o.h[ij]);
2122        Self {
2123            arena: self.arena,
2124            v: self.v + o.v,
2125            g,
2126            h,
2127        }
2128    }
2129
2130    #[inline(always)]
2131    fn sub(&self, o: &Self) -> Self {
2132        self.assert_compatible(o);
2133        let dimension = self.dimension();
2134        let g = arena_vector(self.arena, dimension, |i| self.g[i] - o.g[i]);
2135        let h = arena_square(self.arena, dimension, |_, _, ij| self.h[ij] - o.h[ij]);
2136        Self {
2137            arena: self.arena,
2138            v: self.v - o.v,
2139            g,
2140            h,
2141        }
2142    }
2143
2144    #[inline(always)]
2145    fn mul(&self, o: &Self) -> Self {
2146        self.assert_compatible(o);
2147        let n = self.dimension();
2148        let g = arena_vector(self.arena, n, |i| self.v * o.g[i] + self.g[i] * o.v);
2149        let h = arena_square(self.arena, n, |i, j, ij| {
2150            self.v * o.h[ij] + self.g[i] * o.g[j] + self.g[j] * o.g[i] + self.h[ij] * o.v
2151        });
2152        Self {
2153            arena: self.arena,
2154            v: self.v * o.v,
2155            g,
2156            h,
2157        }
2158    }
2159
2160    #[inline(always)]
2161    fn neg(&self) -> Self {
2162        self.scale(-1.0)
2163    }
2164
2165    #[inline(always)]
2166    fn scale(&self, s: f64) -> Self {
2167        let dimension = self.dimension();
2168        let g = arena_vector(self.arena, dimension, |i| self.g[i] * s);
2169        let h = arena_square(self.arena, dimension, |_, _, ij| self.h[ij] * s);
2170        Self {
2171            arena: self.arena,
2172            v: self.v * s,
2173            g,
2174            h,
2175        }
2176    }
2177
2178    #[inline(always)]
2179    fn compose_unary(&self, d: [f64; 5]) -> Self {
2180        let n = self.dimension();
2181        let g = arena_vector(self.arena, n, |i| d[1] * self.g[i]);
2182        let h = arena_square(self.arena, n, |i, j, ij| {
2183            d[1] * self.h[ij] + d[2] * self.g[i] * self.g[j]
2184        });
2185        Self {
2186            arena: self.arena,
2187            v: d[0],
2188            g,
2189            h,
2190        }
2191    }
2192
2193    /// `addend + Σ_i L_i · f_i(R)` in ONE output block.
2194    ///
2195    /// Every `f_i(R)` shares the composition point, so its channels are
2196    /// `(s0_i, s1_i·R.g, s1_i·R.h + s2_i·R.g⊗R.g)` and the product with `L_i`
2197    /// expands to
2198    ///
2199    /// ```text
2200    /// v   = Σ L_i.v·s0_i
2201    /// g_a = Σ (L_i.v·s1_i)·R.g_a + s0_i·L_i.g_a
2202    /// h_ab = Σ (L_i.v·s1_i)·R.h_ab + (L_i.v·s2_i)·R.g_a·R.g_b
2203    ///          + s1_i·(L_i.g_a·R.g_b + R.g_a·L_i.g_b) + s0_i·L_i.h_ab
2204    /// ```
2205    ///
2206    /// so the `R`-dependent coefficients collapse into two scalars, `Σ L_i.v·s1_i`
2207    /// and `Σ L_i.v·s2_i`, that multiply `R.h` and `R.g⊗R.g` ONCE. The default
2208    /// walks the same algebra through `2N` intermediate jets, each of which
2209    /// allocates and streams its own `n²` block; this writes one.
2210    #[inline]
2211    fn weighted_compose_sum(
2212        lefts: &[Self],
2213        right: &Self,
2214        derivative_stacks: &[[f64; 5]],
2215        addend: &Self,
2216    ) -> Self {
2217        assert_eq!(
2218            lefts.len(),
2219            derivative_stacks.len(),
2220            "weighted compose sum needs one derivative stack per left factor"
2221        );
2222        let arena = addend.arena;
2223        let n = addend.dimension();
2224        for left in lefts {
2225            addend.assert_compatible(left);
2226        }
2227        addend.assert_compatible(right);
2228        let mut value = addend.v;
2229        let mut right_first = 0.0;
2230        let mut right_second = 0.0;
2231        for (left, stack) in lefts.iter().zip(derivative_stacks) {
2232            value += left.v * stack[0];
2233            right_first += left.v * stack[1];
2234            right_second += left.v * stack[2];
2235        }
2236        let g = arena_vector(arena, n, |a| {
2237            let mut channel = addend.g[a] + right_first * right.g[a];
2238            for (left, stack) in lefts.iter().zip(derivative_stacks) {
2239                channel += stack[0] * left.g[a];
2240            }
2241            channel
2242        });
2243        let h = arena_square(arena, n, |a, b, ab| {
2244            let mut channel = addend.h[ab]
2245                + right_first * right.h[ab]
2246                + right_second * right.g[a] * right.g[b];
2247            for (left, stack) in lefts.iter().zip(derivative_stacks) {
2248                channel += stack[1] * (left.g[a] * right.g[b] + right.g[a] * left.g[b])
2249                    + stack[0] * left.h[ab];
2250            }
2251            channel
2252        });
2253        Self {
2254            arena,
2255            v: value,
2256            g,
2257            h,
2258        }
2259    }
2260}
2261
2262/// Runtime-sized one-seed scalar for a Hessian-contracted third derivative.
2263#[derive(Clone, Copy, Debug)]
2264pub struct DynamicOneSeed<'arena> {
2265    /// Base value/gradient/Hessian channels.
2266    pub base: DynamicOrder2<'arena>,
2267    /// Nilpotent `epsilon` coefficient.
2268    pub eps: DynamicOrder2<'arena>,
2269}
2270
2271impl<'arena> DynamicOneSeed<'arena> {
2272    /// Seed one primary with the supplied contraction direction component.
2273    #[inline(always)]
2274    #[must_use]
2275    pub fn seed_direction(
2276        x: f64,
2277        axis: usize,
2278        u_axis: f64,
2279        dimension: usize,
2280        arena: &'arena DynamicJetArena,
2281    ) -> Self {
2282        Self {
2283            base: DynamicOrder2::variable(x, axis, dimension, arena),
2284            eps: DynamicOrder2::constant(u_axis, dimension, arena),
2285        }
2286    }
2287
2288    /// Row-major contracted-third matrix.
2289    #[inline(always)]
2290    #[must_use]
2291    pub fn contracted_third(&self) -> &[f64] {
2292        self.eps.h()
2293    }
2294}
2295
2296impl<'arena> RuntimeJetScalar<'arena> for DynamicOneSeed<'arena> {
2297    type Workspace = DynamicJetArena;
2298
2299    #[inline(always)]
2300    fn constant(c: f64, dimension: usize, arena: &'arena DynamicJetArena) -> Self {
2301        Self {
2302            base: DynamicOrder2::constant(c, dimension, arena),
2303            eps: DynamicOrder2::constant(0.0, dimension, arena),
2304        }
2305    }
2306
2307    #[inline(always)]
2308    fn variable(x: f64, axis: usize, dimension: usize, arena: &'arena DynamicJetArena) -> Self {
2309        Self {
2310            base: DynamicOrder2::variable(x, axis, dimension, arena),
2311            eps: DynamicOrder2::constant(0.0, dimension, arena),
2312        }
2313    }
2314
2315    #[inline(always)]
2316    fn constant_like(&self, c: f64) -> Self {
2317        Self {
2318            base: self.base.constant_like(c),
2319            eps: self.eps.constant_like(0.0),
2320        }
2321    }
2322
2323    #[inline(always)]
2324    fn with_value(&self, value: f64) -> Self {
2325        Self {
2326            base: self.base.with_value(value),
2327            eps: self.eps,
2328        }
2329    }
2330
2331    #[inline(always)]
2332    fn dimension(&self) -> usize {
2333        self.base.dimension()
2334    }
2335
2336    #[inline(always)]
2337    fn value(&self) -> f64 {
2338        self.base.value()
2339    }
2340
2341    #[inline(always)]
2342    fn add(&self, o: &Self) -> Self {
2343        Self {
2344            base: self.base.add(&o.base),
2345            eps: self.eps.add(&o.eps),
2346        }
2347    }
2348
2349    #[inline(always)]
2350    fn sub(&self, o: &Self) -> Self {
2351        Self {
2352            base: self.base.sub(&o.base),
2353            eps: self.eps.sub(&o.eps),
2354        }
2355    }
2356
2357    #[inline(always)]
2358    fn mul(&self, o: &Self) -> Self {
2359        self.base.assert_compatible(&o.base);
2360        self.eps.assert_compatible(&o.eps);
2361        Self {
2362            base: self.base.mul(&o.base),
2363            eps: DynamicOrder2::from_channel_functions(
2364                self.base.v * o.eps.v + self.eps.v * o.base.v,
2365                self.dimension(),
2366                self.base.arena,
2367                |i| {
2368                    self.base.v * o.eps.g[i]
2369                        + self.base.g[i] * o.eps.v
2370                        + self.eps.v * o.base.g[i]
2371                        + self.eps.g[i] * o.base.v
2372                },
2373                |i, j| {
2374                    let ij = i * self.dimension() + j;
2375                    self.base.v * o.eps.h[ij]
2376                        + self.base.g[i] * o.eps.g[j]
2377                        + self.base.g[j] * o.eps.g[i]
2378                        + self.base.h[ij] * o.eps.v
2379                        + self.eps.v * o.base.h[ij]
2380                        + self.eps.g[i] * o.base.g[j]
2381                        + self.eps.g[j] * o.base.g[i]
2382                        + self.eps.h[ij] * o.base.v
2383                },
2384            ),
2385        }
2386    }
2387
2388    #[inline(always)]
2389    fn neg(&self) -> Self {
2390        Self {
2391            base: self.base.neg(),
2392            eps: self.eps.neg(),
2393        }
2394    }
2395
2396    #[inline(always)]
2397    fn scale(&self, s: f64) -> Self {
2398        Self {
2399            base: self.base.scale(s),
2400            eps: self.eps.scale(s),
2401        }
2402    }
2403
2404    #[inline(always)]
2405    fn compose_unary(&self, d: [f64; 5]) -> Self {
2406        let base = self.base.compose_unary(d);
2407        let dimension = self.dimension();
2408        let eps = DynamicOrder2::from_channel_functions(
2409            d[1] * self.eps.v,
2410            dimension,
2411            self.base.arena,
2412            |i| d[2] * self.base.g[i] * self.eps.v + d[1] * self.eps.g[i],
2413            |i, j| {
2414                let ij = i * dimension + j;
2415                d[1] * self.eps.h[ij]
2416                    + d[2]
2417                        * (self.base.g[i] * self.eps.g[j]
2418                            + self.base.g[j] * self.eps.g[i]
2419                            + self.base.h[ij] * self.eps.v)
2420                    + d[3] * self.base.g[i] * self.base.g[j] * self.eps.v
2421            },
2422        );
2423        Self { base, eps }
2424    }
2425}
2426
2427/// Reusable arena plus lane count for runtime directional batches.
2428///
2429/// A caller resets this once per row/chunk and evaluates every requested
2430/// third- or fourth-derivative contraction in one row-program pass. The bump
2431/// retains its largest chunk, so warmed rows do not return to the global
2432/// allocator.
2433#[derive(Debug)]
2434pub struct DynamicJetBatchWorkspace {
2435    arena: DynamicJetArena,
2436    lanes: usize,
2437}
2438
2439impl DynamicJetBatchWorkspace {
2440    /// Create a reusable workspace for `lanes` simultaneous directions.
2441    #[must_use]
2442    pub fn new(lanes: usize) -> Self {
2443        Self {
2444            arena: DynamicJetArena::new(),
2445            lanes,
2446        }
2447    }
2448
2449    /// Reclaim all jet storage and select the next evaluation's lane count.
2450    pub fn reset(&mut self, lanes: usize) {
2451        self.arena.reset();
2452        self.lanes = lanes;
2453    }
2454
2455    /// Bytes retained by the bump allocator after the largest evaluation.
2456    #[must_use]
2457    pub fn allocated_bytes(&self) -> usize {
2458        self.arena.allocated_bytes()
2459    }
2460
2461    /// Allocate a primary array in the same arena as every scalar channel.
2462    #[inline(always)]
2463    pub fn alloc_slice_fill_with<T>(&self, len: usize, fill: impl FnMut(usize) -> T) -> &mut [T] {
2464        self.arena.alloc_slice_fill_with(len, fill)
2465    }
2466}
2467
2468/// Runtime-sized batch of one-seed contractions sharing one order-two base.
2469///
2470/// Lane `l` is algebraically identical to a standalone [`DynamicOneSeed`]
2471/// seeded by direction `u_l`, but the value/gradient/Hessian base is evaluated
2472/// once rather than once per direction. The output lane's epsilon Hessian is
2473/// `sum_c d³f/(dx_a dx_b dx_c) u_l[c]`.
2474#[derive(Clone, Copy, Debug)]
2475pub struct DynamicOneSeedBatch<'arena> {
2476    /// Shared value/gradient/Hessian channels.
2477    pub base: DynamicOrder2<'arena>,
2478    /// One nilpotent epsilon coefficient per contraction direction.
2479    eps: &'arena [DynamicOrder2<'arena>],
2480}
2481
2482impl<'arena> DynamicOneSeedBatch<'arena> {
2483    /// Seed one primary across every direction lane.
2484    #[inline(always)]
2485    #[must_use]
2486    pub fn seed_directions(
2487        x: f64,
2488        axis: usize,
2489        dimension: usize,
2490        workspace: &'arena DynamicJetBatchWorkspace,
2491        mut direction_at: impl FnMut(usize) -> f64,
2492    ) -> Self {
2493        let eps = workspace
2494            .arena
2495            .alloc_slice_fill_with(workspace.lanes, |lane| {
2496                DynamicOrder2::constant(direction_at(lane), dimension, &workspace.arena)
2497            });
2498        Self {
2499            base: DynamicOrder2::variable(x, axis, dimension, &workspace.arena),
2500            eps,
2501        }
2502    }
2503
2504    /// Number of simultaneous contraction directions.
2505    #[inline(always)]
2506    #[must_use]
2507    pub fn lanes(&self) -> usize {
2508        self.eps.len()
2509    }
2510
2511    /// Row-major contracted-third matrix for one direction lane.
2512    #[inline(always)]
2513    #[must_use]
2514    pub fn contracted_third(&self, lane: usize) -> &[f64] {
2515        self.eps[lane].h()
2516    }
2517
2518    #[inline(always)]
2519    fn assert_compatible(&self, other: &Self) {
2520        self.base.assert_compatible(&other.base);
2521        assert_eq!(
2522            self.eps.len(),
2523            other.eps.len(),
2524            "dynamic one-seed batch lane mismatch"
2525        );
2526    }
2527}
2528
2529impl<'arena> RuntimeJetScalar<'arena> for DynamicOneSeedBatch<'arena> {
2530    type Workspace = DynamicJetBatchWorkspace;
2531
2532    #[inline(always)]
2533    fn constant(c: f64, dimension: usize, workspace: &'arena DynamicJetBatchWorkspace) -> Self {
2534        let eps = workspace.arena.alloc_slice_fill_with(workspace.lanes, |_| {
2535            DynamicOrder2::constant(0.0, dimension, &workspace.arena)
2536        });
2537        Self {
2538            base: DynamicOrder2::constant(c, dimension, &workspace.arena),
2539            eps,
2540        }
2541    }
2542
2543    #[inline(always)]
2544    fn variable(
2545        x: f64,
2546        axis: usize,
2547        dimension: usize,
2548        workspace: &'arena DynamicJetBatchWorkspace,
2549    ) -> Self {
2550        let eps = workspace.arena.alloc_slice_fill_with(workspace.lanes, |_| {
2551            DynamicOrder2::constant(0.0, dimension, &workspace.arena)
2552        });
2553        Self {
2554            base: DynamicOrder2::variable(x, axis, dimension, &workspace.arena),
2555            eps,
2556        }
2557    }
2558
2559    #[inline(always)]
2560    fn constant_like(&self, c: f64) -> Self {
2561        let eps = self
2562            .base
2563            .arena
2564            .alloc_slice_fill_with(self.lanes(), |_| self.base.constant_like(0.0));
2565        Self {
2566            base: self.base.constant_like(c),
2567            eps,
2568        }
2569    }
2570
2571    #[inline(always)]
2572    fn with_value(&self, value: f64) -> Self {
2573        Self {
2574            base: self.base.with_value(value),
2575            eps: self.eps,
2576        }
2577    }
2578
2579    #[inline(always)]
2580    fn dimension(&self) -> usize {
2581        self.base.dimension()
2582    }
2583
2584    #[inline(always)]
2585    fn value(&self) -> f64 {
2586        self.base.value()
2587    }
2588
2589    #[inline(always)]
2590    fn add(&self, other: &Self) -> Self {
2591        self.assert_compatible(other);
2592        let eps = self
2593            .base
2594            .arena
2595            .alloc_slice_fill_with(self.eps.len(), |lane| self.eps[lane].add(&other.eps[lane]));
2596        Self {
2597            base: self.base.add(&other.base),
2598            eps,
2599        }
2600    }
2601
2602    #[inline(always)]
2603    fn sub(&self, other: &Self) -> Self {
2604        self.assert_compatible(other);
2605        let eps = self
2606            .base
2607            .arena
2608            .alloc_slice_fill_with(self.eps.len(), |lane| self.eps[lane].sub(&other.eps[lane]));
2609        Self {
2610            base: self.base.sub(&other.base),
2611            eps,
2612        }
2613    }
2614
2615    #[inline(always)]
2616    fn mul(&self, other: &Self) -> Self {
2617        self.assert_compatible(other);
2618        // Lane `l` of a product is `base·ε_l' + ε_l·base'`: one block written
2619        // once, instead of two products and a sum each streaming their own.
2620        let eps = self
2621            .base
2622            .arena
2623            .alloc_slice_fill_with(self.eps.len(), |lane| {
2624                DynamicOrder2::scaled_product_sum(
2625                    &[1.0, 1.0],
2626                    &[self.base, self.eps[lane]],
2627                    &[other.eps[lane], other.base],
2628                )
2629            });
2630        Self {
2631            base: self.base.mul(&other.base),
2632            eps,
2633        }
2634    }
2635
2636    /// `addend + Σ_i L_i · f_i(R)` with ONE shared composition point, lane by
2637    /// lane, on top of the base type's fused form.
2638    ///
2639    /// The nilpotent part of `f_i(R)` is `f_i'(R.base)·R.eps_l`, so lane `l` is
2640    ///
2641    /// ```text
2642    /// addend.eps_l + Σ_i L_i.base·f_i'(R.base)·R.eps_l + Σ_i L_i.eps_l·f_i(R.base)
2643    ///              = R.eps_l · [Σ_i L_i.base·f_i'(R.base)]  +  Σ_i L_i.eps_l·f_i(R.base)
2644    /// ```
2645    ///
2646    /// and BOTH bracketed sums are the base type's `weighted_compose_sum` at the
2647    /// same point `R.base` — the first with the derivative stacks shifted by one,
2648    /// the second with the stacks themselves. The first does not depend on the
2649    /// lane, so it is formed once for the whole batch. The loop this replaces
2650    /// wrote `2N` blocks in EVERY lane and in the base; this writes two shared
2651    /// blocks plus three per lane (gam#979).
2652    #[inline]
2653    fn weighted_compose_sum(
2654        lefts: &[Self],
2655        right: &Self,
2656        derivative_stacks: &[[f64; 5]],
2657        addend: &Self,
2658    ) -> Self {
2659        assert_eq!(
2660            lefts.len(),
2661            derivative_stacks.len(),
2662            "weighted compose sum needs one derivative stack per left factor"
2663        );
2664        for left in lefts {
2665            addend.assert_compatible(left);
2666        }
2667        addend.assert_compatible(right);
2668        let arena = addend.base.arena;
2669        let terms = lefts.len();
2670        let left_bases: &[DynamicOrder2<'arena>] =
2671            arena.alloc_slice_fill_with(terms, |term| lefts[term].base);
2672        // `f'` carries the stack shifted by one, exactly as the composed-sum
2673        // lowering above derives a lane's multiplier jet.
2674        let shifted: &[[f64; 5]] = arena.alloc_slice_fill_with(terms, |term| {
2675            let stack = derivative_stacks[term];
2676            [stack[1], stack[2], stack[3], stack[4], stack[4]]
2677        });
2678        let zero = addend.base.constant_like(0.0);
2679        // Lane-independent: `Σ_i L_i.base · f_i'(R.base)`, formed once.
2680        let derivative_sum =
2681            DynamicOrder2::weighted_compose_sum(left_bases, &right.base, shifted, &zero);
2682        let eps = arena.alloc_slice_fill_with(addend.eps.len(), |lane| {
2683            let left_eps: &[DynamicOrder2<'arena>] =
2684                arena.alloc_slice_fill_with(terms, |term| lefts[term].eps[lane]);
2685            let carried = DynamicOrder2::weighted_compose_sum(
2686                left_eps,
2687                &right.base,
2688                derivative_stacks,
2689                &addend.eps[lane],
2690            );
2691            derivative_sum.multiply_add(&right.eps[lane], &carried)
2692        });
2693        Self {
2694            base: DynamicOrder2::weighted_compose_sum(
2695                left_bases,
2696                &right.base,
2697                derivative_stacks,
2698                &addend.base,
2699            ),
2700            eps,
2701        }
2702    }
2703
2704    #[inline(always)]
2705    fn multiply_add(&self, right: &Self, addend: &Self) -> Self {
2706        self.assert_compatible(right);
2707        self.assert_compatible(addend);
2708        let eps = self
2709            .base
2710            .arena
2711            .alloc_slice_fill_with(self.eps.len(), |lane| {
2712                DynamicOrder2::product_pair_sum_plus(
2713                    &self.base,
2714                    &right.eps[lane],
2715                    &self.eps[lane],
2716                    &right.base,
2717                    &addend.eps[lane],
2718                )
2719            });
2720        Self {
2721            base: self.base.multiply_add(&right.base, &addend.base),
2722            eps,
2723        }
2724    }
2725
2726    #[inline(always)]
2727    fn linear_combination(
2728        inputs: &[Self],
2729        weights: &[f64],
2730        dimension: usize,
2731        workspace: &'arena DynamicJetBatchWorkspace,
2732    ) -> Self {
2733        assert_eq!(inputs.len(), weights.len());
2734        // An empty combination is the zero jet, which is what the generic
2735        // default's fold over no terms returns; the fused body below needs a
2736        // term to read its arena and lane count from.
2737        if inputs.is_empty() {
2738            return Self::constant(0.0, dimension, workspace);
2739        }
2740        let lanes = workspace.lanes;
2741        assert!(
2742            inputs
2743                .iter()
2744                .all(|input| input.eps.len() == lanes && input.dimension() == dimension),
2745            "dynamic one-seed linear-combination jets must share lanes and dimension"
2746        );
2747        let arena = &workspace.arena;
2748        let bases: &[DynamicOrder2<'arena>] =
2749            arena.alloc_slice_fill_with(inputs.len(), |term| inputs[term].base);
2750        let eps = arena.alloc_slice_fill_with(lanes, |lane| {
2751            let lane_inputs: &[DynamicOrder2<'arena>] =
2752                arena.alloc_slice_fill_with(inputs.len(), |term| inputs[term].eps[lane]);
2753            DynamicOrder2::linear_combination(lane_inputs, weights, dimension, arena)
2754        });
2755        Self {
2756            base: DynamicOrder2::linear_combination(bases, weights, dimension, arena),
2757            eps,
2758        }
2759    }
2760
2761    #[inline(always)]
2762    fn affine_composed_sum(
2763        inputs: &[Self],
2764        input_scales: &[f64],
2765        derivative_stacks: &[[f64; 5]],
2766        dimension: usize,
2767        workspace: &'arena DynamicJetBatchWorkspace,
2768    ) -> Self {
2769        assert_eq!(inputs.len(), input_scales.len());
2770        assert_eq!(inputs.len(), derivative_stacks.len());
2771        // Same as above: a sum over no terms is the zero jet.
2772        if inputs.is_empty() {
2773            return Self::constant(0.0, dimension, workspace);
2774        }
2775        let lanes = workspace.lanes;
2776        assert!(
2777            inputs
2778                .iter()
2779                .all(|input| input.eps.len() == lanes && input.dimension() == dimension),
2780            "dynamic one-seed composed-sum jets must share lanes and dimension"
2781        );
2782        let arena = &workspace.arena;
2783        let bases: &[DynamicOrder2<'arena>] =
2784            arena.alloc_slice_fill_with(inputs.len(), |term| inputs[term].base);
2785        // `f_k(s_k x + c_k)` moves lane `l` by `f_k'(·)·s_k·ε_l`: the derivative
2786        // jets, with the input scale folded into their stacks, are shared by
2787        // every lane and each lane is one scaled product sum.
2788        let fprimes: &[DynamicOrder2<'arena>] = arena.alloc_slice_fill_with(inputs.len(), |term| {
2789            let scale = input_scales[term];
2790            let stack = derivative_stacks[term];
2791            inputs[term].base.compose_unary([
2792                stack[1] * scale,
2793                stack[2] * scale * scale,
2794                stack[3] * scale * scale * scale,
2795                stack[4] * scale * scale * scale * scale,
2796                stack[4] * scale * scale * scale * scale,
2797            ])
2798        });
2799        let ones: &[f64] = arena.alloc_slice_fill_with(inputs.len(), |_| 1.0);
2800        let eps = arena.alloc_slice_fill_with(lanes, |lane| {
2801            let lane_inputs: &[DynamicOrder2<'arena>] =
2802                arena.alloc_slice_fill_with(inputs.len(), |term| inputs[term].eps[lane]);
2803            DynamicOrder2::scaled_product_sum(ones, fprimes, lane_inputs)
2804        });
2805        Self {
2806            base: DynamicOrder2::affine_composed_sum(
2807                bases,
2808                input_scales,
2809                derivative_stacks,
2810                dimension,
2811                arena,
2812            ),
2813            eps,
2814        }
2815    }
2816
2817    #[inline(always)]
2818    fn neg(&self) -> Self {
2819        self.scale(-1.0)
2820    }
2821
2822    #[inline(always)]
2823    fn scale(&self, scale: f64) -> Self {
2824        let eps = self
2825            .base
2826            .arena
2827            .alloc_slice_fill_with(self.eps.len(), |lane| self.eps[lane].scale(scale));
2828        Self {
2829            base: self.base.scale(scale),
2830            eps,
2831        }
2832    }
2833
2834    #[inline(always)]
2835    fn compose_unary(&self, derivatives: [f64; 5]) -> Self {
2836        let fprime = self.base.compose_unary([
2837            derivatives[1],
2838            derivatives[2],
2839            derivatives[3],
2840            derivatives[4],
2841            derivatives[4],
2842        ]);
2843        let eps = self
2844            .base
2845            .arena
2846            .alloc_slice_fill_with(self.eps.len(), |lane| fprime.mul(&self.eps[lane]));
2847        Self {
2848            base: self.base.compose_unary(derivatives),
2849            eps,
2850        }
2851    }
2852}
2853
2854/// Runtime-sized batch of two-seed contractions sharing one order-two base.
2855///
2856/// Lane `l` is algebraically identical to a standalone [`DynamicTwoSeed`]
2857/// seeded by the direction pair `(u_l, v_l)`, while the base row expression is
2858/// traversed once for the entire pair batch. Storage is `O(lanes * K^2)`; no
2859/// dense fourth-order tensor is formed.
2860#[derive(Clone, Copy, Debug)]
2861pub struct DynamicTwoSeedBatch<'arena> {
2862    /// Shared value/gradient/Hessian channels.
2863    pub base: DynamicOrder2<'arena>,
2864    eps: &'arena [DynamicOrder2<'arena>],
2865    del: &'arena [DynamicOrder2<'arena>],
2866    eps_del: &'arena [DynamicOrder2<'arena>],
2867}
2868
2869impl<'arena> DynamicTwoSeedBatch<'arena> {
2870    /// Seed one primary across every direction-pair lane.
2871    #[inline(always)]
2872    #[must_use]
2873    pub fn seed_direction_pairs(
2874        x: f64,
2875        axis: usize,
2876        dimension: usize,
2877        workspace: &'arena DynamicJetBatchWorkspace,
2878        mut direction_pair_at: impl FnMut(usize) -> (f64, f64),
2879    ) -> Self {
2880        let directions = workspace
2881            .arena
2882            .alloc_slice_fill_with(workspace.lanes, |lane| direction_pair_at(lane));
2883        let eps = workspace
2884            .arena
2885            .alloc_slice_fill_with(workspace.lanes, |lane| {
2886                DynamicOrder2::constant(directions[lane].0, dimension, &workspace.arena)
2887            });
2888        let del = workspace
2889            .arena
2890            .alloc_slice_fill_with(workspace.lanes, |lane| {
2891                DynamicOrder2::constant(directions[lane].1, dimension, &workspace.arena)
2892            });
2893        let eps_del = workspace.arena.alloc_slice_fill_with(workspace.lanes, |_| {
2894            DynamicOrder2::constant(0.0, dimension, &workspace.arena)
2895        });
2896        Self {
2897            base: DynamicOrder2::variable(x, axis, dimension, &workspace.arena),
2898            eps,
2899            del,
2900            eps_del,
2901        }
2902    }
2903
2904    /// Number of simultaneous contraction pairs.
2905    #[inline(always)]
2906    #[must_use]
2907    pub fn lanes(&self) -> usize {
2908        self.eps.len()
2909    }
2910
2911    /// Row-major contracted-fourth matrix for one direction-pair lane.
2912    #[inline(always)]
2913    #[must_use]
2914    pub fn contracted_fourth(&self, lane: usize) -> &[f64] {
2915        self.eps_del[lane].h()
2916    }
2917
2918    #[inline(always)]
2919    fn assert_compatible(&self, other: &Self) {
2920        self.base.assert_compatible(&other.base);
2921        assert_eq!(
2922            self.eps.len(),
2923            other.eps.len(),
2924            "dynamic two-seed batch lane mismatch"
2925        );
2926        assert_eq!(
2927            self.del.len(),
2928            self.eps.len(),
2929            "dynamic two-seed batch delta mismatch"
2930        );
2931        assert_eq!(
2932            self.eps_del.len(),
2933            self.eps.len(),
2934            "dynamic two-seed batch cross mismatch"
2935        );
2936    }
2937}
2938
2939impl<'arena> RuntimeJetScalar<'arena> for DynamicTwoSeedBatch<'arena> {
2940    type Workspace = DynamicJetBatchWorkspace;
2941
2942    #[inline(always)]
2943    fn constant(c: f64, dimension: usize, workspace: &'arena Self::Workspace) -> Self {
2944        let zero = workspace.arena.alloc_slice_fill_with(workspace.lanes, |_| {
2945            DynamicOrder2::constant(0.0, dimension, &workspace.arena)
2946        });
2947        Self {
2948            base: DynamicOrder2::constant(c, dimension, &workspace.arena),
2949            eps: zero,
2950            del: zero,
2951            eps_del: zero,
2952        }
2953    }
2954
2955    #[inline(always)]
2956    fn variable(x: f64, axis: usize, dimension: usize, workspace: &'arena Self::Workspace) -> Self {
2957        let zero = workspace.arena.alloc_slice_fill_with(workspace.lanes, |_| {
2958            DynamicOrder2::constant(0.0, dimension, &workspace.arena)
2959        });
2960        Self {
2961            base: DynamicOrder2::variable(x, axis, dimension, &workspace.arena),
2962            eps: zero,
2963            del: zero,
2964            eps_del: zero,
2965        }
2966    }
2967
2968    #[inline(always)]
2969    fn constant_like(&self, c: f64) -> Self {
2970        let zero = self
2971            .base
2972            .arena
2973            .alloc_slice_fill_with(self.lanes(), |_| self.base.constant_like(0.0));
2974        Self {
2975            base: self.base.constant_like(c),
2976            eps: zero,
2977            del: zero,
2978            eps_del: zero,
2979        }
2980    }
2981
2982    #[inline(always)]
2983    fn with_value(&self, value: f64) -> Self {
2984        Self {
2985            base: self.base.with_value(value),
2986            eps: self.eps,
2987            del: self.del,
2988            eps_del: self.eps_del,
2989        }
2990    }
2991
2992    #[inline(always)]
2993    fn dimension(&self) -> usize {
2994        self.base.dimension()
2995    }
2996
2997    #[inline(always)]
2998    fn value(&self) -> f64 {
2999        self.base.value()
3000    }
3001
3002    #[inline(always)]
3003    fn add(&self, other: &Self) -> Self {
3004        self.assert_compatible(other);
3005        let arena = self.base.arena;
3006        let eps =
3007            arena.alloc_slice_fill_with(self.lanes(), |lane| self.eps[lane].add(&other.eps[lane]));
3008        let del =
3009            arena.alloc_slice_fill_with(self.lanes(), |lane| self.del[lane].add(&other.del[lane]));
3010        let eps_del = arena.alloc_slice_fill_with(self.lanes(), |lane| {
3011            self.eps_del[lane].add(&other.eps_del[lane])
3012        });
3013        Self {
3014            base: self.base.add(&other.base),
3015            eps,
3016            del,
3017            eps_del,
3018        }
3019    }
3020
3021    #[inline(always)]
3022    fn sub(&self, other: &Self) -> Self {
3023        self.assert_compatible(other);
3024        let arena = self.base.arena;
3025        let eps =
3026            arena.alloc_slice_fill_with(self.lanes(), |lane| self.eps[lane].sub(&other.eps[lane]));
3027        let del =
3028            arena.alloc_slice_fill_with(self.lanes(), |lane| self.del[lane].sub(&other.del[lane]));
3029        let eps_del = arena.alloc_slice_fill_with(self.lanes(), |lane| {
3030            self.eps_del[lane].sub(&other.eps_del[lane])
3031        });
3032        Self {
3033            base: self.base.sub(&other.base),
3034            eps,
3035            del,
3036            eps_del,
3037        }
3038    }
3039
3040    #[inline(always)]
3041    fn mul(&self, other: &Self) -> Self {
3042        self.assert_compatible(other);
3043        let arena = self.base.arena;
3044        let eps = arena.alloc_slice_fill_with(self.lanes(), |lane| {
3045            self.base
3046                .mul(&other.eps[lane])
3047                .add(&self.eps[lane].mul(&other.base))
3048        });
3049        let del = arena.alloc_slice_fill_with(self.lanes(), |lane| {
3050            self.base
3051                .mul(&other.del[lane])
3052                .add(&self.del[lane].mul(&other.base))
3053        });
3054        let eps_del = arena.alloc_slice_fill_with(self.lanes(), |lane| {
3055            self.base
3056                .mul(&other.eps_del[lane])
3057                .add(&self.eps[lane].mul(&other.del[lane]))
3058                .add(&self.del[lane].mul(&other.eps[lane]))
3059                .add(&self.eps_del[lane].mul(&other.base))
3060        });
3061        Self {
3062            base: self.base.mul(&other.base),
3063            eps,
3064            del,
3065            eps_del,
3066        }
3067    }
3068
3069    #[inline(always)]
3070    fn neg(&self) -> Self {
3071        self.scale(-1.0)
3072    }
3073
3074    #[inline(always)]
3075    fn scale(&self, scale: f64) -> Self {
3076        let arena = self.base.arena;
3077        let eps = arena.alloc_slice_fill_with(self.lanes(), |lane| self.eps[lane].scale(scale));
3078        let del = arena.alloc_slice_fill_with(self.lanes(), |lane| self.del[lane].scale(scale));
3079        let eps_del =
3080            arena.alloc_slice_fill_with(self.lanes(), |lane| self.eps_del[lane].scale(scale));
3081        Self {
3082            base: self.base.scale(scale),
3083            eps,
3084            del,
3085            eps_del,
3086        }
3087    }
3088
3089    #[inline(always)]
3090    fn compose_unary(&self, derivatives: [f64; 5]) -> Self {
3091        let arena = self.base.arena;
3092        let fprime = self.base.compose_unary([
3093            derivatives[1],
3094            derivatives[2],
3095            derivatives[3],
3096            derivatives[4],
3097            derivatives[4],
3098        ]);
3099        let fsecond = self.base.compose_unary([
3100            derivatives[2],
3101            derivatives[3],
3102            derivatives[4],
3103            derivatives[4],
3104            derivatives[4],
3105        ]);
3106        let eps = arena.alloc_slice_fill_with(self.lanes(), |lane| fprime.mul(&self.eps[lane]));
3107        let del = arena.alloc_slice_fill_with(self.lanes(), |lane| fprime.mul(&self.del[lane]));
3108        let eps_del = arena.alloc_slice_fill_with(self.lanes(), |lane| {
3109            fsecond
3110                .mul(&self.eps[lane])
3111                .mul(&self.del[lane])
3112                .add(&fprime.mul(&self.eps_del[lane]))
3113        });
3114        Self {
3115            base: self.base.compose_unary(derivatives),
3116            eps,
3117            del,
3118            eps_del,
3119        }
3120    }
3121}
3122
3123/// Runtime-sized two-seed scalar for a Hessian-contracted fourth derivative.
3124#[derive(Clone, Copy, Debug)]
3125pub struct DynamicTwoSeed<'arena> {
3126    /// Base value/gradient/Hessian channels.
3127    pub base: DynamicOrder2<'arena>,
3128    /// Nilpotent `epsilon` coefficient.
3129    pub eps: DynamicOrder2<'arena>,
3130    /// Nilpotent `delta` coefficient.
3131    pub del: DynamicOrder2<'arena>,
3132    /// Mixed `epsilon delta` coefficient.
3133    pub eps_del: DynamicOrder2<'arena>,
3134}
3135
3136impl<'arena> DynamicTwoSeed<'arena> {
3137    /// Seed one primary with both contraction direction components.
3138    #[inline(always)]
3139    #[must_use]
3140    pub fn seed(
3141        x: f64,
3142        axis: usize,
3143        u_axis: f64,
3144        v_axis: f64,
3145        dimension: usize,
3146        arena: &'arena DynamicJetArena,
3147    ) -> Self {
3148        Self {
3149            base: DynamicOrder2::variable(x, axis, dimension, arena),
3150            eps: DynamicOrder2::constant(u_axis, dimension, arena),
3151            del: DynamicOrder2::constant(v_axis, dimension, arena),
3152            eps_del: DynamicOrder2::constant(0.0, dimension, arena),
3153        }
3154    }
3155
3156    /// Row-major contracted-fourth matrix.
3157    #[inline(always)]
3158    #[must_use]
3159    pub fn contracted_fourth(&self) -> &[f64] {
3160        self.eps_del.h()
3161    }
3162}
3163
3164impl<'arena> RuntimeJetScalar<'arena> for DynamicTwoSeed<'arena> {
3165    type Workspace = DynamicJetArena;
3166
3167    #[inline(always)]
3168    fn constant(c: f64, dimension: usize, arena: &'arena DynamicJetArena) -> Self {
3169        Self {
3170            base: DynamicOrder2::constant(c, dimension, arena),
3171            eps: DynamicOrder2::constant(0.0, dimension, arena),
3172            del: DynamicOrder2::constant(0.0, dimension, arena),
3173            eps_del: DynamicOrder2::constant(0.0, dimension, arena),
3174        }
3175    }
3176
3177    #[inline(always)]
3178    fn variable(x: f64, axis: usize, dimension: usize, arena: &'arena DynamicJetArena) -> Self {
3179        Self {
3180            base: DynamicOrder2::variable(x, axis, dimension, arena),
3181            eps: DynamicOrder2::constant(0.0, dimension, arena),
3182            del: DynamicOrder2::constant(0.0, dimension, arena),
3183            eps_del: DynamicOrder2::constant(0.0, dimension, arena),
3184        }
3185    }
3186
3187    #[inline(always)]
3188    fn constant_like(&self, c: f64) -> Self {
3189        Self {
3190            base: self.base.constant_like(c),
3191            eps: self.eps.constant_like(0.0),
3192            del: self.del.constant_like(0.0),
3193            eps_del: self.eps_del.constant_like(0.0),
3194        }
3195    }
3196
3197    #[inline(always)]
3198    fn with_value(&self, value: f64) -> Self {
3199        Self {
3200            base: self.base.with_value(value),
3201            eps: self.eps,
3202            del: self.del,
3203            eps_del: self.eps_del,
3204        }
3205    }
3206
3207    #[inline(always)]
3208    fn dimension(&self) -> usize {
3209        self.base.dimension()
3210    }
3211
3212    #[inline(always)]
3213    fn value(&self) -> f64 {
3214        self.base.value()
3215    }
3216
3217    #[inline(always)]
3218    fn add(&self, o: &Self) -> Self {
3219        Self {
3220            base: self.base.add(&o.base),
3221            eps: self.eps.add(&o.eps),
3222            del: self.del.add(&o.del),
3223            eps_del: self.eps_del.add(&o.eps_del),
3224        }
3225    }
3226
3227    #[inline(always)]
3228    fn sub(&self, o: &Self) -> Self {
3229        Self {
3230            base: self.base.sub(&o.base),
3231            eps: self.eps.sub(&o.eps),
3232            del: self.del.sub(&o.del),
3233            eps_del: self.eps_del.sub(&o.eps_del),
3234        }
3235    }
3236
3237    #[inline(always)]
3238    fn mul(&self, o: &Self) -> Self {
3239        let base = self.base.mul(&o.base);
3240        let eps = self.base.mul(&o.eps).add(&self.eps.mul(&o.base));
3241        let del = self.base.mul(&o.del).add(&self.del.mul(&o.base));
3242        let eps_del = self
3243            .base
3244            .mul(&o.eps_del)
3245            .add(&self.eps.mul(&o.del))
3246            .add(&self.del.mul(&o.eps))
3247            .add(&self.eps_del.mul(&o.base));
3248        Self {
3249            base,
3250            eps,
3251            del,
3252            eps_del,
3253        }
3254    }
3255
3256    #[inline(always)]
3257    fn neg(&self) -> Self {
3258        Self {
3259            base: self.base.neg(),
3260            eps: self.eps.neg(),
3261            del: self.del.neg(),
3262            eps_del: self.eps_del.neg(),
3263        }
3264    }
3265
3266    #[inline(always)]
3267    fn scale(&self, s: f64) -> Self {
3268        Self {
3269            base: self.base.scale(s),
3270            eps: self.eps.scale(s),
3271            del: self.del.scale(s),
3272            eps_del: self.eps_del.scale(s),
3273        }
3274    }
3275
3276    #[inline(always)]
3277    fn compose_unary(&self, d: [f64; 5]) -> Self {
3278        let base = self.base.compose_unary(d);
3279        let fprime = self.base.compose_unary([d[1], d[2], d[3], d[4], d[4]]);
3280        let fsecond = self.base.compose_unary([d[2], d[3], d[4], d[4], d[4]]);
3281        let eps = fprime.mul(&self.eps);
3282        let del = fprime.mul(&self.del);
3283        let eps_del = fsecond
3284            .mul(&self.eps)
3285            .mul(&self.del)
3286            .add(&fprime.mul(&self.eps_del));
3287        Self {
3288            base,
3289            eps,
3290            del,
3291            eps_del,
3292        }
3293    }
3294}
3295
3296// ── Order2<K> ergonomic operator overloads (doc §A.1) ───────────────────
3297//
3298// The dispersion-family row NLLs are written with `+`/`-`/`*` operators over
3299// the primaries (mirroring how they read as `Tower4` expressions). These
3300// delegate channel-for-channel to the inner `Tower2` arithmetic (which has
3301// `Add`/`Mul`; `Sub`/`Neg` are expressed as `+ (-1)·rhs` exactly as the
3302// `crate::nested_dual::JetField::sub` / `crate::nested_dual::JetField::neg` impls do), so an `Order2` expression is
3303// bit-identical to the same `Tower4` expression's order-≤2 channels.
3304
3305impl<const K: usize> std::ops::Add for Order2<K> {
3306    type Output = Self;
3307    #[inline]
3308    fn add(self, o: Self) -> Self {
3309        Order2(self.0 + o.0)
3310    }
3311}
3312
3313impl<const K: usize> std::ops::Add<f64> for Order2<K> {
3314    type Output = Self;
3315    #[inline]
3316    fn add(self, c: f64) -> Self {
3317        Order2(self.0 + c)
3318    }
3319}
3320
3321impl<const K: usize> std::ops::Sub for Order2<K> {
3322    type Output = Self;
3323    #[inline]
3324    fn sub(self, o: Self) -> Self {
3325        Order2(self.0 + o.0.scale(-1.0))
3326    }
3327}
3328
3329impl<const K: usize> std::ops::Sub<f64> for Order2<K> {
3330    type Output = Self;
3331    #[inline]
3332    fn sub(self, c: f64) -> Self {
3333        Order2(self.0 + (-c))
3334    }
3335}
3336
3337impl<const K: usize> std::ops::Mul for Order2<K> {
3338    type Output = Self;
3339    #[inline]
3340    fn mul(self, o: Self) -> Self {
3341        Order2(crate::jet_tower::Tower2::mul(&self.0, &o.0))
3342    }
3343}
3344
3345impl<const K: usize> std::ops::Mul<f64> for Order2<K> {
3346    type Output = Self;
3347    #[inline]
3348    fn mul(self, c: f64) -> Self {
3349        Order2(self.0.scale(c))
3350    }
3351}
3352
3353impl<const K: usize> std::ops::Neg for Order2<K> {
3354    type Output = Self;
3355    #[inline]
3356    fn neg(self) -> Self {
3357        Order2(self.0.scale(-1.0))
3358    }
3359}
3360
3361/// Filtered Hensel lift of a SCALAR implicit state `a(θ)` defined by the
3362/// constraint `F(a, θ) = 0`, evaluated in ANY [`JetScalar`] algebra `S` (doc
3363/// §11, "A generic implicit-lift operator for every production scalar").
3364///
3365/// This is the perf-respecting alternative to lifting through a dense
3366/// `Tower4<K+1>` (which carries the implicit variable as an extra dense axis):
3367/// the state `a` lives directly in the consumer's own `K`-primary algebra
3368/// `S` — `Order2<K>` for value/gradient/Hessian, `Tower4<K>` for the full
3369/// `t3`/`t4` — never paying for an extra variable.
3370///
3371/// **Method.** Fixed-Jacobian Newton in the nilpotent algebra. By the
3372/// filtered-lift theorem (doc §11.1), if `F_a := ∂F/∂a(a₀, θ₀)` is the primal
3373/// Jacobian at the base point and `inv_fa = 1/F_a`, then the iteration
3374/// `A ← A − inv_fa · F(A, θ)` raises the filtration degree of the residual by
3375/// at least one per step: each step kills exactly one graded layer. Starting
3376/// from `A = const(a₀)` (whose residual lies in `F¹` because `θ − θ₀ ∈ 𝔫`),
3377/// `iters` equal to the algebra's nilpotency order returns the *exact* lifted
3378/// jet (`Order2`: 2, `OneSeed`: 3, `Tower4`/`TwoSeed`: 4). The value channel of
3379/// `A` never moves — `F(A, θ).value() = F(a₀, θ₀) = 0` at the certified root —
3380/// so a caller may precompute every primitive's derivative stack at the fixed
3381/// base index once and let the cheap polynomial composition repeat per step.
3382///
3383/// `f` evaluates the constraint `F(a, θ)` in `S` (capturing the seeded
3384/// parameter jets `θ`); `a0` is the certified scalar root `F(a₀, θ₀) ≈ 0`.
3385pub fn filtered_implicit_solve_scalar<const K: usize, S: JetScalar<K>>(
3386    a0: f64,
3387    inv_fa: f64,
3388    iters: usize,
3389    f: impl Fn(&S) -> S,
3390) -> S {
3391    let mut a = S::constant(a0);
3392    for _ in 0..iters {
3393        let residual = f(&a);
3394        a = a.sub(&residual.scale(inv_fa));
3395    }
3396    a
3397}
3398
3399// ── PatternedOrder2<P, K, H>: compile-time sparse Hessian ───────────────
3400
3401/// Runtime-dimension form of [`filtered_implicit_solve_scalar`].
3402///
3403/// The state is lifted directly in the caller's [`RuntimeJetScalar`] algebra,
3404/// so one row expression can serve a runtime-sized value/gradient/Hessian
3405/// evaluation (`DynamicOrder2`), a Hessian-contracted third derivative
3406/// (`DynamicOneSeed`), and a Hessian-contracted fourth derivative
3407/// (`DynamicTwoSeed`). `iters` is the algebra's nilpotency order: two, three,
3408/// and four respectively. No implicit axis is appended to the derivative
3409/// storage.
3410pub fn filtered_implicit_solve_runtime_scalar<'arena, S: RuntimeJetScalar<'arena>>(
3411    a0: f64,
3412    inv_fa: f64,
3413    iters: usize,
3414    dimension: usize,
3415    workspace: &'arena S::Workspace,
3416    f: impl Fn(&S) -> S,
3417) -> S {
3418    let mut a = S::constant(a0, dimension, workspace);
3419    for _ in 0..iters {
3420        let residual = f(&a);
3421        a = a.sub(&residual.scale(inv_fa));
3422    }
3423    a
3424}
3425
3426/// Compile-time upper-triangle Hessian pattern for [`PatternedOrder2`].
3427///
3428/// `PAIRS` contains exactly the `(row, column)` channels a row program can
3429/// produce, with `row <= column`.  Pointwise Taylor algebra never couples one
3430/// Hessian pair through another: output `H[i,j]` depends only on the two input
3431/// `H[i,j]` channels and their `g[i]`/`g[j]` channels.  It is therefore exact to
3432/// omit structurally impossible pairs rather than multiplying their zeros.
3433pub trait HessianPattern<const K: usize, const H: usize> {
3434    const PAIRS: [(usize, usize); H];
3435    const PAIR_BITS: [[u128; K]; K];
3436}
3437
3438/// Build the symmetric axis-pair → patterned-slot lookup used by dependency
3439/// propagation in [`PatternedOrder2`].
3440pub const fn hessian_pair_bits<const K: usize, const H: usize>(
3441    pairs: [(usize, usize); H],
3442) -> [[u128; K]; K] {
3443    let mut table = [[0u128; K]; K];
3444    let mut slot = 0;
3445    while slot < H {
3446        let (i, j) = pairs[slot];
3447        let bit = 1u128 << slot;
3448        table[i][j] = bit;
3449        table[j][i] = bit;
3450        slot += 1;
3451    }
3452    table
3453}
3454
3455/// Exact order-two jet with a dense gradient and a compile-time patterned
3456/// upper-triangle Hessian.
3457///
3458/// This carries `1 + K + H` scalars instead of `1 + K + K²`.  Its arithmetic is
3459/// the same Leibniz/Faà-di-Bruno algebra as [`Order2`], evaluated only for the
3460/// Hessian pairs declared by `P`.  A family row NLL remains written once over
3461/// [`JetScalar`]; the pattern is an execution schedule, not a second derivative
3462/// formula.
3463#[derive(Debug)]
3464pub struct PatternedOrder2<P, const K: usize, const H: usize> {
3465    v: f64,
3466    g: [f64; K],
3467    h: [f64; H],
3468    gradient_mask: u128,
3469    hessian_mask: u128,
3470    pattern: std::marker::PhantomData<fn() -> P>,
3471}
3472
3473impl<P, const K: usize, const H: usize> Copy for PatternedOrder2<P, K, H> {}
3474
3475impl<P, const K: usize, const H: usize> Clone for PatternedOrder2<P, K, H> {
3476    fn clone(&self) -> Self {
3477        *self
3478    }
3479}
3480
3481impl<P, const K: usize, const H: usize> PatternedOrder2<P, K, H>
3482where
3483    P: HessianPattern<K, H>,
3484{
3485    #[inline]
3486    #[must_use]
3487    pub fn g(&self) -> [f64; K] {
3488        self.g
3489    }
3490
3491    /// Expand the patterned upper triangle into the dense symmetric shape
3492    /// required by the existing `RowKernel` interface. Missing pairs are exact
3493    /// structural zeros.
3494    #[inline]
3495    #[must_use]
3496    pub fn h(&self) -> [[f64; K]; K] {
3497        let mut dense = [[0.0; K]; K];
3498        for (slot, &(i, j)) in P::PAIRS.iter().enumerate() {
3499            dense[i][j] = self.h[slot];
3500            dense[j][i] = self.h[slot];
3501        }
3502        dense
3503    }
3504
3505    #[inline]
3506    fn pair_mask_between(left: u128, right: u128) -> u128 {
3507        let mut result = 0u128;
3508        let mut left_axes = left;
3509        while left_axes != 0 {
3510            let i = left_axes.trailing_zeros() as usize;
3511            left_axes &= left_axes - 1;
3512            let mut right_axes = right;
3513            while right_axes != 0 {
3514                let j = right_axes.trailing_zeros() as usize;
3515                right_axes &= right_axes - 1;
3516                result |= P::PAIR_BITS[i][j];
3517            }
3518        }
3519        result
3520    }
3521}
3522
3523impl<P, const K: usize, const H: usize> JetScalar<K> for PatternedOrder2<P, K, H>
3524where
3525    P: HessianPattern<K, H>,
3526{
3527    #[inline]
3528    fn constant(c: f64) -> Self {
3529        Self {
3530            v: c,
3531            g: [0.0; K],
3532            h: [0.0; H],
3533            gradient_mask: 0,
3534            hessian_mask: 0,
3535            pattern: std::marker::PhantomData,
3536        }
3537    }
3538
3539    #[inline]
3540    fn variable(x: f64, axis: usize) -> Self {
3541        let mut out = Self::constant(x);
3542        if axis < K {
3543            out.g[axis] = 1.0;
3544            out.gradient_mask = 1u128 << axis;
3545        }
3546        out
3547    }
3548}
3549
3550impl<P, const K: usize, const H: usize> crate::nested_dual::JetField for PatternedOrder2<P, K, H>
3551where
3552    P: HessianPattern<K, H>,
3553{
3554    #[inline]
3555    fn value(&self) -> f64 {
3556        self.v
3557    }
3558
3559    #[inline]
3560    fn add(&self, other: &Self) -> Self {
3561        let mut out = Self::constant(self.v + other.v);
3562        out.gradient_mask = self.gradient_mask | other.gradient_mask;
3563        let mut gradient_mask = out.gradient_mask;
3564        while gradient_mask != 0 {
3565            let i = gradient_mask.trailing_zeros() as usize;
3566            gradient_mask &= gradient_mask - 1;
3567            out.g[i] = self.g[i] + other.g[i];
3568        }
3569        out.hessian_mask = self.hessian_mask | other.hessian_mask;
3570        let mut hessian_mask = out.hessian_mask;
3571        while hessian_mask != 0 {
3572            let slot = hessian_mask.trailing_zeros() as usize;
3573            hessian_mask &= hessian_mask - 1;
3574            out.h[slot] = self.h[slot] + other.h[slot];
3575        }
3576        out
3577    }
3578
3579    #[inline]
3580    fn sub(&self, other: &Self) -> Self {
3581        let mut out = Self::constant(self.v - other.v);
3582        out.gradient_mask = self.gradient_mask | other.gradient_mask;
3583        let mut gradient_mask = out.gradient_mask;
3584        while gradient_mask != 0 {
3585            let i = gradient_mask.trailing_zeros() as usize;
3586            gradient_mask &= gradient_mask - 1;
3587            out.g[i] = self.g[i] - other.g[i];
3588        }
3589        out.hessian_mask = self.hessian_mask | other.hessian_mask;
3590        let mut hessian_mask = out.hessian_mask;
3591        while hessian_mask != 0 {
3592            let slot = hessian_mask.trailing_zeros() as usize;
3593            hessian_mask &= hessian_mask - 1;
3594            out.h[slot] = self.h[slot] - other.h[slot];
3595        }
3596        out
3597    }
3598
3599    #[inline]
3600    fn mul(&self, other: &Self) -> Self {
3601        let mut out = Self::constant(self.v * other.v);
3602        out.gradient_mask = self.gradient_mask | other.gradient_mask;
3603        let mut gradient_mask = out.gradient_mask;
3604        while gradient_mask != 0 {
3605            let i = gradient_mask.trailing_zeros() as usize;
3606            gradient_mask &= gradient_mask - 1;
3607            out.g[i] = self.v * other.g[i] + self.g[i] * other.v;
3608        }
3609        out.hessian_mask = self.hessian_mask
3610            | other.hessian_mask
3611            | Self::pair_mask_between(self.gradient_mask, other.gradient_mask);
3612        let mut hessian_mask = out.hessian_mask;
3613        while hessian_mask != 0 {
3614            let slot = hessian_mask.trailing_zeros() as usize;
3615            hessian_mask &= hessian_mask - 1;
3616            let (i, j) = P::PAIRS[slot];
3617            out.h[slot] = self.v * other.h[slot]
3618                + self.g[i] * other.g[j]
3619                + self.g[j] * other.g[i]
3620                + self.h[slot] * other.v;
3621        }
3622        out
3623    }
3624
3625    #[inline]
3626    fn neg(&self) -> Self {
3627        self.scale(-1.0)
3628    }
3629
3630    #[inline]
3631    fn scale(&self, scale: f64) -> Self {
3632        let mut out = Self::constant(self.v * scale);
3633        out.gradient_mask = self.gradient_mask;
3634        let mut gradient_mask = out.gradient_mask;
3635        while gradient_mask != 0 {
3636            let i = gradient_mask.trailing_zeros() as usize;
3637            gradient_mask &= gradient_mask - 1;
3638            out.g[i] = self.g[i] * scale;
3639        }
3640        out.hessian_mask = self.hessian_mask;
3641        let mut hessian_mask = out.hessian_mask;
3642        while hessian_mask != 0 {
3643            let slot = hessian_mask.trailing_zeros() as usize;
3644            hessian_mask &= hessian_mask - 1;
3645            out.h[slot] = self.h[slot] * scale;
3646        }
3647        out
3648    }
3649
3650    #[inline]
3651    fn compose_unary(&self, derivatives: [f64; 5]) -> Self {
3652        let mut out = Self::constant(derivatives[0]);
3653        out.gradient_mask = self.gradient_mask;
3654        let mut gradient_mask = out.gradient_mask;
3655        while gradient_mask != 0 {
3656            let i = gradient_mask.trailing_zeros() as usize;
3657            gradient_mask &= gradient_mask - 1;
3658            out.g[i] = derivatives[1] * self.g[i];
3659        }
3660        out.hessian_mask =
3661            self.hessian_mask | Self::pair_mask_between(self.gradient_mask, self.gradient_mask);
3662        let mut hessian_mask = out.hessian_mask;
3663        while hessian_mask != 0 {
3664            let slot = hessian_mask.trailing_zeros() as usize;
3665            hessian_mask &= hessian_mask - 1;
3666            let (i, j) = P::PAIRS[slot];
3667            out.h[slot] = derivatives[2] * self.g[i] * self.g[j] + derivatives[1] * self.h[slot];
3668        }
3669        out
3670    }
3671}
3672
3673// ── Order2<K>: value / gradient / Hessian (doc §A.1) ────────────────────
3674
3675/// Truncated SECOND-order scalar: value `v`, gradient `g_a`, Hessian `H_{ab}`.
3676///
3677/// This is a thin newtype over the production [`crate::jet_tower::Tower2`], so
3678/// its `(v, g, H)` channels are obtained by the SAME formulas — and are
3679/// therefore bit-identical to both [`crate::jet_tower::Tower2`] and the order-≤2
3680/// channels of a full [`crate::jet_tower::Tower4`] (doc §A.1, "Bit-identity with
3681/// the full tower"). The wrapper exists only to satisfy the generic
3682/// [`JetScalar`] interface (the `compose_unary` / `add` / `sub` / `neg` /
3683/// `recip` the trait demands, which `Tower2` does not expose by that shape) —
3684/// every channel is delegated to `Tower2` arithmetic unchanged.
3685#[derive(Clone, Copy, Debug)]
3686pub struct Order2<const K: usize>(pub crate::jet_tower::Tower2<K>);
3687
3688impl<const K: usize> Order2<K> {
3689    /// Read the gradient channel `g_a = ∂ℓ/∂p_a`.
3690    #[inline]
3691    #[must_use]
3692    pub fn g(&self) -> &[f64; K] {
3693        &self.0.g
3694    }
3695
3696    /// Read the Hessian channel.
3697    #[inline]
3698    #[must_use]
3699    pub fn h(&self) -> &[[f64; K]; K] {
3700        &self.0.h
3701    }
3702
3703    /// Consume the jet and move out its value, gradient, and Hessian channels.
3704    #[inline]
3705    #[must_use]
3706    pub fn into_channels(self) -> (f64, [f64; K], [[f64; K]; K]) {
3707        let crate::jet_tower::Tower2 { v, g, h } = self.0;
3708        (v, g, h)
3709    }
3710}
3711
3712impl<const K: usize> JetScalar<K> for Order2<K> {
3713    fn constant(c: f64) -> Self {
3714        Order2(crate::jet_tower::Tower2::constant(c))
3715    }
3716    fn variable(x: f64, axis: usize) -> Self {
3717        Order2(crate::jet_tower::Tower2::variable(x, axis))
3718    }
3719
3720    #[inline(always)]
3721    fn symmetric_quadratic_form<C: SymmetricQuadraticCoefficients>(
3722        inputs: &[Self],
3723        coefficients: &C,
3724    ) -> Self {
3725        assert_eq!(inputs.len(), coefficients.dimension());
3726        let input_dimension = inputs.len();
3727        assert!(input_dimension <= K);
3728        let mut values = [0.0; K];
3729        for axis in 0..input_dimension {
3730            values[axis] = inputs[axis].0.v;
3731        }
3732        let mut projected = [0.0; K];
3733        coefficients.multiply(
3734            &values[..input_dimension],
3735            &mut projected[..input_dimension],
3736        );
3737
3738        let mut out = crate::jet_tower::Tower2::zero();
3739        for axis in 0..input_dimension {
3740            out.v += values[axis] * projected[axis];
3741        }
3742        for primary in 0..K {
3743            let mut channel = 0.0;
3744            for axis in 0..input_dimension {
3745                channel += projected[axis] * inputs[axis].0.g[primary];
3746            }
3747            out.g[primary] = 2.0 * channel;
3748        }
3749        let mut input_gradient = [0.0; K];
3750        let mut projected_gradient = [0.0; K];
3751        for primary_b in 0..K {
3752            for row in 0..input_dimension {
3753                input_gradient[row] = inputs[row].0.g[primary_b];
3754            }
3755            coefficients.multiply(
3756                &input_gradient[..input_dimension],
3757                &mut projected_gradient[..input_dimension],
3758            );
3759            for primary_a in 0..=primary_b {
3760                let mut inherited = 0.0;
3761                let mut curvature = 0.0;
3762                for row in 0..input_dimension {
3763                    inherited += projected[row] * inputs[row].0.h[primary_a][primary_b];
3764                    curvature += inputs[row].0.g[primary_a] * projected_gradient[row];
3765                }
3766                let channel = 2.0 * (inherited + curvature);
3767                out.h[primary_a][primary_b] = channel;
3768                out.h[primary_b][primary_a] = channel;
3769            }
3770        }
3771        Order2(out)
3772    }
3773
3774    #[inline(always)]
3775    fn linear_combination(inputs: &[Self], weights: &[f64]) -> Self {
3776        assert_eq!(inputs.len(), weights.len());
3777        let mut out = crate::jet_tower::Tower2::zero();
3778        for (input, &weight) in inputs.iter().zip(weights) {
3779            out.v += input.0.v * weight;
3780        }
3781        for primary in 0..K {
3782            for (input, &weight) in inputs.iter().zip(weights) {
3783                out.g[primary] += input.0.g[primary] * weight;
3784            }
3785            for other in primary..K {
3786                for (input, &weight) in inputs.iter().zip(weights) {
3787                    out.h[primary][other] += input.0.h[primary][other] * weight;
3788                }
3789                out.h[other][primary] = out.h[primary][other];
3790            }
3791        }
3792        Order2(out)
3793    }
3794
3795    #[inline(always)]
3796    fn add_constant(&self, constant: f64) -> Self {
3797        let mut out = *self;
3798        out.0.v += constant;
3799        out
3800    }
3801
3802    #[inline(always)]
3803    fn multiply_add(&self, right: &Self, addend: &Self) -> Self {
3804        let mut out = crate::jet_tower::Tower2::zero();
3805        out.v = self.0.v * right.0.v + addend.0.v;
3806        for primary in 0..K {
3807            out.g[primary] =
3808                self.0.v * right.0.g[primary] + self.0.g[primary] * right.0.v + addend.0.g[primary];
3809            for other in primary..K {
3810                let channel = self.0.v * right.0.h[primary][other]
3811                    + self.0.g[primary] * right.0.g[other]
3812                    + self.0.g[other] * right.0.g[primary]
3813                    + self.0.h[primary][other] * right.0.v
3814                    + addend.0.h[primary][other];
3815                out.h[primary][other] = channel;
3816                out.h[other][primary] = channel;
3817            }
3818        }
3819        Order2(out)
3820    }
3821
3822    #[inline(always)]
3823    fn product(&self, right: &Self) -> Self {
3824        let mut out = crate::jet_tower::Tower2::zero();
3825        out.v = self.0.v * right.0.v;
3826        for primary in 0..K {
3827            out.g[primary] = self.0.v * right.0.g[primary] + self.0.g[primary] * right.0.v;
3828            for other in primary..K {
3829                let channel = self.0.v * right.0.h[primary][other]
3830                    + self.0.g[primary] * right.0.g[other]
3831                    + self.0.g[other] * right.0.g[primary]
3832                    + self.0.h[primary][other] * right.0.v;
3833                out.h[primary][other] = channel;
3834                out.h[other][primary] = channel;
3835            }
3836        }
3837        Order2(out)
3838    }
3839
3840    #[inline(always)]
3841    fn affine_compose(
3842        &self,
3843        input_scale: f64,
3844        input_shift: f64,
3845        derivative_stack: [f64; 5],
3846    ) -> Self {
3847        assert!(input_shift.is_finite(), "affine input shift must be finite");
3848        let first = derivative_stack[1] * input_scale;
3849        let second = derivative_stack[2] * input_scale * input_scale;
3850        let mut out = crate::jet_tower::Tower2::zero();
3851        out.v = derivative_stack[0];
3852        for primary in 0..K {
3853            out.g[primary] = first * self.0.g[primary];
3854            for other in primary..K {
3855                let channel =
3856                    first * self.0.h[primary][other] + second * self.0.g[primary] * self.0.g[other];
3857                out.h[primary][other] = channel;
3858                out.h[other][primary] = channel;
3859            }
3860        }
3861        Order2(out)
3862    }
3863
3864    #[inline(always)]
3865    fn affine_composed_sum(
3866        inputs: &[Self],
3867        input_scales: &[f64],
3868        derivative_stacks: &[[f64; 5]],
3869    ) -> Self {
3870        assert_eq!(inputs.len(), input_scales.len());
3871        assert_eq!(inputs.len(), derivative_stacks.len());
3872        let mut out = crate::jet_tower::Tower2::zero();
3873        for ((input, &input_scale), stack) in inputs.iter().zip(input_scales).zip(derivative_stacks)
3874        {
3875            let first = stack[1] * input_scale;
3876            let second = stack[2] * input_scale * input_scale;
3877            out.v += stack[0];
3878            for primary in 0..K {
3879                out.g[primary] += first * input.0.g[primary];
3880                for other in primary..K {
3881                    out.h[primary][other] += first * input.0.h[primary][other]
3882                        + second * input.0.g[primary] * input.0.g[other];
3883                }
3884            }
3885        }
3886        for primary in 0..K {
3887            for other in primary + 1..K {
3888                out.h[other][primary] = out.h[primary][other];
3889            }
3890        }
3891        Order2(out)
3892    }
3893
3894    #[inline(always)]
3895    fn shared_multiply_add_affine_composed_sum<const N: usize>(
3896        lefts: &[&Self; N],
3897        right: &Self,
3898        addend: &Self,
3899        addend_scales: &[f64; N],
3900        input_scales: &[f64; N],
3901        derivative_stacks: &[[f64; 5]; N],
3902    ) -> Self {
3903        let (representatives, term_sources, source_count) =
3904            canonical_shared_source_schedule::<N>(|term, representative| {
3905                std::ptr::eq(lefts[term], lefts[representative])
3906                    && addend_scales[term] == addend_scales[representative]
3907            });
3908        let (value, source_derivatives) =
3909            aggregate_shared_source_derivatives(&term_sources, input_scales, derivative_stacks);
3910        let mut source_gradients = [[0.0; K]; N];
3911        let mut out = crate::jet_tower::Tower2::zero();
3912        out.v = value;
3913        let mut right_first = 0.0;
3914        let mut addend_first = 0.0;
3915        for source in 0..source_count {
3916            let term = representatives[source];
3917            let first = source_derivatives[source][1];
3918            right_first += first * lefts[term].0.v;
3919            addend_first += first * addend_scales[term];
3920            for primary in 0..K {
3921                let product_gradient =
3922                    lefts[term].0.v * right.0.g[primary] + lefts[term].0.g[primary] * right.0.v;
3923                let inner_gradient = if addend_scales[term] == 0.0 {
3924                    product_gradient
3925                } else if addend_scales[term] == 1.0 {
3926                    product_gradient + addend.0.g[primary]
3927                } else {
3928                    product_gradient + addend_scales[term] * addend.0.g[primary]
3929                };
3930                source_gradients[source][primary] = inner_gradient;
3931                out.g[primary] += first * lefts[term].0.g[primary] * right.0.v;
3932            }
3933        }
3934        if N != 0 {
3935            for primary in 0..K {
3936                out.g[primary] += right_first * right.0.g[primary];
3937            }
3938        }
3939        let addend_live = addend_scales.iter().any(|&scale| scale != 0.0);
3940        if addend_live {
3941            for primary in 0..K {
3942                out.g[primary] += addend_first * addend.0.g[primary];
3943            }
3944        }
3945        for primary in 0..K {
3946            for other in primary..K {
3947                let mut channel = if N == 0 {
3948                    0.0
3949                } else {
3950                    right_first * right.0.h[primary][other]
3951                };
3952                if addend_live {
3953                    channel += addend_first * addend.0.h[primary][other];
3954                }
3955                for source in 0..source_count {
3956                    let term = representatives[source];
3957                    let local_product_hessian = lefts[term].0.g[primary] * right.0.g[other]
3958                        + lefts[term].0.g[other] * right.0.g[primary]
3959                        + lefts[term].0.h[primary][other] * right.0.v;
3960                    channel += source_derivatives[source][1] * local_product_hessian
3961                        + source_derivatives[source][2]
3962                            * source_gradients[source][primary]
3963                            * source_gradients[source][other];
3964                }
3965                out.h[primary][other] = channel;
3966                out.h[other][primary] = channel;
3967            }
3968        }
3969        Order2(out)
3970    }
3971
3972    #[inline(always)]
3973    fn composed_sum(inputs: &[Self], derivative_stacks: &[[f64; 5]]) -> Self {
3974        assert_eq!(inputs.len(), derivative_stacks.len());
3975        let mut out = crate::jet_tower::Tower2::zero();
3976        for (input, stack) in inputs.iter().zip(derivative_stacks) {
3977            out.v += stack[0];
3978            for primary in 0..K {
3979                out.g[primary] += stack[1] * input.0.g[primary];
3980                for other in primary..K {
3981                    out.h[primary][other] += stack[1] * input.0.h[primary][other]
3982                        + stack[2] * input.0.g[primary] * input.0.g[other];
3983                }
3984            }
3985        }
3986        for primary in 0..K {
3987            for other in primary + 1..K {
3988                out.h[other][primary] = out.h[primary][other];
3989            }
3990        }
3991        Order2(out)
3992    }
3993}
3994
3995impl<const K: usize> crate::nested_dual::JetField for Order2<K> {
3996    fn value(&self) -> f64 {
3997        self.0.v
3998    }
3999    fn add(&self, o: &Self) -> Self {
4000        Order2(self.0 + o.0)
4001    }
4002    fn sub(&self, o: &Self) -> Self {
4003        // Tower2 has no Sub op; subtract by adding the negation, matching
4004        // Tower4::sub (self + o.scale(-1.0)).
4005        Order2(self.0 + o.0.scale(-1.0))
4006    }
4007    fn mul(&self, o: &Self) -> Self {
4008        Order2(crate::jet_tower::Tower2::mul(&self.0, &o.0))
4009    }
4010    fn neg(&self) -> Self {
4011        Order2(self.0.scale(-1.0))
4012    }
4013    fn scale(&self, s: f64) -> Self {
4014        Order2(self.0.scale(s))
4015    }
4016    fn compose_unary(&self, d: [f64; 5]) -> Self {
4017        // Order-≤2 reads only [f, f', f''] of the stack.
4018        Order2(self.0.compose_unary([d[0], d[1], d[2]]))
4019    }
4020    fn constant_like(&self, v: f64) -> Self {
4021        // `Tower2::compose_unary([v, 0, 0])` writes `v` and then multiplies
4022        // every gradient/Hessian channel by an exact zero; skip the K + K²
4023        // multiply-adds and construct the constant. (#932)
4024        <Self as JetScalar<K>>::constant(v)
4025    }
4026    fn with_value(&self, v: f64) -> Self {
4027        let mut out = *self;
4028        out.0.v = v;
4029        out
4030    }
4031}
4032
4033/// Static lowering target for a sum of composed, low-dimensional row atoms.
4034///
4035/// A row likelihood often depends on a large global primary vector only through
4036/// a few small independent indices.  Evaluating the whole expression in an
4037/// `Order2<K>` then pays dense `K²` arithmetic at every intermediate; carrying
4038/// runtime dependency masks replaces that arithmetic with branches and bit
4039/// scans.  This accumulator provides the ahead-of-time alternative: evaluate
4040/// each index once in its natural local dimension `N`, then scatter the exact
4041/// second-order composition into the global `K` channels through a fixed axis
4042/// map.  The family still owns only its scalar index expression and certified
4043/// unary derivative stack; this type owns the universal chain rule.
4044///
4045/// For an atom `q(x_local)` and outer stack `[f(q), f'(q), f''(q)]`, the lowered
4046/// channels are
4047///
4048/// ```text
4049/// g[a_i]       += f' q_i
4050/// H[a_i, a_j] += f' q_ij + f'' q_i q_j.
4051/// ```
4052///
4053/// Only the local upper triangle is evaluated, then mirrored into the global
4054/// symmetric output.  With literal `axes` and fixed `N`, LLVM unrolls this into
4055/// straight-line arithmetic: no dependency masks, sparse-pair lookups, or jet
4056/// temporaries survive into the generated schedule.
4057#[derive(Clone, Copy, Debug)]
4058pub struct MappedOrder2Accumulator<const K: usize> {
4059    value: f64,
4060    gradient: [f64; K],
4061    hessian: [[f64; K]; K],
4062}
4063
4064/// Compile-time-symbolic value/gradient/Hessian of one local row atom.
4065///
4066/// The Hessian stores only its upper triangle, in row-major triangular order.
4067/// Instances are emitted by `gam-row-macros`; unlike a runtime forward jet,
4068/// they contain only final live channels and therefore introduce no seeded
4069/// identity arrays, dependency masks, or zero arithmetic.
4070#[derive(Clone, Copy, Debug)]
4071pub struct StaticOrder2Atom<
4072    const N: usize,
4073    const H: usize,
4074    const GRADIENT_BITS: u128,
4075    const HESSIAN_BITS: u128,
4076> {
4077    value: f64,
4078    gradient: [f64; N],
4079    hessian: [f64; H],
4080}
4081
4082impl<const N: usize, const H: usize, const G: u128, const Q: u128> StaticOrder2Atom<N, H, G, Q> {
4083    /// Construct a generated atom. `H` must equal `N(N+1)/2`.
4084    #[inline(always)]
4085    #[must_use]
4086    pub fn new(value: f64, gradient: [f64; N], hessian: [f64; H]) -> Self {
4087        assert!(H == N * (N + 1) / 2, "invalid packed order-two shape");
4088        assert!(N <= 128 && H <= 128, "static atom sparsity mask overflow");
4089        Self {
4090            value,
4091            gradient,
4092            hessian,
4093        }
4094    }
4095
4096    /// Scalar value of the generated atom.
4097    #[inline(always)]
4098    #[must_use]
4099    pub fn value(&self) -> f64 {
4100        self.value
4101    }
4102
4103    /// Generated local gradient.
4104    #[inline(always)]
4105    #[must_use]
4106    pub fn gradient(&self) -> [f64; N] {
4107        self.gradient
4108    }
4109
4110    /// Generated local Hessian entry. The matrix is symmetric.
4111    #[inline(always)]
4112    #[must_use]
4113    pub fn hessian_at(&self, row: usize, column: usize) -> f64 {
4114        assert!(
4115            row < N && column < N,
4116            "static atom Hessian axis out of range"
4117        );
4118        let (row, column) = if row <= column {
4119            (row, column)
4120        } else {
4121            (column, row)
4122        };
4123        let index = row * (2 * N - row + 1) / 2 + column - row;
4124        self.hessian[index]
4125    }
4126}
4127
4128/// Order-two channel reader accepted by [`MappedOrder2Accumulator`].
4129///
4130/// Both ordinary forward jets and build-time-symbolic atoms implement this
4131/// interface. The accumulator owns the only global scatter/chain rule.
4132pub trait Order2AtomChannels<const N: usize> {
4133    /// Structurally live local gradient channels.
4134    const GRADIENT_BITS: u128;
4135    /// Structurally live packed upper-Hessian channels.
4136    const HESSIAN_BITS: u128;
4137    /// Local gradient entry.
4138    fn gradient_at(&self, axis: usize) -> f64;
4139    /// Local Hessian entry.
4140    fn hessian_at(&self, row: usize, column: usize) -> f64;
4141}
4142
4143impl<const N: usize> Order2AtomChannels<N> for Order2<N> {
4144    const GRADIENT_BITS: u128 = low_mask(N);
4145    const HESSIAN_BITS: u128 = low_mask(N * (N + 1) / 2);
4146
4147    #[inline(always)]
4148    fn gradient_at(&self, axis: usize) -> f64 {
4149        self.0.g[axis]
4150    }
4151
4152    #[inline(always)]
4153    fn hessian_at(&self, row: usize, column: usize) -> f64 {
4154        self.0.h[row][column]
4155    }
4156}
4157
4158impl<const N: usize, const H: usize, const G: u128, const Q: u128> Order2AtomChannels<N>
4159    for StaticOrder2Atom<N, H, G, Q>
4160{
4161    const GRADIENT_BITS: u128 = G;
4162    const HESSIAN_BITS: u128 = Q;
4163
4164    #[inline(always)]
4165    fn gradient_at(&self, axis: usize) -> f64 {
4166        self.gradient[axis]
4167    }
4168
4169    #[inline(always)]
4170    fn hessian_at(&self, row: usize, column: usize) -> f64 {
4171        StaticOrder2Atom::hessian_at(self, row, column)
4172    }
4173}
4174
4175const fn low_mask(channels: usize) -> u128 {
4176    if channels >= 128 {
4177        u128::MAX
4178    } else {
4179        (1u128 << channels) - 1
4180    }
4181}
4182
4183impl<const K: usize> MappedOrder2Accumulator<K> {
4184    /// Empty additive accumulator.
4185    #[inline(always)]
4186    #[must_use]
4187    pub fn zero() -> Self {
4188        Self {
4189            value: 0.0,
4190            gradient: [0.0; K],
4191            hessian: [[0.0; K]; K],
4192        }
4193    }
4194
4195    /// Scatter `f(atom)` using the exact order-two Faà di Bruno rule.
4196    ///
4197    /// `axes[i]` maps local derivative axis `i` to its global primary axis. The
4198    /// map must be injective. Repeated axes describe a non-injective linear
4199    /// pullback whose identified cross terms need multiplicity that this simple
4200    /// scatter deliberately does not represent.
4201    #[inline(always)]
4202    pub fn add_composed<const N: usize, const H: usize, A: Order2AtomChannels<N>>(
4203        &mut self,
4204        atom: &A,
4205        axes: [usize; N],
4206        derivatives: [f64; 3],
4207        value_add: bool,
4208        gradient_add: [bool; N],
4209        hessian_add: [bool; H],
4210    ) {
4211        assert!(H == N * (N + 1) / 2, "invalid mapped Hessian write shape");
4212        assert!(N <= 128 && H <= 128, "mapped atom sparsity mask overflow");
4213        assert!(
4214            axes.iter().all(|&axis| axis < K),
4215            "mapped atom axis must be within the global primary dimension"
4216        );
4217        assert!(
4218            axes.iter()
4219                .enumerate()
4220                .all(|(i, axis)| !axes[..i].contains(axis)),
4221            "mapped atom axes must be injective"
4222        );
4223
4224        if value_add {
4225            self.value += derivatives[0];
4226        } else {
4227            self.value = derivatives[0];
4228        }
4229        let mut packed = 0;
4230        for local_i in 0..N {
4231            let global_i = axes[local_i];
4232            if A::GRADIENT_BITS & (1u128 << local_i) != 0 {
4233                let channel = derivatives[1] * atom.gradient_at(local_i);
4234                if gradient_add[local_i] {
4235                    self.gradient[global_i] += channel;
4236                } else {
4237                    self.gradient[global_i] = channel;
4238                }
4239            }
4240            for local_j in local_i..N {
4241                let global_j = axes[local_j];
4242                let inner_live = A::HESSIAN_BITS & (1u128 << packed) != 0;
4243                let outer_live = A::GRADIENT_BITS & (1u128 << local_i) != 0
4244                    && A::GRADIENT_BITS & (1u128 << local_j) != 0;
4245                let channel = if inner_live {
4246                    let inner = derivatives[1] * atom.hessian_at(local_i, local_j);
4247                    if outer_live {
4248                        inner
4249                            + derivatives[2] * atom.gradient_at(local_i) * atom.gradient_at(local_j)
4250                    } else {
4251                        inner
4252                    }
4253                } else if outer_live {
4254                    derivatives[2] * atom.gradient_at(local_i) * atom.gradient_at(local_j)
4255                } else {
4256                    packed += 1;
4257                    continue;
4258                };
4259                if hessian_add[packed] {
4260                    self.hessian[global_i][global_j] += channel;
4261                    if global_i != global_j {
4262                        self.hessian[global_j][global_i] += channel;
4263                    }
4264                } else {
4265                    self.hessian[global_i][global_j] = channel;
4266                    if global_i != global_j {
4267                        self.hessian[global_j][global_i] = channel;
4268                    }
4269                }
4270                packed += 1;
4271            }
4272        }
4273    }
4274
4275    /// Finish the lowering in the standard row-kernel channel layout.
4276    #[inline(always)]
4277    #[must_use]
4278    pub fn into_channels(self) -> (f64, [f64; K], [[f64; K]; K]) {
4279        (self.value, self.gradient, self.hessian)
4280    }
4281}
4282
4283/// One inner scalar in a runtime-width additive order-two composition.
4284///
4285/// Implementors expose only the inner gradient and Hessian. The corresponding
4286/// outer function's first and second derivatives live beside the source in the
4287/// caller's term type, so several terms that share an inner scalar may be fused
4288/// before entering [`DynamicOrder2Accumulator`].
4289pub trait DynamicOrder2Term {
4290    /// Outer first derivative `f'(q)` for this already-fused source.
4291    fn outer_first(&self) -> f64;
4292
4293    /// Outer second derivative `f''(q)` for this already-fused source.
4294    fn outer_second(&self) -> f64;
4295
4296    /// Inner first derivative `q_i`.
4297    fn inner_gradient(&self, axis: usize) -> f64;
4298
4299    /// Inner second derivative `q_ij`.
4300    fn inner_hessian(&self, row: usize, column: usize) -> f64;
4301}
4302
4303/// Allocation-minimal runtime-width lowering of an additive order-two program.
4304///
4305/// This is the dynamic-width sibling of [`MappedOrder2Accumulator`]. A caller
4306/// first reduces its mathematical row program to a scalar value plus `N`
4307/// independent composed sources. This accumulator then performs the universal
4308/// chain rule
4309///
4310/// ```text
4311/// g_i  = sum_t (f_t' q_t,i)
4312/// H_ij = sum_t (f_t'' q_t,i q_t,j + f_t' q_t,ij)
4313/// ```
4314///
4315/// in one gradient pass and one upper-triangular Hessian pass. It owns exactly
4316/// the two buffers that become the returned gradient and Hessian; no per-term
4317/// derivative buffer or jet temporary is allocated. `N` is const-generic so a
4318/// small fixed source set is visible to LLVM and can be unrolled.
4319#[derive(Debug)]
4320pub struct DynamicOrder2Accumulator {
4321    value: f64,
4322    gradient: Vec<f64>,
4323    hessian: Vec<f64>,
4324}
4325
4326impl DynamicOrder2Accumulator {
4327    /// Lower a fused additive source set at runtime primary width `dimension`.
4328    #[inline(always)]
4329    #[must_use]
4330    pub fn from_composed_sum<T: DynamicOrder2Term, const N: usize>(
4331        dimension: usize,
4332        value: f64,
4333        terms: &[T; N],
4334    ) -> Self {
4335        let mut gradient = vec![0.0; dimension];
4336        let mut hessian = vec![0.0; dimension * dimension];
4337
4338        for axis in 0..dimension {
4339            let mut channel = 0.0;
4340            for term in terms {
4341                channel += term.outer_first() * term.inner_gradient(axis);
4342            }
4343            gradient[axis] = channel;
4344        }
4345
4346        for row in 0..dimension {
4347            for column in row..dimension {
4348                let mut channel = 0.0;
4349                for term in terms {
4350                    let row_gradient = term.inner_gradient(row);
4351                    let column_gradient = term.inner_gradient(column);
4352                    channel += term.outer_second() * row_gradient * column_gradient
4353                        + term.outer_first() * term.inner_hessian(row, column);
4354                }
4355                hessian[row * dimension + column] = channel;
4356                hessian[column * dimension + row] = channel;
4357            }
4358        }
4359
4360        Self {
4361            value,
4362            gradient,
4363            hessian,
4364        }
4365    }
4366
4367    /// Finish the lowering as `(value, gradient, row-major symmetric Hessian)`.
4368    #[inline(always)]
4369    #[must_use]
4370    pub fn into_channels(self) -> (f64, Vec<f64>, Vec<f64>) {
4371        (self.value, self.gradient, self.hessian)
4372    }
4373}
4374
4375// ── Lane-batched Order-2 scalar: 4 rows per pass in SIMD lanes (perf) ────
4376//
4377// The hot per-row jet kernels evaluate ONE row's `(v, g, H)` tower at a time in
4378// scalar `f64`. A hand-written scalar derivative does the same. The throughput
4379// lever a jet has that scalar hand-code cannot is **row batching in SIMD
4380// lanes**: the order-≤2 Leibniz product `Order2::mul` is `O(K²)` independent
4381// per-channel float ops, and EVERY row runs the identical op graph on different
4382// data — the textbook SPMD shape. Packing `LANES = 4` rows into a `wide::f64x4`
4383// and running the algebra once per 4 rows replaces 4 scalar passes with one
4384// vector pass: the `K²` Hessian channel updates become `K²` NEON `.2d` / SSE2
4385// `pd` instructions covering 4 rows each, ~4× fewer FP instructions per row.
4386//
4387// The carried scalar field is abstracted by [`Lane`] so the SAME algebra body
4388// instantiates at `f64` (1 row, used as the bit-identity oracle) or
4389// [`wide::f64x4`] (4 rows). Bit-identity is structural, not approximate:
4390//
4391//   * Every arithmetic op is a plain lane-wise `+` / `-` / `*` (NEVER a fused
4392//     `mul_add`), and IEEE-754 double `+`/`-`/`*`/`/` are correctly rounded and
4393//     deterministic, so lane `i` of an `f64x4` op equals the scalar `f64` op on
4394//     that lane's inputs bit-for-bit.
4395//   * The transcendental derivative STACKS (`exp`/`ln`/`sqrt`/…) are produced
4396//     **per lane by the identical scalar code** ([`Lane::unary3`] unpacks, runs
4397//     the same `[f64; 3]` stack closure the scalar path runs, repacks), so the
4398//     only thing vectorised is the cheap rational tensor composition — the
4399//     library transcendental itself is the exact same `f64::exp` call per lane.
4400//   * The op order mirrors [`crate::jet_tower::Tower2`] term-for-term, so
4401//     [`Order2Lane<f64, K>`] is `to_bits`-identical to the production
4402//     [`Order2<K>`] (= `Tower2<K>`), and [`Order2Lane<f64x4, K>`] lane `i` is
4403//     `to_bits`-identical to that — proven by the `batch_tests` oracle below
4404//     (≥2000 random 4-row batches across `K ∈ {2,3,4,9}`).
4405
4406/// The scalar field a [`Order2Lane`] carries: either a single `f64` (one row,
4407/// the oracle) or a [`wide::f64x4`] (four rows evaluated in SIMD lanes). All ops
4408/// are plain lane-wise IEEE arithmetic, so a vector op equals the scalar op on
4409/// each lane bit-for-bit.
4410pub trait Lane: Copy {
4411    /// How many rows one value of this field carries: 1 for the `f64` oracle,
4412    /// 4 for [`wide::f64x4`]. [`Lane::lane`] indices are bounded by this.
4413    const LANES: usize;
4414    /// Broadcast a scalar to every lane.
4415    fn splat(x: f64) -> Self;
4416    /// Lane-wise `self + o`.
4417    fn add(self, o: Self) -> Self;
4418    /// Lane-wise `self - o`.
4419    fn sub(self, o: Self) -> Self;
4420    /// Lane-wise `self * o`.
4421    fn mul(self, o: Self) -> Self;
4422    /// The `f64` in lane `i`. Panics when `i >= LANES` — a row index past the
4423    /// end of the field is a caller bug, not a value to silently substitute.
4424    fn lane(self, i: usize) -> f64;
4425    /// Build the order-≤2 derivative stack `[f(u), f′(u), f″(u)]` **per lane**
4426    /// from the lane value `u`, via the SAME scalar `stack` closure the
4427    /// per-row path runs (so the transcendental/rational stack is bit-identical
4428    /// to the scalar evaluation — only the subsequent tensor composition is
4429    /// vectorised).
4430    fn unary3(self, stack: impl Fn(f64) -> [f64; 3]) -> [Self; 3];
4431    /// Build the order-≤4 derivative stack `[f, f′, f″, f‴, f⁗]` **per lane**
4432    /// from the lane value `u`, via the SAME scalar `stack` closure the per-row
4433    /// path runs. The one-/two-seed scalars ([`OneSeedLane`] / [`TwoSeedLane`])
4434    /// need outer derivatives one / two orders beyond their order-2 base, so
4435    /// they build their composition stack through this five-entry variant. As
4436    /// with [`unary3`](Lane::unary3), only the transcendental/rational stack is
4437    /// evaluated per lane (bit-identically to the scalar path); the subsequent
4438    /// tensor composition is vectorised.
4439    fn unary5(self, stack: impl Fn(f64) -> [f64; 5]) -> [Self; 5];
4440}
4441
4442impl Lane for f64 {
4443    const LANES: usize = 1;
4444    #[inline]
4445    fn splat(x: f64) -> Self {
4446        x
4447    }
4448    #[inline]
4449    fn add(self, o: Self) -> Self {
4450        self + o
4451    }
4452    #[inline]
4453    fn sub(self, o: Self) -> Self {
4454        self - o
4455    }
4456    #[inline]
4457    fn mul(self, o: Self) -> Self {
4458        self * o
4459    }
4460    #[inline]
4461    fn lane(self, i: usize) -> f64 {
4462        assert!(
4463            i < <Self as Lane>::LANES,
4464            "the f64 Lane carries one row; lane {i} does not exist"
4465        );
4466        self
4467    }
4468    #[inline]
4469    fn unary3(self, stack: impl Fn(f64) -> [f64; 3]) -> [Self; 3] {
4470        stack(self)
4471    }
4472    #[inline]
4473    fn unary5(self, stack: impl Fn(f64) -> [f64; 5]) -> [Self; 5] {
4474        stack(self)
4475    }
4476}
4477
4478impl Lane for wide::f64x4 {
4479    const LANES: usize = 4;
4480    #[inline]
4481    fn splat(x: f64) -> Self {
4482        wide::f64x4::splat(x)
4483    }
4484    #[inline]
4485    fn add(self, o: Self) -> Self {
4486        self + o
4487    }
4488    #[inline]
4489    fn sub(self, o: Self) -> Self {
4490        self - o
4491    }
4492    #[inline]
4493    fn mul(self, o: Self) -> Self {
4494        self * o
4495    }
4496    #[inline]
4497    fn lane(self, i: usize) -> f64 {
4498        self.to_array()[i]
4499    }
4500    #[inline]
4501    fn unary3(self, stack: impl Fn(f64) -> [f64; 3]) -> [Self; 3] {
4502        let a = self.to_array();
4503        let mut d0 = [0.0_f64; 4];
4504        let mut d1 = [0.0_f64; 4];
4505        let mut d2 = [0.0_f64; 4];
4506        for i in 0..4 {
4507            let s = stack(a[i]);
4508            d0[i] = s[0];
4509            d1[i] = s[1];
4510            d2[i] = s[2];
4511        }
4512        [
4513            wide::f64x4::new(d0),
4514            wide::f64x4::new(d1),
4515            wide::f64x4::new(d2),
4516        ]
4517    }
4518    #[inline]
4519    fn unary5(self, stack: impl Fn(f64) -> [f64; 5]) -> [Self; 5] {
4520        let a = self.to_array();
4521        let mut d = [[0.0_f64; 4]; 5];
4522        for i in 0..4 {
4523            let s = stack(a[i]);
4524            for (k, dk) in d.iter_mut().enumerate() {
4525                dk[i] = s[k];
4526            }
4527        }
4528        [
4529            wide::f64x4::new(d[0]),
4530            wide::f64x4::new(d[1]),
4531            wide::f64x4::new(d[2]),
4532            wide::f64x4::new(d[3]),
4533            wide::f64x4::new(d[4]),
4534        ]
4535    }
4536}
4537
4538/// A lane-batched order-≤2 Taylor scalar: value / gradient / Hessian carried in
4539/// a SIMD field [`L: Lane`](Lane). With `L = f64x4` one instance carries FOUR
4540/// rows at once, so the row loop processes 4 rows per vector pass instead of one
4541/// per scalar pass.
4542///
4543/// The channel layout and every float op mirror [`crate::jet_tower::Tower2`]
4544/// term-for-term, so `Order2Lane<f64, K>` is `to_bits`-identical to the
4545/// production [`Order2<K>`] and `Order2Lane<f64x4, K>` lane `i` is
4546/// `to_bits`-identical to that (see the module note and `batch_tests`).
4547#[derive(Clone, Copy, Debug)]
4548pub struct Order2Lane<L: Lane, const K: usize> {
4549    /// Value channel `ℓ` (one entry per lane/row).
4550    pub v: L,
4551    /// Gradient channel `∂ℓ/∂p_a`.
4552    pub g: [L; K],
4553    /// Hessian channel `∂²ℓ/∂p_a∂p_b` (symmetric).
4554    pub h: [[L; K]; K],
4555}
4556
4557/// The 4-rows-per-pass batched order-≤2 scalar (`wide::f64x4` lanes).
4558pub type Order2Batch<const K: usize> = Order2Lane<wide::f64x4, K>;
4559
4560impl<L: Lane, const K: usize> Order2Lane<L, K> {
4561    /// A constant: value `c` in every channel-zero slot.
4562    #[inline]
4563    pub fn constant(c: L) -> Self {
4564        Order2Lane {
4565            v: c,
4566            g: [L::splat(0.0); K],
4567            h: [[L::splat(0.0); K]; K],
4568        }
4569    }
4570
4571    /// The seeded variable `p_axis` at (per-lane) value `value`: unit first
4572    /// derivative in slot `axis`. With `L = f64x4`, `value` packs the four
4573    /// rows' values of primary `axis`.
4574    #[inline]
4575    pub fn variable(value: L, axis: usize) -> Self {
4576        let mut out = Self::constant(value);
4577        out.g[axis] = L::splat(1.0);
4578        out
4579    }
4580
4581    /// Lane-wise `self + o` (mirrors `Tower2` Add: per-channel add).
4582    #[inline]
4583    pub fn add(&self, o: &Self) -> Self {
4584        let mut out = *self;
4585        out.v = self.v.add(o.v);
4586        for i in 0..K {
4587            out.g[i] = self.g[i].add(o.g[i]);
4588            for j in 0..K {
4589                out.h[i][j] = self.h[i][j].add(o.h[i][j]);
4590            }
4591        }
4592        out
4593    }
4594
4595    /// Multiply every channel by the plain scalar `s` (mirrors `Tower2::scale`).
4596    #[inline]
4597    pub fn scale(&self, s: f64) -> Self {
4598        let sl = L::splat(s);
4599        let mut out = *self;
4600        out.v = self.v.mul(sl);
4601        for i in 0..K {
4602            out.g[i] = self.g[i].mul(sl);
4603            for j in 0..K {
4604                out.h[i][j] = self.h[i][j].mul(sl);
4605            }
4606        }
4607        out
4608    }
4609
4610    /// Lane-wise `self - o`, expressed as `self + o·(-1)` exactly as
4611    /// [`Order2::sub`](crate::nested_dual::JetField::sub) / `Tower4::sub` do, so signed-zero handling matches.
4612    #[inline]
4613    pub fn sub(&self, o: &Self) -> Self {
4614        self.add(&o.scale(-1.0))
4615    }
4616
4617    /// Negate every channel (= `scale(-1.0)`, matching [`Order2::neg`](crate::nested_dual::JetField::neg)).
4618    #[inline]
4619    pub fn neg(&self) -> Self {
4620        self.scale(-1.0)
4621    }
4622
4623    /// Exact order-≤2 Leibniz product, term-for-term identical to
4624    /// [`crate::jet_tower::Tower2::mul`] (same factor order, no `mul_add`).
4625    ///
4626    /// The Hessian channel is symmetric under `i ↔ j` (see
4627    /// [`crate::jet_tower::Tower2::mul`] for why the invariant always holds), so
4628    /// we compute the upper triangle `j ≥ i` and mirror it — `K(K+1)/2` lane
4629    /// entry-chains instead of `K²`. Because each lane entry is already a full
4630    /// SIMD op (no cross-`j` lane packing to lose), halving the entry count is a
4631    /// direct throughput win (~18 % on `Order2Lane<f64x4, 9>`, the survival batch
4632    /// kernel, and ~2× on the `f64` oracle). The upper triangle uses the EXACT
4633    /// term order of `Tower2::mul`, so `Order2Lane<f64>` stays `to_bits`-identical
4634    /// to `Order2` (= `Tower2`) and `Order2Lane<f64x4>` lane `i` stays
4635    /// `to_bits`-identical to that; the mirror makes the batch Hessian exactly
4636    /// symmetric, matching the scalar `Tower2::mul` (which mirrors identically).
4637    #[inline]
4638    pub fn mul(&self, o: &Self) -> Self {
4639        let a = self;
4640        let b = o;
4641        let mut out = Self::constant(a.v.mul(b.v));
4642        for i in 0..K {
4643            // a.v*b.g[i] + a.g[i]*b.v
4644            out.g[i] = a.v.mul(b.g[i]).add(a.g[i].mul(b.v));
4645        }
4646        for i in 0..K {
4647            for j in i..K {
4648                // a.v*b.h + a.g[i]*b.g[j] + a.g[j]*b.g[i] + a.h*b.v
4649                let hij =
4650                    a.v.mul(b.h[i][j])
4651                        .add(a.g[i].mul(b.g[j]))
4652                        .add(a.g[j].mul(b.g[i]))
4653                        .add(a.h[i][j].mul(b.v));
4654                out.h[i][j] = hij;
4655                out.h[j][i] = hij;
4656            }
4657        }
4658        out
4659    }
4660
4661    /// Exact order-≤2 Faà di Bruno composition `f ∘ self`, given the per-lane
4662    /// derivative stack `d = [f(u), f′(u), f″(u)]`. Mirrors
4663    /// [`crate::jet_tower::Tower2::compose_unary`] term-for-term (`acc` starts at
4664    /// `0` then accumulates, so signed-zero collapses identically).
4665    #[inline]
4666    pub fn compose_unary(&self, d: [L; 3]) -> Self {
4667        let mut out = Self::constant(d[0]);
4668        for i in 0..K {
4669            let mut acc = L::splat(0.0);
4670            acc = acc.add(d[1].mul(self.g[i]));
4671            out.g[i] = acc;
4672        }
4673        for i in 0..K {
4674            for j in 0..K {
4675                let mut acc = L::splat(0.0);
4676                acc = acc.add(d[1].mul(self.h[i][j]));
4677                acc = acc.add(d[2].mul(self.g[i]).mul(self.g[j]));
4678                out.h[i][j] = acc;
4679            }
4680        }
4681        out
4682    }
4683
4684    /// `e^self`, per-lane stack `[e, e, e]` (matches the [`JetScalar::exp`]
4685    /// default forwarded through `Order2`).
4686    #[inline]
4687    pub fn exp(&self) -> Self {
4688        let d = self.v.unary3(|u| {
4689            let e = u.exp();
4690            [e, e, e]
4691        });
4692        self.compose_unary(d)
4693    }
4694
4695    /// `ln(self)`; caller guarantees positivity. Per-lane stack
4696    /// `[ln u, 1/u, -1/u²]` (matches [`JetScalar::ln`] truncated to order 2).
4697    #[inline]
4698    pub fn ln(&self) -> Self {
4699        let d = self.v.unary3(|u| {
4700            let r = 1.0 / u;
4701            [u.ln(), r, -r * r]
4702        });
4703        self.compose_unary(d)
4704    }
4705
4706    /// `√self`; caller guarantees positivity. Per-lane stack
4707    /// `[s, 0.5/s, -0.25/(u·s)]` (matches [`JetScalar::sqrt`]).
4708    #[inline]
4709    pub fn sqrt(&self) -> Self {
4710        let d = self.v.unary3(|u| {
4711            let s = u.sqrt();
4712            [s, 0.5 / s, -0.25 / (u * s)]
4713        });
4714        self.compose_unary(d)
4715    }
4716
4717    /// `1/self`. Per-lane stack `[r, -r², 2r³]` (matches [`JetScalar::recip`]).
4718    #[inline]
4719    pub fn recip(&self) -> Self {
4720        let d = self.v.unary3(|u| {
4721            let r = 1.0 / u;
4722            let r2 = r * r;
4723            [r, -r2, 2.0 * r2 * r]
4724        });
4725        self.compose_unary(d)
4726    }
4727
4728    /// `self^a` for real `a`; caller guarantees a positive base. Per-lane
4729    /// falling-factorial stack (matches [`JetScalar::powf`]).
4730    #[inline]
4731    pub fn powf(&self, a: f64) -> Self {
4732        let d = self.v.unary3(|u| {
4733            [
4734                u.powf(a),
4735                a * u.powf(a - 1.0),
4736                a * (a - 1.0) * u.powf(a - 2.0),
4737            ]
4738        });
4739        self.compose_unary(d)
4740    }
4741}
4742
4743impl<const K: usize> Order2Batch<K> {
4744    /// Extract lane `i`'s `(v, g, H)` as a production [`Order2<K>`] scalar.
4745    /// Lane `i` is `to_bits`-identical to evaluating the same program at
4746    /// [`Order2<K>`] on row `i` (see `batch_tests`).
4747    #[inline]
4748    #[must_use]
4749    pub fn lane(&self, i: usize) -> Order2<K> {
4750        let mut t = crate::jet_tower::Tower2::<K>::constant(self.v.lane(i));
4751        for a in 0..K {
4752            t.g[a] = self.g[a].lane(i);
4753            for b in 0..K {
4754                t.h[a][b] = self.h[a][b].lane(i);
4755            }
4756        }
4757        Order2(t)
4758    }
4759}
4760
4761// ── Order1<K>: value / gradient only (doc §A.1, first-order prune) ──────
4762
4763/// Truncated FIRST-order scalar: value `v` and gradient `g_a` only — NO Hessian.
4764///
4765/// This is [`Order2`] with the K×K Hessian channel deleted. Its value and
4766/// gradient are computed by the SAME order-≤1 truncation of the Leibniz / Faà
4767/// di Bruno rules that [`Order2`] uses for those two channels, with the float
4768/// operations applied in the identical order — so its `(v, g)` is BIT-IDENTICAL
4769/// to both [`Order2`]'s and a full [`crate::jet_tower::Tower4`]'s order-≤1
4770/// channels. Use it at a consumer that reads ONLY value + gradient (the SAE
4771/// β-border channel: the reconstruction is linear in β, so the Hessian-in-β
4772/// vanishes and the dense K×K Hessian product `Tower2::mul` would build is pure
4773/// discarded work). Order-≤1 value/gradient never read any input's Hessian, so
4774/// dropping that channel changes neither result nor float-op order — it only
4775/// removes the `K²` arithmetic that produced an unread tensor.
4776#[derive(Clone, Copy, Debug)]
4777pub struct Order1<const K: usize> {
4778    /// Value ℓ.
4779    pub v: f64,
4780    /// Gradient ∂ℓ/∂p_a.
4781    pub g: [f64; K],
4782}
4783
4784impl<const K: usize> Order1<K> {
4785    /// Read the gradient channel `g_a = ∂ℓ/∂p_a`.
4786    #[inline]
4787    #[must_use]
4788    pub fn g(&self) -> &[f64; K] {
4789        &self.g
4790    }
4791
4792    /// Consume the jet and move out its value and gradient channels.
4793    #[inline]
4794    #[must_use]
4795    pub fn into_channels(self) -> (f64, [f64; K]) {
4796        (self.v, self.g)
4797    }
4798}
4799
4800impl<const K: usize> JetScalar<K> for Order1<K> {
4801    fn constant(c: f64) -> Self {
4802        // Order2::constant -> Tower2::constant: value c, all derivatives zero.
4803        Order1 { v: c, g: [0.0; K] }
4804    }
4805    fn variable(x: f64, axis: usize) -> Self {
4806        // Order2::variable -> Tower2::variable: unit first derivative in `axis`.
4807        let mut g = [0.0; K];
4808        g[axis] = 1.0;
4809        Order1 { v: x, g }
4810    }
4811}
4812
4813impl<const K: usize> crate::nested_dual::JetField for Order1<K> {
4814    fn value(&self) -> f64 {
4815        self.v
4816    }
4817    fn add(&self, o: &Self) -> Self {
4818        // Tower2 Add: out.v += o.v; out.g[i] += o.g[i] (same float order).
4819        let mut g = self.g;
4820        for i in 0..K {
4821            g[i] += o.g[i];
4822        }
4823        Order1 { v: self.v + o.v, g }
4824    }
4825    fn sub(&self, o: &Self) -> Self {
4826        // Mirror Order2::sub == self + o.scale(-1.0) exactly: scale then add.
4827        self.add(&o.scale(-1.0))
4828    }
4829    fn mul(&self, o: &Self) -> Self {
4830        // Tower2::mul value/grad terms, identical float order:
4831        //   v = a.v*b.v;  g[i] = a.v*b.g[i] + a.g[i]*b.v.
4832        // (The Hessian loop `a.v*b.h + a.g*b.g + ... + a.h*b.v` is the discarded
4833        //  work this type exists to skip; it never feeds v or g.)
4834        let a = self;
4835        let b = o;
4836        let mut g = [0.0; K];
4837        for i in 0..K {
4838            g[i] = a.v * b.g[i] + a.g[i] * b.v;
4839        }
4840        Order1 { v: a.v * b.v, g }
4841    }
4842    fn neg(&self) -> Self {
4843        // Order2::neg == self.0.scale(-1.0).
4844        self.scale(-1.0)
4845    }
4846    fn scale(&self, s: f64) -> Self {
4847        // Tower2::scale: out.v *= s; out.g[i] *= s (same float order).
4848        let mut g = self.g;
4849        for i in 0..K {
4850            g[i] *= s;
4851        }
4852        Order1 { v: self.v * s, g }
4853    }
4854    fn compose_unary(&self, d: [f64; 5]) -> Self {
4855        // Faà di Bruno truncated to order ≤ 1 (matches `faa_di_bruno` /
4856        // `Tower2::compose_unary` for the value and gradient channels):
4857        //   value channel (m=0): d[0].
4858        //   grad channel (positions=[i], single partition {{0}}): d[1]·g[i].
4859        // Order-≤1 reads only d[0], d[1]; trailing stack entries are unused.
4860        let mut g = [0.0; K];
4861        for i in 0..K {
4862            g[i] = d[1] * self.g[i];
4863        }
4864        Order1 { v: d[0], g }
4865    }
4866}
4867
4868// ── OneSeed<K>: one-seed directional, contracted third (doc §A.2) ───────
4869
4870/// One-seed directional scalar: an [`Order2`] base plus ONE nilpotent ε
4871/// (`ε² = 0`) whose coefficient is itself an [`Order2`].
4872///
4873/// A scalar is `s = base + ε·eps`. Arithmetic is the `ε² = 0` truncation of the
4874/// product (doc §A.2): the base parts multiply as ordinary [`Order2`] products,
4875/// and the ε-coefficient picks up `a.base·b.eps + a.eps·b.base`. Composition
4876/// pushes ε through one extra outer derivative.
4877///
4878/// Seed each primary with [`seed_direction`](Self::seed_direction): the base is
4879/// the usual seeded variable (carrying `e_a` for the Hessian channel) and the
4880/// ε-coefficient is the FIXED contraction direction `u_a` (a constant). Then the
4881/// ε-component of the evaluated Hessian channel is the contracted third
4882/// `[eps.h][a][b] = Σ_c ℓ_{abc} u_c` — exactly `row_third_contracted(dir = u)`,
4883/// without materialising `t3`.
4884#[derive(Clone, Copy, Debug)]
4885pub struct OneSeed<const K: usize> {
4886    /// The `ε⁰` part: value / gradient / Hessian of `ℓ`.
4887    pub base: Order2<K>,
4888    /// The `ε¹` part: value / gradient / Hessian of the ε-coefficient. After a
4889    /// `seed_direction(u)` evaluation, `eps.h[a][b] = Σ_c ℓ_{abc} u_c`.
4890    pub eps: Order2<K>,
4891}
4892
4893impl<const K: usize> OneSeed<K> {
4894    /// Seed primary `axis` at value `x` with ε-direction component `u_axis`:
4895    /// `p_axis = p_axis⁰ + x-seed + ε·u_axis`, i.e. base = `variable(x, axis)`
4896    /// and eps = `constant(u_axis)` (doc §A.2 "Seeding").
4897    pub fn seed_direction(x: f64, axis: usize, u_axis: f64) -> Self {
4898        OneSeed {
4899            base: Order2::variable(x, axis),
4900            eps: Order2::constant(u_axis),
4901        }
4902    }
4903
4904    /// The contracted-third channel after a `seed_direction(u)` evaluation:
4905    /// `out[a][b] = Σ_c ℓ_{abc} u_c`, i.e. the ε-coefficient's Hessian (doc §A.2).
4906    pub fn contracted_third(&self) -> [[f64; K]; K] {
4907        *self.eps.h()
4908    }
4909}
4910
4911impl<const K: usize> JetScalar<K> for OneSeed<K> {
4912    fn constant(c: f64) -> Self {
4913        OneSeed {
4914            base: Order2::constant(c),
4915            eps: Order2::constant(0.0),
4916        }
4917    }
4918    fn variable(x: f64, axis: usize) -> Self {
4919        // No ε-direction unless seeded via `seed_direction`.
4920        OneSeed {
4921            base: Order2::variable(x, axis),
4922            eps: Order2::constant(0.0),
4923        }
4924    }
4925}
4926
4927impl<const K: usize> crate::nested_dual::JetField for OneSeed<K> {
4928    fn value(&self) -> f64 {
4929        self.base.value()
4930    }
4931    fn add(&self, o: &Self) -> Self {
4932        OneSeed {
4933            base: self.base.add(&o.base),
4934            eps: self.eps.add(&o.eps),
4935        }
4936    }
4937    fn sub(&self, o: &Self) -> Self {
4938        OneSeed {
4939            base: self.base.sub(&o.base),
4940            eps: self.eps.sub(&o.eps),
4941        }
4942    }
4943    fn mul(&self, o: &Self) -> Self {
4944        // (a.base + ε a.eps)(b.base + ε b.eps), dropping ε².  Build
4945        // the epsilon channels directly instead of materialising two complete
4946        // Order2 products and adding them.  The upper triangle is sufficient:
4947        // every input Hessian is symmetric and this polynomial preserves that
4948        // invariant exactly.
4949        let ab = &self.base.0;
4950        let ae = &self.eps.0;
4951        let bb = &o.base.0;
4952        let be = &o.eps.0;
4953        let mut eps = crate::jet_tower::Tower2::<K>::zero();
4954        eps.v = ab.v * be.v + ae.v * bb.v;
4955        for i in 0..K {
4956            eps.g[i] = ab.v * be.g[i] + ab.g[i] * be.v + ae.v * bb.g[i] + ae.g[i] * bb.v;
4957        }
4958        for i in 0..K {
4959            for j in i..K {
4960                let channel = ab.v * be.h[i][j]
4961                    + ab.g[i] * be.g[j]
4962                    + ab.g[j] * be.g[i]
4963                    + ab.h[i][j] * be.v
4964                    + ae.v * bb.h[i][j]
4965                    + ae.g[i] * bb.g[j]
4966                    + ae.g[j] * bb.g[i]
4967                    + ae.h[i][j] * bb.v;
4968                eps.h[i][j] = channel;
4969                eps.h[j][i] = channel;
4970            }
4971        }
4972        OneSeed {
4973            base: self.base.mul(&o.base),
4974            eps: Order2(eps),
4975        }
4976    }
4977    fn neg(&self) -> Self {
4978        OneSeed {
4979            base: self.base.neg(),
4980            eps: self.eps.neg(),
4981        }
4982    }
4983    fn scale(&self, s: f64) -> Self {
4984        OneSeed {
4985            base: self.base.scale(s),
4986            eps: self.eps.scale(s),
4987        }
4988    }
4989    fn compose_unary(&self, d: [f64; 5]) -> Self {
4990        // f(base + ε eps) = f(base) + ε · f'(base)·eps (ε² = 0).
4991        // Fuse the shifted composition and product into their final channels;
4992        // this removes one temporary Order2 composition and one Order2 product
4993        // from every unary primitive in a directional row program.
4994        let base = self.base.compose_unary([d[0], d[1], d[2], d[3], d[4]]);
4995        let b = &self.base.0;
4996        let e = &self.eps.0;
4997        let mut eps = crate::jet_tower::Tower2::<K>::zero();
4998        eps.v = d[1] * e.v;
4999        for i in 0..K {
5000            eps.g[i] = d[2] * b.g[i] * e.v + d[1] * e.g[i];
5001        }
5002        for i in 0..K {
5003            for j in i..K {
5004                let channel = d[1] * e.h[i][j]
5005                    + d[2] * (b.g[i] * e.g[j] + b.g[j] * e.g[i] + b.h[i][j] * e.v)
5006                    + d[3] * b.g[i] * b.g[j] * e.v;
5007                eps.h[i][j] = channel;
5008                eps.h[j][i] = channel;
5009            }
5010        }
5011        OneSeed {
5012            base,
5013            eps: Order2(eps),
5014        }
5015    }
5016    fn constant_like(&self, v: f64) -> Self {
5017        OneSeed {
5018            base: self.base.constant_like(v),
5019            eps: self.eps.constant_like(0.0),
5020        }
5021    }
5022    fn with_value(&self, v: f64) -> Self {
5023        // The real value channel is the base part's; the ε part carries no
5024        // value of its own.
5025        OneSeed {
5026            base: self.base.with_value(v),
5027            eps: self.eps,
5028        }
5029    }
5030}
5031
5032// ── OneSeedLane<L, K>: lane-batched one-seed directional (doc §A.2) ──────
5033
5034/// Lane-batched [`OneSeed`]: the same one-seed directional scalar with its two
5035/// [`Order2`] parts re-typed to [`Order2Lane<L, K>`], so one `L = f64x4`
5036/// instance carries FOUR rows' contracted-third evaluations per vector pass.
5037///
5038/// Every operation (`add`/`sub`/`mul`/`neg`/`scale`/`compose_unary` and the
5039/// transcendentals) is a term-for-term structural re-type of the scalar
5040/// [`OneSeed`] ops onto the lane-implemented [`Order2Lane`] algebra. With
5041/// `L = f64`, `OneSeedLane<f64, K>` is `to_bits`-identical to [`OneSeed<K>`];
5042/// with `L = f64x4`, lane `i` is `to_bits`-identical to that (see `batch_tests`).
5043#[derive(Clone, Copy, Debug)]
5044pub struct OneSeedLane<L: Lane, const K: usize> {
5045    /// The `ε⁰` part (lane-batched value / gradient / Hessian of `ℓ`).
5046    pub base: Order2Lane<L, K>,
5047    /// The `ε¹` part. After a `seed_direction(u)` evaluation,
5048    /// `eps.h[a][b]` lane `i` is row `i`'s `Σ_c ℓ_{abc} u_c`.
5049    pub eps: Order2Lane<L, K>,
5050}
5051
5052/// The 4-rows-per-pass batched one-seed scalar (`wide::f64x4` lanes).
5053pub type OneSeedBatch<const K: usize> = OneSeedLane<wide::f64x4, K>;
5054
5055impl<L: Lane, const K: usize> OneSeedLane<L, K> {
5056    /// A constant: base = `constant(c)`, ε-part zero (mirrors [`OneSeed::constant`]).
5057    #[inline]
5058    pub fn constant(c: L) -> Self {
5059        OneSeedLane {
5060            base: Order2Lane::constant(c),
5061            eps: Order2Lane::constant(L::splat(0.0)),
5062        }
5063    }
5064
5065    /// The seeded variable `p_axis` at (per-lane) value `value`, no ε-direction
5066    /// (mirrors [`OneSeed::variable`]).
5067    #[inline]
5068    pub fn variable(value: L, axis: usize) -> Self {
5069        OneSeedLane {
5070            base: Order2Lane::variable(value, axis),
5071            eps: Order2Lane::constant(L::splat(0.0)),
5072        }
5073    }
5074
5075    /// Seed primary `axis` at (per-lane) value `value` with ε-direction
5076    /// component `u_axis`: base = `variable(value, axis)`, eps = `constant(u_axis)`
5077    /// (mirrors [`OneSeed::seed_direction`]). With `L = f64x4`, `value` / `u_axis`
5078    /// pack the four rows' values / directions of primary `axis`.
5079    #[inline]
5080    pub fn seed_direction(value: L, axis: usize, u_axis: L) -> Self {
5081        OneSeedLane {
5082            base: Order2Lane::variable(value, axis),
5083            eps: Order2Lane::constant(u_axis),
5084        }
5085    }
5086
5087    /// The contracted-third channel after a `seed_direction(u)` evaluation:
5088    /// `out[a][b]` lane `i` is row `i`'s `Σ_c ℓ_{abc} u_c` (the ε-part Hessian).
5089    #[inline]
5090    #[must_use]
5091    pub fn contracted_third(&self) -> [[L; K]; K] {
5092        self.eps.h
5093    }
5094
5095    /// Lane-wise `self + o` (mirrors [`OneSeed::add`](crate::nested_dual::JetField::add)).
5096    #[inline]
5097    pub fn add(&self, o: &Self) -> Self {
5098        OneSeedLane {
5099            base: self.base.add(&o.base),
5100            eps: self.eps.add(&o.eps),
5101        }
5102    }
5103
5104    /// Lane-wise `self - o` (mirrors [`OneSeed::sub`](crate::nested_dual::JetField::sub)).
5105    #[inline]
5106    pub fn sub(&self, o: &Self) -> Self {
5107        OneSeedLane {
5108            base: self.base.sub(&o.base),
5109            eps: self.eps.sub(&o.eps),
5110        }
5111    }
5112
5113    /// Lane-wise `self · o`, ε² = 0 truncation (mirrors [`OneSeed::mul`](crate::nested_dual::JetField::mul)).
5114    #[inline]
5115    pub fn mul(&self, o: &Self) -> Self {
5116        let ab = &self.base;
5117        let ae = &self.eps;
5118        let bb = &o.base;
5119        let be = &o.eps;
5120        let mut eps = Order2Lane::constant(ab.v.mul(be.v).add(ae.v.mul(bb.v)));
5121        for i in 0..K {
5122            eps.g[i] =
5123                ab.v.mul(be.g[i])
5124                    .add(ab.g[i].mul(be.v))
5125                    .add(ae.v.mul(bb.g[i]))
5126                    .add(ae.g[i].mul(bb.v));
5127        }
5128        for i in 0..K {
5129            for j in i..K {
5130                let channel =
5131                    ab.v.mul(be.h[i][j])
5132                        .add(ab.g[i].mul(be.g[j]))
5133                        .add(ab.g[j].mul(be.g[i]))
5134                        .add(ab.h[i][j].mul(be.v))
5135                        .add(ae.v.mul(bb.h[i][j]))
5136                        .add(ae.g[i].mul(bb.g[j]))
5137                        .add(ae.g[j].mul(bb.g[i]))
5138                        .add(ae.h[i][j].mul(bb.v));
5139                eps.h[i][j] = channel;
5140                eps.h[j][i] = channel;
5141            }
5142        }
5143        OneSeedLane {
5144            base: self.base.mul(&o.base),
5145            eps,
5146        }
5147    }
5148
5149    /// Negate every part (mirrors [`OneSeed::neg`](crate::nested_dual::JetField::neg)).
5150    #[inline]
5151    pub fn neg(&self) -> Self {
5152        OneSeedLane {
5153            base: self.base.neg(),
5154            eps: self.eps.neg(),
5155        }
5156    }
5157
5158    /// Multiply every part by the plain scalar `s` (mirrors [`OneSeed::scale`](crate::nested_dual::JetField::scale)).
5159    #[inline]
5160    pub fn scale(&self, s: f64) -> Self {
5161        OneSeedLane {
5162            base: self.base.scale(s),
5163            eps: self.eps.scale(s),
5164        }
5165    }
5166
5167    /// Exact order-≤2-per-part Faà di Bruno composition `f ∘ self`, given the
5168    /// per-lane outer-derivative stack `d = [f, f′, f″, f‴, f⁗]`. Term-for-term
5169    /// identical to the fused [`OneSeed::compose_unary`](crate::nested_dual::JetField::compose_unary) channels: the base reads
5170    /// `d[0..=2]`, while the ε-coefficient directly evaluates
5171    /// `f′(base)·eps` from `d[1..=3]` without an intermediate jet.
5172    #[inline]
5173    pub fn compose_unary(&self, d: [L; 5]) -> Self {
5174        let base = self.base.compose_unary([d[0], d[1], d[2]]);
5175        let b = &self.base;
5176        let e = &self.eps;
5177        let mut eps = Order2Lane::constant(d[1].mul(e.v));
5178        for i in 0..K {
5179            eps.g[i] = d[2].mul(b.g[i]).mul(e.v).add(d[1].mul(e.g[i]));
5180        }
5181        for i in 0..K {
5182            for j in i..K {
5183                let mixed = b.g[i]
5184                    .mul(e.g[j])
5185                    .add(b.g[j].mul(e.g[i]))
5186                    .add(b.h[i][j].mul(e.v));
5187                let channel = d[1]
5188                    .mul(e.h[i][j])
5189                    .add(d[2].mul(mixed))
5190                    .add(d[3].mul(b.g[i]).mul(b.g[j]).mul(e.v));
5191                eps.h[i][j] = channel;
5192                eps.h[j][i] = channel;
5193            }
5194        }
5195        OneSeedLane { base, eps }
5196    }
5197
5198    /// `e^self`, per-lane stack `[e, e, e, e, e]` (matches [`JetScalar::exp`]).
5199    #[inline]
5200    pub fn exp(&self) -> Self {
5201        let d = self.base.v.unary5(|u| {
5202            let e = u.exp();
5203            [e, e, e, e, e]
5204        });
5205        self.compose_unary(d)
5206    }
5207
5208    /// `ln(self)`; caller guarantees positivity (matches [`JetScalar::ln`]).
5209    #[inline]
5210    pub fn ln(&self) -> Self {
5211        let d = self.base.v.unary5(|u| {
5212            let r = 1.0 / u;
5213            [u.ln(), r, -r * r, 2.0 * r * r * r, -6.0 * r * r * r * r]
5214        });
5215        self.compose_unary(d)
5216    }
5217
5218    /// `√self`; caller guarantees positivity (matches [`JetScalar::sqrt`]).
5219    #[inline]
5220    pub fn sqrt(&self) -> Self {
5221        let d = self.base.v.unary5(|u| {
5222            let s = u.sqrt();
5223            [
5224                s,
5225                0.5 / s,
5226                -0.25 / (u * s),
5227                0.375 / (u * u * s),
5228                -0.9375 / (u * u * u * s),
5229            ]
5230        });
5231        self.compose_unary(d)
5232    }
5233
5234    /// `1/self` (matches [`JetScalar::recip`]).
5235    #[inline]
5236    pub fn recip(&self) -> Self {
5237        let d = self.base.v.unary5(|u| {
5238            let r = 1.0 / u;
5239            let r2 = r * r;
5240            [r, -r2, 2.0 * r2 * r, -6.0 * r2 * r2, 24.0 * r2 * r2 * r]
5241        });
5242        self.compose_unary(d)
5243    }
5244
5245    /// `self^a` for real `a`; caller guarantees a positive base (matches
5246    /// [`JetScalar::powf`]).
5247    #[inline]
5248    pub fn powf(&self, a: f64) -> Self {
5249        let d = self.base.v.unary5(|u| {
5250            [
5251                u.powf(a),
5252                a * u.powf(a - 1.0),
5253                a * (a - 1.0) * u.powf(a - 2.0),
5254                a * (a - 1.0) * (a - 2.0) * u.powf(a - 3.0),
5255                a * (a - 1.0) * (a - 2.0) * (a - 3.0) * u.powf(a - 4.0),
5256            ]
5257        });
5258        self.compose_unary(d)
5259    }
5260
5261    /// `ln Γ(self)`; caller guarantees positivity (matches [`JetScalar::ln_gamma`],
5262    /// same hand-certified stack).
5263    #[inline]
5264    pub fn ln_gamma(&self) -> Self {
5265        let d = self
5266            .base
5267            .v
5268            .unary5(crate::jet_tower::ln_gamma_derivative_stack);
5269        self.compose_unary(d)
5270    }
5271
5272}
5273
5274impl<const K: usize> OneSeedBatch<K> {
5275    /// Extract lane `i`'s parts as a production [`OneSeed<K>`]. Lane `i` is
5276    /// `to_bits`-identical to evaluating the same program at [`OneSeed<K>`] on
5277    /// row `i` (see `batch_tests`).
5278    #[inline]
5279    #[must_use]
5280    pub fn lane(&self, i: usize) -> OneSeed<K> {
5281        OneSeed {
5282            base: self.base.lane(i),
5283            eps: self.eps.lane(i),
5284        }
5285    }
5286}
5287
5288// ── TwoSeed<K>: two-seed, contracted fourth (doc §A.3) ──────────────────
5289
5290/// Two-seed scalar: an [`Order2`] base plus TWO nilpotents ε, δ
5291/// (`ε² = δ² = 0`, `εδ` retained) — four [`Order2`] parts
5292/// `s = base + ε·eps + δ·del + εδ·eps_del`.
5293///
5294/// Product truncates `ε² = δ² = 0` (doc §A.3): each part is built from
5295/// [`Order2`] products of the four input parts. Composition picks up
5296/// successively higher outer derivatives, the cross part carrying the second
5297/// Faà di Bruno term `f''·eps·del + f'·eps_del`.
5298///
5299/// Seed each primary with [`seed`](Self::seed): base = `variable(x, axis)`,
5300/// eps = `constant(u_axis)`, del = `constant(v_axis)`, eps_del = `constant(0)`.
5301/// Then the εδ-component of the evaluated Hessian channel is the contracted
5302/// fourth `[eps_del.h][a][b] = Σ_{cd} ℓ_{abcd} u_c v_d` — exactly
5303/// `row_fourth_contracted(u, v)`, without materialising `t4`.
5304#[derive(Clone, Copy, Debug)]
5305pub struct TwoSeed<const K: usize> {
5306    /// The `ε⁰δ⁰` part: value / grad / Hessian of `ℓ`.
5307    pub base: Order2<K>,
5308    /// The `ε¹δ⁰` part.
5309    pub eps: Order2<K>,
5310    /// The `ε⁰δ¹` part.
5311    pub del: Order2<K>,
5312    /// The `ε¹δ¹` part. After a `seed(u, v)` evaluation,
5313    /// `eps_del.h[a][b] = Σ_{cd} ℓ_{abcd} u_c v_d`.
5314    pub eps_del: Order2<K>,
5315}
5316
5317impl<const K: usize> TwoSeed<K> {
5318    /// Seed primary `axis` at value `x` with ε-direction `u_axis` and
5319    /// δ-direction `v_axis`:
5320    /// `p_axis = p_axis⁰ + x-seed + ε·u_axis + δ·v_axis` (doc §A.3 "Seeding").
5321    pub fn seed(x: f64, axis: usize, u_axis: f64, v_axis: f64) -> Self {
5322        TwoSeed {
5323            base: Order2::variable(x, axis),
5324            eps: Order2::constant(u_axis),
5325            del: Order2::constant(v_axis),
5326            eps_del: Order2::constant(0.0),
5327        }
5328    }
5329
5330    /// The contracted-fourth channel after a `seed(u, v)` evaluation:
5331    /// `out[a][b] = Σ_{cd} ℓ_{abcd} u_c v_d`, i.e. the εδ-coefficient's Hessian.
5332    pub fn contracted_fourth(&self) -> [[f64; K]; K] {
5333        *self.eps_del.h()
5334    }
5335}
5336
5337impl<const K: usize> JetScalar<K> for TwoSeed<K> {
5338    fn constant(c: f64) -> Self {
5339        TwoSeed {
5340            base: Order2::constant(c),
5341            eps: Order2::constant(0.0),
5342            del: Order2::constant(0.0),
5343            eps_del: Order2::constant(0.0),
5344        }
5345    }
5346    fn variable(x: f64, axis: usize) -> Self {
5347        TwoSeed {
5348            base: Order2::variable(x, axis),
5349            eps: Order2::constant(0.0),
5350            del: Order2::constant(0.0),
5351            eps_del: Order2::constant(0.0),
5352        }
5353    }
5354}
5355
5356impl<const K: usize> crate::nested_dual::JetField for TwoSeed<K> {
5357    fn value(&self) -> f64 {
5358        self.base.value()
5359    }
5360    fn add(&self, o: &Self) -> Self {
5361        TwoSeed {
5362            base: self.base.add(&o.base),
5363            eps: self.eps.add(&o.eps),
5364            del: self.del.add(&o.del),
5365            eps_del: self.eps_del.add(&o.eps_del),
5366        }
5367    }
5368    fn sub(&self, o: &Self) -> Self {
5369        TwoSeed {
5370            base: self.base.sub(&o.base),
5371            eps: self.eps.sub(&o.eps),
5372            del: self.del.sub(&o.del),
5373            eps_del: self.eps_del.sub(&o.eps_del),
5374        }
5375    }
5376    fn mul(&self, o: &Self) -> Self {
5377        let a = self;
5378        let b = o;
5379        // Truncate ε² = δ² = 0 (doc §A.3 product table).
5380        let base = a.base.mul(&b.base);
5381        let eps = a.base.mul(&b.eps).add(&a.eps.mul(&b.base));
5382        let del = a.base.mul(&b.del).add(&a.del.mul(&b.base));
5383        let eps_del = a
5384            .base
5385            .mul(&b.eps_del)
5386            .add(&a.eps.mul(&b.del))
5387            .add(&a.del.mul(&b.eps))
5388            .add(&a.eps_del.mul(&b.base));
5389        TwoSeed {
5390            base,
5391            eps,
5392            del,
5393            eps_del,
5394        }
5395    }
5396    fn neg(&self) -> Self {
5397        TwoSeed {
5398            base: self.base.neg(),
5399            eps: self.eps.neg(),
5400            del: self.del.neg(),
5401            eps_del: self.eps_del.neg(),
5402        }
5403    }
5404    fn scale(&self, s: f64) -> Self {
5405        TwoSeed {
5406            base: self.base.scale(s),
5407            eps: self.eps.scale(s),
5408            del: self.del.scale(s),
5409            eps_del: self.eps_del.scale(s),
5410        }
5411    }
5412    fn compose_unary(&self, d: [f64; 5]) -> Self {
5413        // f(s) with s = base + ε eps + δ del + εδ eps_del, ε²=δ²=0:
5414        //   f(s) = f(base)
5415        //        + ε · f'(base)·eps
5416        //        + δ · f'(base)·del
5417        //        + εδ · ( f''(base)·eps·del + f'(base)·eps_del ).
5418        // Each f^{(r)}(base) is the Order2 composition of base with the stack
5419        // shifted r entries (doc §A.3 composition). Order2 reads only the
5420        // leading three entries of whatever stack it is handed, so the trailing
5421        // padding slots are unused (the fixed-length array makes this total).
5422        let base = self.base.compose_unary([d[0], d[1], d[2], d[3], d[4]]);
5423        let fprime = self.base.compose_unary([d[1], d[2], d[3], d[4], d[4]]); // f'(base) as Order2
5424        let fsecond = self.base.compose_unary([d[2], d[3], d[4], d[4], d[4]]); // f''(base) as Order2
5425        let eps = fprime.mul(&self.eps);
5426        let del = fprime.mul(&self.del);
5427        let eps_del = fsecond
5428            .mul(&self.eps)
5429            .mul(&self.del)
5430            .add(&fprime.mul(&self.eps_del));
5431        TwoSeed {
5432            base,
5433            eps,
5434            del,
5435            eps_del,
5436        }
5437    }
5438}
5439
5440// ── TwoSeedLane<L, K>: lane-batched two-seed, contracted fourth (doc §A.3) ─
5441
5442/// Lane-batched [`TwoSeed`]: the same two-seed scalar with its four [`Order2`]
5443/// parts re-typed to [`Order2Lane<L, K>`], so one `L = f64x4` instance carries
5444/// FOUR rows' contracted-fourth evaluations per vector pass.
5445///
5446/// Every operation is a term-for-term structural re-type of the scalar
5447/// [`TwoSeed`] ops onto the lane-implemented [`Order2Lane`] algebra. With
5448/// `L = f64`, `TwoSeedLane<f64, K>` is `to_bits`-identical to [`TwoSeed<K>`];
5449/// with `L = f64x4`, lane `i` is `to_bits`-identical to that (see `batch_tests`).
5450#[derive(Clone, Copy, Debug)]
5451pub struct TwoSeedLane<L: Lane, const K: usize> {
5452    /// The `ε⁰δ⁰` part.
5453    pub base: Order2Lane<L, K>,
5454    /// The `ε¹δ⁰` part.
5455    pub eps: Order2Lane<L, K>,
5456    /// The `ε⁰δ¹` part.
5457    pub del: Order2Lane<L, K>,
5458    /// The `ε¹δ¹` part. After a `seed(u, v)` evaluation, `eps_del.h[a][b]`
5459    /// lane `i` is row `i`'s `Σ_{cd} ℓ_{abcd} u_c v_d`.
5460    pub eps_del: Order2Lane<L, K>,
5461}
5462
5463/// The 4-rows-per-pass batched two-seed scalar (`wide::f64x4` lanes).
5464pub type TwoSeedBatch<const K: usize> = TwoSeedLane<wide::f64x4, K>;
5465
5466impl<L: Lane, const K: usize> TwoSeedLane<L, K> {
5467    /// A constant: base = `constant(c)`, all seed parts zero (mirrors
5468    /// [`TwoSeed::constant`]).
5469    #[inline]
5470    pub fn constant(c: L) -> Self {
5471        let z = Order2Lane::constant(L::splat(0.0));
5472        TwoSeedLane {
5473            base: Order2Lane::constant(c),
5474            eps: z,
5475            del: z,
5476            eps_del: z,
5477        }
5478    }
5479
5480    /// The seeded variable `p_axis` at (per-lane) value `value`, no ε/δ direction
5481    /// (mirrors [`TwoSeed::variable`]).
5482    #[inline]
5483    pub fn variable(value: L, axis: usize) -> Self {
5484        let z = Order2Lane::constant(L::splat(0.0));
5485        TwoSeedLane {
5486            base: Order2Lane::variable(value, axis),
5487            eps: z,
5488            del: z,
5489            eps_del: z,
5490        }
5491    }
5492
5493    /// Seed primary `axis` at (per-lane) value `value` with ε-direction `u_axis`
5494    /// and δ-direction `v_axis` (mirrors [`TwoSeed::seed`]). With `L = f64x4`,
5495    /// each argument packs the four rows' values for primary `axis`.
5496    #[inline]
5497    pub fn seed(value: L, axis: usize, u_axis: L, v_axis: L) -> Self {
5498        TwoSeedLane {
5499            base: Order2Lane::variable(value, axis),
5500            eps: Order2Lane::constant(u_axis),
5501            del: Order2Lane::constant(v_axis),
5502            eps_del: Order2Lane::constant(L::splat(0.0)),
5503        }
5504    }
5505
5506    /// The contracted-fourth channel after a `seed(u, v)` evaluation:
5507    /// `out[a][b]` lane `i` is row `i`'s `Σ_{cd} ℓ_{abcd} u_c v_d`
5508    /// (the εδ-part Hessian).
5509    #[inline]
5510    #[must_use]
5511    pub fn contracted_fourth(&self) -> [[L; K]; K] {
5512        self.eps_del.h
5513    }
5514
5515    /// Lane-wise `self + o` (mirrors [`TwoSeed::add`](crate::nested_dual::JetField::add)).
5516    #[inline]
5517    pub fn add(&self, o: &Self) -> Self {
5518        TwoSeedLane {
5519            base: self.base.add(&o.base),
5520            eps: self.eps.add(&o.eps),
5521            del: self.del.add(&o.del),
5522            eps_del: self.eps_del.add(&o.eps_del),
5523        }
5524    }
5525
5526    /// Lane-wise `self - o` (mirrors [`TwoSeed::sub`](crate::nested_dual::JetField::sub)).
5527    #[inline]
5528    pub fn sub(&self, o: &Self) -> Self {
5529        TwoSeedLane {
5530            base: self.base.sub(&o.base),
5531            eps: self.eps.sub(&o.eps),
5532            del: self.del.sub(&o.del),
5533            eps_del: self.eps_del.sub(&o.eps_del),
5534        }
5535    }
5536
5537    /// Lane-wise `self · o`, ε² = δ² = 0 truncation (mirrors [`TwoSeed::mul`](crate::nested_dual::JetField::mul)).
5538    #[inline]
5539    pub fn mul(&self, o: &Self) -> Self {
5540        let a = self;
5541        let b = o;
5542        let base = a.base.mul(&b.base);
5543        let eps = a.base.mul(&b.eps).add(&a.eps.mul(&b.base));
5544        let del = a.base.mul(&b.del).add(&a.del.mul(&b.base));
5545        let eps_del = a
5546            .base
5547            .mul(&b.eps_del)
5548            .add(&a.eps.mul(&b.del))
5549            .add(&a.del.mul(&b.eps))
5550            .add(&a.eps_del.mul(&b.base));
5551        TwoSeedLane {
5552            base,
5553            eps,
5554            del,
5555            eps_del,
5556        }
5557    }
5558
5559    /// Negate every part (mirrors [`TwoSeed::neg`](crate::nested_dual::JetField::neg)).
5560    #[inline]
5561    pub fn neg(&self) -> Self {
5562        TwoSeedLane {
5563            base: self.base.neg(),
5564            eps: self.eps.neg(),
5565            del: self.del.neg(),
5566            eps_del: self.eps_del.neg(),
5567        }
5568    }
5569
5570    /// Multiply every part by the plain scalar `s` (mirrors [`TwoSeed::scale`](crate::nested_dual::JetField::scale)).
5571    #[inline]
5572    pub fn scale(&self, s: f64) -> Self {
5573        TwoSeedLane {
5574            base: self.base.scale(s),
5575            eps: self.eps.scale(s),
5576            del: self.del.scale(s),
5577            eps_del: self.eps_del.scale(s),
5578        }
5579    }
5580
5581    /// Exact composition `f ∘ self`, given the per-lane outer-derivative stack
5582    /// `d = [f, f′, f″, f‴, f⁗]`. Term-for-term identical to
5583    /// [`TwoSeed::compose_unary`](crate::nested_dual::JetField::compose_unary): base reads `d[0..=2]`, `f′(base)` reads
5584    /// `d[1..=3]`, `f″(base)` reads `d[2..=4]`, and the cross part carries
5585    /// `f″·eps·del + f′·eps_del`.
5586    #[inline]
5587    pub fn compose_unary(&self, d: [L; 5]) -> Self {
5588        let base = self.base.compose_unary([d[0], d[1], d[2]]);
5589        let fprime = self.base.compose_unary([d[1], d[2], d[3]]);
5590        let fsecond = self.base.compose_unary([d[2], d[3], d[4]]);
5591        let eps = fprime.mul(&self.eps);
5592        let del = fprime.mul(&self.del);
5593        let eps_del = fsecond
5594            .mul(&self.eps)
5595            .mul(&self.del)
5596            .add(&fprime.mul(&self.eps_del));
5597        TwoSeedLane {
5598            base,
5599            eps,
5600            del,
5601            eps_del,
5602        }
5603    }
5604
5605    /// `e^self`, per-lane stack `[e; 5]` (matches [`JetScalar::exp`]).
5606    #[inline]
5607    pub fn exp(&self) -> Self {
5608        let d = self.base.v.unary5(|u| {
5609            let e = u.exp();
5610            [e, e, e, e, e]
5611        });
5612        self.compose_unary(d)
5613    }
5614
5615    /// `ln(self)`; caller guarantees positivity (matches [`JetScalar::ln`]).
5616    #[inline]
5617    pub fn ln(&self) -> Self {
5618        let d = self.base.v.unary5(|u| {
5619            let r = 1.0 / u;
5620            [u.ln(), r, -r * r, 2.0 * r * r * r, -6.0 * r * r * r * r]
5621        });
5622        self.compose_unary(d)
5623    }
5624
5625    /// `√self`; caller guarantees positivity (matches [`JetScalar::sqrt`]).
5626    #[inline]
5627    pub fn sqrt(&self) -> Self {
5628        let d = self.base.v.unary5(|u| {
5629            let s = u.sqrt();
5630            [
5631                s,
5632                0.5 / s,
5633                -0.25 / (u * s),
5634                0.375 / (u * u * s),
5635                -0.9375 / (u * u * u * s),
5636            ]
5637        });
5638        self.compose_unary(d)
5639    }
5640
5641    /// `1/self` (matches [`JetScalar::recip`]).
5642    #[inline]
5643    pub fn recip(&self) -> Self {
5644        let d = self.base.v.unary5(|u| {
5645            let r = 1.0 / u;
5646            let r2 = r * r;
5647            [r, -r2, 2.0 * r2 * r, -6.0 * r2 * r2, 24.0 * r2 * r2 * r]
5648        });
5649        self.compose_unary(d)
5650    }
5651
5652    /// `self^a` for real `a`; caller guarantees a positive base (matches
5653    /// [`JetScalar::powf`]).
5654    #[inline]
5655    pub fn powf(&self, a: f64) -> Self {
5656        let d = self.base.v.unary5(|u| {
5657            [
5658                u.powf(a),
5659                a * u.powf(a - 1.0),
5660                a * (a - 1.0) * u.powf(a - 2.0),
5661                a * (a - 1.0) * (a - 2.0) * u.powf(a - 3.0),
5662                a * (a - 1.0) * (a - 2.0) * (a - 3.0) * u.powf(a - 4.0),
5663            ]
5664        });
5665        self.compose_unary(d)
5666    }
5667
5668    /// `ln Γ(self)`; caller guarantees positivity (matches [`JetScalar::ln_gamma`]).
5669    #[inline]
5670    pub fn ln_gamma(&self) -> Self {
5671        let d = self
5672            .base
5673            .v
5674            .unary5(crate::jet_tower::ln_gamma_derivative_stack);
5675        self.compose_unary(d)
5676    }
5677
5678}
5679
5680impl<const K: usize> TwoSeedBatch<K> {
5681    /// Extract lane `i`'s parts as a production [`TwoSeed<K>`]. Lane `i` is
5682    /// `to_bits`-identical to evaluating the same program at [`TwoSeed<K>`] on
5683    /// row `i` (see `batch_tests`).
5684    #[inline]
5685    #[must_use]
5686    pub fn lane(&self, i: usize) -> TwoSeed<K> {
5687        TwoSeed {
5688            base: self.base.lane(i),
5689            eps: self.eps.lane(i),
5690            del: self.del.lane(i),
5691            eps_del: self.eps_del.lane(i),
5692        }
5693    }
5694}
5695
5696// ── Tower3<K>: value / gradient / Hessian / third tensor ────────────────
5697
5698/// The order-≤3 [`crate::jet_tower::Tower3`] is also a [`JetScalar`]. It serves
5699/// consumers that read `.t3` but never `.t4`, avoiding the fourth-tensor
5700/// product/composition work while preserving the lower channels
5701/// bit-for-bit against [`crate::jet_tower::Tower4`].
5702impl<const K: usize> JetScalar<K> for crate::jet_tower::Tower3<K> {
5703    fn constant(c: f64) -> Self {
5704        crate::jet_tower::Tower3::constant(c)
5705    }
5706    fn variable(x: f64, axis: usize) -> Self {
5707        crate::jet_tower::Tower3::variable(x, axis)
5708    }
5709}
5710
5711impl<const K: usize> crate::nested_dual::JetField for crate::jet_tower::Tower3<K> {
5712    fn value(&self) -> f64 {
5713        self.v
5714    }
5715    fn add(&self, o: &Self) -> Self {
5716        *self + *o
5717    }
5718    fn sub(&self, o: &Self) -> Self {
5719        *self + o.scale(-1.0)
5720    }
5721    fn mul(&self, o: &Self) -> Self {
5722        crate::jet_tower::Tower3::mul(self, o)
5723    }
5724    fn neg(&self) -> Self {
5725        self.scale(-1.0)
5726    }
5727    fn scale(&self, s: f64) -> Self {
5728        crate::jet_tower::Tower3::scale(self, s)
5729    }
5730    fn compose_unary(&self, d: [f64; 5]) -> Self {
5731        crate::jet_tower::Tower3::compose_unary(self, [d[0], d[1], d[2], d[3]])
5732    }
5733}
5734
5735// ── Tower4<K>: full dense tower as a JetScalar (the all-channels scalar) ─
5736
5737/// The full dense [`crate::jet_tower::Tower4`] is itself a [`JetScalar`]: it
5738/// carries EVERY channel, so a row expression written ONCE against [`JetScalar`]
5739/// can be evaluated at `Tower4` to obtain the full `(v, g, H, t3, t4)` in one
5740/// pass. This is BOTH the #932 oracle ground truth the packed [`Order2`] /
5741/// [`OneSeed`] / [`TwoSeed`] scalars are pinned against, AND a production scalar:
5742/// a family whose uncontracted third / fourth derivative tensors are needed
5743/// (the BMS rigid `third_full` / `fourth_full` caches) evaluates the SAME
5744/// generic row-NLL expression at `Tower4` and reads `.t3` / `.t4` off the
5745/// result — so the dense tensors come from the single source of truth, not a
5746/// separately hand-written jet. The packed scalars serve the consumers that
5747/// need only `(v, g, H)` (`Order2`) or one / two contractions
5748/// (`OneSeed` / `TwoSeed`) without paying for the dense tensors.
5749impl<const K: usize> JetScalar<K> for crate::jet_tower::Tower4<K> {
5750    fn constant(c: f64) -> Self {
5751        crate::jet_tower::Tower4::constant(c)
5752    }
5753    fn variable(x: f64, axis: usize) -> Self {
5754        crate::jet_tower::Tower4::variable(x, axis)
5755    }
5756}
5757
5758impl<const K: usize> crate::nested_dual::JetField for crate::jet_tower::Tower4<K> {
5759    fn value(&self) -> f64 {
5760        self.v
5761    }
5762    fn add(&self, o: &Self) -> Self {
5763        *self + *o
5764    }
5765    fn sub(&self, o: &Self) -> Self {
5766        *self - *o
5767    }
5768    fn mul(&self, o: &Self) -> Self {
5769        crate::jet_tower::Tower4::mul(self, o)
5770    }
5771    fn neg(&self) -> Self {
5772        self.scale(-1.0)
5773    }
5774    fn scale(&self, s: f64) -> Self {
5775        crate::jet_tower::Tower4::scale(self, s)
5776    }
5777    fn compose_unary(&self, d: [f64; 5]) -> Self {
5778        crate::jet_tower::Tower4::compose_unary(self, d)
5779    }
5780}
5781
5782#[cfg(test)]
5783mod tests {
5784    use super::*;
5785    use crate::jet_tower::{RowProgram, Tower4, program_full_tower};
5786    use crate::nested_dual::JetField;
5787
5788    #[test]
5789    fn runtime_fused_product_composition_preserves_tower4_channels() {
5790        const K: usize = 2;
5791        const N: usize = 9;
5792        let vars = [
5793            Tower4::<K>::variable(0.37, 0),
5794            Tower4::<K>::variable(-0.61, 1),
5795        ];
5796        let upstream = [
5797            vars[0].mul(&vars[1]).add(&vars[0].exp()),
5798            vars[1].mul(&vars[1]).add(&vars[0].scale(0.3)),
5799            vars[0].mul(&vars[0]).sub(&vars[1].scale(-0.2)),
5800        ];
5801        let mut lefts: [Tower4<K>; N] = std::array::from_fn(|term| upstream[term % upstream.len()]);
5802        lefts[4] = lefts[0];
5803        lefts[5] = lefts[0];
5804        let right = upstream[1];
5805        let addend = upstream[2];
5806        let addend_scales: [f64; N] = std::array::from_fn(|term| [-0.0, 1.0, -0.7, 0.25][term % 4]);
5807        let mut input_scales: [f64; N] =
5808            std::array::from_fn(|term| [0.0, -1.3, 0.45, 1.1][term % 4]);
5809        input_scales[0] = -1.1;
5810        input_scales[4] = 1.1;
5811        let stacks: [[f64; 5]; N] = std::array::from_fn(|term| {
5812            let t = term as f64 + 1.0;
5813            [0.17 * t, -0.11 * t, 0.07 * t, -0.03 * t, 0.013 * t]
5814        });
5815
5816        let expected = (0..N).fold(Tower4::<K>::constant(0.0), |sum, term| {
5817            let inner = if addend_scales[term] == 0.0 {
5818                lefts[term].mul(&right)
5819            } else if addend_scales[term] == 1.0 {
5820                JetScalar::multiply_add(&lefts[term], &right, &addend)
5821            } else {
5822                JetScalar::multiply_add(&lefts[term], &right, &addend.scale(addend_scales[term]))
5823            };
5824            sum.add(&JetScalar::affine_compose(
5825                &inner,
5826                input_scales[term],
5827                0.0,
5828                stacks[term],
5829            ))
5830        });
5831        let wrapped_lefts: [FixedRuntimeJet<Tower4<K>, K>; N] =
5832            std::array::from_fn(|term| FixedRuntimeJet::from_inner(lefts[term]));
5833        let wrapped_right = FixedRuntimeJet::from_inner(right);
5834        let wrapped_addend = FixedRuntimeJet::from_inner(addend);
5835        let mut wrapped_left_refs: [&FixedRuntimeJet<Tower4<K>, K>; N] =
5836            std::array::from_fn(|term| &wrapped_lefts[term]);
5837        wrapped_left_refs[4] = &wrapped_lefts[0];
5838        wrapped_left_refs[5] = &wrapped_lefts[0];
5839        let actual = FixedRuntimeJet::<Tower4<K>, K>::shared_multiply_add_affine_composed_sum(
5840            &wrapped_left_refs,
5841            &wrapped_right,
5842            &wrapped_addend,
5843            &addend_scales,
5844            &input_scales,
5845            &stacks,
5846            K,
5847            &(),
5848        )
5849        .into_inner();
5850
5851        let same = |label: &str, got: f64, want: f64| {
5852            let tolerance = 2.0e-13 * got.abs().max(want.abs()).max(1.0);
5853            assert!(
5854                (got - want).abs() <= tolerance,
5855                "{label}: got={got:+.17e}, want={want:+.17e}, tolerance={tolerance:.3e}"
5856            );
5857        };
5858        same("value", actual.v, expected.v);
5859        for a in 0..K {
5860            same("gradient", actual.g[a], expected.g[a]);
5861            for b in 0..K {
5862                same("Hessian", actual.h[a][b], expected.h[a][b]);
5863                for c in 0..K {
5864                    same("third", actual.t3[a][b][c], expected.t3[a][b][c]);
5865                    for d in 0..K {
5866                        same("fourth", actual.t4[a][b][c][d], expected.t4[a][b][c][d]);
5867                    }
5868                }
5869            }
5870        }
5871    }
5872
5873    /// A small polynomial-plus-unary row expression written ONCE, generically
5874    /// over `S: JetScalar<2>`, so it can be evaluated against every scalar:
5875    /// `ℓ = (e^{p0·p1} + 2) · √(p0·p0 + 1) − p1·p1·0.5`.
5876    /// Exercises mul, add/sub, scale, exp, sqrt — every algebra op.
5877    fn row_expr<S: JetScalar<2>>(p: &[S; 2]) -> S {
5878        let g = p[0].mul(&p[1]).exp();
5879        let inner = g.add(&S::constant(2.0));
5880        let radic = p[0].mul(&p[0]).add(&S::constant(1.0)).sqrt();
5881        inner.mul(&radic).sub(&p[1].mul(&p[1]).scale(0.5))
5882    }
5883
5884    /// The same expression exposed through the canonical generic row-program seam.
5885    struct ExprProgram {
5886        p: [f64; 2],
5887    }
5888    impl RowProgram<2> for ExprProgram {
5889        fn n_rows(&self) -> usize {
5890            1
5891        }
5892        fn primaries(&self, row: usize) -> Result<[f64; 2], String> {
5893            if row >= self.n_rows() {
5894                return Err(format!("ExprProgram: row {row} out of range"));
5895            }
5896            Ok(self.p)
5897        }
5898        fn eval<S: JetScalar<2>>(&self, row: usize, p: &[S; 2]) -> Result<S, String> {
5899            if row >= self.n_rows() {
5900                return Err(format!("ExprProgram: row {row} out of range"));
5901            }
5902            Ok(row_expr(p))
5903        }
5904    }
5905
5906    const SEED: [f64; 2] = [0.37, -0.81];
5907    const TOL: f64 = 1e-10;
5908
5909    fn close(a: f64, b: f64, label: &str) {
5910        let band = TOL + TOL * a.abs().max(b.abs());
5911        assert!(
5912            (a - b).abs() <= band,
5913            "{label}: {a:+.15e} vs {b:+.15e} (band {band:.3e})"
5914        );
5915    }
5916
5917    fn tower() -> Tower4<2> {
5918        *program_full_tower(&ExprProgram { p: SEED }, 0).expect("tower")
5919    }
5920
5921    /// Order2 reproduces Tower4's value/grad/Hessian channels exactly.
5922    #[test]
5923    fn order2_matches_tower_value_grad_hessian() {
5924        let t = tower();
5925        let vars: [Order2<2>; 2] = std::array::from_fn(|a| Order2::variable(SEED[a], a));
5926        let s = row_expr(&vars);
5927        close(s.value(), t.v, "value");
5928        for a in 0..2 {
5929            close(s.0.g[a], t.g[a], &format!("grad[{a}]"));
5930            for b in 0..2 {
5931                close(s.h()[a][b], t.h[a][b], &format!("hess[{a}][{b}]"));
5932            }
5933        }
5934    }
5935
5936    #[test]
5937    fn mapped_order2_accumulator_matches_dense_overlapping_atoms() {
5938        const K: usize = 4;
5939        let p = [0.2_f64, 0.7, -0.4, 0.3];
5940        let dense_vars: [Order2<K>; K] =
5941            std::array::from_fn(|axis| Order2::variable(p[axis], axis));
5942        let dense_q0 = dense_vars[3].mul(&dense_vars[1]).add(&dense_vars[3].exp());
5943        let dense_q1 = dense_vars[1].mul(&dense_vars[2]).sub(&dense_vars[2]);
5944        let dense = dense_q0.ln().add(&dense_q1.exp());
5945
5946        let local_q0_vars: [Order2<2>; 2] =
5947            std::array::from_fn(|axis| Order2::variable(p[[3, 1][axis]], axis));
5948        let local_q0 = local_q0_vars[0]
5949            .mul(&local_q0_vars[1])
5950            .add(&local_q0_vars[0].exp());
5951        let local_q1_vars: [Order2<2>; 2] =
5952            std::array::from_fn(|axis| Order2::variable(p[[1, 2][axis]], axis));
5953        let local_q1 = local_q1_vars[0]
5954            .mul(&local_q1_vars[1])
5955            .sub(&local_q1_vars[1]);
5956
5957        let q0 = local_q0.value();
5958        let q1_exp = local_q1.value().exp();
5959        let mut lowered = MappedOrder2Accumulator::<K>::zero();
5960        lowered.add_composed(
5961            &local_q0,
5962            [3, 1],
5963            [q0.ln(), q0.recip(), -1.0 / (q0 * q0)],
5964            false,
5965            [false, false],
5966            [false, false, false],
5967        );
5968        lowered.add_composed(
5969            &local_q1,
5970            [1, 2],
5971            [q1_exp, q1_exp, q1_exp],
5972            true,
5973            [true, false],
5974            [true, false, false],
5975        );
5976        let (value, gradient, hessian) = lowered.into_channels();
5977
5978        close(value, dense.value(), "mapped value");
5979        for i in 0..K {
5980            close(gradient[i], dense.g()[i], &format!("mapped gradient[{i}]"));
5981            for j in 0..K {
5982                close(
5983                    hessian[i][j],
5984                    dense.h()[i][j],
5985                    &format!("mapped Hessian[{i},{j}]"),
5986                );
5987            }
5988        }
5989    }
5990
5991    #[test]
5992    #[should_panic(expected = "mapped atom axes must be injective")]
5993    fn mapped_order2_accumulator_rejects_duplicate_axes() {
5994        let vars: [Order2<2>; 2] = std::array::from_fn(|axis| Order2::variable(0.2, axis));
5995        let atom = vars[0].add(&vars[1]);
5996        let mut lowered = MappedOrder2Accumulator::<2>::zero();
5997        lowered.add_composed(
5998            &atom,
5999            [1, 1],
6000            [0.4, 1.0, 0.0],
6001            false,
6002            [false, false],
6003            [false, false, false],
6004        );
6005    }
6006
6007    #[test]
6008    #[should_panic(expected = "mapped atom axis must be within")]
6009    fn mapped_order2_accumulator_rejects_out_of_range_axes() {
6010        let atom = Order2::<1>::variable(0.2, 0);
6011        let mut lowered = MappedOrder2Accumulator::<2>::zero();
6012        lowered.add_composed(&atom, [2], [0.2, 1.0, 0.0], false, [false], [false]);
6013    }
6014
6015    #[test]
6016    fn dynamic_order2_accumulator_matches_dense_composed_sum() {
6017        const K: usize = 4;
6018
6019        struct Term {
6020            first: f64,
6021            second: f64,
6022            gradient: [f64; K],
6023            hessian: [[f64; K]; K],
6024        }
6025
6026        impl DynamicOrder2Term for Term {
6027            fn outer_first(&self) -> f64 {
6028                self.first
6029            }
6030
6031            fn outer_second(&self) -> f64 {
6032                self.second
6033            }
6034
6035            fn inner_gradient(&self, axis: usize) -> f64 {
6036                self.gradient[axis]
6037            }
6038
6039            fn inner_hessian(&self, row: usize, column: usize) -> f64 {
6040                self.hessian[row][column]
6041            }
6042        }
6043
6044        let p = [0.7, -0.3, 0.2, 0.8];
6045        let vars: [Order2<K>; K] = std::array::from_fn(|axis| Order2::variable(p[axis], axis));
6046        let first_atom = vars[0]
6047            .mul(&vars[1])
6048            .add(&vars[2].exp())
6049            .add(&Order2::constant(1.5));
6050        let second_atom = vars[1].mul(&vars[3]).sub(&vars[0]);
6051        let first_value = first_atom.value();
6052        let second_exp = second_atom.value().exp();
6053        let first_stack = [
6054            first_value.ln(),
6055            first_value.recip(),
6056            -1.0 / (first_value * first_value),
6057            0.0,
6058            0.0,
6059        ];
6060        let second_stack = [second_exp, second_exp, second_exp, second_exp, second_exp];
6061        let dense = first_atom
6062            .compose_unary(first_stack)
6063            .add(&second_atom.compose_unary(second_stack));
6064        let terms = [
6065            Term {
6066                first: first_stack[1],
6067                second: first_stack[2],
6068                gradient: *first_atom.g(),
6069                hessian: *first_atom.h(),
6070            },
6071            Term {
6072                first: second_stack[1],
6073                second: second_stack[2],
6074                gradient: *second_atom.g(),
6075                hessian: *second_atom.h(),
6076            },
6077        ];
6078        let (value, gradient, hessian) = DynamicOrder2Accumulator::from_composed_sum(
6079            K,
6080            first_stack[0] + second_stack[0],
6081            &terms,
6082        )
6083        .into_channels();
6084
6085        close(value, dense.value(), "dynamic value");
6086        for row in 0..K {
6087            close(
6088                gradient[row],
6089                dense.g()[row],
6090                &format!("dynamic gradient[{row}]"),
6091            );
6092            for column in 0..K {
6093                close(
6094                    hessian[row * K + column],
6095                    dense.h()[row][column],
6096                    &format!("dynamic Hessian[{row},{column}]"),
6097                );
6098            }
6099        }
6100    }
6101
6102    #[derive(Clone, Copy, Debug)]
6103    struct FullTwoPattern;
6104
6105    impl HessianPattern<2, 3> for FullTwoPattern {
6106        const PAIRS: [(usize, usize); 3] = [(0, 0), (0, 1), (1, 1)];
6107        const PAIR_BITS: [[u128; 2]; 2] = hessian_pair_bits(Self::PAIRS);
6108    }
6109
6110    /// Patterned order-two arithmetic is channel-identical to dense `Order2`
6111    /// when the pattern covers the expression's complete Hessian support.
6112    #[test]
6113    fn patterned_order2_matches_dense_order2() {
6114        type Sparse = PatternedOrder2<FullTwoPattern, 2, 3>;
6115        let dense_vars: [Order2<2>; 2] = std::array::from_fn(|a| Order2::variable(SEED[a], a));
6116        let sparse_vars: [Sparse; 2] = std::array::from_fn(|a| Sparse::variable(SEED[a], a));
6117        let dense = row_expr(&dense_vars);
6118        let sparse = row_expr(&sparse_vars);
6119        close(sparse.value(), dense.value(), "patterned value");
6120        for i in 0..2 {
6121            close(sparse.g()[i], dense.g()[i], &format!("patterned grad[{i}]"));
6122            for j in 0..2 {
6123                close(
6124                    sparse.h()[i][j],
6125                    dense.h()[i][j],
6126                    &format!("patterned hess[{i}][{j}]"),
6127                );
6128            }
6129        }
6130    }
6131
6132    /// `compose_unary_with` is `to_bits`-identical to the explicit
6133    /// `compose_unary(stack_fn(value))` form. Exercised on [`Order2`] across
6134    /// `K ∈ {2,3,4,9}`, ≥ 4000 random seeded inputs.
6135    #[test]
6136    fn compose_unary_with_scalar_seam_bit_identical() {
6137        fn rand_unit(state: &mut u64) -> f64 {
6138            let mut x = *state;
6139            x ^= x << 13;
6140            x ^= x >> 7;
6141            x ^= x << 17;
6142            *state = x;
6143            2.0 * ((x >> 11) as f64 / ((1u64 << 53) as f64)) - 1.0
6144        }
6145        // A base-value-dependent finite stack standing in for a family stack.
6146        fn stack(u: f64) -> [f64; 5] {
6147            [
6148                u.sin(),
6149                u.cos(),
6150                (2.0 * u).sin(),
6151                (0.5 * u).cos(),
6152                u * u - 0.3,
6153            ]
6154        }
6155        fn run<const K: usize>(state: &mut u64, n: usize) -> usize {
6156            for _ in 0..n {
6157                // A non-trivial Order2<K> jet: a seeded variable pushed through a
6158                // couple of algebra ops so g/h are dense, then exercise the seam.
6159                let base = rand_unit(state);
6160                let mut s = Order2::<K>::variable(base, 0);
6161                for a in 1..K {
6162                    s = crate::nested_dual::JetField::mul(
6163                        &s,
6164                        &Order2::<K>::variable(rand_unit(state), a),
6165                    );
6166                }
6167                let with = s.compose_unary_with(stack);
6168                let explicit = s.compose_unary(stack(s.value()));
6169                assert_eq!(with.value().to_bits(), explicit.value().to_bits(), "value");
6170                for a in 0..K {
6171                    assert_eq!(with.g()[a].to_bits(), explicit.g()[a].to_bits(), "g[{a}]");
6172                    for b in 0..K {
6173                        assert_eq!(
6174                            with.h()[a][b].to_bits(),
6175                            explicit.h()[a][b].to_bits(),
6176                            "h[{a}][{b}]"
6177                        );
6178                    }
6179                }
6180            }
6181            n
6182        }
6183        let mut st = 0x9e37_79b9_7f4a_7c15u64;
6184        let total = run::<2>(&mut st, 1100)
6185            + run::<3>(&mut st, 1100)
6186            + run::<4>(&mut st, 1100)
6187            + run::<9>(&mut st, 1100);
6188        assert_eq!(total, 4400);
6189    }
6190
6191    /// The fused fixed-width OneSeed product/composition preserves every
6192    /// channel of the defining unfused nilpotent algebra. Random symmetric
6193    /// Order2 inputs exercise dense non-seed intermediates, while exact
6194    /// mirrored symmetry is checked as an independent production invariant.
6195    #[test]
6196    fn fused_one_seed_channels_match_unfused_definition_932() {
6197        const K: usize = 8;
6198
6199        fn random_scalar(state: &mut u64) -> f64 {
6200            *state ^= *state << 13;
6201            *state ^= *state >> 7;
6202            *state ^= *state << 17;
6203            ((*state >> 11) as f64 / ((1_u64 << 53) as f64)) * 2.0 - 1.0
6204        }
6205
6206        fn random_order2<const N: usize>(state: &mut u64) -> Order2<N> {
6207            let mut tower = crate::jet_tower::Tower2::<N>::zero();
6208            tower.v = random_scalar(state);
6209            for axis in 0..N {
6210                tower.g[axis] = random_scalar(state);
6211            }
6212            for row in 0..N {
6213                for column in row..N {
6214                    let channel = random_scalar(state);
6215                    tower.h[row][column] = channel;
6216                    tower.h[column][row] = channel;
6217                }
6218            }
6219            Order2(tower)
6220        }
6221
6222        fn assert_channels_close<const N: usize>(
6223            label: &str,
6224            actual: &OneSeed<N>,
6225            expected: &OneSeed<N>,
6226        ) {
6227            for (part_label, actual_part, expected_part, require_exact_symmetry) in [
6228                ("base", &actual.base.0, &expected.base.0, false),
6229                ("eps", &actual.eps.0, &expected.eps.0, true),
6230            ] {
6231                let check = |channel: &str, got: f64, want: f64| {
6232                    let tolerance = 2.0e-14 * got.abs().max(want.abs()).max(1.0);
6233                    assert!(
6234                        (got - want).abs() <= tolerance,
6235                        "{label} {part_label} {channel}: got={got:+.17e} want={want:+.17e}"
6236                    );
6237                };
6238                check("value", actual_part.v, expected_part.v);
6239                for row in 0..N {
6240                    check(
6241                        &format!("gradient[{row}]"),
6242                        actual_part.g[row],
6243                        expected_part.g[row],
6244                    );
6245                    for column in 0..N {
6246                        check(
6247                            &format!("hessian[{row},{column}]"),
6248                            actual_part.h[row][column],
6249                            expected_part.h[row][column],
6250                        );
6251                        if require_exact_symmetry {
6252                            assert_eq!(
6253                                actual_part.h[row][column].to_bits(),
6254                                actual_part.h[column][row].to_bits(),
6255                                "{label} {part_label} Hessian symmetry at [{row},{column}]"
6256                            );
6257                        }
6258                    }
6259                }
6260            }
6261        }
6262
6263        let mut state = 0x9320_1eed_5eed_cafe_u64;
6264        for sample in 0..256 {
6265            let left = OneSeed {
6266                base: random_order2::<K>(&mut state),
6267                eps: random_order2::<K>(&mut state),
6268            };
6269            let right = OneSeed {
6270                base: random_order2::<K>(&mut state),
6271                eps: random_order2::<K>(&mut state),
6272            };
6273
6274            let fused_product = left.mul(&right);
6275            let unfused_product = OneSeed {
6276                base: left.base.mul(&right.base),
6277                eps: left.base.mul(&right.eps).add(&left.eps.mul(&right.base)),
6278            };
6279            assert_channels_close(
6280                &format!("sample {sample} product"),
6281                &fused_product,
6282                &unfused_product,
6283            );
6284
6285            let derivatives: [f64; 5] = std::array::from_fn(|_| random_scalar(&mut state));
6286            let fused_composition = left.compose_unary(derivatives);
6287            let unfused_composition = OneSeed {
6288                base: left.base.compose_unary(derivatives),
6289                eps: left
6290                    .base
6291                    .compose_unary([
6292                        derivatives[1],
6293                        derivatives[2],
6294                        derivatives[3],
6295                        derivatives[4],
6296                        derivatives[4],
6297                    ])
6298                    .mul(&left.eps),
6299            };
6300            assert_channels_close(
6301                &format!("sample {sample} composition"),
6302                &fused_composition,
6303                &unfused_composition,
6304            );
6305        }
6306    }
6307
6308    /// The (test-only) `Tower4: JetScalar` impl is the all-channels oracle scalar:
6309    /// evaluating the SAME generic `row_expr` at `S = Tower4` (through the
6310    /// `JetScalar` trait ops) must reproduce, channel-for-channel, the `Tower4`
6311    /// obtained through the canonical `RowProgram` path (`program_full_tower`).
6312    /// This pins that the full-tower scalar and the contracted scalar oracles above
6313    /// all execute the same generic algebra surface.
6314    #[test]
6315    fn tower4_as_jetscalar_matches_program_tower_all_channels() {
6316        let t = tower();
6317        let vars: [Tower4<2>; 2] = std::array::from_fn(|a| Tower4::variable(SEED[a], a));
6318        let s = row_expr(&vars);
6319        close(s.v, t.v, "tower-jetscalar value");
6320        for a in 0..2 {
6321            close(s.g[a], t.g[a], &format!("tower-jetscalar grad[{a}]"));
6322            for b in 0..2 {
6323                close(
6324                    s.h[a][b],
6325                    t.h[a][b],
6326                    &format!("tower-jetscalar hess[{a}][{b}]"),
6327                );
6328                for c in 0..2 {
6329                    close(
6330                        s.t3[a][b][c],
6331                        t.t3[a][b][c],
6332                        &format!("tower-jetscalar t3[{a}][{b}][{c}]"),
6333                    );
6334                    for d in 0..2 {
6335                        close(
6336                            s.t4[a][b][c][d],
6337                            t.t4[a][b][c][d],
6338                            &format!("tower-jetscalar t4[{a}][{b}][{c}][{d}]"),
6339                        );
6340                    }
6341                }
6342            }
6343        }
6344    }
6345
6346    /// Arena-backed runtime directional jets must reproduce the fixed packed
6347    /// algebras channel-for-channel. This isolates the runtime scalar algebra
6348    /// from every family row program before the SLS/SAE integration oracles.
6349    #[test]
6350    fn runtime_directional_jets_match_fixed_packed_algebra_932() {
6351        fn expression<'arena, S: RuntimeJetScalar<'arena>>(vars: &[S]) -> S {
6352            let bilinear = vars[0].mul(&vars[1]);
6353            let curved = vars[2].scale(0.7).add(&vars[3].mul(&vars[3]).scale(-0.2));
6354            bilinear
6355                .add(&curved)
6356                .exp()
6357                .mul(&vars[4].compose_unary([0.4, -0.3, 0.2, -0.1, 0.05]))
6358        }
6359
6360        const K: usize = 5;
6361        let values = [0.2, -0.7, 0.4, 1.1, -0.3];
6362        let direction_u = [0.5, -0.2, 0.7, -0.4, 0.1];
6363        let direction_v = [-0.3, 0.8, 0.2, 0.6, -0.5];
6364        let close = |actual: f64, expected: f64| {
6365            let tolerance = 1.0e-13 * (1.0 + actual.abs().max(expected.abs()));
6366            assert!((actual - expected).abs() <= tolerance);
6367        };
6368
6369        let fixed_one: Vec<FixedRuntimeJet<OneSeed<K>, K>> = (0..K)
6370            .map(|axis| FixedRuntimeJet {
6371                inner: OneSeed::seed_direction(values[axis], axis, direction_u[axis]),
6372            })
6373            .collect();
6374        let arena_one = DynamicJetArena::new();
6375        let dynamic_one: Vec<DynamicOneSeed<'_>> = (0..K)
6376            .map(|axis| {
6377                DynamicOneSeed::seed_direction(values[axis], axis, direction_u[axis], K, &arena_one)
6378            })
6379            .collect();
6380        let fixed_third = expression(&fixed_one).into_inner().contracted_third();
6381        let dynamic_third = expression(&dynamic_one);
6382        for a in 0..K {
6383            for b in 0..K {
6384                assert_eq!(
6385                    dynamic_third.contracted_third()[a * K + b].to_bits(),
6386                    dynamic_third.contracted_third()[b * K + a].to_bits(),
6387                    "arena third Hessian must be exactly symmetric at ({a},{b})"
6388                );
6389                close(
6390                    dynamic_third.contracted_third()[a * K + b],
6391                    fixed_third[a][b],
6392                );
6393            }
6394        }
6395
6396        let fixed_one_v: Vec<FixedRuntimeJet<OneSeed<K>, K>> = (0..K)
6397            .map(|axis| FixedRuntimeJet {
6398                inner: OneSeed::seed_direction(values[axis], axis, direction_v[axis]),
6399            })
6400            .collect();
6401        let fixed_third_v = expression(&fixed_one_v).into_inner().contracted_third();
6402        let batch_workspace = DynamicJetBatchWorkspace::new(2);
6403        let directions = [direction_u, direction_v];
6404        let batch_vars = batch_workspace.alloc_slice_fill_with(K, |axis| {
6405            DynamicOneSeedBatch::seed_directions(values[axis], axis, K, &batch_workspace, |lane| {
6406                directions[lane][axis]
6407            })
6408        });
6409        let dynamic_batch = expression(batch_vars);
6410        assert_eq!(dynamic_batch.lanes(), 2);
6411        for lane in 0..2 {
6412            let expected = if lane == 0 {
6413                &fixed_third
6414            } else {
6415                &fixed_third_v
6416            };
6417            for a in 0..K {
6418                for b in 0..K {
6419                    close(
6420                        dynamic_batch.contracted_third(lane)[a * K + b],
6421                        expected[a][b],
6422                    );
6423                }
6424            }
6425        }
6426
6427        let fixed_two: Vec<FixedRuntimeJet<TwoSeed<K>, K>> = (0..K)
6428            .map(|axis| FixedRuntimeJet {
6429                inner: TwoSeed::seed(values[axis], axis, direction_u[axis], direction_v[axis]),
6430            })
6431            .collect();
6432        let arena_two = DynamicJetArena::new();
6433        let dynamic_two: Vec<DynamicTwoSeed<'_>> = (0..K)
6434            .map(|axis| {
6435                DynamicTwoSeed::seed(
6436                    values[axis],
6437                    axis,
6438                    direction_u[axis],
6439                    direction_v[axis],
6440                    K,
6441                    &arena_two,
6442                )
6443            })
6444            .collect();
6445        let fixed_fourth = expression(&fixed_two).into_inner().contracted_fourth();
6446        let dynamic_fourth = expression(&dynamic_two);
6447        for a in 0..K {
6448            for b in 0..K {
6449                close(
6450                    dynamic_fourth.contracted_fourth()[a * K + b],
6451                    fixed_fourth[a][b],
6452                );
6453            }
6454        }
6455
6456        let fixed_two_swapped: Vec<FixedRuntimeJet<TwoSeed<K>, K>> = (0..K)
6457            .map(|axis| {
6458                FixedRuntimeJet::from_inner(TwoSeed::seed(
6459                    values[axis],
6460                    axis,
6461                    direction_v[axis],
6462                    direction_u[axis],
6463                ))
6464            })
6465            .collect();
6466        let fixed_fourth_swapped = expression(&fixed_two_swapped)
6467            .into_inner()
6468            .contracted_fourth();
6469        let pair_workspace = DynamicJetBatchWorkspace::new(2);
6470        let direction_pairs = [(direction_u, direction_v), (direction_v, direction_u)];
6471        let pair_vars = pair_workspace.alloc_slice_fill_with(K, |axis| {
6472            DynamicTwoSeedBatch::seed_direction_pairs(
6473                values[axis],
6474                axis,
6475                K,
6476                &pair_workspace,
6477                |lane| (direction_pairs[lane].0[axis], direction_pairs[lane].1[axis]),
6478            )
6479        });
6480        let dynamic_pair_batch = expression(pair_vars);
6481        assert_eq!(dynamic_pair_batch.lanes(), 2);
6482        for lane in 0..2 {
6483            let expected = if lane == 0 {
6484                &fixed_fourth
6485            } else {
6486                &fixed_fourth_swapped
6487            };
6488            for a in 0..K {
6489                for b in 0..K {
6490                    close(
6491                        dynamic_pair_batch.contracted_fourth(lane)[a * K + b],
6492                        expected[a][b],
6493                    );
6494                }
6495            }
6496        }
6497    }
6498
6499    #[test]
6500    fn dynamic_jet_arena_compacts_fragmented_high_water_932() {
6501        const WORDS_PER_ALLOCATION: usize = 1 << 17;
6502        const ALLOCATIONS: usize = 6;
6503
6504        let mut arena = DynamicJetArena::new();
6505        for lane in 0..ALLOCATIONS {
6506            let allocation = arena.alloc_slice_fill_with(WORDS_PER_ALLOCATION, |_| lane as u64);
6507            std::hint::black_box(allocation);
6508        }
6509        let fragmented_high_water = arena.allocated_bytes();
6510
6511        arena.reset();
6512        let compact_high_water = arena.allocated_bytes();
6513        assert!(
6514            compact_high_water >= fragmented_high_water,
6515            "compacted arena must retain the complete fragmented tape"
6516        );
6517
6518        for lane in 0..ALLOCATIONS {
6519            let allocation = arena.alloc_slice_fill_with(WORDS_PER_ALLOCATION, |_| lane as u64);
6520            std::hint::black_box(allocation);
6521        }
6522        assert_eq!(
6523            arena.allocated_bytes(),
6524            compact_high_water,
6525            "equal replay must fit in the compacted chunk"
6526        );
6527
6528        arena.reset();
6529        assert_eq!(
6530            arena.allocated_bytes(),
6531            compact_high_water,
6532            "stable reset must retain the compacted chunk"
6533        );
6534    }
6535}
6536
6537#[cfg(test)]
6538mod batch_tests {
6539    //! SIMD row-batching oracle: prove [`Order2Batch<K>`] (4 rows in
6540    //! `wide::f64x4` lanes) is `to_bits`-identical, on every value/gradient/
6541    //! Hessian channel, to the production [`Order2<K>`] evaluated per row — and
6542    //! that the new scalar field [`Order2Lane<f64, K>`] is too. Composing the two
6543    //! claims, batch lane `i` reproduces the production scalar for row `i` bit
6544    //! for bit, so the 4× throughput is a free lunch (no result change).
6545
6546    use super::{
6547        JetScalar, Lane, OneSeed, OneSeedBatch, OneSeedLane, Order2, Order2Batch, Order2Lane,
6548        TwoSeed, TwoSeedBatch, TwoSeedLane,
6549    };
6550    // The scalar-field algebra (`value`, `add`, …) lives on the shared `JetField`
6551    // base now, so the concrete-typed channel reads below need it in scope.
6552    use crate::nested_dual::JetField;
6553
6554    /// The ops the witness row expression needs, so ONE generic body evaluates
6555    /// at the production [`Order2<K>`], the new scalar [`Order2Lane<f64, K>`],
6556    /// and the batched [`Order2Batch<K>`].
6557    trait RowAlg<const K: usize>: Copy {
6558        fn constant(c: f64) -> Self;
6559        fn add(&self, o: &Self) -> Self;
6560        fn sub(&self, o: &Self) -> Self;
6561        fn mul(&self, o: &Self) -> Self;
6562        fn scale(&self, s: f64) -> Self;
6563        fn exp(&self) -> Self;
6564        fn sqrt(&self) -> Self;
6565        fn recip(&self) -> Self;
6566    }
6567
6568    impl<const K: usize> RowAlg<K> for Order2<K> {
6569        fn constant(c: f64) -> Self {
6570            <Self as JetScalar<K>>::constant(c)
6571        }
6572        fn add(&self, o: &Self) -> Self {
6573            crate::nested_dual::JetField::add(self, o)
6574        }
6575        fn sub(&self, o: &Self) -> Self {
6576            crate::nested_dual::JetField::sub(self, o)
6577        }
6578        fn mul(&self, o: &Self) -> Self {
6579            crate::nested_dual::JetField::mul(self, o)
6580        }
6581        fn scale(&self, s: f64) -> Self {
6582            crate::nested_dual::JetField::scale(self, s)
6583        }
6584        fn exp(&self) -> Self {
6585            JetScalar::exp(self)
6586        }
6587        fn sqrt(&self) -> Self {
6588            JetScalar::sqrt(self)
6589        }
6590        fn recip(&self) -> Self {
6591            JetScalar::recip(self)
6592        }
6593    }
6594
6595    impl<L: Lane, const K: usize> RowAlg<K> for Order2Lane<L, K> {
6596        fn constant(c: f64) -> Self {
6597            Order2Lane::constant(L::splat(c))
6598        }
6599        fn add(&self, o: &Self) -> Self {
6600            Order2Lane::add(self, o)
6601        }
6602        fn sub(&self, o: &Self) -> Self {
6603            Order2Lane::sub(self, o)
6604        }
6605        fn mul(&self, o: &Self) -> Self {
6606            Order2Lane::mul(self, o)
6607        }
6608        fn scale(&self, s: f64) -> Self {
6609            Order2Lane::scale(self, s)
6610        }
6611        fn exp(&self) -> Self {
6612            Order2Lane::exp(self)
6613        }
6614        fn sqrt(&self) -> Self {
6615            Order2Lane::sqrt(self)
6616        }
6617        fn recip(&self) -> Self {
6618            Order2Lane::recip(self)
6619        }
6620    }
6621
6622    /// A dense witness row expression touching every algebra op (mul, add, sub,
6623    /// scale, exp, sqrt, recip) over ALL `K` primaries, so the gradient and the
6624    /// full `K×K` Hessian are dense (no trivially-zero channel). All transcend.
6625    /// arguments are kept finite/positive: `sqrt(s²+1) > 0`, `recip(exp+2) > 0`.
6626    fn row_expr<const K: usize, A: RowAlg<K>>(p: &[A; K]) -> A {
6627        let mut s = A::constant(0.3);
6628        for a in 0..K {
6629            let b = (a + 1) % K;
6630            s = s.add(&p[a].mul(&p[b]).scale(0.1 + 0.05 * a as f64));
6631        }
6632        let e = s.exp();
6633        let r = s.mul(&s).add(&A::constant(1.0)).sqrt();
6634        let denom = e.add(&A::constant(2.0));
6635        e.mul(&r).sub(&s.scale(0.5)).mul(&denom.recip())
6636    }
6637
6638    /// xorshift64 → `f64` in `[-1, 1)`.
6639    fn rand_unit(state: &mut u64) -> f64 {
6640        let mut x = *state;
6641        x ^= x << 13;
6642        x ^= x >> 7;
6643        x ^= x << 17;
6644        *state = x;
6645        let u = (x >> 11) as f64 / ((1u64 << 53) as f64); // [0, 1)
6646        2.0 * u - 1.0
6647    }
6648
6649    /// Returns the number of (batch, row) pairs whose every channel was
6650    /// verified bit-identical, so the caller can assert the expected total ran.
6651    fn check_k<const K: usize>(state: &mut u64, batches: usize) -> usize {
6652        let mut verified_rows = 0usize;
6653        for _ in 0..batches {
6654            // Four independent rows of K primary values.
6655            let rows: [[f64; K]; 4] =
6656                std::array::from_fn(|_| std::array::from_fn(|_| rand_unit(state)));
6657
6658            // Production ground truth, evaluated per row at Order2<K>.
6659            let prod: [Order2<K>; 4] = std::array::from_fn(|r| {
6660                let p: [Order2<K>; K] = std::array::from_fn(|a| Order2::variable(rows[r][a], a));
6661                row_expr(&p)
6662            });
6663
6664            // New scalar field (Order2Lane<f64>), per row.
6665            let scal: [Order2Lane<f64, K>; 4] = std::array::from_fn(|r| {
6666                let p: [Order2Lane<f64, K>; K] =
6667                    std::array::from_fn(|a| Order2Lane::variable(rows[r][a], a));
6668                row_expr(&p)
6669            });
6670
6671            // Batched: 4 rows packed into f64x4 lanes, ONE vector pass.
6672            let pbatch: [Order2Batch<K>; K] = std::array::from_fn(|a| {
6673                let packed = wide::f64x4::new([rows[0][a], rows[1][a], rows[2][a], rows[3][a]]);
6674                Order2Batch::variable(packed, a)
6675            });
6676            let batch = row_expr(&pbatch);
6677
6678            for r in 0..4 {
6679                let g = prod[r].0;
6680                // Order2Lane<f64> == Order2<K> (bit-identical scalar field).
6681                assert_eq!(scal[r].v.to_bits(), g.v.to_bits(), "K={K} scalar v");
6682                // Batch lane r == Order2<K> for row r.
6683                let lr = batch.lane(r).0;
6684                assert_eq!(lr.v.to_bits(), g.v.to_bits(), "K={K} batch lane {r} v");
6685                for a in 0..K {
6686                    assert_eq!(
6687                        scal[r].g[a].to_bits(),
6688                        g.g[a].to_bits(),
6689                        "K={K} scalar g[{a}]"
6690                    );
6691                    assert_eq!(
6692                        lr.g[a].to_bits(),
6693                        g.g[a].to_bits(),
6694                        "K={K} batch lane {r} g[{a}]"
6695                    );
6696                    for b in 0..K {
6697                        assert_eq!(
6698                            scal[r].h[a][b].to_bits(),
6699                            g.h[a][b].to_bits(),
6700                            "K={K} scalar h[{a}][{b}]"
6701                        );
6702                        assert_eq!(
6703                            lr.h[a][b].to_bits(),
6704                            g.h[a][b].to_bits(),
6705                            "K={K} batch lane {r} h[{a}][{b}]"
6706                        );
6707                    }
6708                }
6709                verified_rows += 1;
6710            }
6711        }
6712        verified_rows
6713    }
6714
6715    /// ≥2000 random 4-row batches per K, across K ∈ {2,3,4,9}: every channel of
6716    /// every lane is `to_bits`-identical to the production scalar per row.
6717    #[test]
6718    fn batch_lanes_bit_identical_to_scalar_per_row() {
6719        let mut state = 0x9E37_79B9_7F4A_7C15_u64;
6720        let mut verified = 0usize;
6721        verified += check_k::<2>(&mut state, 2000);
6722        verified += check_k::<3>(&mut state, 2000);
6723        verified += check_k::<4>(&mut state, 2000);
6724        verified += check_k::<9>(&mut state, 2000);
6725        // 4 K-values × 2000 batches × 4 packed rows each, all bit-identical.
6726        assert_eq!(verified, 4 * 2000 * 4, "every batch row must be verified");
6727    }
6728
6729    // ── One-/two-seed lane oracles ──────────────────────────────────────────
6730    //
6731    // The same dense `row_expr` witness program runs over the SEEDED directional
6732    // scalars: the scalar `OneSeed`/`TwoSeed` per row, the `f64`-lane re-type
6733    // (`*SeedLane<f64>`), and the 4-rows-per-pass batch (`*SeedBatch`). The
6734    // headline claim is that the contracted-third / contracted-fourth channel of
6735    // every lane is `to_bits`-identical to the production scalar's per row.
6736
6737    impl<const K: usize> RowAlg<K> for OneSeed<K> {
6738        fn constant(c: f64) -> Self {
6739            <Self as JetScalar<K>>::constant(c)
6740        }
6741        fn add(&self, o: &Self) -> Self {
6742            crate::nested_dual::JetField::add(self, o)
6743        }
6744        fn sub(&self, o: &Self) -> Self {
6745            crate::nested_dual::JetField::sub(self, o)
6746        }
6747        fn mul(&self, o: &Self) -> Self {
6748            crate::nested_dual::JetField::mul(self, o)
6749        }
6750        fn scale(&self, s: f64) -> Self {
6751            crate::nested_dual::JetField::scale(self, s)
6752        }
6753        fn exp(&self) -> Self {
6754            JetScalar::exp(self)
6755        }
6756        fn sqrt(&self) -> Self {
6757            JetScalar::sqrt(self)
6758        }
6759        fn recip(&self) -> Self {
6760            JetScalar::recip(self)
6761        }
6762    }
6763
6764    impl<L: Lane, const K: usize> RowAlg<K> for OneSeedLane<L, K> {
6765        fn constant(c: f64) -> Self {
6766            OneSeedLane::constant(L::splat(c))
6767        }
6768        fn add(&self, o: &Self) -> Self {
6769            OneSeedLane::add(self, o)
6770        }
6771        fn sub(&self, o: &Self) -> Self {
6772            OneSeedLane::sub(self, o)
6773        }
6774        fn mul(&self, o: &Self) -> Self {
6775            OneSeedLane::mul(self, o)
6776        }
6777        fn scale(&self, s: f64) -> Self {
6778            OneSeedLane::scale(self, s)
6779        }
6780        fn exp(&self) -> Self {
6781            OneSeedLane::exp(self)
6782        }
6783        fn sqrt(&self) -> Self {
6784            OneSeedLane::sqrt(self)
6785        }
6786        fn recip(&self) -> Self {
6787            OneSeedLane::recip(self)
6788        }
6789    }
6790
6791    impl<const K: usize> RowAlg<K> for TwoSeed<K> {
6792        fn constant(c: f64) -> Self {
6793            <Self as JetScalar<K>>::constant(c)
6794        }
6795        fn add(&self, o: &Self) -> Self {
6796            crate::nested_dual::JetField::add(self, o)
6797        }
6798        fn sub(&self, o: &Self) -> Self {
6799            crate::nested_dual::JetField::sub(self, o)
6800        }
6801        fn mul(&self, o: &Self) -> Self {
6802            crate::nested_dual::JetField::mul(self, o)
6803        }
6804        fn scale(&self, s: f64) -> Self {
6805            crate::nested_dual::JetField::scale(self, s)
6806        }
6807        fn exp(&self) -> Self {
6808            JetScalar::exp(self)
6809        }
6810        fn sqrt(&self) -> Self {
6811            JetScalar::sqrt(self)
6812        }
6813        fn recip(&self) -> Self {
6814            JetScalar::recip(self)
6815        }
6816    }
6817
6818    impl<L: Lane, const K: usize> RowAlg<K> for TwoSeedLane<L, K> {
6819        fn constant(c: f64) -> Self {
6820            TwoSeedLane::constant(L::splat(c))
6821        }
6822        fn add(&self, o: &Self) -> Self {
6823            TwoSeedLane::add(self, o)
6824        }
6825        fn sub(&self, o: &Self) -> Self {
6826            TwoSeedLane::sub(self, o)
6827        }
6828        fn mul(&self, o: &Self) -> Self {
6829            TwoSeedLane::mul(self, o)
6830        }
6831        fn scale(&self, s: f64) -> Self {
6832            TwoSeedLane::scale(self, s)
6833        }
6834        fn exp(&self) -> Self {
6835            TwoSeedLane::exp(self)
6836        }
6837        fn sqrt(&self) -> Self {
6838            TwoSeedLane::sqrt(self)
6839        }
6840        fn recip(&self) -> Self {
6841            TwoSeedLane::recip(self)
6842        }
6843    }
6844
6845    fn check_oneseed<const K: usize>(state: &mut u64, batches: usize) -> usize {
6846        let mut rows_checked = 0;
6847        for _ in 0..batches {
6848            let rows: [[f64; K]; 4] =
6849                std::array::from_fn(|_| std::array::from_fn(|_| rand_unit(state)));
6850            // Per-row ε-direction.
6851            let u: [[f64; K]; 4] =
6852                std::array::from_fn(|_| std::array::from_fn(|_| rand_unit(state)));
6853
6854            // Production ground truth (scalar OneSeed per row).
6855            let prod: [OneSeed<K>; 4] = std::array::from_fn(|r| {
6856                let p: [OneSeed<K>; K] =
6857                    std::array::from_fn(|a| OneSeed::seed_direction(rows[r][a], a, u[r][a]));
6858                row_expr(&p)
6859            });
6860
6861            // f64-lane re-type per row.
6862            let scal: [OneSeedLane<f64, K>; 4] = std::array::from_fn(|r| {
6863                let p: [OneSeedLane<f64, K>; K] =
6864                    std::array::from_fn(|a| OneSeedLane::seed_direction(rows[r][a], a, u[r][a]));
6865                row_expr(&p)
6866            });
6867
6868            // 4-rows-per-pass batch.
6869            let pbatch: [OneSeedBatch<K>; K] = std::array::from_fn(|a| {
6870                let val = wide::f64x4::new([rows[0][a], rows[1][a], rows[2][a], rows[3][a]]);
6871                let uu = wide::f64x4::new([u[0][a], u[1][a], u[2][a], u[3][a]]);
6872                OneSeedBatch::seed_direction(val, a, uu)
6873            });
6874            let batch = row_expr(&pbatch);
6875
6876            for r in 0..4 {
6877                let want = prod[r].contracted_third();
6878                let got_scal = scal[r].contracted_third();
6879                let got_batch = batch.lane(r).contracted_third();
6880                // Value channel too (sanity that the base program agrees).
6881                assert_eq!(
6882                    scal[r].base.v.to_bits(),
6883                    prod[r].base.value().to_bits(),
6884                    "OneSeed K={K} scalar value"
6885                );
6886                assert_eq!(
6887                    batch.lane(r).base.value().to_bits(),
6888                    prod[r].base.value().to_bits(),
6889                    "OneSeed K={K} batch lane {r} value"
6890                );
6891                for a in 0..K {
6892                    for b in 0..K {
6893                        assert_eq!(
6894                            got_scal[a][b].to_bits(),
6895                            want[a][b].to_bits(),
6896                            "OneSeed K={K} scalar third[{a}][{b}]"
6897                        );
6898                        assert_eq!(
6899                            got_batch[a][b].to_bits(),
6900                            want[a][b].to_bits(),
6901                            "OneSeed K={K} batch lane {r} third[{a}][{b}]"
6902                        );
6903                    }
6904                }
6905                rows_checked += 1;
6906            }
6907        }
6908        rows_checked
6909    }
6910
6911    fn check_twoseed<const K: usize>(state: &mut u64, batches: usize) -> usize {
6912        let mut rows_checked = 0;
6913        for _ in 0..batches {
6914            let rows: [[f64; K]; 4] =
6915                std::array::from_fn(|_| std::array::from_fn(|_| rand_unit(state)));
6916            let u: [[f64; K]; 4] =
6917                std::array::from_fn(|_| std::array::from_fn(|_| rand_unit(state)));
6918            let v: [[f64; K]; 4] =
6919                std::array::from_fn(|_| std::array::from_fn(|_| rand_unit(state)));
6920
6921            let prod: [TwoSeed<K>; 4] = std::array::from_fn(|r| {
6922                let p: [TwoSeed<K>; K] =
6923                    std::array::from_fn(|a| TwoSeed::seed(rows[r][a], a, u[r][a], v[r][a]));
6924                row_expr(&p)
6925            });
6926
6927            let scal: [TwoSeedLane<f64, K>; 4] = std::array::from_fn(|r| {
6928                let p: [TwoSeedLane<f64, K>; K] =
6929                    std::array::from_fn(|a| TwoSeedLane::seed(rows[r][a], a, u[r][a], v[r][a]));
6930                row_expr(&p)
6931            });
6932
6933            let pbatch: [TwoSeedBatch<K>; K] = std::array::from_fn(|a| {
6934                let val = wide::f64x4::new([rows[0][a], rows[1][a], rows[2][a], rows[3][a]]);
6935                let uu = wide::f64x4::new([u[0][a], u[1][a], u[2][a], u[3][a]]);
6936                let vv = wide::f64x4::new([v[0][a], v[1][a], v[2][a], v[3][a]]);
6937                TwoSeedBatch::seed(val, a, uu, vv)
6938            });
6939            let batch = row_expr(&pbatch);
6940
6941            for r in 0..4 {
6942                let want = prod[r].contracted_fourth();
6943                let got_scal = scal[r].contracted_fourth();
6944                let got_batch = batch.lane(r).contracted_fourth();
6945                assert_eq!(
6946                    scal[r].base.v.to_bits(),
6947                    prod[r].base.value().to_bits(),
6948                    "TwoSeed K={K} scalar value"
6949                );
6950                assert_eq!(
6951                    batch.lane(r).base.value().to_bits(),
6952                    prod[r].base.value().to_bits(),
6953                    "TwoSeed K={K} batch lane {r} value"
6954                );
6955                for a in 0..K {
6956                    for b in 0..K {
6957                        assert_eq!(
6958                            got_scal[a][b].to_bits(),
6959                            want[a][b].to_bits(),
6960                            "TwoSeed K={K} scalar fourth[{a}][{b}]"
6961                        );
6962                        assert_eq!(
6963                            got_batch[a][b].to_bits(),
6964                            want[a][b].to_bits(),
6965                            "TwoSeed K={K} batch lane {r} fourth[{a}][{b}]"
6966                        );
6967                    }
6968                }
6969                rows_checked += 1;
6970            }
6971        }
6972        rows_checked
6973    }
6974
6975    /// ≥2000 random 4-row batches per K, across K ∈ {2,3,4,9}: the
6976    /// contracted-third channel of every `OneSeedLane` lane is `to_bits`-identical
6977    /// to the production [`OneSeed`] per row.
6978    #[test]
6979    fn oneseed_lanes_contracted_third_bit_identical() {
6980        let mut state = 0x1234_5678_9ABC_DEF0_u64;
6981        let batches = 2000;
6982        let rows_checked = check_oneseed::<2>(&mut state, batches)
6983            + check_oneseed::<3>(&mut state, batches)
6984            + check_oneseed::<4>(&mut state, batches)
6985            + check_oneseed::<9>(&mut state, batches);
6986        // 4 widths × `batches` batches × 4 rows each: a silently empty inner
6987        // loop would leave this at zero instead of passing as a no-op.
6988        assert_eq!(rows_checked, 4 * batches * 4);
6989    }
6990
6991    /// ≥2000 random 4-row batches per K, across K ∈ {2,3,4,9}: the
6992    /// contracted-fourth channel of every `TwoSeedLane` lane is `to_bits`-identical
6993    /// to the production [`TwoSeed`] per row.
6994    #[test]
6995    fn twoseed_lanes_contracted_fourth_bit_identical() {
6996        let mut state = 0x0FED_CBA9_8765_4321_u64;
6997        let batches = 2000;
6998        let rows_checked = check_twoseed::<2>(&mut state, batches)
6999            + check_twoseed::<3>(&mut state, batches)
7000            + check_twoseed::<4>(&mut state, batches)
7001            + check_twoseed::<9>(&mut state, batches);
7002        // 4 widths × `batches` batches × 4 rows each: a silently empty inner
7003        // loop would leave this at zero instead of passing as a no-op.
7004        assert_eq!(rows_checked, 4 * batches * 4);
7005    }
7006}
7007
7008#[cfg(test)]
7009mod unit_tests {
7010    use super::{JetScalar, OneSeed, Order1, Order2, filtered_implicit_solve_scalar};
7011    use crate::nested_dual::{Dual2, JetField};
7012
7013    // A deliberately mixed beta/family program. Its family derivatives below
7014    // are analytic scalar programs, so these checks have no finite-difference
7015    // truncation or step-size oracle.
7016    fn family_program<const K: usize, S: JetScalar<K>>(x: &S, y: &S, theta: &S) -> S {
7017        let xy = x.mul(y);
7018        let exponential = theta.mul(&xy).exp();
7019        let theta_squared_x_squared = theta.mul(theta).mul(&x.mul(x)).scale(0.375);
7020        let theta_y_cubed = theta.mul(&y.mul(y).mul(y)).scale(-0.2);
7021        exponential
7022            .add(&theta_squared_x_squared)
7023            .add(&theta_y_cubed)
7024    }
7025
7026    fn analytic_family_first<const K: usize, S: JetScalar<K>>(x: &S, y: &S, theta: &S) -> S {
7027        let xy = x.mul(y);
7028        let exponential = theta.mul(&xy).exp();
7029        xy.mul(&exponential)
7030            .add(&theta.mul(&x.mul(x)).scale(0.75))
7031            .add(&y.mul(y).mul(y).scale(-0.2))
7032    }
7033
7034    fn analytic_family_second<const K: usize, S: JetScalar<K>>(x: &S, y: &S, theta: &S) -> S {
7035        let xy = x.mul(y);
7036        let exponential = theta.mul(&xy).exp();
7037        xy.mul(&xy).mul(&exponential).add(&x.mul(x).scale(0.75))
7038    }
7039
7040    fn assert_channel_close(actual: f64, expected: f64, channel: &str) {
7041        let tolerance = 256.0 * f64::EPSILON * (1.0 + actual.abs().max(expected.abs()));
7042        assert!(
7043            (actual - expected).abs() <= tolerance,
7044            "{channel}: actual={actual:.17e}, expected={expected:.17e}, tolerance={tolerance:.3e}"
7045        );
7046    }
7047
7048    fn assert_order2_channels<const K: usize>(
7049        actual: &Order2<K>,
7050        expected: &Order2<K>,
7051        prefix: &str,
7052    ) {
7053        assert_channel_close(actual.value(), expected.value(), &format!("{prefix}.value"));
7054        for a in 0..K {
7055            assert_channel_close(actual.g()[a], expected.g()[a], &format!("{prefix}.g[{a}]"));
7056            for b in 0..K {
7057                assert_channel_close(
7058                    actual.h()[a][b],
7059                    expected.h()[a][b],
7060                    &format!("{prefix}.h[{a}][{b}]"),
7061                );
7062            }
7063        }
7064    }
7065
7066    /// The outer first/second channels carry the family derivative while each
7067    /// inner `Order2` independently carries beta value/gradient/Hessian.
7068    #[test]
7069    fn dual2_order2_extracts_exact_family_value_gradient_hessian_channels() {
7070        const K: usize = 2;
7071        let x0 = 0.7;
7072        let y0 = -0.45;
7073        let theta0 = 0.6;
7074        let x = <Dual2<Order2<K>> as JetScalar<K>>::variable(x0, 0);
7075        let y = <Dual2<Order2<K>> as JetScalar<K>>::variable(y0, 1);
7076        let theta = Dual2 {
7077            v: Order2::constant(theta0),
7078            g: Order2::constant(1.0),
7079            h: Order2::constant(0.0),
7080        };
7081
7082        let actual = family_program(&x, &y, &theta);
7083        let reference_x = Order2::variable(x0, 0);
7084        let reference_y = Order2::variable(y0, 1);
7085        let reference_theta = Order2::constant(theta0);
7086        let expected_first = analytic_family_first(&reference_x, &reference_y, &reference_theta);
7087        let expected_second = analytic_family_second(&reference_x, &reference_y, &reference_theta);
7088
7089        assert_order2_channels(&actual.g, &expected_first, "family_first");
7090        assert_order2_channels(&actual.h, &expected_second, "family_second");
7091    }
7092
7093    /// `g.eps.h[a][b]` is the directional beta drift of the family-Hessian
7094    /// channel, obtained by exact nested AD rather than differencing Hessians.
7095    #[test]
7096    fn dual2_oneseed_extracts_exact_family_hessian_drift() {
7097        const K: usize = 2;
7098        let x0 = 0.7;
7099        let y0 = -0.45;
7100        let theta0 = 0.6;
7101        let direction = [0.3, -0.8];
7102
7103        let mut x = <Dual2<OneSeed<K>> as JetScalar<K>>::variable(x0, 0);
7104        let mut y = <Dual2<OneSeed<K>> as JetScalar<K>>::variable(y0, 1);
7105        x.v.eps = Order2::constant(direction[0]);
7106        y.v.eps = Order2::constant(direction[1]);
7107        let theta = Dual2 {
7108            v: OneSeed::constant(theta0),
7109            g: OneSeed::constant(1.0),
7110            h: OneSeed::constant(0.0),
7111        };
7112
7113        let actual = family_program(&x, &y, &theta);
7114        let reference_x = OneSeed::seed_direction(x0, 0, direction[0]);
7115        let reference_y = OneSeed::seed_direction(y0, 1, direction[1]);
7116        let reference_theta = OneSeed::constant(theta0);
7117        let expected = analytic_family_first(&reference_x, &reference_y, &reference_theta);
7118
7119        assert_order2_channels(&actual.g.eps, &expected.eps, "family_first_drift");
7120    }
7121
7122    // ── Order2 direct property tests ─────────────────────────────────────────
7123
7124    /// `Order2::constant(c)` carries value `c` and zero everywhere else.
7125    #[test]
7126    fn order2_constant_has_zero_derivatives() {
7127        let s = Order2::<3>::constant(7.5);
7128        assert_eq!(s.value(), 7.5);
7129        for a in 0..3 {
7130            assert_eq!(s.g()[a], 0.0, "grad[{a}] should be zero");
7131            for b in 0..3 {
7132                assert_eq!(s.h()[a][b], 0.0, "hess[{a}][{b}] should be zero");
7133            }
7134        }
7135    }
7136
7137    /// `Order2::variable(x, axis)` has unit gradient in slot `axis` and zero Hessian.
7138    #[test]
7139    fn order2_variable_has_unit_gradient_in_seeded_slot() {
7140        let x = -2.5_f64;
7141        let s = Order2::<4>::variable(x, 2);
7142        assert_eq!(s.value(), x);
7143        for a in 0..4 {
7144            let expected_g = if a == 2 { 1.0 } else { 0.0 };
7145            assert_eq!(s.g()[a], expected_g, "grad[{a}]");
7146            for b in 0..4 {
7147                assert_eq!(s.h()[a][b], 0.0, "hess[{a}][{b}] should be zero");
7148            }
7149        }
7150    }
7151
7152    /// `Order2::add` sums gradient channels; `sub` is the inverse on gradients.
7153    /// Uses integer-valued primaries so the value roundtrip is also exact.
7154    #[test]
7155    fn order2_add_sub_roundtrip() {
7156        let p = Order2::<2>::variable(3.0, 0);
7157        let q = Order2::<2>::variable(2.0, 1);
7158        let pq = crate::nested_dual::JetField::add(&p, &q);
7159        // value = 3 + 2 = 5
7160        assert_eq!(pq.value(), 5.0, "add value");
7161        let back = crate::nested_dual::JetField::sub(&pq, &q);
7162        // (p + q) - q gradient should equal p's gradient exactly
7163        for a in 0..2 {
7164            assert_eq!(back.g()[a], p.g()[a], "grad[{a}] roundtrip");
7165        }
7166    }
7167
7168    /// `Order2::mul` of two variables satisfies the Leibniz product rule:
7169    ///   ∂(p·q)/∂p = q,  ∂(p·q)/∂q = p,  ∂²(p·q)/∂p∂q = 1.
7170    #[test]
7171    fn order2_mul_satisfies_leibniz_rule() {
7172        let pv = 3.0_f64;
7173        let qv = -2.0_f64;
7174        let p = Order2::<2>::variable(pv, 0);
7175        let q = Order2::<2>::variable(qv, 1);
7176        let pq = crate::nested_dual::JetField::mul(&p, &q);
7177        assert_eq!(pq.value(), pv * qv, "value = p·q");
7178        assert_eq!(pq.g()[0], qv, "∂(p·q)/∂p = q");
7179        assert_eq!(pq.g()[1], pv, "∂(p·q)/∂q = p");
7180        assert_eq!(pq.h()[0][1], 1.0, "∂²(p·q)/∂p∂q = 1");
7181        assert_eq!(pq.h()[1][0], 1.0, "∂²(p·q)/∂q∂p = 1 (symmetric)");
7182        assert_eq!(pq.h()[0][0], 0.0, "∂²(p·q)/∂p² = 0");
7183        assert_eq!(pq.h()[1][1], 0.0, "∂²(p·q)/∂q² = 0");
7184    }
7185
7186    /// `Order2::scale(s)` multiplies every channel by `s`.
7187    #[test]
7188    fn order2_scale_multiplies_all_channels() {
7189        let p = Order2::<2>::variable(4.0, 0);
7190        let s = 2.5_f64;
7191        let ps = crate::nested_dual::JetField::scale(&p, s);
7192        assert_eq!(ps.value(), 4.0 * s);
7193        assert_eq!(ps.g()[0], 1.0 * s);
7194        assert_eq!(ps.g()[1], 0.0);
7195    }
7196
7197    /// `Order2::exp` at a constant has value `e^c`, gradient `e^c * g`, Hessian `e^c * (g⊗g + H)`.
7198    /// At a seeded variable `p₀`, the first derivative is `e^{p₀}` and second is `e^{p₀}`.
7199    #[test]
7200    fn order2_exp_derivative_stack_correct() {
7201        let p0 = 1.0_f64;
7202        let p = Order2::<1>::variable(p0, 0);
7203        let ep = JetScalar::exp(&p);
7204        let e = p0.exp();
7205        assert!((ep.value() - e).abs() < 1e-15, "exp value");
7206        assert!((ep.g()[0] - e).abs() < 1e-15, "d/dp exp(p) = exp(p)");
7207        assert!((ep.h()[0][0] - e).abs() < 1e-15, "d²/dp² exp(p) = exp(p)");
7208    }
7209
7210    /// `Order2::ln` at a seeded variable: d/dp ln(p) = 1/p, d²/dp² ln(p) = -1/p².
7211    #[test]
7212    fn order2_ln_derivative_stack_correct() {
7213        let p0 = 2.0_f64;
7214        let p = Order2::<1>::variable(p0, 0);
7215        let lnp = JetScalar::ln(&p);
7216        assert!((lnp.value() - p0.ln()).abs() < 1e-15, "ln value");
7217        assert!((lnp.g()[0] - 1.0 / p0).abs() < 1e-15, "d/dp ln(p) = 1/p");
7218        assert!(
7219            (lnp.h()[0][0] - (-1.0 / (p0 * p0))).abs() < 1e-15,
7220            "d²/dp² ln(p) = -1/p²"
7221        );
7222    }
7223
7224    /// `exp` and `ln` are mutual inverses: `ln(exp(p)).value() == p` at the scalar.
7225    #[test]
7226    fn order2_exp_ln_roundtrip_at_value() {
7227        let p0 = 0.8_f64;
7228        let p = Order2::<1>::variable(p0, 0);
7229        let roundtrip = JetScalar::ln(&JetScalar::exp(&p));
7230        assert!((roundtrip.value() - p0).abs() < 1e-14, "ln(exp(p)) ≈ p");
7231    }
7232
7233    // ── Order1 tests ─────────────────────────────────────────────────────────
7234
7235    /// `Order1::constant` carries the correct value with all-zero gradient.
7236    #[test]
7237    fn order1_constant_has_zero_gradient() {
7238        let s = Order1::<3>::constant(-5.0);
7239        assert_eq!(s.value(), -5.0);
7240        for a in 0..3 {
7241            assert_eq!(s.g()[a], 0.0, "g[{a}] should be zero");
7242        }
7243    }
7244
7245    /// `Order1::variable(x, axis)` has unit gradient only in `axis`.
7246    #[test]
7247    fn order1_variable_has_unit_gradient_in_seeded_slot() {
7248        let s = Order1::<3>::variable(2.0, 1);
7249        assert_eq!(s.value(), 2.0);
7250        assert_eq!(s.g()[0], 0.0);
7251        assert_eq!(s.g()[1], 1.0);
7252        assert_eq!(s.g()[2], 0.0);
7253    }
7254
7255    /// `Order1::mul` satisfies the product rule (value and gradient, no Hessian).
7256    #[test]
7257    fn order1_mul_satisfies_product_rule() {
7258        let pv = 3.0_f64;
7259        let qv = -2.0_f64;
7260        let p = Order1::<2>::variable(pv, 0);
7261        let q = Order1::<2>::variable(qv, 1);
7262        let pq = crate::nested_dual::JetField::mul(&p, &q);
7263        assert_eq!(pq.value(), pv * qv);
7264        assert_eq!(pq.g()[0], qv, "∂(p·q)/∂p = q");
7265        assert_eq!(pq.g()[1], pv, "∂(p·q)/∂q = p");
7266    }
7267
7268    /// `Order1::exp` carries the correct value and gradient `e^{p₀}`.
7269    #[test]
7270    fn order1_exp_has_correct_value_and_gradient() {
7271        let p0 = 0.5_f64;
7272        let p = Order1::<2>::variable(p0, 0);
7273        let ep = JetScalar::exp(&p);
7274        let e = p0.exp();
7275        assert!((ep.value() - e).abs() < 1e-15, "exp value");
7276        assert!((ep.g()[0] - e).abs() < 1e-15, "d/dp exp(p)");
7277        assert_eq!(ep.g()[1], 0.0, "irrelevant gradient slot is zero");
7278    }
7279
7280    /// `Order1` and `Order2` agree on value and gradient for the same expression.
7281    #[test]
7282    fn order1_and_order2_agree_on_value_and_gradient() {
7283        let p0 = 1.3_f64;
7284        let q0 = -0.7_f64;
7285        // evaluate (p * q + p).exp() at (p0, q0)
7286        let p1 = Order1::<2>::variable(p0, 0);
7287        let q1 = Order1::<2>::variable(q0, 1);
7288        let expr1 = JetScalar::exp(&crate::nested_dual::JetField::add(
7289            &crate::nested_dual::JetField::mul(&p1, &q1),
7290            &p1,
7291        ));
7292
7293        let p2 = Order2::<2>::variable(p0, 0);
7294        let q2 = Order2::<2>::variable(q0, 1);
7295        let expr2 = JetScalar::exp(&crate::nested_dual::JetField::add(
7296            &crate::nested_dual::JetField::mul(&p2, &q2),
7297            &p2,
7298        ));
7299
7300        assert!(
7301            (expr1.value() - expr2.value()).abs() < 1e-14,
7302            "value mismatch"
7303        );
7304        for a in 0..2 {
7305            assert!(
7306                (expr1.g()[a] - expr2.g()[a]).abs() < 1e-14,
7307                "gradient[{a}] mismatch"
7308            );
7309        }
7310    }
7311
7312    // ── filtered_implicit_solve_scalar ────────────────────────────────────────
7313
7314    /// Lift the trivial linear constraint F(a, θ) = a - θ = 0 through `Order2<1>`.
7315    /// The exact lifted jet is a(θ) = θ, so value=θ₀, gradient=1.
7316    #[test]
7317    fn filtered_implicit_solve_linear_constraint_gives_exact_jet() {
7318        let theta0 = 3.0_f64;
7319        let theta = Order2::<1>::variable(theta0, 0);
7320        // a0 = theta0, F_a = 1, inv_fa = 1; 2 iters suffice for Order2.
7321        let a = filtered_implicit_solve_scalar::<1, Order2<1>>(theta0, 1.0, 2, |a_jet| {
7322            crate::nested_dual::JetField::sub(a_jet, &theta)
7323        });
7324        assert!((a.value() - theta0).abs() < 1e-14, "value = theta0");
7325        // da/dtheta = 1 (identity)
7326        assert!((a.g()[0] - 1.0).abs() < 1e-14, "gradient = 1");
7327        // d²a/dtheta² = 0 (linear)
7328        assert!(a.h()[0][0].abs() < 1e-14, "hessian = 0");
7329    }
7330
7331    /// `filtered_implicit_solve_scalar` on a quadratic constraint F(a,θ)=a²-θ=0
7332    /// with primal root a₀=√θ₀, giving da/dθ = 1/(2√θ₀), d²a/dθ² = -1/(4θ₀^{3/2}).
7333    #[test]
7334    fn filtered_implicit_solve_quadratic_constraint_matches_analytic_derivatives() {
7335        let theta0 = 4.0_f64;
7336        let a0 = theta0.sqrt();
7337        let inv_fa = 1.0 / (2.0 * a0);
7338        let theta = Order2::<1>::variable(theta0, 0);
7339        // F(a,theta) = a*a - theta
7340        let a = filtered_implicit_solve_scalar::<1, Order2<1>>(a0, inv_fa, 2, |a_jet| {
7341            let aa = crate::nested_dual::JetField::mul(a_jet, a_jet);
7342            crate::nested_dual::JetField::sub(&aa, &theta)
7343        });
7344        let tol = 1e-12;
7345        assert!((a.value() - a0).abs() < tol, "value = sqrt(theta0)");
7346        let expected_g = 0.5 / a0;
7347        assert!(
7348            (a.g()[0] - expected_g).abs() < tol,
7349            "da/dtheta = 1/(2*sqrt)"
7350        );
7351        let expected_h = -0.25 / (theta0 * a0);
7352        assert!(
7353            (a.h()[0][0] - expected_h).abs() < tol,
7354            "d2a/dtheta2 = -1/(4*theta^1.5)"
7355        );
7356    }
7357
7358    /// #932 correctness and release racer for the runtime shaped-value
7359    /// primitives. The comparison arm is the exact constant-synthesis idiom
7360    /// removed from the SLS wiggle paths: a unary composition whose derivative
7361    /// stack is identically zero. Both arms allocate the same runtime-width
7362    /// output shape from a warm-reset arena; the only intended difference is
7363    /// whether known-zero channels are written directly or computed by walking
7364    /// the Faà di Bruno composition.
7365    #[test]
7366    fn runtime_shaped_value_primitives_are_exact_and_skip_constant_composition_932() {
7367        use super::{DynamicJetArena, DynamicOrder2, RuntimeJetScalar};
7368        use crate::paired_timing::{SpeedGate, batched, paired_interleaved};
7369
7370        const K: usize = 48;
7371        let arena = DynamicJetArena::new();
7372        let variable = DynamicOrder2::variable(0.75, 7, K, &arena);
7373
7374        let constant = variable.constant_like(1.25);
7375        assert_eq!(constant.value().to_bits(), 1.25_f64.to_bits());
7376        assert_eq!(constant.dimension(), K);
7377        assert!(constant.g().iter().all(|&channel| channel == 0.0));
7378        assert!(constant.h().iter().all(|&channel| channel == 0.0));
7379
7380        let replaced = variable.with_value(-2.5);
7381        assert_eq!(replaced.value().to_bits(), (-2.5_f64).to_bits());
7382        assert_eq!(replaced.g(), variable.g());
7383        assert_eq!(replaced.h(), variable.h());
7384
7385        // The exactness pins above run in every build; the speed contract
7386        // below opens only in the release profile. Both arms allocate the same
7387        // runtime-width output shape from a warm-reset arena and return the same
7388        // quantity; the only intended difference is whether known-zero channels
7389        // are written directly or computed by walking the composition, so the
7390        // direct primitive must be the faster arm.
7391        if cfg!(debug_assertions) {
7392            return;
7393        }
7394        let mut gate = SpeedGate::open("RUNTIME-CONSTANT-932");
7395        let mut direct_arena = DynamicJetArena::new();
7396        let mut composed_arena = DynamicJetArena::new();
7397        let timing = paired_interleaved(
7398            15,
7399            1_000,
7400            0x9320_C057,
7401            batched(16, |nudge| {
7402                direct_arena.reset();
7403                let variable = DynamicOrder2::variable(0.75 + nudge, 7, K, &direct_arena);
7404                let constant = variable.constant_like(1.25);
7405                constant.value() + constant.g()[K - 1] + constant.h()[K * K - 1]
7406            }),
7407            batched(16, |nudge| {
7408                composed_arena.reset();
7409                let variable = DynamicOrder2::variable(0.75 + nudge, 7, K, &composed_arena);
7410                let constant = variable.compose_unary([1.25, 0.0, 0.0, 0.0, 0.0]);
7411                constant.value() + constant.g()[K - 1] + constant.h()[K * K - 1]
7412            }),
7413        );
7414        gate.faster(&format!("dimension={K}"), &timing, "direct", "composed");
7415        gate.finish();
7416    }
7417}
7418
7419#[cfg(test)]
7420mod weighted_compose_sum_979_tests {
7421    //! The fused `addend + Σ_i L_i · f_i(R)` against the loop it replaces.
7422    //!
7423    //! [`RuntimeJetScalar::weighted_compose_sum`]'s default IS that loop, so the
7424    //! contract is that a representation which overrides it agrees with the
7425    //! loop on every channel. [`DynamicOrder2`] overrides it by collapsing the
7426    //! `R`-dependent coefficients into two scalars and writing one output block;
7427    //! the loop writes `2N`. The two sum the same terms in a different order, so
7428    //! they agree to rounding rather than to the bit, and the fixture is chosen
7429    //! to make the difference from a REAL disagreement obvious: dense gradients
7430    //! and dense Hessians on every operand, no zero stack entries, and left
7431    //! factors that are genuine products rather than the coordinate seeds the
7432    //! flexible marginal-slope row happens to pass.
7433    use super::{DynamicJetArena, DynamicOrder2, RuntimeJetScalar};
7434
7435    const DIMENSION: usize = 6;
7436    const TERMS: usize = 4;
7437
7438    fn stacks() -> [[f64; 5]; TERMS] {
7439        [
7440            [0.31, 0.62, -0.24, 0.11, -0.05],
7441            [-0.17, 0.45, 0.33, -0.28, 0.09],
7442            [0.52, -0.38, 0.19, 0.07, -0.13],
7443            [0.28, 0.71, -0.46, 0.22, 0.04],
7444        ]
7445    }
7446
7447    /// A `right` and `TERMS` left factors, all with dense gradient and Hessian
7448    /// channels, built from the algebra rather than seeded flat.
7449    fn operands(arena: &DynamicJetArena) -> (Vec<DynamicOrder2<'_>>, DynamicOrder2<'_>, DynamicOrder2<'_>) {
7450        let vars: Vec<DynamicOrder2<'_>> = (0..DIMENSION)
7451            .map(|axis| {
7452                DynamicOrder2::variable(0.35 - 0.11 * (axis as f64), axis, DIMENSION, arena)
7453            })
7454            .collect();
7455        let right = vars[0]
7456            .mul(&vars[1])
7457            .add(&vars[2].compose_unary([0.9, -0.5, 0.27, -0.14, 0.06]));
7458        let lefts: Vec<DynamicOrder2<'_>> = (0..TERMS)
7459            .map(|term| {
7460                let scale = 0.4 + 0.23 * (term as f64);
7461                vars[term % DIMENSION]
7462                    .mul(&vars[(term + 3) % DIMENSION])
7463                    .scale(scale)
7464                    .add(&vars[(term + 1) % DIMENSION])
7465            })
7466            .collect();
7467        let addend = vars[4].mul(&vars[5]).scale(-0.7);
7468        (lefts, right, addend)
7469    }
7470
7471    /// The default's algebra, written out: one composition and one multiply-add
7472    /// per term, in term order.
7473    fn by_loop<'arena>(
7474        lefts: &[DynamicOrder2<'arena>],
7475        right: &DynamicOrder2<'arena>,
7476        derivative_stacks: &[[f64; 5]],
7477        addend: &DynamicOrder2<'arena>,
7478    ) -> DynamicOrder2<'arena> {
7479        let mut sum = *addend;
7480        for (left, stack) in lefts.iter().zip(derivative_stacks) {
7481            sum = left.multiply_add(&right.compose_unary(*stack), &sum);
7482        }
7483        sum
7484    }
7485
7486    fn close(label: &str, fused: f64, looped: f64) {
7487        let tolerance = 1.0e-13 * fused.abs().max(looped.abs()).max(1.0);
7488        assert!(
7489            (fused - looped).abs() <= tolerance,
7490            "{label}: fused {fused:+.17e} vs loop {looped:+.17e} (allowed {tolerance:.3e})"
7491        );
7492    }
7493
7494    #[test]
7495    fn the_fused_sum_matches_the_composition_and_product_loop() {
7496        let arena = DynamicJetArena::new();
7497        let (lefts, right, addend) = operands(&arena);
7498        let derivative_stacks = stacks();
7499
7500        let fused = DynamicOrder2::weighted_compose_sum(
7501            &lefts,
7502            &right,
7503            &derivative_stacks,
7504            &addend,
7505        );
7506        let looped = by_loop(&lefts, &right, &derivative_stacks, &addend);
7507
7508        close("value", fused.value(), looped.value());
7509        for axis in 0..DIMENSION {
7510            close(&format!("gradient[{axis}]"), fused.g()[axis], looped.g()[axis]);
7511        }
7512        for entry in 0..DIMENSION * DIMENSION {
7513            close(&format!("hessian[{entry}]"), fused.h()[entry], looped.h()[entry]);
7514        }
7515
7516        // NON-VACUITY. Every channel the comparison walks must be able to
7517        // disagree: a fixture whose Hessian is zero would pass on an override
7518        // that dropped the `R.g ⊗ R.g` term outright.
7519        assert!(
7520            fused.value().abs() > 1.0e-6,
7521            "the fixture must produce a nonzero value"
7522        );
7523        assert!(
7524            fused.g().iter().all(|channel| channel.abs() > 1.0e-9),
7525            "every gradient channel must be live: {:?}",
7526            fused.g()
7527        );
7528        assert!(
7529            fused.h().iter().filter(|channel| channel.abs() > 1.0e-9).count()
7530                > DIMENSION * DIMENSION / 2,
7531            "most Hessian channels must be live: {:?}",
7532            fused.h()
7533        );
7534    }
7535
7536    /// The addend is returned unchanged when there are no terms, and one term
7537    /// is the plain product-of-composition — the two edges the fused loop over
7538    /// `lefts` would get wrong by starting from the wrong accumulator.
7539    #[test]
7540    fn the_fused_sum_handles_no_terms_and_one_term() {
7541        let arena = DynamicJetArena::new();
7542        let (lefts, right, addend) = operands(&arena);
7543        let derivative_stacks = stacks();
7544
7545        let empty = DynamicOrder2::weighted_compose_sum(&[], &right, &[], &addend);
7546        close("empty value", empty.value(), addend.value());
7547        for entry in 0..DIMENSION * DIMENSION {
7548            close(
7549                &format!("empty hessian[{entry}]"),
7550                empty.h()[entry],
7551                addend.h()[entry],
7552            );
7553        }
7554
7555        let single = DynamicOrder2::weighted_compose_sum(
7556            &lefts[..1],
7557            &right,
7558            &derivative_stacks[..1],
7559            &addend,
7560        );
7561        let single_loop = by_loop(&lefts[..1], &right, &derivative_stacks[..1], &addend);
7562        close("single value", single.value(), single_loop.value());
7563        for entry in 0..DIMENSION * DIMENSION {
7564            close(
7565                &format!("single hessian[{entry}]"),
7566                single.h()[entry],
7567                single_loop.h()[entry],
7568            );
7569        }
7570    }
7571}
7572
7573#[cfg(test)]
7574mod dynamic_batch_fused_979_tests {
7575    //! The batched one-seed jet's FUSED operations against the generic ones
7576    //! they replace.
7577    //!
7578    //! [`DynamicOneSeedBatch`] overrides `mul`, `multiply_add`,
7579    //! `linear_combination`, `affine_composed_sum` and `weighted_compose_sum`
7580    //! so each writes its result
7581    //! block once instead of building it from a chain of primitive operations
7582    //! whose intermediates are allocated, written and read once each (#979: on
7583    //! the large-scale flex arm the zero-and-refill traffic those chains
7584    //! generate was 54% of the profile). [`DynamicOneSeed`] overrides none of
7585    //! them — it carries only the primitives and inherits every fused operation
7586    //! from the trait's generic default.
7587    //!
7588    //! So evaluating ONE generic expression at both types compares the fused
7589    //! path against the generic one on every channel, and lane `l` of the batch
7590    //! must reproduce the standalone seed for direction `u_l` exactly as the
7591    //! type's contract claims. The expression below is shaped like the flex row
7592    //! program's inner index: a weighted combination of primaries, a
7593    //! multiply-add against it, a composed sum over several outer functions, a
7594    //! weighted sum of compositions at one shared point, and a unary
7595    //! composition on top.
7596
7597    use super::{
7598        DynamicJetArena, DynamicJetBatchWorkspace, DynamicOneSeed, DynamicOneSeedBatch,
7599        RuntimeJetScalar,
7600    };
7601
7602    const DIMENSION: usize = 5;
7603    const LANES: usize = 3;
7604
7605    /// Point the jets are seeded at, and the direction of each lane.
7606    fn point(axis: usize) -> f64 {
7607        0.35 - 0.11 * (axis as f64)
7608    }
7609
7610    fn direction(lane: usize, axis: usize) -> f64 {
7611        // Dense and lane-dependent: a direction with zeros in it could hide a
7612        // term that the fused and generic paths disagree about.
7613        0.23 * ((lane + 1) as f64) - 0.07 * ((axis + 2) as f64) * ((lane + 1) as f64)
7614    }
7615
7616    /// One generic expression over the runtime jet algebra, exercising every
7617    /// operation the batch fuses.
7618    fn expression<'arena, S: RuntimeJetScalar<'arena>>(
7619        vars: &[S],
7620        workspace: &'arena S::Workspace,
7621    ) -> S {
7622        let weights = [1.0, -0.4, 0.75, 0.2, -0.6];
7623        let combined = S::linear_combination(vars, &weights, DIMENSION, workspace);
7624        // A multiply-add against the combination, the shape the score block has.
7625        let scored = vars[1].multiply_add(&combined, &vars[0]);
7626        // A composed sum with distinct input scales and derivative stacks: the
7627        // calibration grid's shape, where the scale is what the fused override
7628        // folds into its multiplier jet.
7629        let stacks = [
7630            [0.31, 0.62, -0.24, 0.11, -0.05],
7631            [-0.17, 0.45, 0.33, -0.28, 0.09],
7632            [0.52, -0.38, 0.19, 0.07, -0.13],
7633        ];
7634        let scales = [0.8, -1.3, 0.45];
7635        let inputs = [scored.clone(), combined.clone(), vars[2].clone()];
7636        let summed = S::affine_composed_sum(&inputs, &scales, &stacks, DIMENSION, workspace);
7637        // A product, as the observed index has.
7638        let producted = summed.mul(&vars[3]);
7639        // A weighted sum of compositions at ONE point: the link-deviation
7640        // shape, where the batch's fused override forms the lane-independent
7641        // derivative sum once and the standalone seed walks the trait default's
7642        // composition-and-product loop. Distinct stacks and distinct left
7643        // factors, so a lane that collapsed them would disagree here.
7644        let deviation_stacks = [
7645            [0.44, -0.21, 0.36, -0.12, 0.05],
7646            [-0.29, 0.58, -0.17, 0.23, -0.08],
7647        ];
7648        let deviation_lefts = [vars[4].clone(), vars[0].clone()];
7649        let warped =
7650            S::weighted_compose_sum(&deviation_lefts, &producted, &deviation_stacks, &summed);
7651        // A unary composition on top, as the observed index has.
7652        warped.compose_unary([0.9, -0.5, 0.27, -0.14, 0.06])
7653    }
7654
7655    fn assert_close(label: &str, fused: &[f64], generic: &[f64]) {
7656        assert_eq!(
7657            fused.len(),
7658            generic.len(),
7659            "{label}: fused length {} != generic length {}",
7660            fused.len(),
7661            generic.len()
7662        );
7663        for (index, (left, right)) in fused.iter().zip(generic).enumerate() {
7664            let scale = left.abs().max(right.abs()).max(1.0);
7665            assert!(
7666                (left - right).abs() <= 1e-12 * scale,
7667                "{label}[{index}]: fused {left:.17e} vs generic {right:.17e}"
7668            );
7669        }
7670    }
7671
7672    /// Lane `l` of the fused batch reproduces the standalone one-seed jet
7673    /// seeded by direction `u_l`, on the value, the gradient, the Hessian and
7674    /// the contracted third derivative.
7675    #[test]
7676    fn the_fused_batch_reproduces_the_generic_one_seed_on_every_channel() {
7677        let workspace = DynamicJetBatchWorkspace::new(LANES);
7678        let batch_vars: Vec<DynamicOneSeedBatch<'_>> = (0..DIMENSION)
7679            .map(|axis| {
7680                DynamicOneSeedBatch::seed_directions(
7681                    point(axis),
7682                    axis,
7683                    DIMENSION,
7684                    &workspace,
7685                    |lane| direction(lane, axis),
7686                )
7687            })
7688            .collect();
7689        let batch = expression(&batch_vars, &workspace);
7690
7691        for lane in 0..LANES {
7692            let arena = DynamicJetArena::new();
7693            let seed_vars: Vec<DynamicOneSeed<'_>> = (0..DIMENSION)
7694                .map(|axis| {
7695                    DynamicOneSeed::seed_direction(
7696                        point(axis),
7697                        axis,
7698                        direction(lane, axis),
7699                        DIMENSION,
7700                        &arena,
7701                    )
7702                })
7703                .collect();
7704            let single = expression(&seed_vars, &arena);
7705
7706            assert!(
7707                (batch.base.v - single.base.v).abs() <= 1e-12 * batch.base.v.abs().max(1.0),
7708                "lane {lane} value: fused {:.17e} vs generic {:.17e}",
7709                batch.base.v,
7710                single.base.v
7711            );
7712            assert_close(&format!("lane {lane} gradient"), batch.base.g(), single.base.g());
7713            assert_close(&format!("lane {lane} hessian"), batch.base.h(), single.base.h());
7714            assert_close(
7715                &format!("lane {lane} contracted third"),
7716                batch.contracted_third(lane),
7717                single.contracted_third(),
7718            );
7719        }
7720    }
7721
7722    /// The expression must actually reach every fused operation with a
7723    /// non-degenerate result: an expression whose contracted third derivative
7724    /// vanished would compare zero against zero and pass whatever the fused
7725    /// operations did.
7726    #[test]
7727    fn the_fused_batch_control_is_not_vacuous() {
7728        let workspace = DynamicJetBatchWorkspace::new(LANES);
7729        let batch_vars: Vec<DynamicOneSeedBatch<'_>> = (0..DIMENSION)
7730            .map(|axis| {
7731                DynamicOneSeedBatch::seed_directions(
7732                    point(axis),
7733                    axis,
7734                    DIMENSION,
7735                    &workspace,
7736                    |lane| direction(lane, axis),
7737                )
7738            })
7739            .collect();
7740        let batch = expression(&batch_vars, &workspace);
7741        assert!(batch.base.v.abs() > 1e-6, "value {:.3e}", batch.base.v);
7742        let gradient_scale = batch
7743            .base
7744            .g()
7745            .iter()
7746            .fold(0.0f64, |worst, value| worst.max(value.abs()));
7747        assert!(gradient_scale > 1e-6, "gradient scale {gradient_scale:.3e}");
7748        let hessian_scale = batch
7749            .base
7750            .h()
7751            .iter()
7752            .fold(0.0f64, |worst, value| worst.max(value.abs()));
7753        assert!(hessian_scale > 1e-6, "hessian scale {hessian_scale:.3e}");
7754        for lane in 0..LANES {
7755            let third_scale = batch
7756                .contracted_third(lane)
7757                .iter()
7758                .fold(0.0f64, |worst, value| worst.max(value.abs()));
7759            assert!(
7760                third_scale > 1e-6,
7761                "lane {lane} contracted-third scale {third_scale:.3e}"
7762            );
7763        }
7764        // The lanes must differ, or one lane's agreement would stand in for all
7765        // of them and a lane-indexing defect would be invisible.
7766        let first = batch.contracted_third(0).to_vec();
7767        let last = batch.contracted_third(LANES - 1).to_vec();
7768        let separation = first
7769            .iter()
7770            .zip(&last)
7771            .fold(0.0f64, |worst, (left, right)| worst.max((left - right).abs()));
7772        assert!(separation > 1e-6, "lane separation {separation:.3e}");
7773    }
7774}