| 167 | |
| 168 | template<typename T> |
| 169 | Array<T> conv2DataGradient(const Array<T> &incoming_gradient, |
| 170 | const Array<T> &original_signal, |
| 171 | const Array<T> &original_filter, |
| 172 | const Array<T> & /*convolved_output*/, |
| 173 | af::dim4 stride, af::dim4 padding, |
| 174 | af::dim4 dilation) { |
| 175 | const dim4 &cDims = incoming_gradient.dims(); |
| 176 | const dim4 &sDims = original_signal.dims(); |
| 177 | const dim4 &fDims = original_filter.dims(); |
| 178 | |
| 179 | Array<T> collapsed_filter = original_filter; |
| 180 | |
| 181 | collapsed_filter = flip(collapsed_filter, {1, 1, 0, 0}); |
| 182 | collapsed_filter = modDims(collapsed_filter, |
| 183 | dim4(fDims[0] * fDims[1] * fDims[2], fDims[3])); |
| 184 | |
| 185 | Array<T> collapsed_gradient = incoming_gradient; |
| 186 | collapsed_gradient = reorder(collapsed_gradient, dim4(0, 1, 3, 2)); |
| 187 | collapsed_gradient = modDims( |
| 188 | collapsed_gradient, dim4(cDims[0] * cDims[1] * cDims[3], cDims[2])); |
| 189 | |
| 190 | Array<T> res = |
| 191 | matmul(collapsed_gradient, collapsed_filter, AF_MAT_NONE, AF_MAT_TRANS); |
| 192 | res = modDims(res, dim4(res.dims()[0] / sDims[3], sDims[3], |
| 193 | fDims[0] * fDims[1], sDims[2])); |
| 194 | res = reorder(res, dim4(0, 2, 3, 1)); |
| 195 | |
| 196 | const bool retCols = false; |
| 197 | res = wrap_dilated(res, sDims[0], sDims[1], fDims[0], fDims[1], stride[0], |
| 198 | stride[1], padding[0], padding[1], dilation[0], |
| 199 | dilation[1], retCols); |
| 200 | |
| 201 | return res; |
| 202 | } |
| 203 | |
| 204 | template<typename T> |
| 205 | Array<T> conv2FilterGradient(const Array<T> &incoming_gradient, |