| 212 | |
| 213 | template<typename InT, typename AccT, bool Expand, int ConvDim> |
| 214 | void convolve2_separable(InT *optr, InT const *const iptr, |
| 215 | AccT const *const fptr, af::dim4 const &oDims, |
| 216 | af::dim4 const &sDims, af::dim4 const &orgDims, |
| 217 | dim_t fDim, af::dim4 const &oStrides, |
| 218 | af::dim4 const &sStrides, dim_t fStride) { |
| 219 | UNUSED(orgDims); |
| 220 | UNUSED(sStrides); |
| 221 | UNUSED(fStride); |
| 222 | for (dim_t j = 0; j < oDims[1]; ++j) { |
| 223 | dim_t jOff = j * oStrides[1]; |
| 224 | dim_t cj = j + (ConvDim == 1) * (Expand ? 0 : fDim >> 1); |
| 225 | |
| 226 | for (dim_t i = 0; i < oDims[0]; ++i) { |
| 227 | dim_t iOff = i * oStrides[0]; |
| 228 | dim_t ci = i + (ConvDim == 0) * (Expand ? 0 : fDim >> 1); |
| 229 | |
| 230 | AccT accum = scalar<AccT>(0); |
| 231 | |
| 232 | for (dim_t f = 0; f < fDim; ++f) { |
| 233 | InT f_val = fptr[f]; |
| 234 | InT s_val; |
| 235 | |
| 236 | if (ConvDim == 0) { |
| 237 | dim_t offi = ci - f; |
| 238 | bool isCIValid = offi >= 0 && offi < sDims[0]; |
| 239 | bool isCJValid = cj >= 0 && cj < sDims[1]; |
| 240 | s_val = (isCJValid && isCIValid ? iptr[cj * sDims[0] + offi] |
| 241 | : scalar<InT>(0)); |
| 242 | } else { |
| 243 | dim_t offj = cj - f; |
| 244 | bool isCIValid = ci >= 0 && ci < sDims[0]; |
| 245 | bool isCJValid = offj >= 0 && offj < sDims[1]; |
| 246 | s_val = (isCJValid && isCIValid ? iptr[offj * sDims[0] + ci] |
| 247 | : scalar<InT>(0)); |
| 248 | } |
| 249 | |
| 250 | accum += AccT(s_val * f_val); |
| 251 | } |
| 252 | optr[iOff + jOff] = InT(accum); |
| 253 | } |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | template<typename InT, typename AccT, bool Expand> |
| 258 | void convolve2(Param<InT> out, CParam<InT> signal, CParam<AccT> c_filter, |