Skip to content

quad_over_lin: form the composition Jacobian through the dispatchers - #151

Merged
dance858 merged 1 commit into
mainfrom
quad-over-lin-dispatcher-jacobian
Oct 12, 2026
Merged

dance858 merged 1 commit into
mainfrom
quad-over-lin-dispatcher-jacobian

Conversation

@dance858

Copy link
Copy Markdown
Collaborator

For an affine child x = f(u) the Jacobian row is (2 f(u)/y)^T J_f plus one entry, -value/y, at y's column. It was built with count_nonzero_cols, insert_idx and yTA_fill_values on the engine's CSC mirror of J_f, with a hand-maintained version stamp.

This forms it the way quad_form does: d = 2 f(u)/y held as an n x 1 permuted_dense is the dispatcher's transposed operand, so BTA_matrices_*(J_f, d) gives d^T J_f with the column pattern derived from J_f whatever its kind; a one-entry sparse row carries the y derivative; sum_matrices_* combines them into the node's Jacobian. A new quad_over_lin_expr holds the three handles. The leaf case and the Hessian are unchanged.

Two side effects: the fill is linear in nnz(J_f) where yTA_fill_values searched the output row per column, and the branch now calls jacobian_init / eval_jacobian on the child (no-ops for a new_linear child with a preset Jacobian), so any affine child works, not only a linear operator.

After this, yTA_fill_values, count_nonzero_cols and insert_idx have no engine caller (library PR moving them to tests/legacy follows), and matmul.c is the last user of the engine's CSC mirror.

Verified locally: Release, Debug and UBSan builds, 293 engine tests pass, guard-malloc + leaks --atExit clean, clang-format clean.

🤖 Generated with Claude Code

For an affine child x = f(u) the Jacobian row is (2 f(u)/y)^T J_f plus one
entry, -value/y, at y's column. It was built with count_nonzero_cols,
insert_idx and yTA_fill_values on the engine's CSC mirror of J_f, with a
hand-maintained version stamp. Form it like quad_form instead: d = 2 f(u)/y
held as an n x 1 permuted_dense is the dispatcher's transposed operand, so
BTA_matrices_* gives d^T J_f with the column pattern derived from J_f, a
one-entry sparse row carries the y derivative, and sum_matrices_* combines
them into the node's Jacobian. A new quad_over_lin_expr holds the three
handles. The leaf case and the Hessian are unchanged.

The branch now calls jacobian_init / eval_jacobian on the child (no-ops for
a linear operator with a preset Jacobian), so any affine child works.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@dance858
dance858 merged commit 5ca34d7 into main Oct 12, 2026
14 checks passed
@dance858
dance858 deleted the quad-over-lin-dispatcher-jacobian branch October 15, 2026 05:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant