47#ifdef ENABLE_ARRAY_INDEX_CHECKING
48#define Array_check_enabled
59 static int num_allocated;
61 static bool show_index_check_message;
62 static double memory_in_use;
63 static double memory_returned;
64 static void memory(
const std::string& prefix=
"");
65 static void stats(
const std::string& prefix=
"");
66 static bool write_enabled;
79 Array(
const int num_rows,
const int num_cols)
85 if ((num_rows <= 0) || (num_cols <= 0)) {
89 allocate(num_rows, num_cols);
94 Array(
const int num_rows,
const int num_cols, T* data)
96 data_reference_ =
true;
99 size_ = nrows_ * ncols_;
103 Array(std::initializer_list<std::initializer_list<T>> lst)
108 for (
auto &row : lst) {
111 num_cols = row.size();
112 }
else if (row.size() != num_cols) {
113 throw std::runtime_error(
"[Array initializer_list ctor] Column data is of unequal size.");
117 allocate(num_rows, num_cols);
121 for (
auto &row_data : lst) {
122 auto it = row_data.begin();
123 for (
int col = 0; col < row_data.size(); col++, it++) {
124 data_[row + col*nrows_] = *it;
135 Array(
const Array &rhs)
137 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0)) {
141 allocate(rhs.nrows_, rhs.ncols_);
143 memcpy(data_, rhs.data_, size_*
sizeof(T));
150 Array& operator=(
const Array& rhs)
156 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0)) {
160 if ((nrows_ != rhs.nrows_) || (ncols_ != rhs.ncols_)) {
162 allocate(rhs.nrows_, rhs.ncols_);
165 memcpy(data_, rhs.data_,
sizeof(T) * size_);
169 Array& operator=(
const double value)
171 for (
int i = 0; i < size_; i++) {
179 if (data_ !=
nullptr) {
180 #if Array_gather_stats
181 memory_in_use -=
sizeof(T)*size_;
182 memory_returned +=
sizeof(T)*size_;
185 if (!data_reference_) {
196 friend std::ostream& operator << (std::ostream& out,
const Array<T>& lhs)
198 for (
int i = 0; i < lhs.size(); i++) {
200 if (i != lhs.size()-1) {
213 if (data_ !=
nullptr) {
214 if (data_reference_) {
215 throw std::runtime_error(
"[Array] Can't clear an Array with reference data.");
218 #if Array_gather_stats
219 memory_in_use -=
sizeof(T) * size_;;
220 memory_returned +=
sizeof(T) * size_;;
241 void print(
const std::string& label)
243 printf(
"%s %d x %d \n", label.c_str(), nrows_, ncols_);
244 for (
int i = 0; i < nrows_; i++) {
246 for (
int j = 0; j < ncols_; j++) {
247 printf(
"%.16e", value(i,j));
260 void resize(
const int num_rows,
const int num_cols)
266 if ((num_rows <= 0) || (num_cols <= 0)) {
270 if (data_ !=
nullptr) {
271 if (data_reference_) {
272 throw std::runtime_error(
"[Array] Can't resize an Array with reference data.");
279 #if Array_gather_stats
280 memory_in_use -=
sizeof(T) * size_;;
281 memory_returned +=
sizeof(T) * size_;;
285 allocate(num_rows, num_cols);
295 return size_ *
sizeof(T);
305 if ((nrows_ > 0) || (ncols_ > 0)) {
312 void read(
const std::string& file_name)
314 auto fp = fopen(file_name.c_str(),
"rb");
316 fread(&size,
sizeof(
int), 1, fp);
317 fread(data_,
sizeof(
double), size, fp);
321 void write(
const std::string& label,
bool memory=
true, T offset={})
const
323 if (!write_enabled) {
327 auto file_prefix = build_file_prefix(label);
328 auto file_name = file_prefix +
"_cm.bin";
332 auto fp = fopen(file_name.c_str(),
"wb");
333 fwrite(&size_,
sizeof(
int), 1, fp);
334 fwrite(data_,
sizeof(T), size_, fp);
340 void append(
const std::string& label,
bool memory=
true, T offset={})
const
342 if (!write_enabled) {
346 auto file_prefix = build_file_prefix(label);
347 auto file_name = file_prefix +
"_cm.bin";
351 auto fp = fopen(file_name.c_str(),
"ab");
352 fwrite(data_,
sizeof(T), size_, fp);
356 const T& operator()(
const int i)
const
359 throw std::runtime_error(
"[Array(i)] Index " + std::to_string(i) +
" is out of bounds.");
364 T& operator()(
const int i)
367 throw std::runtime_error(
"[Array(i)] Index " + std::to_string(i) +
" is out of bounds.");
374 const T& operator()(
const int row,
const int col)
const
376 #ifdef Array_check_enabled
377 check_index(row, col);
379 return data_[row + col*nrows_];
382 T& operator()(
const int row,
const int col)
384 #ifdef Array_check_enabled
385 check_index(row, col);
387 return data_[row + col*nrows_];
392 Vector<T> col(
const int col,
const std::array<int,2>& range={-1,-1})
const
394 #ifdef Array_check_enabled
397 int start_row, end_row;
399 if (range[0] != -1) {
400 start_row = range[0];
402 #ifdef Array_check_enabled
403 check_index(start_row, col);
404 check_index(end_row, col);
412 for (
int row = start_row; row < end_row; row++) {
413 values[row] = value(row,col);
420 Vector<T> vector_col(nrows_, &data_[col*nrows_]);
426 T* col_data(
const int col) {
427 return &data_[col*nrows_];
436 for (
int i = 0; i < columns.size(); i++) {
438 #ifdef Array_check_enabled
449 Vector<T> row(
const int row,
const std::array<int,2>& range={-1,-1})
451 #ifdef Array_check_enabled
457 for (
int col = 0; col < ncols_; col++) {
458 values[col] = value(row,col);
468 #ifdef Array_check_enabled
474 for (
int i = 0; i < indexes.size(); i++) {
475 int col = indexes[i];
476 #ifdef Array_check_enabled
477 check_index(row, col);
479 values[i] = value(row,col);
487 Array<T> rows(
const int start_row,
const int end_row)
const
489 #ifdef Array_check_enabled
490 check_index(start_row, 0);
491 check_index(end_row, 0);
493 int num_rows = end_row - start_row + 1;
494 Array<T> values(num_rows, ncols_ );
496 for (
int row = 0; row < num_rows; row++) {
497 for (
int col = 0; col < ncols_; col++) {
498 values(row,col) = data_[(row+start_row) + col*nrows_];
506 Vector<T> rows(
const int start_row,
const int end_row,
const int col)
const
508 #ifdef Array_check_enabled
509 check_index(start_row, 0);
510 check_index(end_row, 0);
512 int num_rows = end_row - start_row + 1;
515 for (
int row = 0; row < num_rows; row++) {
516 values(row) = data_[(row+start_row) + col*nrows_];
523 std::vector<T> values(
const std::array<int,2>& rows,
const std::array<int,2>& cols,
const int stride=1)
const
525 std::vector<T> values;
527 for (
int i = rows[0]; i <= rows[1]; i += stride) {
528 for (
int j = cols[0]; j <= cols[1]; j += stride) {
529 values.push_back(value(i,j));
538 void set_col(
const int col,
const Vector<T>& values,
const std::array<int,2>& range={-1,-1})
540 #ifdef Array_check_enabled
543 int start_row, end_row;
545 if (range[0] != -1) {
546 start_row = range[0];
548 #ifdef Array_check_enabled
549 check_index(start_row, col);
550 check_index(end_row, col);
557 for (
int row = 0; row < values.size(); row++) {
558 data_[row + col*nrows_] = values[row];
564 void set_row(
const int row,
const Vector<T>& values)
const
566 #ifdef Array_check_enabled
569 for (
int col = 0; col < values.size(); col++) {
570 data_[row + col*nrows_] = values[col];
576 void set_row(
const int row, std::initializer_list<T> row_data)
const
578 auto it = row_data.begin();
579 for (
int col = 0; col < ncols_; col++, it++) {
580 data_[row + col*nrows_] = *it;
586 void set_row(
const int row,
const T value)
const
588 #ifdef Array_check_enabled
591 for (
int col = 0; col < ncols_; col++) {
592 data_[row + col*nrows_] = value;
598 void set_row(
const int row,
int offset,
const Vector<T>& values)
const
600 #ifdef Array_check_enabled
602 check_index(row, offset+values.size()-1);
604 for (
int col = 0; col < values.size(); col++) {
605 int ocol = col + offset;
606 #ifdef Array_check_enabled
607 check_index(row, ocol);
609 data_[row + ocol*nrows_] = values[col];
615 void set_rows(
const int start_row,
const int end_row,
const Array<T>& values)
const
617 #ifdef Array_check_enabled
618 check_index(start_row, 0);
619 check_index(end_row, 0);
621 int num_rows = end_row - start_row + 1;
623 if (ncols_ != values.ncols_) {
624 throw std::runtime_error(
"[Array set_rows] Arrays have different column sizes. ");
627 for (
int row = 0; row < num_rows; row++) {
628 for (
int col = 0; col < ncols_; col++) {
629 data_[(row+start_row) + col*nrows_] = values(row,col);;
641 for (
int i = 1; i < size_; i++) {
642 if (data_[i] > max_v) {
652 for (
int i = 1; i < size_; i++) {
653 if (data_[i] < min_v) {
662 Array<T> operator+(
const Array<T>& array)
const
664 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
665 throw std::runtime_error(
"[Array addition] Arrays have diffent shapes. ");
667 Array<T> result(nrows_, ncols_);
668 for (
int j = 0; j < ncols_; j++) {
669 for (
int i = 0; i < nrows_; i++) {
670 result(i, j) = data_[i + j*nrows_] + array(i,j);
678 Array<T> operator-(
const Array<T>& array)
const
680 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
681 throw std::runtime_error(
"[Array subtraction] Arrays have diffent shapes. ");
683 Array<T> result(nrows_, ncols_);
684 for (
int j = 0; j < ncols_; j++) {
685 for (
int i = 0; i < nrows_; i++) {
686 result(i, j) = data_[i + j*nrows_] - array(i,j);
695 Array<T> operator*(
const Array<T>& array)
const
697 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
698 throw std::runtime_error(
"[Array multiply] Arrays have diffent shapes. ");
701 Array<T> result(nrows_, ncols_);
703 for (
int j = 0; j < ncols_; j++) {
704 for (
int i = 0; i < nrows_; i++) {
705 result(i, j) = (*this)(i,j) * array(i,j);
715 Array<T> operator / (
const Array<T>& array)
const
717 Array<T> result(nrows_, array.ncols_);
718 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
719 throw std::runtime_error(
"[Array divide] Arrays number of columns or number of rows are not equal.");
722 for (
int j = 0; j < ncols_; j++) {
723 for (
int i = 0; i < nrows_; i++) {
724 result(i, j) = (*this)(i,j) / array(i,j);
732 Array<T> operator+=(
const Array<T>& array)
const
734 for (
int j = 0; j < ncols_; j++) {
735 for (
int i = 0; i < nrows_; i++) {
736 data_[i + j*nrows_] += array(i,j);
744 Array<T> operator-=(
const Array<T>& array)
const
746 for (
int j = 0; j < ncols_; j++) {
747 for (
int i = 0; i < nrows_; i++) {
748 data_[i + j*nrows_] -= array(i,j);
756 Array<T> operator*=(
const Array<T>& array)
const
758 for (
int j = 0; j < ncols_; j++) {
759 for (
int i = 0; i < nrows_; i++) {
760 data_[i + j*nrows_] *= array(i,j);
768 Array<T> operator*(
const T value)
const
770 Array<T> result(nrows_, ncols_);
771 for (
int j = 0; j < ncols_; j++) {
772 for (
int i = 0; i < nrows_; i++) {
773 result(i,j) = value * data_[i + j*nrows_];
779 friend const Array<T> operator*(
const T value,
const Array& rhs)
781 Array<T> result(rhs.nrows_, rhs.ncols_);
782 for (
int j = 0; j < rhs.ncols_; j++) {
783 for (
int i = 0; i < rhs.nrows_; i++) {
784 result(i,j) = value * rhs.data_[i + j*rhs.nrows_];
793 Array<T> operator / (
const T value)
const
796 throw std::runtime_error(+
"Array Divide by zero.");
798 Array<T> result(nrows_, ncols_);
799 for (
int j = 0; j < ncols_; j++) {
800 for (
int i = 0; i < nrows_; i++) {
801 result(i,j) = data_[i + j*nrows_] / value;
810 friend const Array<T> operator / (
const T value,
const Array& rhs)
812 Array<T> result(rhs.nrows_, rhs.ncols_);
813 for (
int j = 0; j < rhs.ncols_; j++) {
814 for (
int i = 0; i < rhs.nrows_; i++) {
815 result(i,j) = value / rhs.data_[i + j*rhs.nrows_];
824 Array<T> operator-(
const T value)
const
826 Array<T> result(nrows_, ncols_);
827 for (
int j = 0; j < ncols_; j++) {
828 for (
int i = 0; i < nrows_; i++) {
829 result(i,j) = data_[i + j*nrows_] - value;
837 Array<T> operator+=(
const T value)
const
839 for (
int j = 0; j < ncols_; j++) {
840 for (
int i = 0; i < nrows_; i++) {
841 data_[i + j*nrows_] += value;
849 Array<T> operator-()
const
851 Array<T> result(nrows_, ncols_);
852 for (
int j = 0; j < ncols_; j++) {
853 for (
int i = 0; i < nrows_; i++) {
854 result(i,j) = -(data_[i + j*nrows_]);
862 Array<T> operator-=(
const T value)
const
864 for (
int j = 0; j < ncols_; j++) {
865 for (
int i = 0; i < nrows_; i++) {
866 data_[i + j*nrows_] -= value;
875 friend const Array<T> operator-(
const T value,
const Array& rhs)
877 Array<T> result(rhs.nrows_, rhs.ncols_);
878 for (
int j = 0; j < rhs.ncols_; j++) {
879 for (
int i = 0; i < rhs.nrows_; i++) {
880 result(i,j) = value - rhs.data_[i + j*rhs.nrows_];
888 friend Array<T> abs(
const Array& rhs)
890 Array<T> result(rhs.nrows_, rhs.ncols_);
891 for (
int j = 0; j < rhs.ncols_; j++) {
892 for (
int i = 0; i < rhs.nrows_; i++) {
893 result(i,j) = fabs(rhs.data_[i + j*rhs.nrows_]);
901 friend T max(
const Array& arg)
903 T max_v = arg.data_[0];
904 for (
int i = 1; i < arg.size_; i++) {
905 if (arg.data_[i] > max_v) {
906 max_v = arg.data_[i];
914 friend Array<T> sqrt(
const Array& arg)
916 Array<T> result(arg.nrows_, arg.ncols_);
917 for (
int j = 0; j < arg.ncols_; j++) {
918 for (
int i = 0; i < arg.nrows_; i++) {
919 result(i,j) = sqrt(arg.data_[i + j*arg.nrows_]);
927 T sum_row(
const int row)
const
929 #ifdef Array_check_enabled
933 for (
int col = 0; col < ncols_; col++) {
934 sum += data_[row + col*nrows_];
947 void allocate(
const int num_rows,
const int num_cols)
949 data_reference_ =
false;
952 size_ = nrows_ * ncols_;
953 #if Array_gather_stats
954 memory_in_use +=
sizeof(T)*size_;
957 if (data_ !=
nullptr) {
962 data_ =
new T [size_];
963 memset(data_, 0,
sizeof(T)*size_);
969 inline T value(
const int row,
const int col)
const
971 return data_[row + col*nrows_];
974 void check_index(
const int row,
const int col)
const
976 if (show_index_check_message) {
977 std::cout <<
"[Array] **********************************" << std::endl;
978 std::cout <<
"[Array] WARNING: Index checking is enabled " << std::endl;
979 std::cout <<
"[Array] **********************************" << std::endl;
980 show_index_check_message =
false;
983 if (data_ ==
nullptr) {
987 if ((row < 0) || (row >= nrows_) || (col < 0) || (col >= ncols_)) {
988 auto nr_str = std::to_string(nrows_);
989 auto nc_str = std::to_string(ncols_);
990 auto dims = nr_str +
" x " + nc_str;
991 auto index_str =
" " + std::to_string(row) +
"," + std::to_string(col) +
" ";
992 throw std::runtime_error(+
"Index (row,col)=" + index_str +
" is out of bounds for " +
1004 bool data_reference_ =
false;
The Vector template class is used for storing int and double data.
Definition Vector.h:50