Skip to content

Commit 806d094

Browse files
committed
happy with convolve.c
1 parent 945ae93 commit 806d094

1 file changed

Lines changed: 11 additions & 27 deletions

File tree

‎src/atoms/affine/convolve.c‎

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,8 @@
2828
/* 1D full convolution: y = conv(a, child), where a is a length-m kernel
2929
* held by param_source and child is a length-n vector. Output length is
3030
* m + n - 1. In matrix form, y = T(a) @ child, where T(a) is the
31-
* (m+n-1) x n Toeplitz matrix with T(a)[k, j] = a[k-j] when 0 <= k-j < m.
32-
*
33-
* Forward and Hessian backprop (w' = T(a)^T w) are direct loops, avoiding
34-
* CSR traversal and AT materialization. Jacobian values go through the
35-
* existing block-left-mult path so composite children work correctly.
36-
*
37-
* When param_source is updatable, forward() refreshes T(a)'s CSR values
38-
* from the new kernel before running the convolution. The sparsity of
39-
* T(a) is kernel-independent (staircase), so only values are rewritten. */
31+
* (m+n-1) x n Toeplitz/convolution matrix with T(a)[k, j] = a[k-j] when
32+
* 0 <= k-j < m. */
4033

4134
static void forward(expr *node, const double *u)
4235
{
@@ -118,17 +111,14 @@ static void eval_wsum_hess(expr *node, const double *w)
118111
{
119112
expr *child = node->left;
120113
convolve_expr *cnode = (convolve_expr *) node;
121-
int m = cnode->m;
122-
int n = cnode->n;
123114
const double *a = cnode->param_source->value;
124115
double *w_prime = node->work->dwork;
125116

126-
/* w' = T(a)^T w. T(a)^T[j, k] = a[k-j] for j <= k < j+m, so
127-
w'[j] = sum_{i=0..m-1} a[i] * w[i + j]. */
128-
for (int j = 0; j < n; j++)
117+
/* w' = conv_matrix.T w, so w'[j] = sum_{i=0..m-1} a[i] * w[i + j]. */
118+
for (int j = 0; j < cnode->n; j++)
129119
{
130120
double sum = 0.0;
131-
for (int i = 0; i < m; i++)
121+
for (int i = 0; i < cnode->m; i++)
132122
{
133123
sum += a[i] * w[i + j];
134124
}
@@ -160,18 +150,18 @@ expr *new_convolve(expr *param_node, expr *child)
160150
is shape-agnostic (flat buffers of size m + n - 1). Output shape
161151
matches the input orientation. */
162152
int m = param_node->size;
163-
int n, out_d1, out_d2;
153+
int n, d1, d2;
164154
if (child->d2 == 1)
165155
{
166156
n = child->d1;
167-
out_d1 = m + n - 1;
168-
out_d2 = 1;
157+
d1 = m + n - 1;
158+
d2 = 1;
169159
}
170160
else if (child->d1 == 1)
171161
{
172162
n = child->d2;
173-
out_d1 = 1;
174-
out_d2 = m + n - 1;
163+
d1 = 1;
164+
d2 = m + n - 1;
175165
}
176166
else
177167
{
@@ -180,15 +170,9 @@ expr *new_convolve(expr *param_node, expr *child)
180170
exit(1);
181171
}
182172

183-
if (m < 1 || n < 1)
184-
{
185-
fprintf(stderr, "Error in new_convolve: m and n must be >= 1\n");
186-
exit(1);
187-
}
188-
189173
convolve_expr *cnode = (convolve_expr *) SP_CALLOC(1, sizeof(convolve_expr));
190174
expr *node = &cnode->base;
191-
init_expr(node, out_d1, out_d2, child->n_vars, forward, jacobian_init_impl,
175+
init_expr(node, d1, d2, child->n_vars, forward, jacobian_init_impl,
192176
eval_jacobian, is_affine, wsum_hess_init_impl, eval_wsum_hess,
193177
free_type_data);
194178
node->left = child;

0 commit comments

Comments
 (0)