blob: 2d27951b736e0ce85279c1621ba0facccc209040 [file] [log] [blame]
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
Matthew Bentham246bd462020-01-20 16:16:06 +00008#include <armnn/TypesUtils.hpp>
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01009#include <armnn/utility/Assert.hpp>
10#include <armnn/utility/IgnoreUnused.hpp>
Jan Eilers53ef7952021-06-02 12:01:25 +010011#include <armnn/utility/NumericCast.hpp>
Matteo Martincighe011d202019-11-28 11:35:47 +000012#include <armnnUtils/FloatingPointConverter.hpp>
Jan Eilers53ef7952021-06-02 12:01:25 +010013#include <armnnUtils/TensorUtils.hpp>
Matteo Martincighe011d202019-11-28 11:35:47 +000014
Aron Virginas-Tard4f0fea2019-04-09 14:08:06 +010015#include <ResolveType.hpp>
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010016
17namespace armnn
18{
19
20class BaseIterator
21{
22public:
23 BaseIterator() {}
24
25 virtual ~BaseIterator() {}
26
27 virtual BaseIterator& operator++() = 0;
28
29 virtual BaseIterator& operator+=(const unsigned int increment) = 0;
30
31 virtual BaseIterator& operator-=(const unsigned int increment) = 0;
Francis Murtagh43aec582019-05-27 12:14:10 +010032
33 virtual BaseIterator& operator[](const unsigned int index) = 0;
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010034};
35
Derek Lambertif30f7d32019-04-09 10:25:02 +010036template<typename IType>
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010037class Decoder : public BaseIterator
38{
39public:
Derek Lambertif30f7d32019-04-09 10:25:02 +010040 Decoder() {}
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010041
42 virtual ~Decoder() {}
43
Matthew Benthamc394a6d2019-06-24 12:51:25 +010044 virtual void Reset(void*) = 0;
45
Derek Lambertif30f7d32019-04-09 10:25:02 +010046 virtual IType Get() const = 0;
Finn Williamsb9dcfe62020-09-17 15:58:31 +010047
Finn Williamsea8ce702020-09-29 19:54:00 +010048 virtual std::vector<float>
49 DecodeTensor(const TensorShape &tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +010050 bool isDepthwise = false) = 0;
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010051};
52
Derek Lambertif30f7d32019-04-09 10:25:02 +010053template<typename IType>
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010054class Encoder : public BaseIterator
55{
56public:
Derek Lambertif30f7d32019-04-09 10:25:02 +010057 Encoder() {}
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010058
59 virtual ~Encoder() {}
60
Matthew Benthamc394a6d2019-06-24 12:51:25 +010061 virtual void Reset(void*) = 0;
62
Derek Lambertif30f7d32019-04-09 10:25:02 +010063 virtual void Set(IType right) = 0;
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +010064
65 virtual IType Get() const = 0;
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010066};
67
68template<typename T, typename Base>
69class TypedIterator : public Base
70{
71public:
Matthew Benthamc394a6d2019-06-24 12:51:25 +010072 TypedIterator(T* data = nullptr)
Francis Murtagh43aec582019-05-27 12:14:10 +010073 : m_Iterator(data), m_Start(data)
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010074 {}
75
Matthew Benthamc394a6d2019-06-24 12:51:25 +010076 void Reset(void* data) override
77 {
78 m_Iterator = reinterpret_cast<T*>(data);
79 m_Start = m_Iterator;
80 }
81
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010082 TypedIterator& operator++() override
83 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010084 ARMNN_ASSERT(m_Iterator);
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010085 ++m_Iterator;
86 return *this;
87 }
88
89 TypedIterator& operator+=(const unsigned int increment) override
90 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010091 ARMNN_ASSERT(m_Iterator);
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010092 m_Iterator += increment;
93 return *this;
94 }
95
96 TypedIterator& operator-=(const unsigned int increment) override
97 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010098 ARMNN_ASSERT(m_Iterator);
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +010099 m_Iterator -= increment;
100 return *this;
101 }
102
Francis Murtagh43aec582019-05-27 12:14:10 +0100103 TypedIterator& operator[](const unsigned int index) override
104 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100105 ARMNN_ASSERT(m_Iterator);
Francis Murtagh43aec582019-05-27 12:14:10 +0100106 m_Iterator = m_Start + index;
107 return *this;
108 }
109
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +0100110protected:
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100111 T* m_Iterator;
Francis Murtagh43aec582019-05-27 12:14:10 +0100112 T* m_Start;
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100113};
114
Derek Lambertif30f7d32019-04-09 10:25:02 +0100115class QASymm8Decoder : public TypedIterator<const uint8_t, Decoder<float>>
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100116{
117public:
118 QASymm8Decoder(const uint8_t* data, const float scale, const int32_t offset)
119 : TypedIterator(data), m_Scale(scale), m_Offset(offset) {}
120
Matthew Benthamc394a6d2019-06-24 12:51:25 +0100121 QASymm8Decoder(const float scale, const int32_t offset)
122 : QASymm8Decoder(nullptr, scale, offset) {}
123
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100124 float Get() const override
125 {
126 return armnn::Dequantize(*m_Iterator, m_Scale, m_Offset);
127 }
Finn Williamsea8ce702020-09-29 19:54:00 +0100128 std::vector<float> DecodeTensor (const TensorShape& tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100129 const bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100130 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100131 IgnoreUnused(isDepthwise);
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100132
Finn Williamsea8ce702020-09-29 19:54:00 +0100133 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100134 std::vector<float> decodedTensor;
135 decodedTensor.reserve(size);
136
137 for (uint32_t i = 0; i < size; ++i)
138 {
139 this->operator[](i);
140 decodedTensor.emplace_back(armnn::Dequantize(*m_Iterator, m_Scale, m_Offset));
141 }
142
143 return decodedTensor;
144 }
145
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100146private:
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100147
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100148 const float m_Scale;
149 const int32_t m_Offset;
150};
151
Ryan OShea9add1202020-02-07 10:06:33 +0000152class QASymmS8Decoder : public TypedIterator<const int8_t, Decoder<float>>
153{
154public:
155 QASymmS8Decoder(const int8_t* data, const float scale, const int32_t offset)
156 : TypedIterator(data), m_Scale(scale), m_Offset(offset) {}
157
158 QASymmS8Decoder(const float scale, const int32_t offset)
159 : QASymmS8Decoder(nullptr, scale, offset) {}
160
161 float Get() const override
162 {
163 return armnn::Dequantize(*m_Iterator, m_Scale, m_Offset);
164 }
Finn Williamsea8ce702020-09-29 19:54:00 +0100165 std::vector<float> DecodeTensor (const TensorShape& tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100166 const bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100167 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100168 IgnoreUnused(isDepthwise);
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100169
Finn Williamsea8ce702020-09-29 19:54:00 +0100170 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100171 std::vector<float> decodedTensor;
172 decodedTensor.reserve(size);
173
174 for (uint32_t i = 0; i < size; ++i)
175 {
176 this->operator[](i);
177 decodedTensor.emplace_back(armnn::Dequantize(*m_Iterator, m_Scale, m_Offset));
178 }
179
180 return decodedTensor;
181 }
182
Ryan OShea9add1202020-02-07 10:06:33 +0000183private:
184 const float m_Scale;
185 const int32_t m_Offset;
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100186
Ryan OShea9add1202020-02-07 10:06:33 +0000187};
188
Finn Williamsfd271062019-12-04 14:27:27 +0000189class QSymmS8Decoder : public TypedIterator<const int8_t, Decoder<float>>
190{
191public:
192 QSymmS8Decoder(const int8_t* data, const float scale, const int32_t offset)
193 : TypedIterator(data), m_Scale(scale), m_Offset(offset) {}
194
195 QSymmS8Decoder(const float scale, const int32_t offset)
196 : QSymmS8Decoder(nullptr, scale, offset) {}
197
198 float Get() const override
199 {
200 return armnn::Dequantize(*m_Iterator, m_Scale, m_Offset);
201 }
Finn Williamsea8ce702020-09-29 19:54:00 +0100202 std::vector<float> DecodeTensor (const TensorShape& tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100203 const bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100204 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100205 IgnoreUnused(isDepthwise);
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100206
Finn Williamsea8ce702020-09-29 19:54:00 +0100207 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100208 std::vector<float> decodedTensor;
209 decodedTensor.reserve(size);
210
211 for (uint32_t i = 0; i < size; ++i)
212 {
213 this->operator[](i);
214 decodedTensor.emplace_back(armnn::Dequantize(*m_Iterator, m_Scale, m_Offset));
215 }
216
217 return decodedTensor;
218 }
219
Finn Williamsfd271062019-12-04 14:27:27 +0000220private:
221 const float m_Scale;
222 const int32_t m_Offset;
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100223
Finn Williamsfd271062019-12-04 14:27:27 +0000224};
225
Derek Lambertif30f7d32019-04-09 10:25:02 +0100226class QSymm16Decoder : public TypedIterator<const int16_t, Decoder<float>>
Sadik Armagan2999a022019-04-09 14:20:12 +0100227{
228public:
229 QSymm16Decoder(const int16_t* data, const float scale, const int32_t offset)
230 : TypedIterator(data), m_Scale(scale), m_Offset(offset) {}
231
Matthew Benthamc394a6d2019-06-24 12:51:25 +0100232 QSymm16Decoder(const float scale, const int32_t offset)
233 : QSymm16Decoder(nullptr, scale, offset) {}
234
Sadik Armagan2999a022019-04-09 14:20:12 +0100235 float Get() const override
236 {
237 return armnn::Dequantize(*m_Iterator, m_Scale, m_Offset);
238 }
Finn Williamsea8ce702020-09-29 19:54:00 +0100239 std::vector<float> DecodeTensor (const TensorShape& tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100240 const bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100241 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100242 IgnoreUnused(isDepthwise);
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100243
Finn Williamsea8ce702020-09-29 19:54:00 +0100244 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100245 std::vector<float> decodedTensor;
246 decodedTensor.reserve(size);
247
248 for (uint32_t i = 0; i < size; ++i)
249 {
250 this->operator[](i);
251 decodedTensor.emplace_back(armnn::Dequantize(*m_Iterator, m_Scale, m_Offset));
252 }
253
254 return decodedTensor;
255 }
256
Sadik Armagan2999a022019-04-09 14:20:12 +0100257private:
258 const float m_Scale;
259 const int32_t m_Offset;
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100260
Sadik Armagan2999a022019-04-09 14:20:12 +0100261};
262
Matthew Jacksone69c3992019-09-09 14:31:21 +0100263class Float16Decoder : public TypedIterator<const Half, Decoder<float>>
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100264{
265public:
Matthew Jacksone69c3992019-09-09 14:31:21 +0100266 Float16Decoder(const Half* data)
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100267 : TypedIterator(data) {}
268
Matthew Jacksone69c3992019-09-09 14:31:21 +0100269 Float16Decoder()
270 : Float16Decoder(nullptr) {}
271
272 float Get() const override
273 {
274 float val = 0.f;
275 armnnUtils::FloatingPointConverter::ConvertFloat16To32(m_Iterator, 1, &val);
276 return val;
277 }
Finn Williamsea8ce702020-09-29 19:54:00 +0100278 std::vector<float> DecodeTensor (const TensorShape& tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100279 const bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100280 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100281 IgnoreUnused(isDepthwise);
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100282
Finn Williamsea8ce702020-09-29 19:54:00 +0100283 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100284 std::vector<float> decodedTensor;
285 decodedTensor.reserve(size);
286
287 for (uint32_t i = 0; i < size; ++i)
288 {
289 float val = 0.f;
290 this->operator[](i);
291 armnnUtils::FloatingPointConverter::ConvertFloat16To32(m_Iterator, 1, &val);
292 decodedTensor.emplace_back(val);
293 }
294
295 return decodedTensor;
296 }
297
298
Matthew Jacksone69c3992019-09-09 14:31:21 +0100299};
300
301class Float32Decoder : public TypedIterator<const float, Decoder<float>>
302{
303public:
304 Float32Decoder(const float* data)
305 : TypedIterator(data) {}
306
307 Float32Decoder()
308 : Float32Decoder(nullptr) {}
Matthew Benthamc394a6d2019-06-24 12:51:25 +0100309
Derek Lambertif30f7d32019-04-09 10:25:02 +0100310 float Get() const override
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100311 {
Derek Lambertif30f7d32019-04-09 10:25:02 +0100312 return *m_Iterator;
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100313 }
Finn Williamsea8ce702020-09-29 19:54:00 +0100314 std::vector<float> DecodeTensor (const TensorShape& tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100315 const bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100316 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100317 IgnoreUnused(isDepthwise);
Finn Williamsea8ce702020-09-29 19:54:00 +0100318 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100319 std::vector<float> decodedTensor;
320
321 decodedTensor.reserve(size);
322 decodedTensor.assign(m_Start, m_Start + size);
323
324 return decodedTensor;
325 }
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100326};
327
Mike Kelly9b398322019-05-22 17:21:49 +0100328class ScaledInt32Decoder : public TypedIterator<const int32_t, Decoder<float>>
329{
330public:
331 ScaledInt32Decoder(const int32_t* data, const float scale)
332 : TypedIterator(data), m_Scale(scale) {}
333
Matthew Benthamc394a6d2019-06-24 12:51:25 +0100334 ScaledInt32Decoder(const float scale)
335 : ScaledInt32Decoder(nullptr, scale) {}
336
Mike Kelly9b398322019-05-22 17:21:49 +0100337 float Get() const override
338 {
339 return static_cast<float>(*m_Iterator) * m_Scale;
340 }
Finn Williamsea8ce702020-09-29 19:54:00 +0100341 std::vector<float> DecodeTensor (const TensorShape& tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100342 const bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100343 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100344 IgnoreUnused(isDepthwise);
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100345
Finn Williamsea8ce702020-09-29 19:54:00 +0100346 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100347 std::vector<float> decodedTensor;
348 decodedTensor.reserve(size);
349
350 for (uint32_t i = 0; i < size; ++i)
351 {
352 this->operator[](i);
353 decodedTensor.emplace_back(static_cast<float>(*m_Iterator) * m_Scale);
354 }
355
356 return decodedTensor;
357 }
358
Mike Kelly9b398322019-05-22 17:21:49 +0100359private:
360 const float m_Scale;
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100361
Mike Kelly9b398322019-05-22 17:21:49 +0100362};
363
Aron Virginas-Tar198ee402019-08-02 18:54:28 +0100364class Int32Decoder : public TypedIterator<const int32_t, Decoder<float>>
365{
366public:
367 Int32Decoder(const int32_t* data)
368 : TypedIterator(data) {}
369
370 Int32Decoder()
371 : Int32Decoder(nullptr) {}
372
373 float Get() const override
374 {
375 return static_cast<float>(*m_Iterator);
376 }
Finn Williamsea8ce702020-09-29 19:54:00 +0100377 std::vector<float> DecodeTensor (const TensorShape& tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100378 const bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100379 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100380 IgnoreUnused(isDepthwise);
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100381
Finn Williamsea8ce702020-09-29 19:54:00 +0100382 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100383 std::vector<float> decodedTensor;
384 decodedTensor.reserve(size);
385
386 for (uint32_t i = 0; i < size; ++i)
387 {
388 this->operator[](i);
389 decodedTensor.emplace_back(static_cast<float>(*m_Iterator));
390 }
391
392 return decodedTensor;
393 }
Aron Virginas-Tar198ee402019-08-02 18:54:28 +0100394};
395
Finn Williamscbd2c232020-06-22 15:58:32 +0100396class Int32ToInt32tDecoder : public TypedIterator<const int32_t, Decoder<int32_t>>
397{
398public:
399 Int32ToInt32tDecoder(const int32_t* data)
400 : TypedIterator(data){}
401
402 Int32ToInt32tDecoder()
403 : Int32ToInt32tDecoder(nullptr) {}
404
405 int32_t Get() const override
406 {
407 return *m_Iterator;
408 }
Finn Williamsea8ce702020-09-29 19:54:00 +0100409 std::vector<float> DecodeTensor (const TensorShape& tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100410 const bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100411 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100412 IgnoreUnused(isDepthwise);
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100413
Finn Williamsea8ce702020-09-29 19:54:00 +0100414 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100415 std::vector<float> decodedTensor;
416 decodedTensor.reserve(size);
417
418 for (uint32_t i = 0; i < size; ++i)
419 {
420 this->operator[](i);
Rob Hughesc013bc82021-07-14 09:31:31 +0100421 decodedTensor.emplace_back(static_cast<float>(*m_Iterator));
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100422 }
423
424 return decodedTensor;
425 }
Finn Williamscbd2c232020-06-22 15:58:32 +0100426};
427
Sadik Armaganb60dd242020-03-19 13:53:16 +0000428class BooleanDecoder : public TypedIterator<const uint8_t, Decoder<float>>
429{
430public:
431 BooleanDecoder(const uint8_t* data)
432 : TypedIterator(data) {}
433
434 BooleanDecoder()
435 : BooleanDecoder(nullptr) {}
436
437 float Get() const override
438 {
439 return *m_Iterator;
440 }
Finn Williamsea8ce702020-09-29 19:54:00 +0100441 std::vector<float> DecodeTensor (const TensorShape& tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100442 const bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100443 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100444 IgnoreUnused(isDepthwise);
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100445
Finn Williamsea8ce702020-09-29 19:54:00 +0100446 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100447 std::vector<float> decodedTensor;
448 decodedTensor.reserve(size);
449
450 for (uint32_t i = 0; i < size; ++i)
451 {
452 this->operator[](i);
453 decodedTensor.emplace_back(*m_Iterator);
454 }
455
456 return decodedTensor;
457 }
Sadik Armaganb60dd242020-03-19 13:53:16 +0000458};
459
James Conroyaba90cd2020-11-06 16:28:18 +0000460class BooleanDecoderBool : public TypedIterator<const uint8_t, Decoder<bool>>
461{
462public:
463 BooleanDecoderBool(const uint8_t* data)
464 : TypedIterator(data) {}
465
466 BooleanDecoderBool()
467 : BooleanDecoderBool(nullptr) {}
468
469 bool Get() const override
470 {
471 return *m_Iterator;
472 }
473
474 std::vector<float> DecodeTensor(const TensorShape& tensorShape,
James Conroyaba90cd2020-11-06 16:28:18 +0000475 const bool isDepthwise) override
476 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100477 IgnoreUnused(isDepthwise);
James Conroyaba90cd2020-11-06 16:28:18 +0000478
479 const unsigned int size = tensorShape.GetNumElements();
480 std::vector<float> decodedTensor;
481 decodedTensor.reserve(size);
482
483 for (uint32_t i = 0; i < size; ++i)
484 {
485 this->operator[](i);
486 decodedTensor.emplace_back(*m_Iterator);
487 }
488
489 return decodedTensor;
490 }
491};
492
Derek Lambertif30f7d32019-04-09 10:25:02 +0100493class QASymm8Encoder : public TypedIterator<uint8_t, Encoder<float>>
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100494{
495public:
496 QASymm8Encoder(uint8_t* data, const float scale, const int32_t offset)
497 : TypedIterator(data), m_Scale(scale), m_Offset(offset) {}
498
Matthew Benthamc394a6d2019-06-24 12:51:25 +0100499 QASymm8Encoder(const float scale, const int32_t offset)
500 : QASymm8Encoder(nullptr, scale, offset) {}
501
Derek Lambertif30f7d32019-04-09 10:25:02 +0100502 void Set(float right) override
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100503 {
504 *m_Iterator = armnn::Quantize<uint8_t>(right, m_Scale, m_Offset);
505 }
506
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +0100507 float Get() const override
508 {
509 return armnn::Dequantize(*m_Iterator, m_Scale, m_Offset);
510 }
511
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100512private:
513 const float m_Scale;
514 const int32_t m_Offset;
515};
516
Ryan OShea9add1202020-02-07 10:06:33 +0000517class QASymmS8Encoder : public TypedIterator<int8_t, Encoder<float>>
518{
519public:
520 QASymmS8Encoder(int8_t* data, const float scale, const int32_t offset)
521 : TypedIterator(data), m_Scale(scale), m_Offset(offset) {}
522
523 QASymmS8Encoder(const float scale, const int32_t offset)
524 : QASymmS8Encoder(nullptr, scale, offset) {}
525
526 void Set(float right) override
527 {
528 *m_Iterator = armnn::Quantize<int8_t>(right, m_Scale, m_Offset);
529 }
530
531 float Get() const override
532 {
533 return armnn::Dequantize(*m_Iterator, m_Scale, m_Offset);
534 }
535
536private:
537 const float m_Scale;
538 const int32_t m_Offset;
539};
540
Finn Williamsfd271062019-12-04 14:27:27 +0000541class QSymmS8Encoder : public TypedIterator<int8_t, Encoder<float>>
542{
543public:
544 QSymmS8Encoder(int8_t* data, const float scale, const int32_t offset)
545 : TypedIterator(data), m_Scale(scale), m_Offset(offset) {}
546
547 QSymmS8Encoder(const float scale, const int32_t offset)
548 : QSymmS8Encoder(nullptr, scale, offset) {}
549
550 void Set(float right) override
551 {
552 *m_Iterator = armnn::Quantize<int8_t>(right, m_Scale, m_Offset);
553 }
554
555 float Get() const override
556 {
557 return armnn::Dequantize(*m_Iterator, m_Scale, m_Offset);
558 }
559
560private:
561 const float m_Scale;
562 const int32_t m_Offset;
563};
564
Derek Lambertif30f7d32019-04-09 10:25:02 +0100565class QSymm16Encoder : public TypedIterator<int16_t, Encoder<float>>
566{
567public:
568 QSymm16Encoder(int16_t* data, const float scale, const int32_t offset)
569 : TypedIterator(data), m_Scale(scale), m_Offset(offset) {}
570
Matthew Benthamc394a6d2019-06-24 12:51:25 +0100571 QSymm16Encoder(const float scale, const int32_t offset)
572 : QSymm16Encoder(nullptr, scale, offset) {}
573
Derek Lambertif30f7d32019-04-09 10:25:02 +0100574 void Set(float right) override
575 {
576 *m_Iterator = armnn::Quantize<int16_t>(right, m_Scale, m_Offset);
577 }
578
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +0100579 float Get() const override
580 {
581 return armnn::Dequantize(*m_Iterator, m_Scale, m_Offset);
582 }
583
Derek Lambertif30f7d32019-04-09 10:25:02 +0100584private:
585 const float m_Scale;
586 const int32_t m_Offset;
587};
588
Matthew Jacksone69c3992019-09-09 14:31:21 +0100589class Float16Encoder : public TypedIterator<Half, Encoder<float>>
Derek Lambertif30f7d32019-04-09 10:25:02 +0100590{
591public:
Matthew Jacksone69c3992019-09-09 14:31:21 +0100592 Float16Encoder(Half* data)
Derek Lambertif30f7d32019-04-09 10:25:02 +0100593 : TypedIterator(data) {}
594
Matthew Jacksone69c3992019-09-09 14:31:21 +0100595 Float16Encoder()
596 : Float16Encoder(nullptr) {}
597
598 void Set(float right) override
599 {
600 armnnUtils::FloatingPointConverter::ConvertFloat32To16(&right, 1, m_Iterator);
601 }
602
603 float Get() const override
604 {
605 float val = 0.f;
606 armnnUtils::FloatingPointConverter::ConvertFloat16To32(m_Iterator, 1, &val);
607 return val;
608 }
609};
610
611class Float32Encoder : public TypedIterator<float, Encoder<float>>
612{
613public:
614 Float32Encoder(float* data)
615 : TypedIterator(data) {}
616
617 Float32Encoder()
618 : Float32Encoder(nullptr) {}
Matthew Benthamc394a6d2019-06-24 12:51:25 +0100619
Derek Lambertif30f7d32019-04-09 10:25:02 +0100620 void Set(float right) override
621 {
622 *m_Iterator = right;
623 }
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +0100624
625 float Get() const override
626 {
627 return *m_Iterator;
628 }
Derek Lambertif30f7d32019-04-09 10:25:02 +0100629};
630
Aron Virginas-Tar198ee402019-08-02 18:54:28 +0100631class Int32Encoder : public TypedIterator<int32_t, Encoder<float>>
632{
633public:
634 Int32Encoder(int32_t* data)
635 : TypedIterator(data) {}
636
637 Int32Encoder()
638 : Int32Encoder(nullptr) {}
639
640 void Set(float right) override
641 {
642 *m_Iterator = static_cast<int32_t>(right);
643 }
644
645 float Get() const override
646 {
647 return static_cast<float>(*m_Iterator);
648 }
649};
650
Finn Williamscbd2c232020-06-22 15:58:32 +0100651class Int32ToInt32tEncoder : public TypedIterator<int32_t, Encoder<int32_t>>
652{
653public:
654 Int32ToInt32tEncoder(int32_t* data)
655 : TypedIterator(data){}
656
657 Int32ToInt32tEncoder()
658 : Int32ToInt32tEncoder(nullptr) {}
659
660 void Set(int32_t right) override
661 {
662 *m_Iterator = right;
663 }
664
665 int32_t Get() const override
666 {
667 return *m_Iterator;
668 }
669};
670
Derek Lambertif30f7d32019-04-09 10:25:02 +0100671class BooleanEncoder : public TypedIterator<uint8_t, Encoder<bool>>
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100672{
673public:
674 BooleanEncoder(uint8_t* data)
675 : TypedIterator(data) {}
676
Matthew Benthamc394a6d2019-06-24 12:51:25 +0100677 BooleanEncoder()
678 : BooleanEncoder(nullptr) {}
679
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100680 void Set(bool right) override
681 {
682 *m_Iterator = right;
683 }
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +0100684
685 bool Get() const override
686 {
687 return *m_Iterator;
688 }
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100689};
690
Jan Eilers53ef7952021-06-02 12:01:25 +0100691/// PerAxisIterator for per-axis quantization. Iterates over a tensor as layed out in memory and keeps track
692/// of the axis index.
Keith Davis5236e1d2019-11-04 08:58:33 +0000693template<typename T, typename Base>
694class PerAxisIterator : public Base
695{
696public:
Jan Eilers53ef7952021-06-02 12:01:25 +0100697 PerAxisIterator(T* data = nullptr,
698 unsigned int axisFactor = 0,
699 unsigned int axisDimensionality=0)
700 : m_Iterator(data),
701 m_Start(data),
702 m_AxisIndex(0), // iterates over the dimension of axis
703 m_AxisDimensionality(axisDimensionality), // tensorShape[quantization_dim]
704 m_AxisFactor(axisFactor),
705 m_Index(0)
Keith Davis5236e1d2019-11-04 08:58:33 +0000706 {}
707
Jan Eilers53ef7952021-06-02 12:01:25 +0100708 PerAxisIterator(T* data = nullptr,
709 const armnn::TensorShape& tensorShape = TensorShape(),
710 const unsigned int axis = 0)
711 : m_Iterator(data),
712 m_Start(data),
713 m_AxisIndex(0),
714 m_Index(0)
Keith Davis5236e1d2019-11-04 08:58:33 +0000715 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100716 m_AxisDimensionality = tensorShape[axis];
717 m_AxisFactor = armnnUtils::GetNumElementsAfter(tensorShape, axis);
Keith Davis5236e1d2019-11-04 08:58:33 +0000718 }
719
720 void Reset(void* data) override
721 {
722 m_Iterator = reinterpret_cast<T*>(data);
723 m_Start = m_Iterator;
724 m_AxisIndex = 0;
Jan Eilers53ef7952021-06-02 12:01:25 +0100725 m_Index = 0;
Keith Davis5236e1d2019-11-04 08:58:33 +0000726 }
727
728 PerAxisIterator& operator++() override
729 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100730 ++m_Index;
731 this -> operator[](m_Index);
Keith Davis5236e1d2019-11-04 08:58:33 +0000732 return *this;
733 }
734
735 PerAxisIterator& operator+=(const unsigned int increment) override
736 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100737 m_Index += increment;
738 this -> operator[](m_Index);
Keith Davis5236e1d2019-11-04 08:58:33 +0000739 return *this;
740 }
741
742 PerAxisIterator& operator-=(const unsigned int decrement) override
743 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100744 m_Index -= decrement;
745 this -> operator[](m_Index);
746 return *this;
747 }
748
749
750 inline PerAxisIterator& SetIndexOnMem(const unsigned int index)
751 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100752 ARMNN_ASSERT(m_Iterator);
Jan Eilers53ef7952021-06-02 12:01:25 +0100753 m_Iterator = m_Start + index;
754 if (index < m_AxisFactor)
755 {
756 m_AxisIndex = 0;
757 }
758 else
759 {
760 m_AxisIndex = (index / m_AxisFactor) % m_AxisDimensionality;
761 }
762 m_Index = index;
Keith Davis5236e1d2019-11-04 08:58:33 +0000763 return *this;
764 }
765
766 PerAxisIterator& operator[](const unsigned int index) override
767 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100768 SetIndexOnMem(index);
Keith Davis5236e1d2019-11-04 08:58:33 +0000769 return *this;
770 }
771
772 protected:
773 T* m_Iterator;
774 T* m_Start;
775 unsigned int m_AxisIndex;
Jan Eilers53ef7952021-06-02 12:01:25 +0100776 unsigned int m_AxisDimensionality; // tensorShape[quantization_dim]
Keith Davis5236e1d2019-11-04 08:58:33 +0000777 unsigned int m_AxisFactor;
Jan Eilers53ef7952021-06-02 12:01:25 +0100778 unsigned int m_Index;
Keith Davis5236e1d2019-11-04 08:58:33 +0000779};
780
781class QSymm8PerAxisDecoder : public PerAxisIterator<const int8_t, Decoder<float>>
782{
783public:
Jan Eilers53ef7952021-06-02 12:01:25 +0100784 QSymm8PerAxisDecoder(const int8_t* data, const armnn::TensorInfo& tensorInfo)
785 : PerAxisIterator(data, tensorInfo.GetShape(), tensorInfo.GetQuantizationDim().value()),
786 m_Scales(tensorInfo.GetQuantizationScales())
787 {}
Keith Davis5236e1d2019-11-04 08:58:33 +0000788
789 float Get() const override
790 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100791 return armnn::Dequantize(*m_Iterator, GetScale(), 0);
Keith Davis5236e1d2019-11-04 08:58:33 +0000792 }
793
794 // Get scale of the current value
795 float GetScale() const
796 {
Finn Williamsea8ce702020-09-29 19:54:00 +0100797 return m_Scales[m_AxisIndex];
Keith Davis5236e1d2019-11-04 08:58:33 +0000798 }
799
Finn Williamsea8ce702020-09-29 19:54:00 +0100800 std::vector<float> DecodeTensor(const TensorShape &tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100801 bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100802 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100803 IgnoreUnused(isDepthwise);
Finn Williamsea8ce702020-09-29 19:54:00 +0100804
Jan Eilers53ef7952021-06-02 12:01:25 +0100805 const unsigned int size = tensorShape.GetNumElements();
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100806 std::vector<float> decodedTensor;
807 decodedTensor.reserve(size);
808
Jan Eilers53ef7952021-06-02 12:01:25 +0100809 for (uint32_t i = 0; i < size; ++i)
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100810 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100811 SetIndexOnMem(i);
812 decodedTensor.emplace_back(armnn::Dequantize(*m_Iterator, GetScale(), 0));
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100813 }
814 return decodedTensor;
815 }
816
Keith Davis5236e1d2019-11-04 08:58:33 +0000817private:
Finn Williamsea8ce702020-09-29 19:54:00 +0100818 std::vector<float> m_Scales;
Keith Davis5236e1d2019-11-04 08:58:33 +0000819};
820
821class QSymm8PerAxisEncoder : public PerAxisIterator<int8_t, Encoder<float>>
822{
823public:
824 QSymm8PerAxisEncoder(int8_t* data, const std::vector<float>& scale, unsigned int axisFactor)
825 : PerAxisIterator(data, axisFactor), m_Scale(scale) {}
826
827 void Set(float right)
828 {
829 *m_Iterator = armnn::Quantize<int8_t>(right, m_Scale[m_AxisIndex], 0);
830 }
831
832 float Get() const
833 {
834 return armnn::Dequantize(*m_Iterator, m_Scale[m_AxisIndex], 0);
835 }
836
837 // Get scale of the current value
838 float GetScale() const
839 {
840 return m_Scale[m_AxisIndex];
841 }
842
843private:
844 std::vector<float> m_Scale;
845};
846
Aron Virginas-Tarb67f9572019-11-04 15:00:19 +0000847class ScaledInt32PerAxisDecoder : public PerAxisIterator<const int32_t, Decoder<float>>
848{
849public:
Jan Eilers53ef7952021-06-02 12:01:25 +0100850 ScaledInt32PerAxisDecoder(const int32_t* data, const armnn::TensorInfo tensorInfo)
851 : PerAxisIterator(data, tensorInfo.GetShape(), tensorInfo.GetQuantizationDim().value()),
852 m_Scales(tensorInfo.GetQuantizationScales())
853 {}
Aron Virginas-Tarb67f9572019-11-04 15:00:19 +0000854
855 float Get() const override
856 {
857 return armnn::Dequantize(*m_Iterator, m_Scales[m_AxisIndex], 0);
858 }
859
860 // Get scale of the current value
861 float GetScale() const
862 {
863 return m_Scales[m_AxisIndex];
864 }
865
Finn Williamsea8ce702020-09-29 19:54:00 +0100866 std::vector<float> DecodeTensor(const TensorShape &tensorShape,
Finn Williamsea8ce702020-09-29 19:54:00 +0100867 bool isDepthwise) override
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100868 {
Finn Williamsea8ce702020-09-29 19:54:00 +0100869 const uint32_t size = tensorShape.GetNumElements();
Finn Williamsea8ce702020-09-29 19:54:00 +0100870
871 const uint32_t stepSize = isDepthwise ?
872 tensorShape[2] * tensorShape[3] : tensorShape.GetNumElements() / tensorShape[0];
873
Jan Eilers53ef7952021-06-02 12:01:25 +0100874 const uint32_t stepNum = size / stepSize;
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100875
876 std::vector<float> decodedTensor;
877 decodedTensor.reserve(size);
878
Finn Williamsea8ce702020-09-29 19:54:00 +0100879 // channelMultiplier is only used in depthwise convolutions and in other cases will have no effect
880 // stepSize is the length of a contiguous area sharing a quantization scale within a tensor
881 // stepNum is the number of those steps/blocks in the tensor
Jan Eilers53ef7952021-06-02 12:01:25 +0100882 for (uint32_t step = 0; step < stepNum; ++step)
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100883 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100884 //scale = (channelMultiplier * step + mult) % scaleSize;
885 for (uint32_t i = 0; i < stepSize; ++i)
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100886 {
Jan Eilers53ef7952021-06-02 12:01:25 +0100887 unsigned int index = step * stepSize + i;
888 this->operator[](index);
889 decodedTensor.emplace_back(armnn::Dequantize(*m_Iterator, m_Scales[step], 0));
Finn Williamsb9dcfe62020-09-17 15:58:31 +0100890 }
891 }
892 return decodedTensor;
893 }
894
Aron Virginas-Tarb67f9572019-11-04 15:00:19 +0000895private:
896 std::vector<float> m_Scales;
897};
898
899} // namespace armnn