namespace ov::reference::fake_quantize_details

namespace fake_quantize_details {

// global functions

template <typename T>
static T quantize(
    const T arg,
    const T in_low,
    const T in_high,
    const T out_low,
    const T out_high,
    const T levels_minus_one
    );

static std::vector<size_t> compute_strides(
    const ov::Shape& out_shape,
    const ov::Shape& shape
    );

static std::tuple<size_t, size_t> get_inner_stride(
    size_t num_output_elements,
    const ov::Shape& output_shape,
    const ov::Shape& shape,
    size_t current_output_inner_stride
    );

template <typename T, typename F>
static void fake_quantize_non_unit_inner_stride(
    const T \* arg,
    const T \* in_low,
    const T \* in_high,
    const T \* out_low,
    const T \* out_high,
    T \* out,
    const Shape& arg_shape,
    T levels_minus_one,
    size_t input_inner_stride,
    const F& get_outer_strides
    );

template <typename T, typename F>
static void fake_quantize_unit_inner_stride(
    const T \* arg,
    const T \* in_low,
    const T \* in_high,
    const T \* out_low,
    const T \* out_high,
    T \* out,
    const Shape& arg_shape,
    T levels_minus_one,
    size_t input_inner_stride,
    const F& get_outer_strides
    );

template <typename T, typename F>
static void fake_quantize_unit_output_intervals_inner_stride(
    const T \* arg,
    const T \* in_low,
    const T \* in_high,
    const T \* out_low,
    const T \* out_high,
    T \* out,
    const Shape& arg_shape,
    T levels_minus_one,
    size_t input_inner_stride,
    const F& get_outer_strides
    );

template <typename T, typename F>
static void fake_quantize_unit_input_intervals_inner_stride(
    const T \* arg,
    const T \* in_low,
    const T \* in_high,
    const T \* out_low,
    const T \* out_high,
    T \* out,
    const Shape& arg_shape,
    T levels_minus_one,
    size_t input_inner_stride,
    const F& get_outer_strides
    );

template <typename T, typename F>
static void transform(
    const T \* first1,
    const T \*const last1,
    const T \* first2,
    const T \* first3,
    T \* out,
    const F& f
    );

template <typename T, typename F>
static void transform(
    const T \* first1,
    const T \*const last1,
    const T \* first2,
    const T \* first3,
    const T \* first4,
    const T \* first5,
    T \* out,
    const F& f
    );

template <typename T, typename F1, typename F2>
static void fake_quantize_loop(
    const Shape& arg_shape,
    const T \* arg,
    const T \* in_low,
    const T \* in_high,
    const T \* out_low,
    const T \* out_high,
    T \* out,
    size_t input_inner_stride,
    const F1& get_outer_strides,
    const F2& quantize_loop
    );

template <typename T, typename F>
void fake_quantize_non_unit_inner_stride(
    const T \* arg,
    const T \* in_low,
    const T \* in_high,
    const T \* out_low,
    const T \* out_high,
    T \* out,
    const Shape& arg_shape,
    T levels_minus_one,
    size_t input_inner_stride,
    const F& get_outer_strides
    );

template <typename T, typename F>
void fake_quantize_unit_inner_stride(
    const T \* arg,
    const T \* in_low,
    const T \* in_high,
    const T \* out_low,
    const T \* out_high,
    T \* out,
    const Shape& arg_shape,
    T levels_minus_one,
    size_t input_inner_stride,
    const F& get_outer_strides
    );

template <typename T, typename F>
void fake_quantize_unit_output_intervals_inner_stride(
    const T \* arg,
    const T \* in_low,
    const T \* in_high,
    const T \* out_low,
    const T \* out_high,
    T \* out,
    const Shape& arg_shape,
    T levels_minus_one,
    size_t input_inner_stride,
    const F& get_outer_strides
    );

template <typename T, typename F>
void fake_quantize_unit_input_intervals_inner_stride(
    const T \* arg,
    const T \* in_low,
    const T \* in_high,
    const T \* out_low,
    const T \* out_high,
    T \* out,
    const Shape& arg_shape,
    T levels_minus_one,
    size_t input_inner_stride,
    const F& get_outer_strides
    );

} // namespace fake_quantize_details