| 21 | |
| 22 | template<typename T> |
| 23 | void shift(Param<T> out, CParam<T> in, const af::dim4 sdims) { |
| 24 | T* outPtr = out.get(); |
| 25 | const T* inPtr = in.get(); |
| 26 | |
| 27 | const af::dim4 oDims = out.dims(); |
| 28 | const af::dim4 ist = in.strides(); |
| 29 | const af::dim4 ost = out.strides(); |
| 30 | |
| 31 | int sdims_[4]; |
| 32 | // Need to do this because we are mapping output to input in the kernel |
| 33 | for (int i = 0; i < 4; i++) { |
| 34 | // sdims_[i] will always be positive and always [0, oDims[i]]. |
| 35 | // Negative shifts are converted to position by going the other way |
| 36 | // round |
| 37 | sdims_[i] = -(sdims[i] % (int)oDims[i]) + oDims[i] * (sdims[i] > 0); |
| 38 | assert(sdims_[i] >= 0 && sdims_[i] <= oDims[i]); |
| 39 | } |
| 40 | |
| 41 | for (dim_t ow = 0; ow < oDims[3]; ow++) { |
| 42 | const int oW = ow * ost[3]; |
| 43 | const int iw = simple_mod((ow + sdims_[3]), oDims[3]); |
| 44 | const int iW = iw * ist[3]; |
| 45 | for (dim_t oz = 0; oz < oDims[2]; oz++) { |
| 46 | const int oZW = oW + oz * ost[2]; |
| 47 | const int iz = simple_mod((oz + sdims_[2]), oDims[2]); |
| 48 | const int iZW = iW + iz * ist[2]; |
| 49 | for (dim_t oy = 0; oy < oDims[1]; oy++) { |
| 50 | const int oYZW = oZW + oy * ost[1]; |
| 51 | const int iy = simple_mod((oy + sdims_[1]), oDims[1]); |
| 52 | const int iYZW = iZW + iy * ist[1]; |
| 53 | for (dim_t ox = 0; ox < oDims[0]; ox++) { |
| 54 | const int oIdx = oYZW + ox; |
| 55 | const int ix = simple_mod((ox + sdims_[0]), oDims[0]); |
| 56 | const int iIdx = iYZW + ix; |
| 57 | |
| 58 | outPtr[oIdx] = inPtr[iIdx]; |
| 59 | } |
| 60 | } |
| 61 | } |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | } // namespace kernel |
| 66 | } // namespace cpu |
nothing calls this directly
no test coverage detected