| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LEAKY_RELU_H_ |
| #define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LEAKY_RELU_H_ |
|
|
| #include <algorithm> |
| #include <limits> |
|
|
| #include "edge-impulse-sdk/tensorflow/lite/kernels/internal/common.h" |
|
|
| namespace tflite { |
| namespace reference_ops { |
|
|
| inline void LeakyRelu(const tflite::LeakyReluParams& params, |
| const RuntimeShape& input_shape, const float* input_data, |
| const RuntimeShape& output_shape, float* output_data) { |
| const int flat_size = MatchingFlatSize(input_shape, output_shape); |
| for (int i = 0; i < flat_size; ++i) { |
| const float val = input_data[i]; |
| |
| output_data[i] = val > 0 ? val : val * params.alpha; |
| } |
| } |
|
|
| template <typename T> |
| inline void QuantizeLeakyRelu(const LeakyReluParams& params, |
| const RuntimeShape& input_shape, |
| const T* input_data, |
| const RuntimeShape& output_shape, |
| T* output_data) { |
| const int flat_size = MatchingFlatSize(input_shape, output_shape); |
| static const int32_t quantized_min = std::numeric_limits<T>::min(); |
| static const int32_t quantized_max = std::numeric_limits<T>::max(); |
| for (int i = 0; i < flat_size; ++i) { |
| const int32_t input_value = input_data[i] - params.input_offset; |
| int32_t unclamped_output; |
| if (input_value >= 0) { |
| unclamped_output = params.output_offset + |
| MultiplyByQuantizedMultiplier( |
| input_value, params.output_multiplier_identity, |
| params.output_shift_identity); |
| } else { |
| unclamped_output = params.output_offset + |
| MultiplyByQuantizedMultiplier( |
| input_value, params.output_multiplier_alpha, |
| params.output_shift_alpha); |
| } |
| const T clamped_output = |
| std::min(quantized_max, std::max(quantized_min, unclamped_output)); |
| output_data[i] = static_cast<T>(clamped_output); |
| } |
| } |
|
|
| } |
| } |
|
|
| #endif |
|
|