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 | |
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 | } |
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 | } |
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 | } |
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 { |
47 | 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: |
60 | static dim_t right(float s, dim_t x_max) { |
61 | return nstl::min(ceil_idx(s), x_max - 1); |
62 | } |
63 | static dim_t left(float s) { return nstl::max((dim_t)s, (dim_t)0); } |
64 | }; |
65 | |
66 | struct bwd_linear_coeffs_t { |
67 | 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: |
78 | 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 | } |
81 | 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 | } |
84 | 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 | } |
88 | 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 | |