20#ifdef ENABLE_ARRAY_INDEX_CHECKING
21#define Array_check_enabled
32 static int num_allocated;
34 static double memory_in_use;
35 static double memory_returned;
36 static void memory(
const std::string& prefix=
"");
37 static void stats(
const std::string& prefix=
"");
38 static bool write_enabled;
51 Array(
const int num_rows,
const int num_cols)
57 if ((num_rows <= 0) || (num_cols <= 0)) {
61 allocate(num_rows, num_cols);
66 Array(
const int num_rows,
const int num_cols, T* data)
68 data_reference_ =
true;
71 size_ = nrows_ * ncols_;
75 Array(std::initializer_list<std::initializer_list<T>> lst)
80 for (
auto &row : lst) {
83 num_cols = row.size();
84 }
else if (row.size() != num_cols) {
85 throw std::runtime_error(
"[Array initializer_list ctor] Column data is of unequal size.");
89 allocate(num_rows, num_cols);
93 for (
auto &row_data : lst) {
94 auto it = row_data.begin();
95 for (
int col = 0; col < row_data.size(); col++, it++) {
96 data_[row + col*nrows_] = *it;
107 Array(
const Array &rhs)
109 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0)) {
113 allocate(rhs.nrows_, rhs.ncols_);
115 memcpy(data_, rhs.data_, size_*
sizeof(T));
122 Array& operator=(
const Array& rhs)
128 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0)) {
132 if ((nrows_ != rhs.nrows_) || (ncols_ != rhs.ncols_)) {
134 allocate(rhs.nrows_, rhs.ncols_);
137 memcpy(data_, rhs.data_,
sizeof(T) * size_);
141 Array& operator=(
const double value)
143 for (
int i = 0; i < size_; i++) {
151 if (data_ !=
nullptr) {
152 #if Array_gather_stats
153 memory_in_use -=
sizeof(T)*size_;
154 memory_returned +=
sizeof(T)*size_;
157 if (!data_reference_) {
168 friend std::ostream& operator << (std::ostream& out,
const Array<T>& lhs)
170 for (
int i = 0; i < lhs.size(); i++) {
172 if (i != lhs.size()-1) {
185 if (data_ !=
nullptr) {
186 if (data_reference_) {
187 throw std::runtime_error(
"[Array] Can't clear an Array with reference data.");
190 #if Array_gather_stats
191 memory_in_use -=
sizeof(T) * size_;;
192 memory_returned +=
sizeof(T) * size_;;
213 void print(
const std::string& label)
215 printf(
"%s %d x %d \n", label.c_str(), nrows_, ncols_);
216 for (
int i = 0; i < nrows_; i++) {
218 for (
int j = 0; j < ncols_; j++) {
219 printf(
"%.16e", value(i,j));
232 void resize(
const int num_rows,
const int num_cols)
238 if ((num_rows <= 0) || (num_cols <= 0)) {
242 if (data_ !=
nullptr) {
243 if (data_reference_) {
244 throw std::runtime_error(
"[Array] Can't resize an Array with reference data.");
251 #if Array_gather_stats
252 memory_in_use -=
sizeof(T) * size_;;
253 memory_returned +=
sizeof(T) * size_;;
257 allocate(num_rows, num_cols);
267 return size_ *
sizeof(T);
277 if ((nrows_ > 0) || (ncols_ > 0)) {
284 void read(
const std::string& file_name)
286 auto fp = fopen(file_name.c_str(),
"rb");
288 fread(&size,
sizeof(
int), 1, fp);
289 fread(data_,
sizeof(
double), size, fp);
293 void write(
const std::string& label,
bool memory=
true, T offset={})
const
295 if (!write_enabled) {
299 auto file_prefix = build_file_prefix(label);
300 auto file_name = file_prefix +
"_cm.bin";
304 auto fp = fopen(file_name.c_str(),
"wb");
305 fwrite(&size_,
sizeof(
int), 1, fp);
306 fwrite(data_,
sizeof(T), size_, fp);
312 void append(
const std::string& label,
bool memory=
true, T offset={})
const
314 if (!write_enabled) {
318 auto file_prefix = build_file_prefix(label);
319 auto file_name = file_prefix +
"_cm.bin";
323 auto fp = fopen(file_name.c_str(),
"ab");
324 fwrite(data_,
sizeof(T), size_, fp);
328 const T& operator()(
const int i)
const
331 throw std::runtime_error(
"[Array(i)] Index " + std::to_string(i) +
" is out of bounds.");
336 T& operator()(
const int i)
339 throw std::runtime_error(
"[Array(i)] Index " + std::to_string(i) +
" is out of bounds.");
346 const T& operator()(
const int row,
const int col)
const
348 #ifdef Array_check_enabled
349 check_index(row, col);
351 return data_[row + col*nrows_];
354 T& operator()(
const int row,
const int col)
356 #ifdef Array_check_enabled
357 check_index(row, col);
359 return data_[row + col*nrows_];
364 Vector<T> col(
const int col,
const std::array<int,2>& range={-1,-1})
const
366 #ifdef Array_check_enabled
369 int start_row, end_row;
371 if (range[0] != -1) {
372 start_row = range[0];
374 #ifdef Array_check_enabled
375 check_index(start_row, col);
376 check_index(end_row, col);
384 for (
int row = start_row; row < end_row; row++) {
385 values[row] = value(row,col);
392 Vector<T> vector_col(nrows_, &data_[col*nrows_]);
398 T* col_data(
const int col) {
399 return &data_[col*nrows_];
408 for (
int i = 0; i < columns.size(); i++) {
410 #ifdef Array_check_enabled
421 Vector<T> row(
const int row,
const std::array<int,2>& range={-1,-1})
423 #ifdef Array_check_enabled
429 for (
int col = 0; col < ncols_; col++) {
430 values[col] = value(row,col);
440 #ifdef Array_check_enabled
446 for (
int i = 0; i < indexes.size(); i++) {
447 int col = indexes[i];
448 #ifdef Array_check_enabled
449 check_index(row, col);
451 values[i] = value(row,col);
459 Array<T> rows(
const int start_row,
const int end_row)
const
461 #ifdef Array_check_enabled
462 check_index(start_row, 0);
463 check_index(end_row, 0);
465 int num_rows = end_row - start_row + 1;
466 Array<T> values(num_rows, ncols_ );
468 for (
int row = 0; row < num_rows; row++) {
469 for (
int col = 0; col < ncols_; col++) {
470 values(row,col) = data_[(row+start_row) + col*nrows_];
478 Vector<T> rows(
const int start_row,
const int end_row,
const int col)
const
480 #ifdef Array_check_enabled
481 check_index(start_row, 0);
482 check_index(end_row, 0);
484 int num_rows = end_row - start_row + 1;
487 for (
int row = 0; row < num_rows; row++) {
488 values(row) = data_[(row+start_row) + col*nrows_];
495 std::vector<T> values(
const std::array<int,2>& rows,
const std::array<int,2>& cols,
const int stride=1)
const
497 std::vector<T> values;
499 for (
int i = rows[0]; i <= rows[1]; i += stride) {
500 for (
int j = cols[0]; j <= cols[1]; j += stride) {
501 values.push_back(value(i,j));
510 void set_col(
const int col,
const Vector<T>& values,
const std::array<int,2>& range={-1,-1})
512 #ifdef Array_check_enabled
515 int start_row, end_row;
517 if (range[0] != -1) {
518 start_row = range[0];
520 #ifdef Array_check_enabled
521 check_index(start_row, col);
522 check_index(end_row, col);
529 for (
int row = 0; row < values.size(); row++) {
530 data_[row + col*nrows_] = values[row];
536 void set_row(
const int row,
const Vector<T>& values)
const
538 #ifdef Array_check_enabled
541 for (
int col = 0; col < values.size(); col++) {
542 data_[row + col*nrows_] = values[col];
548 void set_row(
const int row, std::initializer_list<T> row_data)
const
550 auto it = row_data.begin();
551 for (
int col = 0; col < ncols_; col++, it++) {
552 data_[row + col*nrows_] = *it;
558 void set_row(
const int row,
const T value)
const
560 #ifdef Array_check_enabled
563 for (
int col = 0; col < ncols_; col++) {
564 data_[row + col*nrows_] = value;
570 void set_row(
const int row,
int offset,
const Vector<T>& values)
const
572 #ifdef Array_check_enabled
574 check_index(row, offset+values.size()-1);
576 for (
int col = 0; col < values.size(); col++) {
577 int ocol = col + offset;
578 #ifdef Array_check_enabled
579 check_index(row, ocol);
581 data_[row + ocol*nrows_] = values[col];
587 void set_rows(
const int start_row,
const int end_row,
const Array<T>& values)
const
589 #ifdef Array_check_enabled
590 check_index(start_row, 0);
591 check_index(end_row, 0);
593 int num_rows = end_row - start_row + 1;
595 if (ncols_ != values.ncols_) {
596 throw std::runtime_error(
"[Array set_rows] Arrays have different column sizes. ");
599 for (
int row = 0; row < num_rows; row++) {
600 for (
int col = 0; col < ncols_; col++) {
601 data_[(row+start_row) + col*nrows_] = values(row,col);;
613 for (
int i = 1; i < size_; i++) {
614 if (data_[i] > max_v) {
624 for (
int i = 1; i < size_; i++) {
625 if (data_[i] < min_v) {
634 Array<T> operator+(
const Array<T>& array)
const
636 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
637 throw std::runtime_error(
"[Array addition] Arrays have diffent shapes. ");
639 Array<T> result(nrows_, ncols_);
640 for (
int j = 0; j < ncols_; j++) {
641 for (
int i = 0; i < nrows_; i++) {
642 result(i, j) = data_[i + j*nrows_] + array(i,j);
650 Array<T> operator-(
const Array<T>& array)
const
652 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
653 throw std::runtime_error(
"[Array subtraction] Arrays have diffent shapes. ");
655 Array<T> result(nrows_, ncols_);
656 for (
int j = 0; j < ncols_; j++) {
657 for (
int i = 0; i < nrows_; i++) {
658 result(i, j) = data_[i + j*nrows_] - array(i,j);
667 Array<T> operator*(
const Array<T>& array)
const
669 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
670 throw std::runtime_error(
"[Array multiply] Arrays have diffent shapes. ");
673 Array<T> result(nrows_, ncols_);
675 for (
int j = 0; j < ncols_; j++) {
676 for (
int i = 0; i < nrows_; i++) {
677 result(i, j) = (*this)(i,j) * array(i,j);
687 Array<T> operator / (
const Array<T>& array)
const
689 Array<T> result(nrows_, array.ncols_);
690 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
691 throw std::runtime_error(
"[Array divide] Arrays number of columns or number of rows are not equal.");
694 for (
int j = 0; j < ncols_; j++) {
695 for (
int i = 0; i < nrows_; i++) {
696 result(i, j) = (*this)(i,j) / array(i,j);
704 Array<T> operator+=(
const Array<T>& array)
const
706 for (
int j = 0; j < ncols_; j++) {
707 for (
int i = 0; i < nrows_; i++) {
708 data_[i + j*nrows_] += array(i,j);
716 Array<T> operator-=(
const Array<T>& array)
const
718 for (
int j = 0; j < ncols_; j++) {
719 for (
int i = 0; i < nrows_; i++) {
720 data_[i + j*nrows_] -= array(i,j);
728 Array<T> operator*=(
const Array<T>& array)
const
730 for (
int j = 0; j < ncols_; j++) {
731 for (
int i = 0; i < nrows_; i++) {
732 data_[i + j*nrows_] *= array(i,j);
740 Array<T> operator*(
const T value)
const
742 Array<T> result(nrows_, ncols_);
743 for (
int j = 0; j < ncols_; j++) {
744 for (
int i = 0; i < nrows_; i++) {
745 result(i,j) = value * data_[i + j*nrows_];
751 friend const Array<T> operator*(
const T value,
const Array& rhs)
753 Array<T> result(rhs.nrows_, rhs.ncols_);
754 for (
int j = 0; j < rhs.ncols_; j++) {
755 for (
int i = 0; i < rhs.nrows_; i++) {
756 result(i,j) = value * rhs.data_[i + j*rhs.nrows_];
765 Array<T> operator / (
const T value)
const
768 throw std::runtime_error(+
"Array Divide by zero.");
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) = data_[i + j*nrows_] / value;
782 friend const Array<T> operator / (
const T value,
const Array& rhs)
784 Array<T> result(rhs.nrows_, rhs.ncols_);
785 for (
int j = 0; j < rhs.ncols_; j++) {
786 for (
int i = 0; i < rhs.nrows_; i++) {
787 result(i,j) = value / rhs.data_[i + j*rhs.nrows_];
796 Array<T> operator-(
const T value)
const
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;
809 Array<T> operator+=(
const T value)
const
811 for (
int j = 0; j < ncols_; j++) {
812 for (
int i = 0; i < nrows_; i++) {
813 data_[i + j*nrows_] += value;
821 Array<T> operator-()
const
823 Array<T> result(nrows_, ncols_);
824 for (
int j = 0; j < ncols_; j++) {
825 for (
int i = 0; i < nrows_; i++) {
826 result(i,j) = -(data_[i + j*nrows_]);
834 Array<T> operator-=(
const T value)
const
836 for (
int j = 0; j < ncols_; j++) {
837 for (
int i = 0; i < nrows_; i++) {
838 data_[i + j*nrows_] -= value;
847 friend const Array<T> operator-(
const T value,
const Array& rhs)
849 Array<T> result(rhs.nrows_, rhs.ncols_);
850 for (
int j = 0; j < rhs.ncols_; j++) {
851 for (
int i = 0; i < rhs.nrows_; i++) {
852 result(i,j) = value - rhs.data_[i + j*rhs.nrows_];
860 friend Array<T> abs(
const Array& rhs)
862 Array<T> result(rhs.nrows_, rhs.ncols_);
863 for (
int j = 0; j < rhs.ncols_; j++) {
864 for (
int i = 0; i < rhs.nrows_; i++) {
865 result(i,j) = fabs(rhs.data_[i + j*rhs.nrows_]);
873 friend T max(
const Array& arg)
875 T max_v = arg.data_[0];
876 for (
int i = 1; i < arg.size_; i++) {
877 if (arg.data_[i] > max_v) {
878 max_v = arg.data_[i];
886 friend Array<T> sqrt(
const Array& arg)
888 Array<T> result(arg.nrows_, arg.ncols_);
889 for (
int j = 0; j < arg.ncols_; j++) {
890 for (
int i = 0; i < arg.nrows_; i++) {
891 result(i,j) = sqrt(arg.data_[i + j*arg.nrows_]);
899 T sum_row(
const int row)
const
901 #ifdef Array_check_enabled
905 for (
int col = 0; col < ncols_; col++) {
906 sum += data_[row + col*nrows_];
919 void allocate(
const int num_rows,
const int num_cols)
921 data_reference_ =
false;
924 size_ = nrows_ * ncols_;
925 #if Array_gather_stats
926 memory_in_use +=
sizeof(T)*size_;
929 if (data_ !=
nullptr) {
934 data_ =
new T [size_];
935 memset(data_, 0,
sizeof(T)*size_);
941 inline T value(
const int row,
const int col)
const
943 return data_[row + col*nrows_];
946 void check_index(
const int row,
const int col)
const
948 if (data_ ==
nullptr) {
952 if ((row < 0) || (row >= nrows_) || (col < 0) || (col >= ncols_)) {
953 auto nr_str = std::to_string(nrows_);
954 auto nc_str = std::to_string(ncols_);
955 auto dims = nr_str +
" x " + nc_str;
956 auto index_str =
" " + std::to_string(row) +
"," + std::to_string(col) +
" ";
957 throw std::runtime_error(+
"Index (row,col)=" + index_str +
" is out of bounds for " +
969 bool data_reference_ =
false;
The Vector template class is used for storing int and double data.
Definition Vector.h:23