18#include "kernels/Utils.h"
36 if (dynamic_shape_vector !=
nullptr)
38 input_shape.
resize(dynamic_shape_vector->dimensionsCount());
40 for (
int n = 0; n < dynamic_shape_vector->dimensionsCount(); ++n)
42 input_shape.
setDim(n, dynamic_shape_vector->dims(n));
54 case Activation::NONE:
55 *activation_min = std::numeric_limits<T>::lowest();
56 *activation_max = std::numeric_limits<T>::max();
58 case Activation::RELU:
60 *activation_max = std::numeric_limits<T>::max();
62 case Activation::RELU_N1_TO_1:
66 case Activation::RELU6:
71 assert(
false &&
"Unsupported activation.");
76 int32_t n_col, int32_t *output)
78 for (
int i = 0; i < n_row; ++i)
81 for (
int j = 0; j < n_col; ++j)
85 output[i] += row_sum * scalar;
95 for (
int i = 0; i < N; ++i)
97 if (input_shape1.
dims(i) != input_shape2.
dims(i))
106 float *activation_max);
108 int32_t *activation_max);
110 int64_t *activation_max);
115 const float x_log2 = std::log(x) * (1.0f / std::log(2.0f));
116 const float x_log2_rounded = std::round(x_log2);
117 const float x_log2_fracpart = x_log2 - x_log2_rounded;
119 *log2_result =
static_cast<int>(x_log2_rounded);
120 return std::abs(x_log2_fracpart) < 1e-3f;
125 const double max_input_rescaled = 1.0 * ((1 << input_integer_bits) - 1) *
126 (1LL << (total_signed_bits - input_integer_bits)) /
127 (1LL << input_left_shift);
131 return static_cast<int>(std::floor(max_input_rescaled));
134static void calculateActivationRangeQuantizedImpl(
Activation activation, int32_t qmin, int32_t qmax,
135 int32_t zero_point,
float scale,
136 int32_t *activation_min, int32_t *activation_max)
138 auto quantize = [scale, zero_point](
float x) {
139 return zero_point +
static_cast<int32_t
>(std::round(x / scale));
144 case Activation::NONE:
145 case Activation::TANH:
146 *activation_min = qmin;
147 *activation_max = qmax;
149 case Activation::RELU:
150 *activation_min = std::max(qmin, quantize(0.0f));
151 *activation_max = qmax;
153 case Activation::RELU_N1_TO_1:
154 *activation_min = std::max(qmin, quantize(-1.0f));
155 *activation_max = std::min(qmax, quantize(1.0f));
157 case Activation::RELU6:
158 *activation_min = std::max(qmin, quantize(0.0f));
159 *activation_max = std::min(qmax, quantize(6.0f));
162 assert(
false &&
"Unsupported activation.");
166static void calculateActivationRangeQuantizedImpl(
Activation activation, int32_t qmin, int32_t qmax,
167 const circle::Tensor *output,
168 int32_t *activation_min, int32_t *activation_max)
170 const float scale = Tensor::scale(output);
171 const int32_t zero_point = Tensor::zero_point(output);
173 calculateActivationRangeQuantizedImpl(activation, qmin, qmax, zero_point, zero_point,
174 activation_min, activation_max);
178 float output_scale,
DataType data_type,
179 int32_t *activation_min, int32_t *activation_max)
187 qmax = std::numeric_limits<uint8_t>::max();
190 qmin = -std::numeric_limits<int8_t>::max();
191 qmax = std::numeric_limits<int8_t>::max();
195 assert(output_zero_point == 0);
196 qmin = -std::numeric_limits<int16_t>::max();
197 qmax = std::numeric_limits<int16_t>::max();
200 assert(
false &&
"Unsupported type.");
203 calculateActivationRangeQuantizedImpl(activation, qmin, qmax, output_zero_point, output_scale,
204 activation_min, activation_max);
208 int32_t *activation_min, int32_t *activation_max)
210 assert(Tensor::zero_points(output).
size() == 1);
211 const float scale = Tensor::scale(output);
212 const int32_t zero_point = Tensor::zero_point(output);
214 activation_min, activation_max);
217void quantizeMultiplier(
double double_multiplier, int32_t *quantized_multiplier,
int *shift)
219 if (double_multiplier == 0.0)
221 *quantized_multiplier = 0;
226 const double q = std::frexp(double_multiplier, shift);
227 auto q_fixed =
static_cast<int64_t
>(std::round(q * (int64_t(1) << 31)));
229 if (q_fixed == (int64_t(1) << 31))
234 assert(q_fixed <= std::numeric_limits<int32_t>::max());
250 *quantized_multiplier =
static_cast<int32_t
>(q_fixed);
256 assert(double_multiplier < 1.0);
257 assert(double_multiplier > 0.0);
266 const circle::Tensor *input2)
268 const int num_input1_dims = Tensor::num_dims(input1);
269 const int num_input2_dims = Tensor::num_dims(input2);
270 const int num_out_dims = std::max(num_input1_dims, num_input2_dims);
273 for (
int i = 0; i < num_out_dims; ++i)
275 const int32_t input1_dim =
276 i < num_input1_dims ?
Tensor::dim(input1, num_input1_dims - i - 1) : 1;
277 const int32_t input2_dim =
278 i < num_input2_dims ?
Tensor::dim(input2, num_input2_dims - i - 1) : 1;
280 bool need_broadcast = input1_dim != input2_dim;
281 bool can_broadcast = input1_dim == 1 || input2_dim == 1;
luci_interpreter::RuntimeShape * getDynamicShapeTensor(const circle::Tensor *tensor)
int32_t dimensionsCount() const
int32_t dims(int i) const
void setDim(int i, int32_t val)
void resize(int dimensions_count)
#define LUCI_INTERPRETER_CHECK(cond)
const luci_interpreter::RuntimeShape output_shape
bool checkedLog2(const float x, int *log2_result)
int calculateInputRadius(int input_integer_bits, int input_left_shift, int total_signed_bits)
Shape calculateShapeForBroadcast(const Shape &input1_shape, const Shape &input2_shape)
bool areShapesEqual(const luci_interpreter::RuntimeShape &input_shape1, const luci_interpreter::RuntimeShape &input_shape2)
tflite::RuntimeShape getTensorShape(const Tensor *tensor)
luci_interpreter::FusedActFunc Activation
void calculateActivationRange(Activation activation, T *activation_min, T *activation_max)
void quantizeMultiplierSmallerThanOneExp(double double_multiplier, int32_t *quantized_multiplier, int *left_shift)
void calculateActivationRangeQuantized(Activation activation, const Tensor *output, int32_t *activation_min, int32_t *activation_max)
void quantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift)
void matrixScalarMultiplyAccumulate(const int8_t *matrix, int32_t scalar, int32_t n_row, int32_t n_col, int32_t *output)
luci_interpreter::RuntimeShape getTensorRuntimeShape(const circle::Tensor *circle_tensor, BaseRuntimeGraph *runtime_graph)
DataType
"scalar" value type
Index shift(const Index &in_index, const Shape &shift_from)
const loco::Dimension & dim(uint32_t axis) const