blob: 06c9b61154ead114147742c01c6bcf3064454bce [file] [log] [blame]
Georgios Pinitas4c5469b2019-05-21 13:32:43 +01001/*
2 * Copyright (c) 2019 ARM Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#ifndef __ARM_COMPUTE_QUANTIZATION_INFO_H__
25#define __ARM_COMPUTE_QUANTIZATION_INFO_H__
26
27#include "arm_compute/core/Rounding.h"
Manuel Bottini3689fcd2019-06-14 17:18:12 +010028#include "utils/misc/Utility.h"
Georgios Pinitas4c5469b2019-05-21 13:32:43 +010029
30#include <cstddef>
31#include <vector>
32
33namespace arm_compute
34{
35using qasymm8_t = uint8_t; /**< 8 bit quantized asymmetric scalar value */
36using qsymm8_t = int8_t; /**< 8 bit quantized symmetric scalar value */
37
38/** Quantization info when assuming per layer quantization */
39struct UniformQuantizationInfo
40{
41 /** Default constructor */
42 UniformQuantizationInfo()
43 : scale(0.f), offset(0)
44 {
45 }
46 /** Constructor
47 *
48 * @param[in] scale Quantization scale
49 * @param[in] offset Quantization offset
50 */
51 UniformQuantizationInfo(float scale, int32_t offset)
52 : scale(scale), offset(offset)
53 {
54 }
55 /** Checks if the scale and offset are both zero */
56 bool empty() const
57 {
58 return (scale == 0) && (offset == 0);
59 }
60
61 float scale;
62 int32_t offset;
63};
64
65/** Quantization information */
66struct QuantizationInfo
67{
68 /** Default constructor */
69 QuantizationInfo() noexcept
70 : scale(),
71 offset()
72 {
73 }
74 /** Construct quantization info.
75 *
76 * @note Used for symmetric quantization
77 *
78 * @param[in] scale Scale.
79 */
80 QuantizationInfo(float scale)
81 : scale(1, scale), offset()
82 {
83 }
84 /** Construct quantization info.
85 *
86 * @note Used for asymmetric quantization
87 *
88 * @param[in] scale Scale.
89 * @param[in] offset Offset.
90 */
91 QuantizationInfo(float scale, int offset)
92 : scale(1, scale), offset(1, offset)
93 {
94 }
95 /** Construct quantization info.
96 *
97 * @note Used for symmetric per channel quantization
98 *
99 * @param[in] scale Scale.
100 */
101 QuantizationInfo(std::vector<float> scale)
102 : scale(scale), offset()
103 {
104 }
105 /** Indicates whether this QuantizationInfo has valid settings or not
106 *
107 * @return True if the this has invalid settings.
108 */
109 bool empty() const
110 {
111 return scale.empty() && offset.empty();
112 }
113 /** Return per layer quantization info
114 *
115 * @return Uniform quantization information in case of empty information zero is returned in the respective fields
116 */
117 UniformQuantizationInfo uniform() const
118 {
119 UniformQuantizationInfo uqinfo;
120 uqinfo.scale = scale.empty() ? 0 : scale[0];
121 uqinfo.offset = offset.empty() ? 0 : offset[0];
122
123 return uqinfo;
124 }
125
126 std::vector<float> scale; /**< Vector containing scaling factors */
127 std::vector<int32_t> offset; /**< Vector containing zero offsets */
128};
129
130/** Check whether two quantization info are equal.
131 *
132 * @param[in] lhs RHS quantization info.
133 * @param[in] rhs LHS quantization info.
134 *
135 * @return True if the given quantization info is the same.
136 */
137inline bool operator==(const QuantizationInfo &lhs, const QuantizationInfo &rhs)
138{
139 return (lhs.scale == rhs.scale) && (lhs.offset == rhs.offset);
140}
141
142/** Check whether two quantization info are not equal.
143 *
144 * @param[in] lhs RHS quantization info.
145 * @param[in] rhs LHS quantization info.
146 *
147 * @return True if the given quantization info is the same.
148 */
149inline bool operator!=(const QuantizationInfo &lhs, const QuantizationInfo &rhs)
150{
151 return !(operator==(lhs, rhs));
152}
153
154/** Check whether two quantization info are equal.
155 *
156 * @param[in] lhs RHS quantization info.
157 * @param[in] rhs LHS quantization info.
158 *
159 * @return True if the given quantization info is the same.
160 */
161inline bool operator==(const UniformQuantizationInfo &lhs, const UniformQuantizationInfo &rhs)
162{
163 return (lhs.scale == rhs.scale) && (lhs.offset == rhs.offset);
164}
165
166/** Check whether two quantization info are not equal.
167 *
168 * @param[in] lhs RHS quantization info.
169 * @param[in] rhs LHS quantization info.
170 *
171 * @return True if the given quantization info is the same.
172 */
173inline bool operator!=(const UniformQuantizationInfo &lhs, const UniformQuantizationInfo &rhs)
174{
175 return !(operator==(lhs, rhs));
176}
177
178/** Quantize a value given a asymmetric quantization scheme
179 *
180 * @param[in] value Value to quantize
181 * @param[in] qinfo Quantization information to use for quantizing
182 * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
183 *
184 * @return Quantized value
185 */
186inline uint8_t quantize_qasymm8(float value, const UniformQuantizationInfo &qinfo, RoundingPolicy rounding_policy = RoundingPolicy::TO_NEAREST_UP)
187{
188 int quantized = arm_compute::round(value / qinfo.scale, rounding_policy) + qinfo.offset;
189 quantized = std::max(0, std::min(quantized, 255));
190 return quantized;
191}
192
193/** Quantize a value given a asymmetric quantization scheme
194 *
195 * @param[in] value Value to quantize
196 * @param[in] qinfo Quantization information to use for quantizing
197 * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
198 *
199 * @return Quantized value
200 */
201inline uint8_t quantize_qasymm8(float value, const QuantizationInfo &qinfo, RoundingPolicy rounding_policy = RoundingPolicy::TO_NEAREST_UP)
202{
203 UniformQuantizationInfo uqinfo = qinfo.uniform();
204 int quantized = arm_compute::round(value / uqinfo.scale, rounding_policy) + uqinfo.offset;
205 quantized = std::max(0, std::min(quantized, 255));
206 return quantized;
207}
208
209/** Quantize a value given a symmetric quantization scheme
210 *
211 * @param[in] value Value to quantize
212 * @param[in] qinfo Quantization information to use for quantizing
213 *
214 * @return Quantized value
215 */
216inline int8_t quantize_qsymm8(float value, const QuantizationInfo &qinfo)
217{
218 int quantized = arm_compute::round(value / qinfo.uniform().scale, RoundingPolicy::TO_NEAREST_UP);
219 quantized = std::max(-128, std::min(quantized, 127));
220 return quantized;
221}
222
223/** Dequantize a value given a asymmetric quantization scheme
224 *
225 * @param[in] value Value to dequantize
226 * @param[in] qinfo Quantization information to use for dequantizing
227 *
228 * @return Dequantized value
229 */
230inline float dequantize_qasymm8(uint8_t value, const UniformQuantizationInfo &qinfo)
231{
232 return (static_cast<int>(value) - qinfo.offset) * qinfo.scale;
233}
234
235/** Dequantize a value given a asymmetric quantization scheme
236 *
237 * @param[in] value Value to dequantize
238 * @param[in] qinfo Quantization information to use for dequantizing
239 *
240 * @return Dequantized value
241 */
242inline float dequantize_qasymm8(uint8_t value, const QuantizationInfo &qinfo)
243{
244 UniformQuantizationInfo uqinfo = qinfo.uniform();
245 return (static_cast<int>(value) - uqinfo.offset) * uqinfo.scale;
246}
247
248/** Dequantize a value given a symmetric quantization scheme
249 *
250 * @param[in] value Value to dequantize
251 * @param[in] qinfo Quantization information to use for dequantizing
252 *
253 * @return Dequantized value
254 */
255inline float dequantize_qsymm8(int8_t value, const QuantizationInfo &qinfo)
256{
257 return value * qinfo.uniform().scale;
258}
Manuel Bottini3689fcd2019-06-14 17:18:12 +0100259
260/** Quantize a value given a 16-bit symmetric quantization scheme
261 *
262 * @param[in] value Value to quantize
263 * @param[in] qinfo Quantization information to use for quantizing
264 * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
265 *
266 * @return Quantized value
267 */
268inline int16_t quantize_qsymm16(float value, const UniformQuantizationInfo &qinfo, RoundingPolicy rounding_policy = RoundingPolicy::TO_NEAREST_UP)
269{
270 int quantized = arm_compute::round(value / qinfo.scale, rounding_policy);
271 quantized = arm_compute::utility::clamp<int, int16_t>(quantized);
272 return quantized;
273}
274
275/** Dequantize a value given a 16-bit symmetric quantization scheme
276 *
277 * @param[in] value Value to dequantize
278 * @param[in] qinfo Quantization information to use for dequantizing
279 *
280 * @return Dequantized value
281 */
282inline float dequantize_qsymm16(int16_t value, const UniformQuantizationInfo &qinfo)
283{
284 return value * qinfo.scale;
285}
286
287/** Quantize a value given a 16-bit symmetric quantization scheme
288 *
289 * @param[in] value Value to quantize
290 * @param[in] qinfo Quantization information to use for quantizing
291 *
292 * @return Quantized value
293 */
294inline int16_t quantize_qsymm16(float value, const QuantizationInfo &qinfo)
295{
296 return quantize_qsymm16(value, qinfo.uniform());
297}
298
299/** Dequantize a value given a 16-bit symmetric quantization scheme
300 *
301 * @param[in] value Value to dequantize
302 * @param[in] qinfo Quantization information to use for dequantizing
303 *
304 * @return Dequantized value
305 */
306inline float dequantize_qsymm16(int16_t value, const QuantizationInfo &qinfo)
307{
308 return dequantize_qsymm16(value, qinfo.uniform());
309}
310
Georgios Pinitas4c5469b2019-05-21 13:32:43 +0100311} // namespace arm_compute
312#endif /*__ARM_COMPUTE_QUANTIZATION_INFO_H__ */