GEGELATI
array2DWrapper.h
1
37#ifndef ARRAY_2D_WRAPPER_H
38#define ARRAY_2D_WRAPPER_H
39
40#include "data/arrayWrapper.h"
41#include "data/dataHandler.h"
42#include "data/demangle.h"
43
44namespace Data {
45
67 template <class T> class Array2DWrapper : public ArrayWrapper<T>
68 {
69 private:
85 mutable std::map<std::type_index, std::tuple<size_t, size_t, size_t>>
86 cachedAddressSpace;
87
88 protected:
90 size_t width;
91
93 size_t height;
94
106 size_t getAddressSpace(const std::type_info& type, size_t* dim1,
107 size_t* dim2) const;
108
109 public:
120 Array2DWrapper(const size_t w = 2, const size_t h = 4,
121 std::vector<T>* ptr = nullptr);
122
124 Array2DWrapper(const Array2DWrapper& other) = default;
125
127 virtual ~Array2DWrapper() = default;
128
135 virtual DataHandler* clone() const override;
136
138 virtual size_t getAddressSpace(
139 const std::type_info& type) const override;
140
142 virtual std::vector<size_t> getAddressesAccessed(
143 const std::type_info& type, const size_t address) const override;
144
146 virtual UntypedSharedPtr getDataAt(const std::type_info& type,
147 const size_t address) const override;
148
149#ifdef CODE_GENERATION
151 virtual std::vector<size_t> getDimensionsSize() const override;
152#endif
153 };
154
155 template <class T>
156 inline Array2DWrapper<T>::Array2DWrapper(const size_t w, const size_t h,
157 std::vector<T>* ptr)
158 : ArrayWrapper<T>(w * h, ptr), height(h), width(w)
159 {
160 }
161
162 // Declare the child class for use in clone
163 template <class T> class PrimitiveTypeArray2D;
164
165 template <class T> DataHandler* Array2DWrapper<T>::clone() const
166 {
167 // Create a constantCopy of the ArrayWrapper content.
168 DataHandler* result = new PrimitiveTypeArray2D<T>(*this);
169
170 return result;
171 }
172
173 template <typename T>
175 const std::type_info& type, const size_t address) const
176 {
177 // Initialize the result
178 std::vector<size_t> result;
179
180 // If the accessed address is valid fill the result.
181 size_t arrayHeight;
182 size_t arrayWidth;
183 const size_t space =
184 this->getAddressSpace(type, &arrayHeight, &arrayWidth);
185 if (space > address) {
186 // For the native type.
187 if (type == typeid(T)) {
188 result.push_back(address);
189 }
190 else {
191 // Else, the type is the array type.
192 size_t addressH = address / (this->width - arrayWidth + 1);
193 size_t addressW = address % (this->width - arrayWidth + 1);
194 size_t addressSrc = (addressH * this->width) + addressW;
195 size_t idxDst = 0;
196 for (size_t idxHeight = 0; idxHeight < arrayHeight;
197 idxHeight++) {
198 for (size_t idxWidth = 0; idxWidth < arrayWidth;
199 idxWidth++) {
200 size_t idxSrc = (idxHeight * this->width) + idxWidth;
201 result.push_back(addressSrc + idxSrc);
202 }
203 }
204 }
205 }
206 return result;
207 }
208
209 template <typename T>
210 size_t Array2DWrapper<T>::getAddressSpace(const std::type_info& type) const
211 {
212 // Use the utility function
213 return this->getAddressSpace(type, nullptr, nullptr);
214 }
215
216 template <typename T>
217 size_t Array2DWrapper<T>::getAddressSpace(const std::type_info& type,
218 size_t* dim1, size_t* dim2) const
219 {
220 // Has the result been cached
221 auto iter = this->cachedAddressSpace.find(type);
222 if (iter != this->cachedAddressSpace.end()) {
223 if (dim1 != nullptr) {
224 *dim1 = std::get<1>(iter->second);
225 }
226 if (dim2 != nullptr) {
227 *dim2 = std::get<2>(iter->second);
228 }
229 return std::get<0>(iter->second);
230 }
231
232 size_t result = 0;
233 // The parent function is not used to avoid performing 2 regex matches.
234 if (type == typeid(T)) {
235 this->cachedAddressSpace.emplace(
236 type, std::make_tuple(this->nbElements, 0, 0));
237 result = this->nbElements;
238 }
239
240 // Check if it is a 1D or 2D array
241 // with a size (h and w) inferior to the container dimensions.
242 if (result == 0) {
243 std::string typeName = DEMANGLE_TYPEID_NAME(type.name());
244 std::string regex{DEMANGLE_TYPEID_NAME(typeid(T).name())};
245 regex.append("\\s*(const\\s*)?\\[([0-9]+)\\](\\[([0-9]+)\\])?");
246 std::regex arrayType(regex);
247 std::cmatch cm;
248 if (std::regex_match(typeName.c_str(), cm, arrayType)) {
249 int typeH = 0;
250 int typeW = 0;
251 if (cm[2].matched && !cm[4].matched) {
252 // 1D array
253 typeH = 1;
254 typeW = std::atoi(cm[2].str().c_str());
255 }
256 else if (cm[2].matched && cm[4].matched) {
257 // 2D array
258 typeH = std::atoi(cm[2].str().c_str());
259 typeW = std::atoi(cm[4].str().c_str());
260 }
261
262 // Make sure dimensions are valid for this array
263 // Only spatially coherent data can be provided.
264 // Data spanning over several lines can not be
265 // provided
266 if (typeH <= this->height && typeW <= this->width) {
267 result = (this->height - typeH + 1) *
268 ((this->width - typeW + 1));
269 if (dim1 != nullptr) {
270 *dim1 = typeH;
271 }
272 if (dim2 != nullptr) {
273 *dim2 = typeW;
274 }
275 this->cachedAddressSpace.emplace(
276 type, std::make_tuple(result, typeH, typeW));
277 }
278 }
279 }
280
281 return result;
282 }
283
284 template <typename T>
286 const size_t address) const
287 {
288#ifndef NDEBUG
289 // Throw exception in case of invalid arguments.
291#endif
292
293 if (type == typeid(T)) {
294 UntypedSharedPtr result(
295 &(this->containerPtr->at(address)),
296 UntypedSharedPtr::emptyDestructor<const T>());
297 return result;
298 }
299
300 // Else, the only other supported type is cstyle array (1D or 2D).
301 // Because 2D arrays are array with the second dimension set to 1,
302 // all the following code is generic
303
304 size_t arrayHeight = 0;
305 size_t arrayWidth = 0;
306 size_t addressableSpace =
307 this->getAddressSpace(type, &arrayHeight, &arrayWidth);
308
309 // Types was checked before trying to produce
310 // a return value
311 auto array = new T[arrayHeight * arrayWidth];
312
313 // Copy its content
314 size_t addressH = address / (this->width - arrayWidth + 1);
315 size_t addressW = address % (this->width - arrayWidth + 1);
316 size_t addressSrc = (addressH * this->width) + addressW;
317 size_t idxDst = 0;
318 for (size_t idxHeight = 0; idxHeight < arrayHeight; idxHeight++) {
319 for (size_t idxWidth = 0; idxWidth < arrayWidth; idxWidth++) {
320 size_t idxSrc = (idxHeight * this->width) + idxWidth;
321 array[idxDst++] = this->containerPtr->at(addressSrc + idxSrc);
322 }
323 }
324
325 // Create the UntypedSharedPtr
326 UntypedSharedPtr result{
327 std::make_shared<UntypedSharedPtr::Model<const T[]>>(array)};
328 return result;
329 }
330
331#ifdef CODE_GENERATION
332 template <class T>
333 std::vector<size_t> Array2DWrapper<T>::getDimensionsSize() const
334 {
335 std::vector<size_t> sizes = {height, width};
336 return sizes;
337 }
338#endif
339} // namespace Data
340#endif // !ARRAY_2D_WRAPPER_H
341
342// Include PrimitiveTypeArray2D to ensure availability of the used clone method.
343#include "data/primitiveTypeArray2D.h"
DataHandler for 2D arrays of primitive types.
Definition: array2DWrapper.h:68
size_t width
Number of columns of the 2D array.
Definition: array2DWrapper.h:90
virtual std::vector< size_t > getAddressesAccessed(const std::type_info &type, const size_t address) const override
Inherited from DataHandler.
Definition: array2DWrapper.h:174
size_t height
Number of lines of the 2D array.
Definition: array2DWrapper.h:93
virtual UntypedSharedPtr getDataAt(const std::type_info &type, const size_t address) const override
Inherited from DataHandler.
Definition: array2DWrapper.h:285
virtual ~Array2DWrapper()=default
Default destructor.
size_t getAddressSpace(const std::type_info &type, size_t *dim1, size_t *dim2) const
Utility function for the class.
Definition: array2DWrapper.h:217
virtual std::vector< size_t > getDimensionsSize() const override
Inherited from DataHandler.
Definition: array2DWrapper.h:333
virtual DataHandler * clone() const override
Return a PrimitiveTypeArray2D<T> where all data of the Array2DWrapper has been copied.
Definition: array2DWrapper.h:165
Array2DWrapper(const size_t w=2, const size_t h=4, std::vector< T > *ptr=nullptr)
Constructor for the 2D array.
Definition: array2DWrapper.h:156
Array2DWrapper(const Array2DWrapper &other)=default
Default copy constructor.
Definition: arrayWrapper.h:69
void checkAddressAndType(const std::type_info &type, const size_t &address) const
Definition: arrayWrapper.h:221
Base class for all sources of data to be accessed by a TPG Instruction executed within a Program.
Definition: dataHandler.h:54
DataHandler for 2D arrays of primitive types.
Definition: primitiveTypeArray2D.h:69
Class behaving as a std::shared_ptr whose type is not templated.
Definition: untypedSharedPtr.h:72
Definition: array2DWrapper.h:44