| 174 | |
| 175 | template<typename T> |
| 176 | Array<T> convolve2_base(const Array<T> &signal, const Array<T> &filter, |
| 177 | const dim4 &stride, const dim4 &padding, |
| 178 | const dim4 &dilation) { |
| 179 | dim4 sDims = signal.dims(); |
| 180 | dim4 fDims = filter.dims(); |
| 181 | |
| 182 | dim_t outputWidth = |
| 183 | 1 + (sDims[0] + 2 * padding[0] - (((fDims[0] - 1) * dilation[0]) + 1)) / |
| 184 | stride[0]; |
| 185 | dim_t outputHeight = |
| 186 | 1 + (sDims[1] + 2 * padding[1] - (((fDims[1] - 1) * dilation[1]) + 1)) / |
| 187 | stride[1]; |
| 188 | |
| 189 | const bool retCols = false; |
| 190 | Array<T> unwrapped = |
| 191 | unwrap(signal, fDims[0], fDims[1], stride[0], stride[1], padding[0], |
| 192 | padding[1], dilation[0], dilation[1], retCols); |
| 193 | |
| 194 | unwrapped = reorder(unwrapped, dim4(1, 2, 0, 3)); |
| 195 | dim4 uDims = unwrapped.dims(); |
| 196 | unwrapped = |
| 197 | modDims(unwrapped, dim4(uDims[0] * uDims[1], uDims[2] * uDims[3])); |
| 198 | |
| 199 | Array<T> collapsedFilter = filter; |
| 200 | |
| 201 | collapsedFilter = flip(collapsedFilter, {1, 1, 0, 0}); |
| 202 | collapsedFilter = modDims(collapsedFilter, |
| 203 | dim4(fDims[0] * fDims[1] * fDims[2], fDims[3])); |
| 204 | |
| 205 | T alpha = scalar<T>(1.0); |
| 206 | T beta = scalar<T>(0.0); |
| 207 | const int Mdim = 1; |
| 208 | const int Ndim = 1; |
| 209 | Array<T> res = createEmptyArray<T>( |
| 210 | dim4(unwrapped.dims()[Mdim], collapsedFilter.dims()[Ndim], |
| 211 | unwrapped.dims()[2], unwrapped.dims()[3])); |
| 212 | gemm(res, AF_MAT_TRANS, AF_MAT_NONE, &alpha, unwrapped, collapsedFilter, |
| 213 | &beta); |
| 214 | res = modDims(res, dim4(outputWidth, outputHeight, signal.dims()[3], |
| 215 | collapsedFilter.dims()[1])); |
| 216 | Array<T> out = reorder(res, dim4(0, 1, 3, 2)); |
| 217 | |
| 218 | return out; |
| 219 | } |
| 220 | |
| 221 | template<typename T> |
| 222 | Array<T> convolve2(Array<T> const &signal, Array<T> const &filter, |