From 6594d18c7cf79e4e4afb4401498300b2233f8e50 Mon Sep 17 00:00:00 2001 From: dance858 Date: Tue, 13 Oct 2026 17:15:33 +0200 Subject: [PATCH 1/2] left_matmul: one Jacobian path through BA_kron_matrices_* Pins sparsediff_linalg to the head of sparsediff_linalg#33 (stacked on #32; untagged, to be repinned to v0.5.1). The dense and sparse jacobian_init / eval_jacobian pairs become one pair calling the new dispatcher, which routes on A's kind and on n_blocks == 1. vector_mult.c includes matmul.h, where #32 moved DA_matrices_fill_values. Co-Authored-By: Claude Opus 5.5 --- sparsediff_linalg | 2 +- src/atoms/affine/left_matmul.c | 78 +++++----------------------------- src/atoms/affine/vector_mult.c | 1 + 3 files changed, 12 insertions(+), 69 deletions(-) diff --git a/sparsediff_linalg b/sparsediff_linalg index 4c12185..8ba0c7b 160000 --- a/sparsediff_linalg +++ b/sparsediff_linalg @@ -1 +1 @@ -Subproject commit 4c1218595c0e4b5e5dc3af57dd1da3550f998e58 +Subproject commit 8ba0c7b32f3ab3a78c84fb88235d2e73efecc0ad diff --git a/src/atoms/affine/left_matmul.c b/src/atoms/affine/left_matmul.c index 322e321..d760af7 100644 --- a/src/atoms/affine/left_matmul.c +++ b/src/atoms/affine/left_matmul.c @@ -17,7 +17,6 @@ */ #include "atoms/affine.h" #include "sparsediff_linalg/dense.h" -#include "sparsediff_linalg/matmul.h" #include "sparsediff_linalg/matmul_kron.h" #include "sparsediff_linalg/matrix.h" #include "sparsediff_linalg/tracked_alloc.h" @@ -109,81 +108,26 @@ static void free_type_data(expr *node) lnode->param_source = NULL; } -/* jacobian_init for dense left matmul */ -static void jacobian_init_dense(expr *node) +/* J_y = kron(I_p, A) J_f; the dispatcher routes on A's kind and on p == 1. */ +static void jacobian_init_impl(expr *node) { /* initialize jacobian of child */ expr *x = node->left; left_matmul_expr *lnode = (left_matmul_expr *) node; jacobian_init(x); - /* initialize this node's jacobian */ - if (lnode->n_blocks == 1) - { - node->jacobian = BA_matrices_alloc(lnode->A, x->jacobian); - } - else - { - node->jacobian = - BA_dense_kron_matrices_alloc(lnode->A, lnode->n_blocks, x->jacobian); - } -} - -/* eval_jacobian for dense left matmul. */ -static void eval_jacobian_dense(expr *node) -{ - /* evaluate jacobian of child */ - left_matmul_expr *lnode = (left_matmul_expr *) node; - expr *x = node->left; - eval_jacobian(x); - - if (lnode->n_blocks == 1) - { - BA_matrices_fill_values(lnode->A, x->jacobian, node->jacobian); - } - else - { - BA_dense_kron_matrices_fill_values(lnode->A, lnode->n_blocks, x->jacobian, - node->jacobian); - } + node->jacobian = BA_kron_matrices_alloc(lnode->A, lnode->n_blocks, x->jacobian); } -/* jacobian_init for sparse left matmul */ -static void jacobian_init_sparse(expr *node) -{ - /* initialize jacobian of child */ - expr *x = node->left; - left_matmul_expr *lnode = (left_matmul_expr *) node; - jacobian_init(x); - - /* J_y = A J_f through the dispatchers, like the dense case. */ - if (lnode->n_blocks == 1) - { - node->jacobian = BA_matrices_alloc(lnode->A, x->jacobian); - return; - } - - /* J_y = kron(I_p, A) J_f */ - node->jacobian = - BA_sparse_kron_matrices_alloc(lnode->A, lnode->n_blocks, x->jacobian); -} - -/* eval_jacobian for sparse left matmul */ -static void eval_jacobian_sparse(expr *node) +static void eval_jacobian_impl(expr *node) { /* evaluate jacobian of child */ left_matmul_expr *lnode = (left_matmul_expr *) node; expr *x = node->left; eval_jacobian(x); - if (lnode->n_blocks == 1) - { - BA_matrices_fill_values(lnode->A, x->jacobian, node->jacobian); - return; - } - - BA_sparse_kron_matrices_fill_values(lnode->A, lnode->n_blocks, x->jacobian, - node->jacobian); + BA_kron_matrices_fill_values(lnode->A, lnode->n_blocks, x->jacobian, + node->jacobian); } static void wsum_hess_init_impl(expr *node) @@ -264,10 +208,8 @@ expr *new_left_matmul(expr *param_node, expr *u, const CSR_matrix *A) left_matmul_expr *lnode = (left_matmul_expr *) sp_calloc(1, sizeof(left_matmul_expr)); expr *node = &lnode->base; - /* Sparse A: a single block goes through BA_matrices_*, the kron form - through BA_sparse_kron_matrices_*. */ - init_expr(node, d1, d2, u->n_vars, forward, jacobian_init_sparse, - eval_jacobian_sparse, is_affine, wsum_hess_init_impl, + init_expr(node, d1, d2, u->n_vars, forward, jacobian_init_impl, + eval_jacobian_impl, is_affine, wsum_hess_init_impl, eval_wsum_hess_impl, free_type_data); node->left = u; expr_retain(u); @@ -300,8 +242,8 @@ expr *new_left_matmul_dense(expr *param_node, expr *u, int m, int n, left_matmul_expr *lnode = (left_matmul_expr *) sp_calloc(1, sizeof(left_matmul_expr)); expr *node = &lnode->base; - init_expr(node, d1, d2, u->n_vars, forward, jacobian_init_dense, - eval_jacobian_dense, is_affine, wsum_hess_init_impl, + init_expr(node, d1, d2, u->n_vars, forward, jacobian_init_impl, + eval_jacobian_impl, is_affine, wsum_hess_init_impl, eval_wsum_hess_impl, free_type_data); node->left = u; expr_retain(u); diff --git a/src/atoms/affine/vector_mult.c b/src/atoms/affine/vector_mult.c index 3b59897..f68500a 100644 --- a/src/atoms/affine/vector_mult.c +++ b/src/atoms/affine/vector_mult.c @@ -16,6 +16,7 @@ * limitations under the License. */ #include "atoms/affine.h" +#include "sparsediff_linalg/matmul.h" #include "sparsediff_linalg/tracked_alloc.h" #include "subexpr.h" #include From c41282657fee124b272ac1bf949178f7cdfd56e1 Mon Sep 17 00:00:00 2001 From: dance858 Date: Tue, 13 Oct 2026 17:48:03 +0200 Subject: [PATCH 2/2] Pin sparsediff_linalg to v0.5.1 Co-Authored-By: Claude Opus 5.5 --- sparsediff_linalg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sparsediff_linalg b/sparsediff_linalg index 8ba0c7b..74392a1 160000 --- a/sparsediff_linalg +++ b/sparsediff_linalg @@ -1 +1 @@ -Subproject commit 8ba0c7b32f3ab3a78c84fb88235d2e73efecc0ad +Subproject commit 74392a18c774b6fa159838ee6a3666ee645e9d66