diff --git a/reg_field.h b/reg_field.h index b1146a9..f1628aa 100755 --- a/reg_field.h +++ b/reg_field.h @@ -674,7 +674,12 @@ void matvec_absolute_rls( offset_t nall = nbatch + ndim; offset_t osc = stride_out[nall]; offset_t isc = stride_inp[nall]; - offset_t wsc = stride_wgt[nall]; + // RLS: wgt has wc=1 (a single weight broadcast across all `nc` field + // channels), so the per-channel stride must be forced to 0 -- using the + // tensor's real (size-1) last-dim stride here indexes wgt[stride*c] for + // c>0, walking off the wc=1 buffer into the next voxel's weight (or OOB + // at the last voxel). See fastfields-cpu-lib#62. + offset_t wsc = 0; offset_t nc = size[nall]; offset_t numel = prod(size, nall); // no outer loop across channels @@ -721,7 +726,12 @@ void diag_absolute_rls( offset_t nall = nbatch + ndim; offset_t osc = stride_out[nall]; - offset_t wsc = stride_wgt[nall]; + // RLS: wgt has wc=1 (a single weight broadcast across all `nc` field + // channels), so the per-channel stride must be forced to 0 -- using the + // tensor's real (size-1) last-dim stride here indexes wgt[stride*c] for + // c>0, walking off the wc=1 buffer into the next voxel's weight (or OOB + // at the last voxel). See fastfields-cpu-lib#62. + offset_t wsc = 0; offset_t nc = size[nall]; offset_t numel = prod(size, nall); // no outer loop across channels @@ -775,7 +785,12 @@ void relax_absolute_rls_( offset_t osc = stride_sol[nall]; offset_t hsc = stride_hes[nall]; offset_t gsc = stride_grd[nall]; - offset_t wsc = stride_wgt[nall]; + // RLS: wgt has wc=1 (a single weight broadcast across all `nc` field + // channels), so the per-channel stride must be forced to 0 -- using the + // tensor's real (size-1) last-dim stride here indexes wgt[stride*c] for + // c>0, walking off the wc=1 buffer into the next voxel's weight (or OOB + // at the last voxel). See fastfields-cpu-lib#62. + offset_t wsc = 0; offset_t nc = size[nall]; offset_t numel = prod(size, nall); // no outer loop across channels @@ -1043,7 +1058,12 @@ void matvec_membrane_rls( offset_t nall = nbatch + ndim; offset_t osc = stride_out[nall]; offset_t isc = stride_inp[nall]; - offset_t wsc = stride_wgt[nall]; + // RLS: wgt has wc=1 (a single weight broadcast across all `nc` field + // channels), so the per-channel stride must be forced to 0 -- using the + // tensor's real (size-1) last-dim stride here indexes wgt[stride*c] for + // c>0, walking off the wc=1 buffer into the next voxel's weight (or OOB + // at the last voxel). See fastfields-cpu-lib#62. + offset_t wsc = 0; offset_t nc = size[nall]; offset_t numel = prod(size, nall); // no outer loop across channels @@ -1096,7 +1116,12 @@ void diag_membrane_rls( reduce_t voxel_size[ndim]; fillfrom(voxel_size, _voxel_size); offset_t nall = nbatch + ndim; offset_t osc = stride_out[nall]; - offset_t wsc = stride_wgt[nall]; + // RLS: wgt has wc=1 (a single weight broadcast across all `nc` field + // channels), so the per-channel stride must be forced to 0 -- using the + // tensor's real (size-1) last-dim stride here indexes wgt[stride*c] for + // c>0, walking off the wc=1 buffer into the next voxel's weight (or OOB + // at the last voxel). See fastfields-cpu-lib#62. + offset_t wsc = 0; offset_t nc = size[nall]; offset_t numel = prod(size, nall); // no outer loop across channels @@ -1156,7 +1181,12 @@ void relax_membrane_rls_( offset_t osc = stride_sol[nall]; offset_t hsc = stride_hes[nall]; offset_t gsc = stride_grd[nall]; - offset_t wsc = stride_wgt[nall]; + // RLS: wgt has wc=1 (a single weight broadcast across all `nc` field + // channels), so the per-channel stride must be forced to 0 -- using the + // tensor's real (size-1) last-dim stride here indexes wgt[stride*c] for + // c>0, walking off the wc=1 buffer into the next voxel's weight (or OOB + // at the last voxel). See fastfields-cpu-lib#62. + offset_t wsc = 0; offset_t nc = size[nall]; offset_t numel = prod(size, nall); // no outer loop across channels @@ -1452,7 +1482,12 @@ void matvec_bending_rls( offset_t nall = nbatch + ndim; offset_t osc = stride_out[nall]; offset_t isc = stride_inp[nall]; - offset_t wsc = stride_wgt[nall]; + // RLS: wgt has wc=1 (a single weight broadcast across all `nc` field + // channels), so the per-channel stride must be forced to 0 -- using the + // tensor's real (size-1) last-dim stride here indexes wgt[stride*c] for + // c>0, walking off the wc=1 buffer into the next voxel's weight (or OOB + // at the last voxel). See fastfields-cpu-lib#62. + offset_t wsc = 0; offset_t nc = size[nall]; offset_t numel = prod(size, nall); // no outer loop across channels @@ -1506,7 +1541,12 @@ void diag_bending_rls( reduce_t voxel_size[ndim]; fillfrom(voxel_size, _voxel_size); offset_t nall = nbatch + ndim; offset_t osc = stride_out[nall]; - offset_t wsc = stride_wgt[nall]; + // RLS: wgt has wc=1 (a single weight broadcast across all `nc` field + // channels), so the per-channel stride must be forced to 0 -- using the + // tensor's real (size-1) last-dim stride here indexes wgt[stride*c] for + // c>0, walking off the wc=1 buffer into the next voxel's weight (or OOB + // at the last voxel). See fastfields-cpu-lib#62. + offset_t wsc = 0; offset_t nc = size[nall]; offset_t numel = prod(size, nall); // no outer loop across channels @@ -1567,7 +1607,12 @@ void relax_bending_rls_( offset_t osc = stride_sol[nall]; offset_t hsc = stride_hes[nall]; offset_t gsc = stride_grd[nall]; - offset_t wsc = stride_wgt[nall]; + // RLS: wgt has wc=1 (a single weight broadcast across all `nc` field + // channels), so the per-channel stride must be forced to 0 -- using the + // tensor's real (size-1) last-dim stride here indexes wgt[stride*c] for + // c>0, walking off the wc=1 buffer into the next voxel's weight (or OOB + // at the last voxel). See fastfields-cpu-lib#62. + offset_t wsc = 0; offset_t nc = size[nall]; offset_t numel = prod(size, nall); // no outer loop across channels