| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_QUANTIZE_H_ |
| #define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_QUANTIZE_H_ |
|
|
| #include <algorithm> |
| #include <limits> |
| #include <vector> |
|
|
| #include "edge-impulse-sdk/tensorflow/lite/kernels/internal/common.h" |
| #include "edge-impulse-sdk/tensorflow/lite/kernels/internal/compatibility.h" |
| #include "edge-impulse-sdk/tensorflow/lite/kernels/internal/cppmath.h" |
| #include "edge-impulse-sdk/tensorflow/lite/kernels/internal/types.h" |
|
|
| namespace tflite { |
|
|
| namespace reference_ops { |
|
|
| template <typename InputT, typename OutputT> |
| inline void AffineQuantize(const tflite::QuantizationParams& op_params, |
| const RuntimeShape& input_shape, |
| const InputT* input_data, |
| const RuntimeShape& output_shape, |
| OutputT* output_data) { |
| const int32_t zero_point = op_params.zero_point; |
| const double scale = op_params.scale; |
| const int flat_size = MatchingFlatSize(input_shape, output_shape); |
| static constexpr int32_t min_val = std::numeric_limits<OutputT>::min(); |
| static constexpr int32_t max_val = std::numeric_limits<OutputT>::max(); |
|
|
| for (int i = 0; i < flat_size; i++) { |
| const InputT val = input_data[i]; |
| int32_t unclamped = |
| static_cast<int32_t>(TfLiteRound(val / static_cast<float>(scale))) + |
| zero_point; |
| int32_t clamped = std::min(std::max(unclamped, min_val), max_val); |
| output_data[i] = clamped; |
| } |
| } |
|
|
| |
| template <typename InputT, typename OutputT> |
| inline void PerChannelQuantize( |
| const tflite::PerChannelQuantizationParams& op_params, |
| const RuntimeShape& input_shape, const InputT* input_data, |
| const RuntimeShape& output_shape, OutputT* output_data) { |
| |
| MatchingFlatSize(input_shape, output_shape); |
|
|
| const int32_t* zero_point = op_params.zero_point; |
| const float* scale = op_params.scale; |
| const int32_t quantized_dimension = op_params.quantized_dimension; |
| const int32_t num_dims = input_shape.DimensionsCount(); |
| const int32_t* dims_data = input_shape.DimsData(); |
| std::vector<int> current_dim(num_dims, 0); |
| static constexpr int32_t min_val = std::numeric_limits<OutputT>::min(); |
| static constexpr int32_t max_val = std::numeric_limits<OutputT>::max(); |
|
|
| do { |
| size_t offset = |
| ReducedOutputOffset(num_dims, reinterpret_cast<const int*>(dims_data), |
| current_dim.data(), 0, nullptr); |
| const InputT val = input_data[offset]; |
| const int channel = current_dim[quantized_dimension]; |
| int32_t unclamped = static_cast<int32_t>(TfLiteRound( |
| val / static_cast<float>(scale[channel]))) + |
| zero_point[channel]; |
| int32_t clamped = std::min(std::max(unclamped, min_val), max_val); |
| output_data[offset] = static_cast<OutputT>(clamped); |
| } while (NextIndex(num_dims, reinterpret_cast<const int*>(dims_data), |
| current_dim.data())); |
| } |
|
|
| } |
|
|
| } |
| #endif |
|
|