20#ifdef ENABLE_ARRAY_INDEX_CHECKING
21#define Array_check_enabled
32 static int num_allocated;
34 static bool show_index_check_message;
35 static double memory_in_use;
36 static double memory_returned;
37 static void memory(
const std::string& prefix=
"");
38 static void stats(
const std::string& prefix=
"");
39 static bool write_enabled;
52 Array(
const int num_rows,
const int num_cols)
58 if ((num_rows <= 0) || (num_cols <= 0)) {
62 allocate(num_rows, num_cols);
67 Array(
const int num_rows,
const int num_cols, T* data)
69 data_reference_ =
true;
72 size_ = nrows_ * ncols_;
76 Array(std::initializer_list<std::initializer_list<T>> lst)
81 for (
auto &row : lst) {
84 num_cols = row.size();
85 }
else if (row.size() != num_cols) {
86 throw std::runtime_error(
"[Array initializer_list ctor] Column data is of unequal size.");
90 allocate(num_rows, num_cols);
94 for (
auto &row_data : lst) {
95 auto it = row_data.begin();
96 for (
int col = 0; col < row_data.size(); col++, it++) {
97 data_[row + col*nrows_] = *it;
108 Array(
const Array &rhs)
110 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0)) {
114 allocate(rhs.nrows_, rhs.ncols_);
116 memcpy(data_, rhs.data_, size_*
sizeof(T));
123 Array& operator=(
const Array& rhs)
129 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0)) {
133 if ((nrows_ != rhs.nrows_) || (ncols_ != rhs.ncols_)) {
135 allocate(rhs.nrows_, rhs.ncols_);
138 memcpy(data_, rhs.data_,
sizeof(T) * size_);
142 Array& operator=(
const double value)
144 for (
int i = 0; i < size_; i++) {
152 if (data_ !=
nullptr) {
153 #if Array_gather_stats
154 memory_in_use -=
sizeof(T)*size_;
155 memory_returned +=
sizeof(T)*size_;
158 if (!data_reference_) {
169 friend std::ostream& operator << (std::ostream& out,
const Array<T>& lhs)
171 for (
int i = 0; i < lhs.size(); i++) {
173 if (i != lhs.size()-1) {
186 if (data_ !=
nullptr) {
187 if (data_reference_) {
188 throw std::runtime_error(
"[Array] Can't clear an Array with reference data.");
191 #if Array_gather_stats
192 memory_in_use -=
sizeof(T) * size_;;
193 memory_returned +=
sizeof(T) * size_;;
214 void print(
const std::string& label)
216 printf(
"%s %d x %d \n", label.c_str(), nrows_, ncols_);
217 for (
int i = 0; i < nrows_; i++) {
219 for (
int j = 0; j < ncols_; j++) {
220 printf(
"%.16e", value(i,j));
233 void resize(
const int num_rows,
const int num_cols)
239 if ((num_rows <= 0) || (num_cols <= 0)) {
243 if (data_ !=
nullptr) {
244 if (data_reference_) {
245 throw std::runtime_error(
"[Array] Can't resize an Array with reference data.");
252 #if Array_gather_stats
253 memory_in_use -=
sizeof(T) * size_;;
254 memory_returned +=
sizeof(T) * size_;;
258 allocate(num_rows, num_cols);
268 return size_ *
sizeof(T);
278 if ((nrows_ > 0) || (ncols_ > 0)) {
285 void read(
const std::string& file_name)
287 auto fp = fopen(file_name.c_str(),
"rb");
289 fread(&size,
sizeof(
int), 1, fp);
290 fread(data_,
sizeof(
double), size, fp);
294 void write(
const std::string& label,
bool memory=
true, T offset={})
const
296 if (!write_enabled) {
300 auto file_prefix = build_file_prefix(label);
301 auto file_name = file_prefix +
"_cm.bin";
305 auto fp = fopen(file_name.c_str(),
"wb");
306 fwrite(&size_,
sizeof(
int), 1, fp);
307 fwrite(data_,
sizeof(T), size_, fp);
313 void append(
const std::string& label,
bool memory=
true, T offset={})
const
315 if (!write_enabled) {
319 auto file_prefix = build_file_prefix(label);
320 auto file_name = file_prefix +
"_cm.bin";
324 auto fp = fopen(file_name.c_str(),
"ab");
325 fwrite(data_,
sizeof(T), size_, fp);
329 const T& operator()(
const int i)
const
332 throw std::runtime_error(
"[Array(i)] Index " + std::to_string(i) +
" is out of bounds.");
337 T& operator()(
const int i)
340 throw std::runtime_error(
"[Array(i)] Index " + std::to_string(i) +
" is out of bounds.");
347 const T& operator()(
const int row,
const int col)
const
349 #ifdef Array_check_enabled
350 check_index(row, col);
352 return data_[row + col*nrows_];
355 T& operator()(
const int row,
const int col)
357 #ifdef Array_check_enabled
358 check_index(row, col);
360 return data_[row + col*nrows_];
365 Vector<T> col(
const int col,
const std::array<int,2>& range={-1,-1})
const
367 #ifdef Array_check_enabled
370 int start_row, end_row;
372 if (range[0] != -1) {
373 start_row = range[0];
375 #ifdef Array_check_enabled
376 check_index(start_row, col);
377 check_index(end_row, col);
385 for (
int row = start_row; row < end_row; row++) {
386 values[row] = value(row,col);
393 Vector<T> vector_col(nrows_, &data_[col*nrows_]);
399 T* col_data(
const int col) {
400 return &data_[col*nrows_];
409 for (
int i = 0; i < columns.size(); i++) {
411 #ifdef Array_check_enabled
422 Vector<T> row(
const int row,
const std::array<int,2>& range={-1,-1})
424 #ifdef Array_check_enabled
430 for (
int col = 0; col < ncols_; col++) {
431 values[col] = value(row,col);
441 #ifdef Array_check_enabled
447 for (
int i = 0; i < indexes.size(); i++) {
448 int col = indexes[i];
449 #ifdef Array_check_enabled
450 check_index(row, col);
452 values[i] = value(row,col);
460 Array<T> rows(
const int start_row,
const int end_row)
const
462 #ifdef Array_check_enabled
463 check_index(start_row, 0);
464 check_index(end_row, 0);
466 int num_rows = end_row - start_row + 1;
467 Array<T> values(num_rows, ncols_ );
469 for (
int row = 0; row < num_rows; row++) {
470 for (
int col = 0; col < ncols_; col++) {
471 values(row,col) = data_[(row+start_row) + col*nrows_];
479 Vector<T> rows(
const int start_row,
const int end_row,
const int col)
const
481 #ifdef Array_check_enabled
482 check_index(start_row, 0);
483 check_index(end_row, 0);
485 int num_rows = end_row - start_row + 1;
488 for (
int row = 0; row < num_rows; row++) {
489 values(row) = data_[(row+start_row) + col*nrows_];
496 std::vector<T> values(
const std::array<int,2>& rows,
const std::array<int,2>& cols,
const int stride=1)
const
498 std::vector<T> values;
500 for (
int i = rows[0]; i <= rows[1]; i += stride) {
501 for (
int j = cols[0]; j <= cols[1]; j += stride) {
502 values.push_back(value(i,j));
511 void set_col(
const int col,
const Vector<T>& values,
const std::array<int,2>& range={-1,-1})
513 #ifdef Array_check_enabled
516 int start_row, end_row;
518 if (range[0] != -1) {
519 start_row = range[0];
521 #ifdef Array_check_enabled
522 check_index(start_row, col);
523 check_index(end_row, col);
530 for (
int row = 0; row < values.size(); row++) {
531 data_[row + col*nrows_] = values[row];
537 void set_row(
const int row,
const Vector<T>& values)
const
539 #ifdef Array_check_enabled
542 for (
int col = 0; col < values.size(); col++) {
543 data_[row + col*nrows_] = values[col];
549 void set_row(
const int row, std::initializer_list<T> row_data)
const
551 auto it = row_data.begin();
552 for (
int col = 0; col < ncols_; col++, it++) {
553 data_[row + col*nrows_] = *it;
559 void set_row(
const int row,
const T value)
const
561 #ifdef Array_check_enabled
564 for (
int col = 0; col < ncols_; col++) {
565 data_[row + col*nrows_] = value;
571 void set_row(
const int row,
int offset,
const Vector<T>& values)
const
573 #ifdef Array_check_enabled
575 check_index(row, offset+values.size()-1);
577 for (
int col = 0; col < values.size(); col++) {
578 int ocol = col + offset;
579 #ifdef Array_check_enabled
580 check_index(row, ocol);
582 data_[row + ocol*nrows_] = values[col];
588 void set_rows(
const int start_row,
const int end_row,
const Array<T>& values)
const
590 #ifdef Array_check_enabled
591 check_index(start_row, 0);
592 check_index(end_row, 0);
594 int num_rows = end_row - start_row + 1;
596 if (ncols_ != values.ncols_) {
597 throw std::runtime_error(
"[Array set_rows] Arrays have different column sizes. ");
600 for (
int row = 0; row < num_rows; row++) {
601 for (
int col = 0; col < ncols_; col++) {
602 data_[(row+start_row) + col*nrows_] = values(row,col);;
614 for (
int i = 1; i < size_; i++) {
615 if (data_[i] > max_v) {
625 for (
int i = 1; i < size_; i++) {
626 if (data_[i] < min_v) {
635 Array<T> operator+(
const Array<T>& array)
const
637 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
638 throw std::runtime_error(
"[Array addition] Arrays have diffent shapes. ");
640 Array<T> result(nrows_, ncols_);
641 for (
int j = 0; j < ncols_; j++) {
642 for (
int i = 0; i < nrows_; i++) {
643 result(i, j) = data_[i + j*nrows_] + array(i,j);
651 Array<T> operator-(
const Array<T>& array)
const
653 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
654 throw std::runtime_error(
"[Array subtraction] Arrays have diffent shapes. ");
656 Array<T> result(nrows_, ncols_);
657 for (
int j = 0; j < ncols_; j++) {
658 for (
int i = 0; i < nrows_; i++) {
659 result(i, j) = data_[i + j*nrows_] - array(i,j);
668 Array<T> operator*(
const Array<T>& array)
const
670 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
671 throw std::runtime_error(
"[Array multiply] Arrays have diffent shapes. ");
674 Array<T> result(nrows_, ncols_);
676 for (
int j = 0; j < ncols_; j++) {
677 for (
int i = 0; i < nrows_; i++) {
678 result(i, j) = (*this)(i,j) * array(i,j);
688 Array<T> operator / (
const Array<T>& array)
const
690 Array<T> result(nrows_, array.ncols_);
691 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
692 throw std::runtime_error(
"[Array divide] Arrays number of columns or number of rows are not equal.");
695 for (
int j = 0; j < ncols_; j++) {
696 for (
int i = 0; i < nrows_; i++) {
697 result(i, j) = (*this)(i,j) / array(i,j);
705 Array<T> operator+=(
const Array<T>& array)
const
707 for (
int j = 0; j < ncols_; j++) {
708 for (
int i = 0; i < nrows_; i++) {
709 data_[i + j*nrows_] += array(i,j);
717 Array<T> operator-=(
const Array<T>& array)
const
719 for (
int j = 0; j < ncols_; j++) {
720 for (
int i = 0; i < nrows_; i++) {
721 data_[i + j*nrows_] -= array(i,j);
729 Array<T> operator*=(
const Array<T>& array)
const
731 for (
int j = 0; j < ncols_; j++) {
732 for (
int i = 0; i < nrows_; i++) {
733 data_[i + j*nrows_] *= array(i,j);
741 Array<T> operator*(
const T value)
const
743 Array<T> result(nrows_, ncols_);
744 for (
int j = 0; j < ncols_; j++) {
745 for (
int i = 0; i < nrows_; i++) {
746 result(i,j) = value * data_[i + j*nrows_];
752 friend const Array<T> operator*(
const T value,
const Array& rhs)
754 Array<T> result(rhs.nrows_, rhs.ncols_);
755 for (
int j = 0; j < rhs.ncols_; j++) {
756 for (
int i = 0; i < rhs.nrows_; i++) {
757 result(i,j) = value * rhs.data_[i + j*rhs.nrows_];
766 Array<T> operator / (
const T value)
const
769 throw std::runtime_error(+
"Array Divide by zero.");
771 Array<T> result(nrows_, ncols_);
772 for (
int j = 0; j < ncols_; j++) {
773 for (
int i = 0; i < nrows_; i++) {
774 result(i,j) = data_[i + j*nrows_] / value;
783 friend const Array<T> operator / (
const T value,
const Array& rhs)
785 Array<T> result(rhs.nrows_, rhs.ncols_);
786 for (
int j = 0; j < rhs.ncols_; j++) {
787 for (
int i = 0; i < rhs.nrows_; i++) {
788 result(i,j) = value / rhs.data_[i + j*rhs.nrows_];
797 Array<T> operator-(
const T value)
const
799 Array<T> result(nrows_, ncols_);
800 for (
int j = 0; j < ncols_; j++) {
801 for (
int i = 0; i < nrows_; i++) {
802 result(i,j) = data_[i + j*nrows_] - value;
810 Array<T> operator+=(
const T value)
const
812 for (
int j = 0; j < ncols_; j++) {
813 for (
int i = 0; i < nrows_; i++) {
814 data_[i + j*nrows_] += value;
822 Array<T> operator-()
const
824 Array<T> result(nrows_, ncols_);
825 for (
int j = 0; j < ncols_; j++) {
826 for (
int i = 0; i < nrows_; i++) {
827 result(i,j) = -(data_[i + j*nrows_]);
835 Array<T> operator-=(
const T value)
const
837 for (
int j = 0; j < ncols_; j++) {
838 for (
int i = 0; i < nrows_; i++) {
839 data_[i + j*nrows_] -= value;
848 friend const Array<T> operator-(
const T value,
const Array& rhs)
850 Array<T> result(rhs.nrows_, rhs.ncols_);
851 for (
int j = 0; j < rhs.ncols_; j++) {
852 for (
int i = 0; i < rhs.nrows_; i++) {
853 result(i,j) = value - rhs.data_[i + j*rhs.nrows_];
861 friend Array<T> abs(
const Array& rhs)
863 Array<T> result(rhs.nrows_, rhs.ncols_);
864 for (
int j = 0; j < rhs.ncols_; j++) {
865 for (
int i = 0; i < rhs.nrows_; i++) {
866 result(i,j) = fabs(rhs.data_[i + j*rhs.nrows_]);
874 friend T max(
const Array& arg)
876 T max_v = arg.data_[0];
877 for (
int i = 1; i < arg.size_; i++) {
878 if (arg.data_[i] > max_v) {
879 max_v = arg.data_[i];
887 friend Array<T> sqrt(
const Array& arg)
889 Array<T> result(arg.nrows_, arg.ncols_);
890 for (
int j = 0; j < arg.ncols_; j++) {
891 for (
int i = 0; i < arg.nrows_; i++) {
892 result(i,j) = sqrt(arg.data_[i + j*arg.nrows_]);
900 T sum_row(
const int row)
const
902 #ifdef Array_check_enabled
906 for (
int col = 0; col < ncols_; col++) {
907 sum += data_[row + col*nrows_];
920 void allocate(
const int num_rows,
const int num_cols)
922 data_reference_ =
false;
925 size_ = nrows_ * ncols_;
926 #if Array_gather_stats
927 memory_in_use +=
sizeof(T)*size_;
930 if (data_ !=
nullptr) {
935 data_ =
new T [size_];
936 memset(data_, 0,
sizeof(T)*size_);
942 inline T value(
const int row,
const int col)
const
944 return data_[row + col*nrows_];
947 void check_index(
const int row,
const int col)
const
949 if (show_index_check_message) {
950 std::cout <<
"[Array] **********************************" << std::endl;
951 std::cout <<
"[Array] WARNING: Index checking is enabled " << std::endl;
952 std::cout <<
"[Array] **********************************" << std::endl;
953 show_index_check_message =
false;
956 if (data_ ==
nullptr) {
960 if ((row < 0) || (row >= nrows_) || (col < 0) || (col >= ncols_)) {
961 auto nr_str = std::to_string(nrows_);
962 auto nc_str = std::to_string(ncols_);
963 auto dims = nr_str +
" x " + nc_str;
964 auto index_str =
" " + std::to_string(row) +
"," + std::to_string(col) +
" ";
965 throw std::runtime_error(+
"Index (row,col)=" + index_str +
" is out of bounds for " +
977 bool data_reference_ =
false;
The Vector template class is used for storing int and double data.
Definition Vector.h:23