1 /* Copyright (C) 2018 Federico Simmross Wattenberg,
2 * Manuel Rodríguez Cayetano,
3 * Javier Royuela del Val,
4 * Elena Martín González,
6 * Marcos Martín Fernández and
7 * Carlos Alberola López
9 * This file is part of OpenCLIPER.
11 * OpenCLIPER is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 3 of the License.
15 * OpenCLIPER is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with OpenCLIPER; If not, see <http://www.gnu.org/licenses/>.
26 * Federico Simmross Wattenberg
27 * E.T.S.I. Telecomunicación
28 * Universidad de Valladolid
30 * 47011 Valladolid, Spain.
36 * Created on: 26 de oct. de 2016
40 #include<OpenCLIPER/ConcreteNDArray.hpp>
43 namespace OpenCLIPER {
46 * @brief Constructor without parameters, initializes class fields. It calls superclass default constructor.
49 ConcreteNDArray<T>::ConcreteNDArray(): NDArray() {
53 * @brief Constructor for storing spatial dimensions and empty data in class fields (element data type is complexType).
55 * This constructor has move semantics (in spite of not using && notation):
56 * after call, parameters memory deallocation is responsibility of this class
57 * (parameters are set to nullptr at the end of the method).
58 * @param[in,out] pSpatialDims vector with sizes of each spatial dimension
61 ConcreteNDArray<complexType>::ConcreteNDArray(std::vector<dimIndexType>*& pSpatialDims) {
62 setDims(pSpatialDims);
63 complexType complexZero(0.0,0.0);
64 std::vector <complexType>* pHostComplexDataLocal = new std::vector <complexType>(this->size(), complexZero);
65 setHostData(pHostComplexDataLocal);
69 * @brief Constructor for storing spatial dimensions and empty data in class fields (element data type is dimIndexType).
71 * This constructor has move semantics (in spite of not using && notation):
72 * after call, parameters memory deallocation is responsibility of this class
73 * (parameters are set to nullptr at the end of the method).
74 * @param[in,out] pSpatialDims vector with sizes of each spatial dimension
77 ConcreteNDArray<dimIndexType>::ConcreteNDArray(std::vector<dimIndexType>*& pSpatialDims) {
78 setDims(pSpatialDims);
79 std::vector <dimIndexType>* pHostUnsignedDataLocal = new std::vector <dimIndexType>(this->size(), 0);
80 setHostData(pHostUnsignedDataLocal);
84 * @brief Constructor for storing spatial dimensions and empty data in class fields (element data type is realType).
86 * This constructor has move semantics (in spite of not using && notation):
87 * after call, parameters memory deallocation is responsibility of this class
88 * (parameters are set to nullptr at the end of the method).
89 * @param[in,out] pSpatialDims vector with sizes of each spatial dimension
92 ConcreteNDArray<realType>::ConcreteNDArray(std::vector<dimIndexType>*& pSpatialDims) {
93 setDims(pSpatialDims);
94 std::vector <realType>* pHostLocal = new std::vector <realType>(this->size(), 0.0);
95 setHostData(pHostLocal);
99 * @brief Constructor for storing spatial dimensions and data in class fields.
100 * This constructor has move semantics (in spite of not using && notation):
101 * after call, parameters memory deallocation is responsibility of this class
102 * (parameters are set to nullptr at the end of the method).
103 * @param[in,out] pSpatialDims vector with sizes of each spatial dimension
104 * @param[in,out] pHostData vector of \<T\> type data elements stored in host memory
107 ConcreteNDArray<T>::ConcreteNDArray(std::vector<dimIndexType>*& pSpatialDims, std::vector<T>*&pHostData) {
108 setDims(pSpatialDims);
109 setHostData(pHostData);
113 * @brief Constructor that reads data for the ConcreteNDArray object from a file in raw format.
114 * @param[in] completeFileName name of the file to be read for getting data
115 * @param[in,out] pSpatialDims vector with NDArray spatial dimensions (move semantics, ownership of the vector is transferred from caller to this object)
118 ConcreteNDArray<T>::ConcreteNDArray(const string completeFileName, vector<dimIndexType>*& pSpatialDims) {
119 vector<T>* pTempData;
120 setDims(pSpatialDims); // store dimension vector and set parameter to nullptr (move semantics)
121 pTempData = new vector<T>; // vector for data
122 pTempData->resize(this->size()); //size(): product of size of each dimension
123 std::ifstream f(completeFileName, std::ios::binary);
125 throw std::invalid_argument(completeFileName + " cannot be read\n");
127 // get length of file:
129 int fileLength = f.tellg();
131 //CERR (completeFileName << " file length: " << fileLength << " bytes\n");
132 f.read(reinterpret_cast<char*>(pTempData->data()), this->size() * sizeof(T));
133 // store data and set parameter to nullptr (move semantics)
134 setHostData(pTempData);
139 * @brief Constructor that creates a copy of a ConcreteNDArray object with complexType data type elements (dimensions are copied always,
140 * image data only if copyData parameter is true).
141 * @param[in] pSourceData ConcreteNDArray object source of spatial and temporal dimensions (complexType elements)
142 * @param[in] copyData data (not only dimensions) are copied if this parameter is true (default value: false)
145 ConcreteNDArray<complexType>::ConcreteNDArray(const NDArray* pSourceData, bool copyData) {
146 vector<dimIndexType>* pLocalDims = new vector<dimIndexType>(*(pSourceData->getDims()));
148 vector<complexType>* pLocalHostData;
150 const ConcreteNDArray<complexType>* pTypedSourceData = static_cast<const ConcreteNDArray<complexType>*>(pSourceData);
151 pLocalHostData = new vector<complexType>(*(pTypedSourceData->getHostData()));
153 // Create image data initialized to a vector of complex values (0.0, 0.0) and with a number of values equal to the
154 // multiplication of dims vector values
155 complexType zeroElement(0.0, 0.0);
156 pLocalHostData = new std::vector<complexType>(pSourceData->size(), zeroElement);
158 setHostData(pLocalHostData);
162 * @brief Constructor that creates a copy of a ConcreteNDArray object with dimIndexType data type elements (dimensions are copied always,
163 * image data only if copyData parameter is true).
164 * @param[in] pSourceData ConcreteNDArray object source of spatial and temporal dimensions (dimIndexType elements)
165 * @param[in] copyData data (not only dimensions) are copied if this parameter is true (default value: false)
168 ConcreteNDArray<dimIndexType>::ConcreteNDArray(const NDArray* pSourceData, bool copyData) {
169 vector<dimIndexType>* pLocalDims = new vector<dimIndexType>(*(pSourceData->getDims()));
171 vector<dimIndexType>* pLocalHostData;
173 const ConcreteNDArray<dimIndexType>* pTypedSourceData = static_cast<const ConcreteNDArray<dimIndexType>*>(pSourceData);
174 pLocalHostData = new vector<dimIndexType>(*(pTypedSourceData->getHostData()));
176 dimIndexType zeroElement = 0;
177 pLocalHostData = new std::vector<dimIndexType>(pSourceData->size(), zeroElement);
179 setHostData(pLocalHostData);
183 * @brief Constructor that creates a copy of a ConcreteNDArray object with realType data type elements (dimensions are copied always,
184 * image data only if copyData parameter is true).
185 * @param[in] pSourceData ConcreteNDArray object source of spatial and temporal dimensions (realType elements)
186 * @param[in] copyData data (not only dimensions) are copied if this parameter is true (default value: false)
189 ConcreteNDArray<realType>::ConcreteNDArray(const NDArray* pSourceData, bool copyData) {
190 vector<dimIndexType>* pLocalDims = new vector<dimIndexType>(*(pSourceData->getDims()));
192 vector<realType>* pLocalHostData;
194 const ConcreteNDArray<realType>* pTypedSourceData = static_cast<const ConcreteNDArray<realType>*>(pSourceData);
195 pLocalHostData = new vector<realType>(*(pTypedSourceData->getHostData()));
197 realType zeroElement = 0.0;
198 pLocalHostData = new std::vector<realType>(pSourceData->size(), zeroElement);
200 setHostData(pLocalHostData);
204 * @brief Constructor for reading data from a matlab variable
205 * @param[in] matvar matlab array variable read from file
206 * @param[in] numOfSpatialDims number of dimensions of matlab array variable that are used as data spatial dimensions
207 * @param[in] nDArrayOffsetInElements offset (in number of elements) from matlab variable beginning to start reading from
210 ConcreteNDArray<T>::ConcreteNDArray(matvar_t *matvar, dimIndexType numOfSpatialDims, dimIndexType nDArrayOffsetInElements) {
211 loadMatlabHostData(matvar, numOfSpatialDims, nDArrayOffsetInElements);
212 #ifdef ConcreteNDArray_DEBUG
213 CERR(hostDataToString("ConcreteNDArray: "));
218 * @brief Gets one element from a matlab variable (previously read from a matlab file), base data type is complexType
219 * @param[in] matvar matlab array variable previously read from file
220 * @param[in] offsetInBytes offset from beginning of matlab variable (in bytes) where element data must be read
223 inline void ConcreteNDArray<complexType>::loadMatlabHostDataElement(matvar_t* matvar, dimIndexType offsetInBytes) {
224 mat_complex_split_t *complex_data = (mat_complex_split_t *) matvar->data;
225 char* pCharRealPart = (char *) complex_data->Re;
226 char* pCharImagPart = (char *) complex_data->Im;
227 complexType complexElement;
228 realType realPart, imagPart;
229 realPart = *((realType*)(pCharRealPart + offsetInBytes));
230 imagPart = *((realType*)(pCharImagPart + offsetInBytes));
231 complexElement = {realPart, imagPart};
232 pHostData->push_back(complexElement);
233 #ifdef ConcreteNDArray_DEBUG
234 CERR(realPart << "+" << imagPart << "i" << std::endl);
239 * @brief Gets one element from a matlab variable (previously read from a matlab file), base data type is dimIndexType
240 * @param[in] matvar matlab array variable previously read from file
241 * @param[in] offsetInBytes offset from beginning of matlab variable (in bytes) where element data must be read
244 inline void ConcreteNDArray<dimIndexType>::loadMatlabHostDataElement(matvar_t* matvar, dimIndexType offsetInBytes) {
245 char *data = (char*)matvar->data;
246 dimIndexType element;
247 element = *((dimIndexType *)(data + offsetInBytes));
248 pHostData->push_back(element);
249 #ifdef ConcreteNDArray_DEBUG
250 CERR(element << std::endl);
255 * @brief Gets one element from a matlab variable (previously read from a matlab file), base data type is realType
256 * @param[in] matvar matlab array variable previously read from file
257 * @param[in] offsetInBytes offset from beginning of matlab variable (in bytes) where element data must be read
260 inline void ConcreteNDArray<realType>::loadMatlabHostDataElement(matvar_t* matvar, dimIndexType offsetInBytes) {
261 char *data = (char*)matvar->data;
263 element = *((realType *)(data + offsetInBytes));
264 pHostData->push_back(element);
265 #ifdef ConcreteNDArray_DEBUG
266 CERR(element << std::endl);
271 * @brief Destructor, frees all previously allocated memory
274 ConcreteNDArray<T>::~ConcreteNDArray() {
275 #ifdef ConcreteNDArray_DEBUG
276 CERR("~ConcreteNDArray() begins..." << std::endl);
278 if (pHostData != nullptr) {
279 // If host2device have not been called, pHostBuffer and pHostImage point to pHostData->data,
280 // and they must be set to nullptr (to avoid accesses to deallocated memory after pHostData has been reset)
281 if (pHostBuffer == pHostData->data()) {
282 pHostBuffer = nullptr;
284 if (pHostImage == pHostData->data()) {
285 pHostImage = nullptr;
287 pHostData.reset(); // pHostData is a smart pointer
289 #ifdef ConcreteNDArray_DEBUG
290 CERR("~ConcreteNDArray() ends" << std::endl);
295 * @brief Converts one data element of an NDArray to a text representation
296 * @param[in] pElementsArray pointer to array of elements
297 * @param[in] index1D 1-dimensional index for element from array
298 * @return string with text representation of data element
300 template <class T> const std::string ConcreteNDArray<T>::elementToString(const void *pElementsArray, dimIndexType index1D) const {
302 if (typeid(T) == typeid(complexType)) {
303 complexType* pTypedArray;
304 pTypedArray = (complexType *) pElementsArray;
305 stringValue = "(" + std::to_string(pTypedArray[index1D].real()) + "," +
306 std::to_string(pTypedArray[index1D].imag()) + ")";
307 } else if (typeid(T) == typeid(dimIndexType)) {
308 dimIndexType* pTypedArray;
309 pTypedArray = (dimIndexType*) pElementsArray;
310 stringValue = std::to_string(pTypedArray[index1D]);
311 } else if (typeid(T) == typeid(realType)) {
312 realType* pTypedArray;
313 pTypedArray = (realType*) pElementsArray;
314 stringValue = std::to_string(pTypedArray[index1D]);
316 throw invalid_argument("element data type not supported in elementToString method: " + string(typeid(T).name()));
322 * @brief Calculates rows, columns, slices, ... offsets for accessing images/volumes stored as 1D arrays of \<T\> type
324 * @return pointer to vector variable storing strides
327 vector <dimIndexType>* ConcreteNDArray<T>::calcUnaligned1DArrayStridesFromNDArrayDims() const {
328 vector<dimIndexType>* pSpatialDimsStridesVector = new vector<dimIndexType>();
329 // dimensions order is columns, rows, slices, ...
330 dimIndexType acumStride;
331 if (typeid(T) == typeid(complexType)) {
332 acumStride = 2;// every column has 2 floats (real and imaginary part of complex number)
333 } else if (typeid(T) == typeid(realType)) {
334 acumStride = 1;// every column has 1 float (instead of 2 floats, real and imaginary part of complex number, for a ComplexNDArray)
335 } else if (typeid(T) == typeid(dimIndexType)) {
336 acumStride = 1;// every column has 1 uint (instead of 2 floats, real and imaginary part of complex number, for a ComplexNDArray)
338 throw invalid_argument("Unsupported type in calcUnaligned1DArrayStridesFromNDArrayDims method: " + string(typeid(this).name()));
340 for (dimIndexType spatialDimId = 0; spatialDimId < getNDims(); spatialDimId++) {
341 pSpatialDimsStridesVector->push_back(acumStride);
342 acumStride *= getDims()->at(spatialDimId); // new stride is equal to previous stride * previous dimension
344 return pSpatialDimsStridesVector;
347 // Doxygen comments not needed, inherited from superclass method of the same name
349 inline void ConcreteNDArray<complexType>::dumpMatlabElement(MatVarInfo* pMatVarInfo, dimIndexType matlabElementOffset,
350 dimIndexType nDArrayElementOffset, SyncSource syncSource) {
351 mat_complex_split_t* complexData = (mat_complex_split_t*) pMatVarInfo->getData();
352 // WARNING!! pointer arithmetic depends on base type (pointer + offset operation increments pointer in a number of bytes equal
353 // to offset multiplied by the base data type size in bytes, you must not explicity multiply offset by base data type size!!)
354 realType* realPart = ((realType*) complexData->Re) + matlabElementOffset;
355 realType* imagPart = ((realType*) complexData->Im) + matlabElementOffset;
356 realType* source; // type of base element (real, not complexType)
357 switch (syncSource) {
358 case SyncSource::BUFFER_ONLY:
359 source = (realType*)(getHostBuffer());
361 case SyncSource::IMAGE_ONLY:
362 source = (realType*)(getHostImage());
365 throw invalid_argument("Unsupported SyncSource in dumpMatlabElement");
367 // real and imaginary parts in OpenCL buffer/images stored in contiguous positions (nDArrayElementOffset: real part,
368 // nDArrayElementOffset + 1: imaginary part
369 *realPart = (source)[nDArrayElementOffset];
370 *imagPart = (source)[nDArrayElementOffset+1];
374 inline void ConcreteNDArray<dimIndexType>::dumpMatlabElement(MatVarInfo* pMatVarInfo, dimIndexType matlabElementOffset,
375 dimIndexType nDArrayElementOffset, SyncSource syncSource) {
376 dimIndexType* typedData = ((dimIndexType*) pMatVarInfo->getData()) + matlabElementOffset;
377 dimIndexType* source;
378 switch (syncSource) {
379 case SyncSource::BUFFER_ONLY:
380 source = (dimIndexType*)(getHostBuffer());
382 case SyncSource::IMAGE_ONLY:
383 source = (dimIndexType*)(getHostImage());
386 throw invalid_argument("Unsupported SyncSource in dumpMatlabElement");
388 *typedData = (source)[nDArrayElementOffset];
392 inline void ConcreteNDArray<realType>::dumpMatlabElement(MatVarInfo* pMatVarInfo, dimIndexType matlabElementOffset,
393 dimIndexType nDArrayElementOffset, SyncSource syncSource) {
394 realType* typedData = ((realType*) pMatVarInfo->getData()) + matlabElementOffset;
396 switch (syncSource) {
397 case SyncSource::BUFFER_ONLY:
398 source = (realType*)(getHostBuffer());
400 case SyncSource::IMAGE_ONLY:
401 source = (realType*)(getHostImage());
404 throw invalid_argument("Unsupported SyncSource in dumpMatlabElement");
406 *typedData = (source)[nDArrayElementOffset];
409 #include<OpenCLIPER/ConcreteNDArrayPrototypes.hpp>
410 } //namespace OpenCLIPER