2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include "kernels/Utils.h"
25 namespace luci_interpreter
30 void calculateActivationRange(Activation activation, float *activation_min, float *activation_max)
34 case Activation::NONE:
35 case Activation::TANH:
36 *activation_min = std::numeric_limits<float>::lowest();
37 *activation_max = std::numeric_limits<float>::max();
39 case Activation::RELU:
41 *activation_max = std::numeric_limits<float>::max();
43 case Activation::RELU_N1_TO_1:
47 case Activation::RELU6:
52 throw std::runtime_error("Unsupported activation.");
56 static void calculateActivationRangeQuantizedImpl(Activation activation, int32_t qmin, int32_t qmax,
57 const Tensor *output, int32_t *activation_min,
58 int32_t *activation_max)
60 const float scale = output->scale();
61 const int32_t zero_point = output->zero_point();
63 auto quantize = [scale, zero_point](float x) {
64 return zero_point + static_cast<int32_t>(std::round(x / scale));
69 case Activation::NONE:
70 case Activation::TANH:
71 *activation_min = qmin;
72 *activation_max = qmax;
74 case Activation::RELU:
75 *activation_min = std::max(qmin, quantize(0.0f));
76 *activation_max = qmax;
78 case Activation::RELU_N1_TO_1:
79 *activation_min = std::max(qmin, quantize(-1.0f));
80 *activation_max = std::min(qmax, quantize(1.0f));
82 case Activation::RELU6:
83 *activation_min = std::max(qmin, quantize(0.0f));
84 *activation_max = std::min(qmax, quantize(6.0f));
87 throw std::runtime_error("Unsupported activation.");
91 void calculateActivationRangeQuantized(Activation activation, const Tensor *output,
92 int32_t *activation_min, int32_t *activation_max)
94 assert(output->zero_points().size() == 1);
97 switch (output->element_type())
101 qmax = std::numeric_limits<uint8_t>::max();
104 qmin = -std::numeric_limits<int8_t>::max();
105 qmax = std::numeric_limits<int8_t>::max();
108 // For now, assume that signed int16 type implies signed symmetric quantization.
109 assert(output->zero_point() == 0);
110 qmin = -std::numeric_limits<int16_t>::max();
111 qmax = std::numeric_limits<int16_t>::max();
114 throw std::runtime_error("Unsupported type.");
117 calculateActivationRangeQuantizedImpl(activation, qmin, qmax, output, activation_min,
121 void quantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift)
123 if (double_multiplier == 0.0)
125 *quantized_multiplier = 0;
130 const double q = std::frexp(double_multiplier, shift);
131 auto q_fixed = static_cast<int64_t>(std::round(q * (INT64_C(1) << 31)));
133 if (q_fixed == (INT64_C(1) << 31))
138 assert(q_fixed <= std::numeric_limits<int32_t>::max());
139 // A shift amount smaller than -31 would cause all bits to be shifted out
140 // and thus all results would be zero. We implement that instead with
141 // q_fixed==0, so as to avoid hitting issues with right-shift
142 // operations with shift amounts greater than 31. Note that this happens
143 // roughly when abs(double_multiplier) < 2^-31 and the present handling means
144 // that we're effectively flushing tiny double_multiplier's to zero.
145 // We could conceivably handle values in the range (roughly) [32, 63]
146 // as 'denormals' i.e. (shift==0, q_fixed < 2^30). In that point of view
147 // the present handling is just doing 'flush denormals to zero'. We could
148 // reconsider and actually generate nonzero denormals if a need arises.
154 *quantized_multiplier = static_cast<int32_t>(q_fixed);
157 void quantizeMultiplierSmallerThanOneExp(double double_multiplier, int32_t *quantized_multiplier,
160 assert(double_multiplier < 1.0);
161 assert(double_multiplier > 0.0);
163 quantizeMultiplier(double_multiplier, quantized_multiplier, &shift);
168 Shape calculateShapeForBroadcast(const Shape &input1_shape, const Shape &input2_shape)
170 const int num_input1_dims = input1_shape.num_dims();
171 const int num_input2_dims = input2_shape.num_dims();
172 const int num_out_dims = std::max(num_input1_dims, num_input2_dims);
173 Shape output_shape(num_out_dims);
175 for (int i = 0; i < num_out_dims; ++i)
177 const int32_t input1_dim = i < num_input1_dims ? input1_shape.dim(num_input1_dims - i - 1) : 1;
178 const int32_t input2_dim = i < num_input2_dims ? input2_shape.dim(num_input2_dims - i - 1) : 1;
179 assert(input1_dim == input2_dim || input1_dim == 1 || input2_dim == 1);
180 output_shape.dim(num_out_dims - i - 1) = std::max(input1_dim, input2_dim);
186 } // namespace kernels
187 } // namespace luci_interpreter