| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_MEAN_H_ |
| #define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_MEAN_H_ |
|
|
| #include <algorithm> |
|
|
| #include "edge-impulse-sdk/tensorflow/lite/kernels/internal/common.h" |
|
|
| namespace tflite { |
| namespace reference_integer_ops { |
|
|
| template <typename integer_type> |
| inline void Mean(const tflite::MeanParams& op_params, int32_t multiplier, |
| int32_t shift, const RuntimeShape& unextended_input_shape, |
| const integer_type* input_data, int32_t input_zero_point, |
| const RuntimeShape& unextended_output_shape, |
| integer_type* output_data, int32_t output_zero_point) { |
| |
| |
| TFLITE_CHECK_EQ(unextended_input_shape.DimensionsCount(), 4); |
| TFLITE_CHECK_LE(unextended_output_shape.DimensionsCount(), 4); |
| const RuntimeShape input_shape = |
| RuntimeShape::ExtendedShape(4, unextended_input_shape); |
| const RuntimeShape output_shape = |
| RuntimeShape::ExtendedShape(4, unextended_output_shape); |
| const int output_batch = output_shape.Dims(0); |
| const int output_height = output_shape.Dims(1); |
| const int output_width = output_shape.Dims(2); |
| const int output_depth = output_shape.Dims(3); |
| const int input_height = input_shape.Dims(1); |
| const int input_width = input_shape.Dims(2); |
| const int num_elements_in_axis = input_width * input_height; |
|
|
| TFLITE_CHECK_EQ(op_params.axis_count, 2); |
| TFLITE_CHECK((op_params.axis[0] == 1 && op_params.axis[1] == 2) || |
| (op_params.axis[0] == 2 && op_params.axis[1] == 1)); |
| TFLITE_CHECK_EQ(output_height, 1); |
| TFLITE_CHECK_EQ(output_width, 1); |
|
|
| static constexpr int32_t kMinInt = std::numeric_limits<integer_type>::min(); |
| static constexpr int32_t kMaxInt = std::numeric_limits<integer_type>::max(); |
|
|
| for (int out_b = 0; out_b < output_batch; ++out_b) { |
| for (int out_d = 0; out_d < output_depth; ++out_d) { |
| int32_t acc = 0; |
| for (int in_h = 0; in_h < input_height; ++in_h) { |
| for (int in_w = 0; in_w < input_width; ++in_w) { |
| acc += input_data[Offset(input_shape, out_b, in_h, in_w, out_d)] - |
| input_zero_point; |
| } |
| } |
| acc = MultiplyByQuantizedMultiplier(acc, multiplier, shift); |
| acc = acc > 0 ? (acc + num_elements_in_axis / 2) / num_elements_in_axis |
| : (acc - num_elements_in_axis / 2) / num_elements_in_axis; |
| acc += output_zero_point; |
| acc = std::min(std::max(acc, kMinInt), kMaxInt); |
| output_data[Offset(output_shape, out_b, 0, 0, out_d)] = |
| static_cast<integer_type>(acc); |
| } |
| } |
| } |
|
|
| } |
| } |
|
|
| #endif |
|
|