#ifndef CPU_RESAMPLING_UTILS_HPP
#define CPU_RESAMPLING_UTILS_HPP
#include <cmath>
#include "common/c_types_map.hpp"
#include "cpu/simple_q10n.hpp"
namespace dnnl {
namespace impl {
namespace cpu {
namespace resampling_utils {
static inline float linear_map(dim_t y, dim_t y_max, dim_t x_max) {
float y_f = static_cast<float>(y);
float x_max_f = static_cast<float>(x_max);
float y_max_f = static_cast<float>(y_max);
return ((y_f + 0.5f) * x_max_f / y_max_f) - 0.5f;
}
static inline dim_t nearest_idx(dim_t y, dim_t y_max, dim_t x_max) {
return (dim_t)roundf(linear_map(y, y_max, x_max));
}
static inline dim_t ceil_idx(float x_f) {
if (x_f < 0) return (dim_t)0;
dim_t x = static_cast<dim_t>(x_f);
bool x_is_exact = static_cast<float>(x) == x_f;
return x_is_exact ? x : x + 1;
}
static inline float linear_weight(int i, dim_t x, dim_t y_max, dim_t x_max) {
float s = linear_map(x, y_max, x_max);
float s_trunc = std::trunc(s);
float w = nstl::abs(s - s_trunc);
return i == 0 ? 1.f - w : w;
}
struct linear_coeffs_t {
linear_coeffs_t(dim_t y, dim_t y_max, dim_t x_max) {
float s = linear_map(y, y_max, x_max);
idx[0] = left(s);
idx[1] = right(s, x_max);
wei[1] = nstl::abs(
s - static_cast<float>(q10n::saturate<float>(idx[0])));
wei[0] = 1.f - wei[1];
}
dim_t idx[2];
float wei[2];
private:
static dim_t right(float s, dim_t x_max) {
return nstl::min(ceil_idx(s), x_max - 1);
}
static dim_t left(float s) { return nstl::max((dim_t)s, (dim_t)0); }
};
struct bwd_linear_coeffs_t {
bwd_linear_coeffs_t(dim_t x, dim_t y_max, dim_t x_max) {
start[0] = x == 0 ? 0 : left_start(x, y_max, x_max);
start[1] = right_start(x, y_max, x_max);
end[0] = left_end(x, y_max, x_max);
end[1] = x == x_max - 1 ? y_max : right_end(x, y_max, x_max);
}
dim_t start[2], end[2];
private:
static dim_t left_start(dim_t x, dim_t y_max, dim_t x_max) {
return ceil_idx(linear_map(x, x_max, y_max));
}
static dim_t left_end(dim_t x, dim_t y_max, dim_t x_max) {
return nstl::min(ceil_idx(linear_map(x + 1, x_max, y_max)), y_max);
}
static dim_t right_start(dim_t x, dim_t y_max, dim_t x_max) {
float s = linear_map(x - 1, x_max, y_max);
return s < 0 ? 0 : (dim_t)(s) + 1;
}
static dim_t right_end(dim_t x, dim_t y_max, dim_t x_max) {
float s = linear_map(x, x_max, y_max);
return nstl::min(s < 0 ? 0 : (dim_t)s + 1, y_max);
}
};
}
} } }
#endif