Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / onert-micro / luci-interpreter / include / luci_interpreter / core / Tensor.h
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef LUCI_INTERPRETER_CORE_TENSOR_H
18 #define LUCI_INTERPRETER_CORE_TENSOR_H
19
20 #include "luci_interpreter/core/DataType.h"
21 #include "luci_interpreter/core/reader/CircleMicroReader.h"
22
23 #include <cassert>
24 #include <cstddef>
25 #include <cstdint>
26 #include <memory>
27 #include <string>
28 #include <vector>
29
30 namespace luci_interpreter
31 {
32
33 static constexpr int kMaxSmallSize = 5;
34
35 class RuntimeShape
36 {
37 public:
38   RuntimeShape(const RuntimeShape &other) : _size(other.dimensionsCount())
39   {
40     std::memcpy(dimsData(), other.dimsData(), sizeof(int32_t) * _size);
41   }
42
43   // Returns the total count of elements, that is the size when flattened into a
44   // vector.
45   inline int flatSize() const
46   {
47     int buffer_size = 1;
48     const int *dims_data = reinterpret_cast<const int *>(dimsData());
49     for (int i = 0; i < _size; i++)
50     {
51       buffer_size *= dims_data[i];
52     }
53     return buffer_size;
54   }
55
56   inline int32_t *dimsData() { return _dims; }
57   inline const int32_t *dimsData() const { return _dims; }
58
59   RuntimeShape() : _size(0) {}
60
61   explicit RuntimeShape(int dimensions_count) : _size(dimensions_count)
62   {
63     assert(dimensions_count <= kMaxSmallSize);
64     assert(dimensions_count >= 0);
65   }
66
67   RuntimeShape(int dimensions_count, const int32_t *dims_data) : _size(0)
68   {
69     resize(dimensions_count);
70     int32_t *dst_dims = dimsData();
71     std::memcpy(dst_dims, dims_data, dimensions_count * sizeof(int32_t));
72   }
73
74   RuntimeShape(int new_shape_size, const RuntimeShape &shape, int pad_value) : _size(0)
75   {
76     resize(new_shape_size);
77     const int size_increase = new_shape_size - shape.dimensionsCount();
78     for (int i = 0; i < size_increase; ++i)
79     {
80       setDim(i, pad_value);
81     }
82     std::memcpy(dimsData() + size_increase, shape.dimsData(),
83                 sizeof(int32_t) * shape.dimensionsCount());
84   }
85
86   RuntimeShape(int shape_size, int32_t value) : _size(0)
87   {
88     resize(shape_size);
89     for (int i = 0; i < shape_size; ++i)
90     {
91       setDim(i, value);
92     }
93   }
94
95   inline static RuntimeShape extendedShape(int new_shape_size, const RuntimeShape &shape)
96   {
97     return RuntimeShape(new_shape_size, shape, 1);
98   }
99
100   bool operator==(const RuntimeShape &comp) const
101   {
102     return this->_size == comp._size &&
103            std::memcmp(dimsData(), comp.dimsData(), _size * sizeof(int32_t)) == 0;
104   }
105
106   inline int32_t dimensionsCount() const { return _size; }
107
108   inline int32_t dims(int i) const
109   {
110     assert(i <= _size);
111     assert(i >= 0);
112     return _dims[i];
113   }
114   inline void setDim(int i, int32_t val)
115   {
116     assert(i <= _size);
117     assert(i >= 0);
118     _dims[i] = val;
119   }
120
121   inline void resize(int dimensions_count)
122   {
123     assert(dimensions_count <= kMaxSmallSize);
124     assert(dimensions_count >= 0);
125     _size = dimensions_count;
126   }
127
128 private:
129   int32_t _size;
130   int32_t _dims[kMaxSmallSize];
131 };
132
133 class Tensor
134 {
135 public:
136 #ifndef DIS_QUANT
137   static float scale(const circle::Tensor *circle_tensor)
138   {
139     const auto *quant_params = circle_tensor->quantization();
140     if (quant_params == nullptr)
141     {
142       assert(false && "There is no quantization params");
143       return 0;
144     }
145
146     return *quant_params->scale()->cbegin();
147   }
148
149   static int32_t zero_point(const circle::Tensor *circle_tensor)
150   {
151     const auto *quant_params = circle_tensor->quantization();
152     if (quant_params == nullptr)
153     {
154       assert(false && "There is no quantization params");
155       return 0;
156     }
157
158     return *quant_params->zero_point()->cbegin();
159   }
160
161   static const std::vector<float> scales(const circle::Tensor *circle_tensor)
162   {
163     const auto *quant_params = circle_tensor->quantization();
164     if (quant_params == nullptr)
165     {
166       assert(false && "There is no quantization params");
167       return {};
168     }
169     assert(quant_params->scale() != nullptr);
170     std::vector<float> scales(quant_params->scale()->cbegin(), quant_params->scale()->cend());
171
172     return scales;
173   }
174
175   static const std::vector<int32_t> zero_points(const circle::Tensor *circle_tensor)
176   {
177     const auto *quant_params = circle_tensor->quantization();
178     if (quant_params == nullptr)
179     {
180       assert(false && "There is no quantization params");
181       return {};
182     }
183     assert(quant_params->zero_point() != nullptr);
184     std::vector<int32_t> zero_points(quant_params->zero_point()->cbegin(),
185                                      quant_params->zero_point()->cend());
186
187     return zero_points;
188   }
189
190   static int32_t quantized_dimension(const circle::Tensor *circle_tensor)
191   {
192     const auto *quant_params = circle_tensor->quantization();
193     if (quant_params == nullptr)
194     {
195       assert(false && "There is no quantization params");
196       return 0;
197     }
198     return quant_params->quantized_dimension();
199   }
200 #endif
201
202   static bool is_constant_tensor(const luci_interpreter::CircleReader *reader,
203                                  const circle::Tensor *circle_tensor)
204   {
205     return reader->buffers()[circle_tensor->buffer()]->data() != nullptr;
206   }
207
208   static DataType element_type(const circle::Tensor *circle_tensor)
209   {
210     return luci_datatype(circle_tensor->type());
211   }
212
213   static VectorWrapper<int32_t> tensor_shape(const circle::Tensor *circle_tensor)
214   {
215     return wrap(circle_tensor->shape());
216   }
217
218   static int num_dims(const circle::Tensor *circle_tensor)
219   {
220     // TODO check removing of wrap
221     auto const const_dims = wrap(circle_tensor->shape());
222     return const_dims.size();
223   }
224
225   static int32_t dim(const circle::Tensor *circle_tensor, int i)
226   {
227     // TODO check removing of wrap
228     assert(i >= 0);
229     auto const const_dims = wrap(circle_tensor->shape());
230     assert(i < const_dims.size());
231
232     return const_dims[i];
233   }
234
235   static int32_t num_elements(const circle::Tensor *circle_tensor)
236   {
237     int32_t result = 1;
238     auto const const_dims = wrap(circle_tensor->shape());
239     for (const int32_t dim : const_dims)
240     {
241       result *= dim;
242     }
243     return result;
244   }
245 };
246
247 } // namespace luci_interpreter
248
249 #endif // LUCI_INTERPRETER_CORE_TENSOR_H