1 /*******************************************************************************
2 * Copyright 2019-2020 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16 
17 #ifndef CPU_RESAMPLING_UTILS_HPP
18 #define CPU_RESAMPLING_UTILS_HPP
19 
20 #include "common/c_types_map.hpp"
21 
22 #include "cpu/simple_q10n.hpp"
23 
24 namespace dnnl {
25 namespace impl {
26 namespace cpu {
27 
28 namespace resampling_utils {
29 
linear_map(dim_t y,dim_t y_max,dim_t x_max)30 static inline float linear_map(dim_t y, dim_t y_max, dim_t x_max) {
31     return ((y + 0.5f) * x_max / y_max) - 0.5f;
32 }
nearest_idx(dim_t y,dim_t y_max,dim_t x_max)33 static inline dim_t nearest_idx(dim_t y, dim_t y_max, dim_t x_max) {
34     return (dim_t)roundf(linear_map(y, y_max, x_max));
35 }
ceil_idx(float x)36 static inline dim_t ceil_idx(float x) {
37     if (x < 0) return (dim_t)0;
38     return (dim_t)x == x ? (dim_t)x : (dim_t)x + 1;
39 }
linear_weight(int i,dim_t x,dim_t y_max,dim_t x_max)40 static inline float linear_weight(int i, dim_t x, dim_t y_max, dim_t x_max) {
41     float s = linear_map(x, y_max, x_max);
42     float w = nstl::abs(s - (dim_t)s);
43     return i == 0 ? 1.f - w : w;
44 };
45 
46 struct linear_coeffs_t {
linear_coeffs_tdnnl::impl::cpu::resampling_utils::linear_coeffs_t47     linear_coeffs_t(dim_t y, dim_t y_max, dim_t x_max) {
48         float s = linear_map(y, y_max, x_max);
49         idx[0] = left(s);
50         idx[1] = right(s, x_max);
51         wei[1] = nstl::abs(s - saturate<float>(idx[0]));
52         wei[0] = 1.f - wei[1];
53     }
54     // left and right index of source image used for interpolation
55     dim_t idx[2];
56     // left and right interpolation weights
57     float wei[2];
58 
59 private:
rightdnnl::impl::cpu::resampling_utils::linear_coeffs_t60     static dim_t right(float s, dim_t x_max) {
61         return nstl::min(ceil_idx(s), x_max - 1);
62     }
leftdnnl::impl::cpu::resampling_utils::linear_coeffs_t63     static dim_t left(float s) { return nstl::max((dim_t)s, (dim_t)0); }
64 };
65 
66 struct bwd_linear_coeffs_t {
bwd_linear_coeffs_tdnnl::impl::cpu::resampling_utils::bwd_linear_coeffs_t67     bwd_linear_coeffs_t(dim_t x, dim_t y_max, dim_t x_max) {
68         start[0] = x == 0 ? 0 : left_start(x, y_max, x_max);
69         start[1] = right_start(x, y_max, x_max);
70         end[0] = left_end(x, y_max, x_max);
71         end[1] = x == x_max - 1 ? y_max : right_end(x, y_max, x_max);
72     }
73     // index range (from start to end) of source image used as left and right
74     // edge for interpolation
75     dim_t start[2], end[2];
76 
77 private:
left_startdnnl::impl::cpu::resampling_utils::bwd_linear_coeffs_t78     static dim_t left_start(dim_t x, dim_t y_max, dim_t x_max) {
79         return ceil_idx(linear_map(x, x_max, y_max));
80     }
left_enddnnl::impl::cpu::resampling_utils::bwd_linear_coeffs_t81     static dim_t left_end(dim_t x, dim_t y_max, dim_t x_max) {
82         return nstl::min(ceil_idx(linear_map(x + 1, x_max, y_max)), y_max);
83     }
right_startdnnl::impl::cpu::resampling_utils::bwd_linear_coeffs_t84     static dim_t right_start(dim_t x, dim_t y_max, dim_t x_max) {
85         float s = linear_map(x - 1, x_max, y_max);
86         return s < 0 ? 0 : (dim_t)(s) + 1;
87     }
right_enddnnl::impl::cpu::resampling_utils::bwd_linear_coeffs_t88     static dim_t right_end(dim_t x, dim_t y_max, dim_t x_max) {
89         float s = linear_map(x, x_max, y_max);
90         return nstl::min(s < 0 ? 0 : (dim_t)s + 1, y_max);
91     }
92 };
93 
94 } // namespace resampling_utils
95 
96 } // namespace cpu
97 } // namespace impl
98 } // namespace dnnl
99 
100 #endif
101