/*******************************************************************************
* Copyright 2019 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License")* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
#include "gpu/intel/include/dispatch.h"
#include "gpu/intel/include/post_ops.h"
#include "gpu/intel/include/types.h"
#if IS_FWD == 1
KERNEL_ATTR
__kernel void ref_resampling_fwd(
__global const DATA_T *src, __global DST_DATA_T *dst POST_OP_ARGS) {
const uint mb = GWS_GET_MB() const uint c = GWS_GET_C() const uint od = GWS_GET_OD() const uint oh = GWS_GET_OH() const uint ow = GWS_GET_OW() const float id = (od + .5f) * ID / OD const float ih = (oh + .5f) * IH / OH const float iw = (ow + .5f) * IW / OW
float result const uint dst_index = DST_OFF(mb, c, od, oh, ow)
if (mb >= DST_D0 || c >= DST_D1) {
dst[dst_index] = TO_DST(0.0f) return }
#if RESAMPLING_ALG_NEAREST
const uint src_index = SRC_OFF(mb, c, (uint)id, (uint)ih, (uint)iw) result = CONVERT_FLOAT_T(src[src_index])#else
const int id0 = max((int)floor(id - .5f), 0) const int id1 = min((int)ceil(id - .5f), ID - 1) const int ih0 = max((int)floor(ih - .5f), 0) const int ih1 = min((int)ceil(ih - .5f), IH - 1) const int iw0 = max((int)floor(iw - .5f), 0) const int iw1 = min((int)ceil(iw - .5f), IW - 1)
const float wd[2] = {1.0f - fabs(id - .5f - id0), fabs(id - .5f - id0)} const float wh[2] = {1.0f - fabs(ih - .5f - ih0), fabs(ih - .5f - ih0)} const float ww[2] = {1.0f - fabs(iw - .5f - iw0), fabs(iw - .5f - iw0)}
const int ih_arr[2] = {ih0, ih1} const int iw_arr[2] = {iw0, iw1}
float cd[2][2] for_(int i = 0 for (int j = 0 cd[i][j] = CONVERT_FLOAT_T(
src[SRC_OFF(mb, c, id0, ih_arr[i], iw_arr[j])])
* wd[0]
+ CONVERT_FLOAT_T(
src[SRC_OFF(mb, c, id1, ih_arr[i], iw_arr[j])])
* wd[1] float ch[2] for (int i = 0 ch[i] = cd[0][i] * wh[0] + cd[1][i] * wh[1]
result = ch[0] * ww[0] + ch[1] * ww[1]
#endif
float sum_src#if WITH_SUM
sum_src = DST_TO_REF(dst[dst_index])#endif
#if NDIMS == 3
const unsigned po_d2 = ow const unsigned po_d3 = 0 const unsigned po_d4 = 0#elif NDIMS == 4
const unsigned po_d2 = oh const unsigned po_d3 = ow const unsigned po_d4 = 0#elif NDIMS == 5
const unsigned po_d2 = od const unsigned po_d3 = oh const unsigned po_d4 = ow#else
const unsigned po_d2 = 0 const unsigned po_d3 = 0 const unsigned po_d4 = 0#endif
APPLY_POST_OPS_SERIAL(result, sum_src, mb, c, po_d2, po_d3, po_d4, 0) dst[dst_index] = TO_DST(result)}
#endif
#if IS_BWD == 1
float linear(int x, int fo, int fi) {
return ((x + .5f) * fo / fi) - .5f}
KERNEL_ATTR
__kernel void ref_resampling_bwd(
__global DATA_T *diff_src, __global const DST_DATA_T *diff_dst) {
#define CEIL(x) max((int)ceil(x), (int)0)
#define L(x, fo, fi) linear(x, fo, fi)
#define LS(x, fo, fi) CEIL(L(x, fo, fi))
#define RS(x, fo, fi) \
L((int)x - 1, fo, fi) < 0 ? 0 : (int)(L((int)x - 1, fo, fi)) + 1
#define LE(x, fo, fi, lim) min(CEIL(L(x + 1, fo, fi)), (int)lim)
#define RE(x, fo, fi, lim) \
min((L(x, fo, fi) < 0 ? 0 : (int)(L(x, fo, fi)) + 1), (int)lim)
const uint mb = GWS_GET_MB() const uint c = GWS_GET_C() const uint id = GWS_GET_ID() const uint ih = GWS_GET_IH() const uint iw = GWS_GET_IW() const uint src_index = SRC_OFF(mb, c, id, ih, iw)
if (mb >= DST_D0 || c >= DST_D1) {
diff_src[src_index] = TO_DST(0.f) return }
#if RESAMPLING_ALG_NEAREST
int od_start = CEIL(id * FD - .5f) int oh_start = CEIL(ih * FH - .5f) int ow_start = CEIL(iw * FW - .5f) int od_end = CEIL((id + 1.f) * FD - .5f) int oh_end = CEIL((ih + 1.f) * FH - .5f) int ow_end = CEIL((iw + 1.f) * FW - .5f) float src_val = 0 for (int i = od_start for (int j = oh_start for (int k = ow_start const int dst_index = DST_OFF(mb, c, i, j, k) src_val += DST_TO_REF(diff_dst[dst_index]) }
}
}
#else
int left_sd = id == 0 ? 0 : LS(id, OD, ID) int left_sh = ih == 0 ? 0 : LS(ih, OH, IH) int left_sw = iw == 0 ? 0 : LS(iw, OW, IW) int right_sd = RS(id, OD, ID) int right_sh = RS(ih, OH, IH) int right_sw = RS(iw, OW, IW) int left_ed = LE(id, OD, ID, OD) int left_eh = LE(ih, OH, IH, OH) int left_ew = LE(iw, OW, IW, OW) int right_ed = id == (ID - 1) ? OD : RE(id, OD, ID, OD) int right_eh = ih == (IH - 1) ? OH : RE(ih, OH, IH, OH) int right_ew = iw == (IW - 1) ? OW : RE(iw, OW, IW, OW) int od_start[2] = {left_sd, right_sd} int oh_start[2] = {left_sh, right_sh} int ow_start[2] = {left_sw, right_sw} int od_end[2] = {left_ed, right_ed} int oh_end[2] = {left_eh, right_eh} int ow_end[2] = {left_ew, right_ew} float src_val = 0.0f for (int c1 = 0 for (int c2 = 0 for (int c3 = 0 for (int i = od_start[c1] for (int j = oh_start[c2] for (int k = ow_start[c3] float dst_val = DST_TO_REF(
diff_dst[DST_OFF(mb, c, i, j, k)]) float d = L(i, ID, OD) float h = L(j, IH, OH) float w = L(k, IW, OW) float Wid = c1 == 0 ? 1.f - fabs(d - (int)d)
: fabs(d - (int)d) float Wih = c2 == 0 ? 1.f - fabs(h - (int)h)
: fabs(h - (int)h) float Wiw = c3 == 0 ? 1.f - fabs(w - (int)w)
: fabs(w - (int)w) src_val += dst_val * Wid * Wih * Wiw }
}
}
}
}
}
#endif
#if DT_S32 == 1
diff_src[src_index] = CONVERT_DATA_T(src_val)#else // #if DT_S32 == 1
diff_src[src_index] = TO_DATA_T(src_val)#endif // #else // #if DT_S32 == 1
}
#endif