blob: 94f7e76c3eb87557369f96535c3828438d2b9e70 [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"
28
29#include <cstddef>
30#include <vector>
31
32namespace arm_compute
33{
34using qasymm8_t = uint8_t; /**< 8 bit quantized asymmetric scalar value */
35using qsymm8_t = int8_t; /**< 8 bit quantized symmetric scalar value */
36
37/** Quantization info when assuming per layer quantization */
38struct UniformQuantizationInfo
39{
40 /** Default constructor */
41 UniformQuantizationInfo()
42 : scale(0.f), offset(0)
43 {
44 }
45 /** Constructor
46 *
47 * @param[in] scale Quantization scale
48 * @param[in] offset Quantization offset
49 */
50 UniformQuantizationInfo(float scale, int32_t offset)
51 : scale(scale), offset(offset)
52 {
53 }
54 /** Checks if the scale and offset are both zero */
55 bool empty() const
56 {
57 return (scale == 0) && (offset == 0);
58 }
59
60 float scale;
61 int32_t offset;
62};
63
64/** Quantization information */
65struct QuantizationInfo
66{
67 /** Default constructor */
68 QuantizationInfo() noexcept
69 : scale(),
70 offset()
71 {
72 }
73 /** Construct quantization info.
74 *
75 * @note Used for symmetric quantization
76 *
77 * @param[in] scale Scale.
78 */
79 QuantizationInfo(float scale)
80 : scale(1, scale), offset()
81 {
82 }
83 /** Construct quantization info.
84 *
85 * @note Used for asymmetric quantization
86 *
87 * @param[in] scale Scale.
88 * @param[in] offset Offset.
89 */
90 QuantizationInfo(float scale, int offset)
91 : scale(1, scale), offset(1, offset)
92 {
93 }
94 /** Construct quantization info.
95 *
96 * @note Used for symmetric per channel quantization
97 *
98 * @param[in] scale Scale.
99 */
100 QuantizationInfo(std::vector<float> scale)
101 : scale(scale), offset()
102 {
103 }
104 /** Indicates whether this QuantizationInfo has valid settings or not
105 *
106 * @return True if the this has invalid settings.
107 */
108 bool empty() const
109 {
110 return scale.empty() && offset.empty();
111 }
112 /** Return per layer quantization info
113 *
114 * @return Uniform quantization information in case of empty information zero is returned in the respective fields
115 */
116 UniformQuantizationInfo uniform() const
117 {
118 UniformQuantizationInfo uqinfo;
119 uqinfo.scale = scale.empty() ? 0 : scale[0];
120 uqinfo.offset = offset.empty() ? 0 : offset[0];
121
122 return uqinfo;
123 }
124
125 std::vector<float> scale; /**< Vector containing scaling factors */
126 std::vector<int32_t> offset; /**< Vector containing zero offsets */
127};
128
129/** Check whether two quantization info are equal.
130 *
131 * @param[in] lhs RHS quantization info.
132 * @param[in] rhs LHS quantization info.
133 *
134 * @return True if the given quantization info is the same.
135 */
136inline bool operator==(const QuantizationInfo &lhs, const QuantizationInfo &rhs)
137{
138 return (lhs.scale == rhs.scale) && (lhs.offset == rhs.offset);
139}
140
141/** Check whether two quantization info are not equal.
142 *
143 * @param[in] lhs RHS quantization info.
144 * @param[in] rhs LHS quantization info.
145 *
146 * @return True if the given quantization info is the same.
147 */
148inline bool operator!=(const QuantizationInfo &lhs, const QuantizationInfo &rhs)
149{
150 return !(operator==(lhs, rhs));
151}
152
153/** Check whether two quantization info are equal.
154 *
155 * @param[in] lhs RHS quantization info.
156 * @param[in] rhs LHS quantization info.
157 *
158 * @return True if the given quantization info is the same.
159 */
160inline bool operator==(const UniformQuantizationInfo &lhs, const UniformQuantizationInfo &rhs)
161{
162 return (lhs.scale == rhs.scale) && (lhs.offset == rhs.offset);
163}
164
165/** Check whether two quantization info are not equal.
166 *
167 * @param[in] lhs RHS quantization info.
168 * @param[in] rhs LHS quantization info.
169 *
170 * @return True if the given quantization info is the same.
171 */
172inline bool operator!=(const UniformQuantizationInfo &lhs, const UniformQuantizationInfo &rhs)
173{
174 return !(operator==(lhs, rhs));
175}
176
177/** Quantize a value given a asymmetric quantization scheme
178 *
179 * @param[in] value Value to quantize
180 * @param[in] qinfo Quantization information to use for quantizing
181 * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
182 *
183 * @return Quantized value
184 */
185inline uint8_t quantize_qasymm8(float value, const UniformQuantizationInfo &qinfo, RoundingPolicy rounding_policy = RoundingPolicy::TO_NEAREST_UP)
186{
187 int quantized = arm_compute::round(value / qinfo.scale, rounding_policy) + qinfo.offset;
188 quantized = std::max(0, std::min(quantized, 255));
189 return quantized;
190}
191
192/** Quantize a value given a asymmetric quantization scheme
193 *
194 * @param[in] value Value to quantize
195 * @param[in] qinfo Quantization information to use for quantizing
196 * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
197 *
198 * @return Quantized value
199 */
200inline uint8_t quantize_qasymm8(float value, const QuantizationInfo &qinfo, RoundingPolicy rounding_policy = RoundingPolicy::TO_NEAREST_UP)
201{
202 UniformQuantizationInfo uqinfo = qinfo.uniform();
203 int quantized = arm_compute::round(value / uqinfo.scale, rounding_policy) + uqinfo.offset;
204 quantized = std::max(0, std::min(quantized, 255));
205 return quantized;
206}
207
208/** Quantize a value given a symmetric quantization scheme
209 *
210 * @param[in] value Value to quantize
211 * @param[in] qinfo Quantization information to use for quantizing
212 *
213 * @return Quantized value
214 */
215inline int8_t quantize_qsymm8(float value, const QuantizationInfo &qinfo)
216{
217 int quantized = arm_compute::round(value / qinfo.uniform().scale, RoundingPolicy::TO_NEAREST_UP);
218 quantized = std::max(-128, std::min(quantized, 127));
219 return quantized;
220}
221
222/** Dequantize a value given a asymmetric quantization scheme
223 *
224 * @param[in] value Value to dequantize
225 * @param[in] qinfo Quantization information to use for dequantizing
226 *
227 * @return Dequantized value
228 */
229inline float dequantize_qasymm8(uint8_t value, const UniformQuantizationInfo &qinfo)
230{
231 return (static_cast<int>(value) - qinfo.offset) * qinfo.scale;
232}
233
234/** Dequantize a value given a asymmetric quantization scheme
235 *
236 * @param[in] value Value to dequantize
237 * @param[in] qinfo Quantization information to use for dequantizing
238 *
239 * @return Dequantized value
240 */
241inline float dequantize_qasymm8(uint8_t value, const QuantizationInfo &qinfo)
242{
243 UniformQuantizationInfo uqinfo = qinfo.uniform();
244 return (static_cast<int>(value) - uqinfo.offset) * uqinfo.scale;
245}
246
247/** Dequantize a value given a symmetric quantization scheme
248 *
249 * @param[in] value Value to dequantize
250 * @param[in] qinfo Quantization information to use for dequantizing
251 *
252 * @return Dequantized value
253 */
254inline float dequantize_qsymm8(int8_t value, const QuantizationInfo &qinfo)
255{
256 return value * qinfo.uniform().scale;
257}
258} // namespace arm_compute
259#endif /*__ARM_COMPUTE_QUANTIZATION_INFO_H__ */