| 242 | |
| 243 | template<typename T> |
| 244 | Array<T> data_gradient_base(const Array<T> &incoming_gradient, |
| 245 | const Array<T> &original_signal, |
| 246 | const Array<T> &original_filter, |
| 247 | const Array<T> &convolved_output, af::dim4 stride, |
| 248 | af::dim4 padding, af::dim4 dilation) { |
| 249 | UNUSED(convolved_output); |
| 250 | const dim4 &cDims = incoming_gradient.dims(); |
| 251 | const dim4 &sDims = original_signal.dims(); |
| 252 | const dim4 &fDims = original_filter.dims(); |
| 253 | |
| 254 | Array<T> collapsed_filter = original_filter; |
| 255 | |
| 256 | collapsed_filter = flip(collapsed_filter, {1, 1, 0, 0}); |
| 257 | collapsed_filter = modDims(collapsed_filter, |
| 258 | dim4(fDims[0] * fDims[1] * fDims[2], fDims[3])); |
| 259 | |
| 260 | Array<T> collapsed_gradient = incoming_gradient; |
| 261 | collapsed_gradient = reorder(collapsed_gradient, dim4(0, 1, 3, 2)); |
| 262 | collapsed_gradient = modDims( |
| 263 | collapsed_gradient, dim4(cDims[0] * cDims[1] * cDims[3], cDims[2])); |
| 264 | |
| 265 | T alpha = scalar<T>(1.0); |
| 266 | T beta = scalar<T>(0.0); |
| 267 | const int Mdim = 0; |
| 268 | const int Ndim = 0; |
| 269 | Array<T> res = createEmptyArray<T>( |
| 270 | dim4(collapsed_gradient.dims()[Mdim], collapsed_filter.dims()[Ndim], |
| 271 | collapsed_gradient.dims()[3], collapsed_gradient.dims()[3])); |
| 272 | gemm(res, AF_MAT_NONE, AF_MAT_TRANS, &alpha, collapsed_gradient, |
| 273 | collapsed_filter, &beta); |
| 274 | res = modDims(res, dim4(res.dims()[0] / sDims[3], sDims[3], |
| 275 | fDims[0] * fDims[1], sDims[2])); |
| 276 | res = reorder(res, dim4(0, 2, 3, 1)); |
| 277 | |
| 278 | const bool retCols = false; |
| 279 | res = wrap_dilated(res, sDims[0], sDims[1], fDims[0], fDims[1], stride[0], |
| 280 | stride[1], padding[0], padding[1], dilation[0], |
| 281 | dilation[1], retCols); |
| 282 | |
| 283 | return res; |
| 284 | } |
| 285 | |
| 286 | #ifdef WITH_CUDNN |
| 287 | template<typename T> |