utils_array.h
Go to the documentation of this file.
1
12#ifndef CCGL_UTILS_ARRAY_H
13#define CCGL_UTILS_ARRAY_H
14
15#include <new> // std::nothrow
16#include <cstdarg> // variable arguments
17#include <iostream>
18#include <vector>
19#include <sstream>
20#include <fstream>
21#include "basic.h"
22
23using std::vector;
24using std::cout;
25using std::endl;
26using std::nothrow;
27
28namespace ccgl {
33namespace utils_array {
41template <typename T, typename INI_T>
42bool Initialize1DArray(int row, T*& data, INI_T init_value);
43
51template <typename T, typename INI_T>
52bool Initialize1DArray(int row, T*& data, INI_T* init_data);
53
54template <typename T, typename INI_T>
55bool Initialize1DArray4ItpWeight(int row, T*& data, INI_T* init_data, int itp_weight_data_length);
72template <typename T, typename INI_T>
73bool Initialize2DArray(int row, int col, T**& data, INI_T init_value);
74
84template <typename T, typename INI_T>
85bool Initialize2DArray(int row, int col, T**& data, INI_T** init_data);
86
95template <typename T1, typename T2>
96bool Initialize2DArray(T1* init_data, int& rows, int& max_cols, T2**& data);
97
102template <typename T>
103void Release1DArray(T*& data);
104
109template <typename T>
110void Release2DArray(T**& data);
111
129template <typename T>
130void BatchRelease1DArray(T*& data, ...);
131
145template <typename T>
146void BatchRelease2DArray(int nrows, T**& data, ...);
147
153void Output1DArrayToTxtFile(int n, const float* data, const char* filename);
154
160void Output2DArrayToTxtFile(int rows, int cols, const float** data, const char* filename);
161
173template <typename T>
174void Read1DArrayFromTxtFile(const char* filename, int& rows, T*& data);
175
187template <typename T>
188void Read2DArrayFromTxtFile(const char* filename, int& rows, T**& data);
189
190
199template <typename T>
200bool Read2DArrayFromCsvFile(const char* filename, const vector<string>* header, std::vector<std::vector<T>>& data);
201
212template <typename T>
213void Read2DArrayFromString(const char* s, int& rows, T**& data);
214
221template <typename T>
222bool ValueInVector(T val, const vector<T>& vec);
223
229template <typename T>
230void RemoveValueInVector(T val, vector<T>& vec);
231
241template <typename T>
242class Array2D {
243 T** data_ptr;
244 vuint32_t m_rows;
245 vuint32_t m_cols;
246
247 T** create2DArray(vuint32_t nrows, vuint32_t ncols, const T& val = T()) {
248 T** ptr = nullptr;
249 T* pool = nullptr;
250 try {
251 ptr = new(nothrow) T*[nrows]; // allocate pointers (Do not throw here)
252 pool = new(nothrow) T[nrows*ncols]; // allocate pool (Do not throw here)
253 for (vuint32_t i = 0; i < nrows * ncols; i++) {
254 pool[i] = val;
255 }
256 // now point the row pointers to the appropriate positions in the memory pool
257 for (vuint32_t i = 0; i < nrows; ++i, pool += ncols) {
258 ptr[i] = pool;
259 }
260 return ptr;
261 } catch (std::bad_alloc& ex) {
262 delete[] ptr; // either this is nullptr or it was allocated
263 // throw ex; // memory allocation error
264 }
265 }
266
267public:
268 typedef T value_type;
269 T** data() {
270 return data_ptr;
271 }
272
273 vuint32_t get_rows() const { return m_rows; }
274
275 vuint32_t get_cols() const { return m_cols; }
276
277 Array2D() : data_ptr(nullptr), m_rows(0), m_cols(0) {}
278 Array2D(vuint32_t rows, vuint32_t cols, const T& val = T()) {
279 if (rows <= 0)
280 throw std::invalid_argument("number of rows is 0"); // TODO, DO not throw here
281 if (cols <= 0)
282 throw std::invalid_argument("number of columns is 0"); // TODO, DO not throw here
283 data_ptr = create2DArray(rows, cols, val);
284 m_rows = rows;
285 m_cols = cols;
286 }
287
288 ~Array2D() {
289 if (data_ptr) {
290 delete[] data_ptr[0]; // remove the pool
291 delete[] data_ptr; // remove the pointers
292 }
293 }
294
295 Array2D(const Array2D& rhs) : m_rows(rhs.m_rows), m_cols(rhs.m_cols) {
296 data_ptr = create2DArray(m_rows, m_cols);
297 std::copy(&rhs.data_ptr[0][0], &rhs.data_ptr[m_rows - 1][m_cols], &data_ptr[0][0]);
298 }
299
300 Array2D(Array2D&& rhs) NOEXCEPT {
301 data_ptr = rhs.data_ptr;
302 m_rows = rhs.m_rows;
303 m_cols = rhs.m_cols;
304 rhs.data_ptr = nullptr;
305 }
306
307 Array2D& operator=(Array2D&& rhs) NOEXCEPT {
308 if (&rhs != this) {
309 swap(rhs, *this);
310 }
311 return *this;
312 }
313
314 void swap(Array2D& left, Array2D& right) {
315 std::swap(left.data_ptr, right.data_ptr);
316 std::swap(left.m_cols, right.m_cols);
317 std::swap(left.m_rows, right.m_rows);
318 }
319
320 Array2D& operator = (const Array2D& rhs) {
321 if (&rhs != this) {
322 Array2D temp(rhs);
323 swap(*this, temp);
324 }
325 return *this;
326 }
327
328 T* operator[](vuint32_t row) {
329 return data_ptr[row];
330 }
331
332 const T* operator[](vuint32_t row) const {
333 return data_ptr[row];
334 }
335
336 void create(vuint32_t rows, vuint32_t cols, const T& val = T()) {
337 *this = Array2D(rows, cols, val);
338 }
339};
340
341
342/************ Implementation of template functions ******************/
343template <typename T, typename INI_T>
344bool Initialize1DArray(const int row, T*& data, const INI_T init_value) {
345 if (nullptr != data) {
346 //Should allow an array to re-enter this function then just return? --wyj
347 //cout << "The input 1D array pointer is not nullptr. No initialization performed!" << endl;
348 return false;
349 }
350 if (row <= 0) {
351 cout << "The data length MUST be greater than 0!" << endl;
352 data = nullptr;
353 return false;
354 }
355 data = new(nothrow)T[row];
356 if (nullptr == data) {
357 delete[] data;
358 cout << "Bad memory allocated during 1D array initialization!" << endl;
359 data = nullptr;
360 return false;
361 }
362 T init = static_cast<T>(init_value);
363#pragma omp parallel for
364 for (int i = 0; i < row; i++) {
365 data[i] = init;
366 }
367 return true;
368}
369
370template <typename T, typename INI_T>
371bool Initialize1DArray(const int row, T*& data, INI_T* const init_data) {
372 if (nullptr != data) {
373 // cout << "The input 1D array pointer is not nullptr. No initialization performed!" << endl;
374 return false;
375 }
376 data = new(nothrow) T[row];
377 if (nullptr == data) {
378 delete[] data;
379 cout << "Bad memory allocated during 1D array initialization!" << endl;
380 return false;
381 }
382 if (nullptr == init_data) {
383 cout << "The input parameter init_data MUST NOT be nullptr!" << endl;
384 return false;
385 }
386#pragma omp parallel for
387 for (int i = 0; i < row; i++) {
388 data[i] = static_cast<T>(init_data[i]);
389 }
390 return true;
391}
392
393template <typename T, typename INI_T>
394bool Initialize2DArray(const int row, const int col, T**& data, const INI_T init_value) {
395 if (row <= 0 || col <= 0) {
396 cout << "The row and col should not be less or equal to ZERO!" << endl;
397 return false;
398 }
399 if (nullptr != data) {
400 // cout << "The input 2D array pointer is not nullptr. No initialization performed!" << endl;
401 return false;
402 }
403 data = new(nothrow) T*[row];
404 if (nullptr == data) {
405 delete[] data;
406 cout << "Bad memory allocated during initialize rows of the 2D array!" << endl;
407 return false;
408 }
409 T* pool = nullptr;
410 pool = new(nothrow) T[row * col];
411 if (nullptr == pool) {
412 delete[] pool;
413 cout << "Bad memory allocated during initialize data pool of the 2D array!" << endl;
414 return false;
415 }
416 // Initialize the data pool
417 T init = static_cast<T>(init_value);
418#pragma omp parallel for
419 for (int i = 0; i < row * col; i++) {
420 pool[i] = init;
421 }
422 // Now point the row pointers to the appropriate positions in the data pool
423 for (int i = 0; i < row; ++i, pool += col) {
424 data[i] = pool;
425 }
426 return true;
427}
428
429template <typename T, typename INI_T>
430bool Initialize2DArray(const int row, const int col, T**& data,
431 INI_T** const init_data) {
432 bool flag = Initialize2DArray(row, col, data, init_data[0][0]);
433 if (!flag) { return false; }
434#pragma omp parallel for
435 for (int i = 0; i < row; i++) {
436 for (int j = 0; j < col; j++) {
437 data[i][j] = static_cast<T>(init_data[i][j]);
438 }
439 }
440 return true;
441}
442
443template <typename T1, typename T2>
444bool Initialize2DArray(T1* init_data, int& rows, int& max_cols, T2**& data) {
445 int idx = 0;
446 rows = CVT_INT(init_data[idx++]);
447 data = new(nothrow) T2* [rows];
448 if (nullptr == data) {
449 delete[] data;
450 cout << "Bad memory allocated during initialize rows of the 2D array!" << endl;
451 return false;
452 }
453 T2* pool = nullptr;
454 // Get actual data length of init_data, excluding the first element which is 'rows'
455 int* cols = new int[rows];
456 max_cols = -1;
457 for (int i = 0; i < rows; i++) {
458 cols[i] = CVT_INT(init_data[idx]);
459 idx += cols[i] + 1;
460 if (cols[i] > max_cols) { max_cols = cols[i]; }
461 }
462 int length = idx - 1;
463 // New a 1d array to store data
464 Initialize1DArray(length, pool, init_data + 1);
465 // Now point the row pointers to the appropriate positions in the data pool
466 int pos = 0;
467 for (int i = 0; i < rows; ++i) {
468 data[i] = pool + pos;
469 pos += cols[i] + 1;
470 }
471 delete[] cols;
472 return true;
473}
474
475template <typename T>
476void Release1DArray(T*& data) {
477 if (nullptr != data) {
478 delete[] data;
479 data = nullptr;
480 }
481}
482
483template <typename T>
484void Release2DArray(T**& data) {
485 if (nullptr == data) {
486 return;
487 }
488 delete[] data[0]; // delete the memory pool
489 delete[] data; // delete row pointers
490 data = nullptr;
491}
492
493template <typename T>
494void BatchRelease1DArray(T*& data, ...) {
495 va_list arg_ptr;
496 va_start(arg_ptr, data);
497 Release1DArray(data);
498 T* arg_value = va_arg(arg_ptr, T*);
499 while (nullptr != arg_value) {
500 Release1DArray(arg_value);
501 arg_value = va_arg(arg_ptr, T*);
502 }
503 va_end(arg_ptr);
504}
505
506template <typename T>
507void BatchRelease2DArray(const int nrows, T**& data, ...) {
508 va_list arg_ptr;
509 va_start(arg_ptr, data);
510 Release2DArray(nrows, data);
511 T** arg_value = va_arg(arg_ptr, T**);
512 while (nullptr != arg_value) {
513 Release2DArray(nrows, arg_value);
514 arg_value = va_arg(arg_ptr, T**);
515 }
516 va_end(arg_ptr);
517}
518
519template <typename T>
520bool ValueInVector(const T val, const vector<T>& vec) {
521 if (vec.empty()) {
522 return false;
523 }
524 if (find(vec.begin(), vec.end(), val) == vec.end()) {
525 return false;
526 }
527 return true;
528}
529
530template <typename T>
531void RemoveValueInVector(const T val, vector<T>& vec) {
532 for (auto iter = vec.begin(); iter != vec.end();) {
533 if (*iter == val) {
534 iter = vec.erase(iter);
535 } else {
536 ++iter;
537 }
538 }
539}
540
541template <typename T>
542bool Read2DArrayFromCsvFile(const char* filename, const vector<string>* header, std::vector<std::vector<T>>& data) {
543 std::ifstream ifs(filename);
544 std::string line;
545 if (!ifs.is_open()) {
546 std::cerr << "Error: Open file " << filename << " failed!" << std::endl;
547 return false;
548 }
549 vector<int> col_idx;
550 if (header != nullptr) {
551 int i = 0;
552 std::getline(ifs, line);
553 std::stringstream ss(line);
554 std::string value;
555 while (getline(ss, value, ',')) {
556 if (ValueInVector(value, *header)) {
557 col_idx.push_back(i);
558 }
559 i++;
560 }
561 }
562 while (std::getline(ifs, line)) {
563 int i = 0;
564 std::vector<T> row;
565 std::stringstream ss(line);
566 std::string value;
567 while (getline(ss, value, ',')) {
568 if (ValueInVector(i, col_idx)) {
569 row.push_back(static_cast<T>(std::stod(value)));
570 }
571 i++;
572 }
573 data.push_back(row);
574 }
575 ifs.close();
576 return true;
577}
578
579} /* utils_array */
580} /* namespace: ccgl */
581
582#endif /* CCGL_UTILS_ARRAY_H */
Basic definitions.
#define NOEXCEPT
A compatible reference to noexcept or throw() if not supported by the compiler.
Definition: basic.h:153
#define CVT_INT(param)
A reference to the postfix of executable file for RELWITHDEBINFO mode.
Definition: basic.h:325
Rudimentary RAII class of 2D Array which occupy successive memory.
Definition: utils_array.h:242
void Release1DArray(T *&data)
Release DT_Array1D data.
Definition: utils_array.h:476
bool Initialize1DArray(int row, T *&data, INI_T init_value)
Initialize DT_Array1D data.
Definition: utils_array.h:344
bool Initialize2DArray(int row, int col, T **&data, INI_T init_value)
Initialize DT_Array2D data.
Definition: utils_array.h:394
void Read2DArrayFromTxtFile(const char *filename, int &rows, T **&data)
Read 2D array from file The input file should follow the format: a 2D array sized rows * rows.
Definition: utils_array.cpp:40
void RemoveValueInVector(T val, vector< T > &vec)
Remove value in vector container.
Definition: utils_array.h:531
void Output2DArrayToTxtFile(const int rows, const int cols, const float **data, const char *filename)
Write 2D array to a file.
Definition: utils_array.cpp:16
void BatchRelease1DArray(T *&data,...)
Batch release of 1D array Variable arguments with the end of nullptr.
Definition: utils_array.h:494
bool ValueInVector(T val, const vector< T > &vec)
If value in vector container.
Definition: utils_array.h:520
void Read2DArrayFromString(const char *s, int &rows, T **&data)
Read 2D array from string The input string should follow the format: float value, total number is row...
Definition: utils_array.cpp:58
void Output1DArrayToTxtFile(const int n, const float *data, const char *filename)
Write 1D array to a file.
Definition: utils_array.cpp:8
bool Read2DArrayFromCsvFile(const char *filename, const vector< string > *header, std::vector< std::vector< T > > &data)
Read csv.
Definition: utils_array.h:542
void BatchRelease2DArray(int nrows, T **&data,...)
Batch release of 2D array,.
Definition: utils_array.h:507
void Read1DArrayFromTxtFile(const char *filename, int &rows, T *&data)
Read 1D array from file The input file should follow the format: a 1D array sized rows * 1.
Definition: utils_array.cpp:28
void Release2DArray(T **&data)
Release DT_Array2D data.
Definition: utils_array.h:484
Common Cross-platform Geographic Library (CCGL)
Definition: basic.cpp:17