svMultiPhysics
Loading...
Searching...
No Matches
Array.h
1// SPDX-FileCopyrightText: Copyright (c) Stanford University, The Regents of the University of California, and others.
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include "Vector.h"
5#include "utils.h"
6
7#ifndef ARRAY_H
8#define ARRAY_H
9
10#include <algorithm>
11#include <array>
12#include <cstring>
13#include <float.h>
14#include <iostream>
15#include <math.h>
16#include <vector>
17
18// If set then check Array indexes.
19//
20#ifdef ENABLE_ARRAY_INDEX_CHECKING
21#define Array_check_enabled
22#endif
23
24/// @brief The Array template class implements a simple interface to 2D arrays.
25//
26template<typename T>
27class Array
28{
29 public:
30 // Some variables used to monitor Array object allocation.
31 static int id;
32 static int num_allocated;
33 static int active;
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;
39
40 Array()
41 {
42 id += 1;
43 nrows_ = 0;
44 ncols_ = 0;
45 size_ = 0;
46 data_ = nullptr;
47 num_allocated += 1;
48 active += 1;
49 };
50
51 Array(const int num_rows, const int num_cols)
52 {
53 // [NOTE] This is tfu but need to mimic fortran.
54 nrows_ = num_rows;
55 ncols_ = num_cols;
56
57 if ((num_rows <= 0) || (num_cols <= 0)) {
58 return;
59 }
60
61 allocate(num_rows, num_cols);
62 num_allocated += 1;
63 active += 1;
64 }
65
66 Array(const int num_rows, const int num_cols, T* data)
67 {
68 data_reference_ = true;
69 nrows_ = num_rows;
70 ncols_ = num_cols;
71 size_ = nrows_ * ncols_;
72 data_ = data;
73 }
74
75 Array(std::initializer_list<std::initializer_list<T>> lst)
76 {
77 int num_rows = 0;
78 int num_cols = 0;
79
80 for (auto &row : lst) {
81 num_rows += 1;
82 if (num_cols == 0) {
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.");
86 }
87 }
88
89 allocate(num_rows, num_cols);
90
91 int row = 0;
92
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;
97 }
98 row += 1;
99 }
100
101 num_allocated += 1;
102 active += 1;
103 }
104
105 /// @brief Array copy
106 //
107 Array(const Array &rhs)
108 {
109 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0)) {
110 return;
111 }
112
113 allocate(rhs.nrows_, rhs.ncols_);
114
115 memcpy(data_, rhs.data_, size_*sizeof(T));
116 num_allocated += 1;
117 active += 1;
118 }
119
120 /// @brief Array assignment
121 //
122 Array& operator=(const Array& rhs)
123 {
124 if (this == &rhs) {
125 return *this;
126 }
127
128 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0)) {
129 return *this;
130 }
131
132 if ((nrows_ != rhs.nrows_) || (ncols_ != rhs.ncols_)) {
133 clear();
134 allocate(rhs.nrows_, rhs.ncols_);
135 }
136
137 memcpy(data_, rhs.data_, sizeof(T) * size_);
138 return *this;
139 }
140
141 Array& operator=(const double value)
142 {
143 for (int i = 0; i < size_; i++) {
144 data_[i] = value;
145 }
146 return *this;
147 }
148
149 ~Array()
150 {
151 if (data_ != nullptr) {
152 #if Array_gather_stats
153 memory_in_use -= sizeof(T)*size_;
154 memory_returned += sizeof(T)*size_;
155 active -= 1;
156 #endif
157 if (!data_reference_) {
158 delete [] data_;
159 }
160 data_ = nullptr;
161 size_ = 0;
162 id -= 1;
163 nrows_ = 0;
164 ncols_ = 0;
165 }
166 };
167
168 friend std::ostream& operator << (std::ostream& out, const Array<T>& lhs)
169 {
170 for (int i = 0; i < lhs.size(); i++) {
171 out << lhs.data_[i];
172 if (i != lhs.size()-1) {
173 out << ", ";
174 }
175 }
176 return out;
177 }
178
179 /// @brief Free the array data.
180 ///
181 /// This is to replicate the Fortran DEALLOCATE().
182 //
183 void clear()
184 {
185 if (data_ != nullptr) {
186 if (data_reference_) {
187 throw std::runtime_error("[Array] Can't clear an Array with reference data.");
188 }
189 delete [] data_;
190 #if Array_gather_stats
191 memory_in_use -= sizeof(T) * size_;;
192 memory_returned += sizeof(T) * size_;;
193 #endif
194 }
195 nrows_ = 0;
196 ncols_ = 0;
197 size_ = 0;
198 data_ = nullptr;
199 }
200
201 int ncols() const
202 {
203 return ncols_;
204 }
205
206 int nrows() const
207 {
208 return nrows_;
209 }
210
211 /// @brief Print by rows and columns.
212 //
213 void print(const std::string& label)
214 {
215 printf("%s %d x %d \n", label.c_str(), nrows_, ncols_);
216 for (int i = 0; i < nrows_; i++) {
217 printf("[ ");
218 for (int j = 0; j < ncols_; j++) {
219 printf("%.16e", value(i,j));
220 if (j == ncols_-1) {
221 printf(" ]");
222 } else {
223 printf(", ");
224 }
225 }
226 printf("\n");
227 }
228 }
229
230 /// @brief Resize the array.
231 //
232 void resize(const int num_rows, const int num_cols)
233 {
234 // [NOTE] This is tfu but need to mimic fortran.
235 nrows_ = num_rows;
236 ncols_ = num_cols;
237
238 if ((num_rows <= 0) || (num_cols <= 0)) {
239 return;
240 }
241
242 if (data_ != nullptr) {
243 if (data_reference_) {
244 throw std::runtime_error("[Array] Can't resize an Array with reference data.");
245 }
246 delete [] data_;
247 data_ = nullptr;
248 size_ = 0;
249 nrows_ = 0;
250 ncols_ = 0;
251 #if Array_gather_stats
252 memory_in_use -= sizeof(T) * size_;;
253 memory_returned += sizeof(T) * size_;;
254 #endif
255 }
256
257 allocate(num_rows, num_cols);
258 }
259
260 int size() const
261 {
262 return size_;
263 }
264
265 int msize() const
266 {
267 return size_ * sizeof(T);
268 }
269
270 /// @brief Test if an array has rows or columns set
271 /// but no data.
272 ///
273 /// [NOTE] This is tfu but need to mimic fortran.
274 //
275 bool allocated()
276 {
277 if ((nrows_ > 0) || (ncols_ > 0)) {
278 return true;
279 }
280
281 return false;
282 }
283
284 void read(const std::string& file_name)
285 {
286 auto fp = fopen(file_name.c_str(), "rb");
287 int size;
288 fread(&size, sizeof(int), 1, fp);
289 fread(data_, sizeof(double), size, fp);
290 fclose(fp);
291 }
292
293 void write(const std::string& label, bool memory=true, T offset={}) const
294 {
295 if (!write_enabled) {
296 return;
297 }
298
299 auto file_prefix = build_file_prefix(label);
300 auto file_name = file_prefix + "_cm.bin";
301
302 // Write binary file.
303 //
304 auto fp = fopen(file_name.c_str(), "wb");
305 fwrite(&size_, sizeof(int), 1, fp);
306 fwrite(data_, sizeof(T), size_, fp);
307 fclose(fp);
308 }
309
310 /// @brief Append data to a file.
311 //
312 void append(const std::string& label, bool memory=true, T offset={}) const
313 {
314 if (!write_enabled) {
315 return;
316 }
317
318 auto file_prefix = build_file_prefix(label);
319 auto file_name = file_prefix + "_cm.bin";
320
321 /// @brief Append binary file.
322 //
323 auto fp = fopen(file_name.c_str(), "ab");
324 fwrite(data_, sizeof(T), size_, fp);
325 fclose(fp);
326 }
327
328 const T& operator()(const int i) const
329 {
330 if (i >= size_) {
331 throw std::runtime_error("[Array(i)] Index " + std::to_string(i) + " is out of bounds.");
332 }
333 return data_[i];
334 }
335
336 T& operator()(const int i)
337 {
338 if (i >= size_) {
339 throw std::runtime_error("[Array(i)] Index " + std::to_string(i) + " is out of bounds.");
340 }
341 return data_[i];
342 }
343
344 /// @brief (i,j) operators
345 //
346 const T& operator()(const int row, const int col) const
347 {
348 #ifdef Array_check_enabled
349 check_index(row, col);
350 #endif
351 return data_[row + col*nrows_];
352 }
353
354 T& operator()(const int row, const int col)
355 {
356 #ifdef Array_check_enabled
357 check_index(row, col);
358 #endif
359 return data_[row + col*nrows_];
360 }
361
362 /// @brief Get a column from the array as a Vector.
363 //
364 Vector<T> col(const int col, const std::array<int,2>& range={-1,-1}) const
365 {
366 #ifdef Array_check_enabled
367 check_index(0, col);
368 #endif
369 int start_row, end_row;
370
371 if (range[0] != -1) {
372 start_row = range[0];
373 end_row = range[1];
374 #ifdef Array_check_enabled
375 check_index(start_row, col);
376 check_index(end_row, col);
377 #endif
378 } else {
379 start_row = 0;
380 end_row = nrows_;
381 }
382
383 Vector<T> values(nrows_);
384 for (int row = start_row; row < end_row; row++) {
385 values[row] = value(row,col);
386 }
387 return values;
388 }
389
390 Vector<T> rcol(const int col) const
391 {
392 Vector<T> vector_col(nrows_, &data_[col*nrows_]);
393 return vector_col;
394 }
395
396 /// @brief Return a pointer to the internal data for the given column.
397 //
398 T* col_data(const int col) {
399 return &data_[col*nrows_];
400 }
401
402 /// @brief Get one or more columns from the array as Vectors.
403 //
404 Vector<Vector<T>> cols(const Vector<int>& columns) const
405 {
406 Vector<Vector<T>> values(columns.size());
407
408 for (int i = 0; i < columns.size(); i++) {
409 int j = columns[i];
410 #ifdef Array_check_enabled
411 check_index(0, j);
412 #endif
413 values[i] = col(j);
414 }
415
416 return values;
417 }
418
419 /// @brief Get a row from the array as a Vector.
420 //
421 Vector<T> row(const int row, const std::array<int,2>& range={-1,-1})
422 {
423 #ifdef Array_check_enabled
424 check_index(row, 0);
425 #endif
426
427 Vector<T> values(ncols_);
428
429 for (int col = 0; col < ncols_; col++) {
430 values[col] = value(row,col);
431 }
432
433 return values;
434 }
435
436 /// @brief Get row values from the array using an index of columns.
437 //
438 Vector<T> rows(const int row, const Vector<int>& indexes) const
439 {
440 #ifdef Array_check_enabled
441 check_index(row, 0);
442 #endif
443
444 Vector<T> values(indexes.size());
445
446 for (int i = 0; i < indexes.size(); i++) {
447 int col = indexes[i];
448 #ifdef Array_check_enabled
449 check_index(row, col);
450 #endif
451 values[i] = value(row,col);
452 }
453
454 return values;
455 }
456
457 /// @brief Get a set of rows using a start and end row index.
458 //
459 Array<T> rows(const int start_row, const int end_row) const
460 {
461 #ifdef Array_check_enabled
462 check_index(start_row, 0);
463 check_index(end_row, 0);
464 #endif
465 int num_rows = end_row - start_row + 1;
466 Array<T> values(num_rows, ncols_ );
467
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_];
471 }
472 }
473 return values;
474 }
475
476 /// @brief Get a range of rows for the given column.
477 //
478 Vector<T> rows(const int start_row, const int end_row, const int col) const
479 {
480 #ifdef Array_check_enabled
481 check_index(start_row, 0);
482 check_index(end_row, 0);
483 #endif
484 int num_rows = end_row - start_row + 1;
485 Vector<T> values(num_rows);
486
487 for (int row = 0; row < num_rows; row++) {
488 values(row) = data_[(row+start_row) + col*nrows_];
489 }
490 return values;
491 }
492
493 /// @brief Return a vector of values for a range of rows and columns.
494 //
495 std::vector<T> values(const std::array<int,2>& rows, const std::array<int,2>& cols, const int stride=1) const
496 {
497 std::vector<T> values;
498
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));
502 }
503 }
504
505 return values;
506 }
507
508 /// @brief Set column values from a vector of values.
509 //
510 void set_col(const int col, const Vector<T>& values, const std::array<int,2>& range={-1,-1})
511 {
512 #ifdef Array_check_enabled
513 check_index(0, col);
514 #endif
515 int start_row, end_row;
516
517 if (range[0] != -1) {
518 start_row = range[0];
519 end_row = range[1];
520 #ifdef Array_check_enabled
521 check_index(start_row, col);
522 check_index(end_row, col);
523 #endif
524 } else {
525 start_row = 0;
526 end_row = nrows_;
527 }
528
529 for (int row = 0; row < values.size(); row++) {
530 data_[row + col*nrows_] = values[row];
531 }
532 }
533
534 /// @brief Set row values from a vector of values.
535 //
536 void set_row(const int row, const Vector<T>& values) const
537 {
538 #ifdef Array_check_enabled
539 check_index(row, 0);
540 #endif
541 for (int col = 0; col < values.size(); col++) {
542 data_[row + col*nrows_] = values[col];
543 }
544 }
545
546 /// @brief Set row values from an initializer list {}..
547 //
548 void set_row(const int row, std::initializer_list<T> row_data) const
549 {
550 auto it = row_data.begin();
551 for (int col = 0; col < ncols_; col++, it++) {
552 data_[row + col*nrows_] = *it;
553 }
554 }
555
556 /// @brief Set row values from a scalar.
557 //
558 void set_row(const int row, const T value) const
559 {
560 #ifdef Array_check_enabled
561 check_index(row, 0);
562 #endif
563 for (int col = 0; col < ncols_; col++) {
564 data_[row + col*nrows_] = value;
565 }
566 }
567
568 /// @brief Set row values from a vector of values at the given column offset.
569 //
570 void set_row(const int row, int offset, const Vector<T>& values) const
571 {
572 #ifdef Array_check_enabled
573 check_index(row, 0);
574 check_index(row, offset+values.size()-1);
575 #endif
576 for (int col = 0; col < values.size(); col++) {
577 int ocol = col + offset;
578 #ifdef Array_check_enabled
579 check_index(row, ocol);
580 #endif
581 data_[row + ocol*nrows_] = values[col];
582 }
583 }
584
585 /// @brief Set a set of rows using a start and end row index.
586 //
587 void set_rows(const int start_row, const int end_row, const Array<T>& values) const
588 {
589 #ifdef Array_check_enabled
590 check_index(start_row, 0);
591 check_index(end_row, 0);
592 #endif
593 int num_rows = end_row - start_row + 1;
594
595 if (ncols_ != values.ncols_) {
596 throw std::runtime_error("[Array set_rows] Arrays have different column sizes. ");
597 }
598
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);;
602 }
603 }
604 }
605
606 ///////////////////////////////////////////////////
607 // M a t h e m a t i c a l o p e r a t o r s //
608 ///////////////////////////////////////////////////
609
610 T max() const
611 {
612 T max_v = data_[0];
613 for (int i = 1; i < size_; i++) {
614 if (data_[i] > max_v) {
615 max_v = data_[i];
616 }
617 }
618 return max_v;
619 }
620
621 T min() const
622 {
623 T min_v = data_[0];
624 for (int i = 1; i < size_; i++) {
625 if (data_[i] < min_v) {
626 min_v = data_[i];
627 }
628 }
629 return min_v;
630 }
631
632 /// @brief Add arrays.
633 //
634 Array<T> operator+(const Array<T>& array) const
635 {
636 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
637 throw std::runtime_error("[Array addition] Arrays have diffent shapes. ");
638 }
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);
643 }
644 }
645 return result;
646 }
647
648 /// @brief Subtract arrays.
649 //
650 Array<T> operator-(const Array<T>& array) const
651 {
652 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
653 throw std::runtime_error("[Array subtraction] Arrays have diffent shapes. ");
654 }
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);
659 }
660 }
661 return result;
662 }
663
664 /// @brief Multiply two arrays component-wise to reproduce Fortran.
665 /// C = A * B
666 //
667 Array<T> operator*(const Array<T>& array) const
668 {
669 if ((nrows_ != array.nrows_) || (ncols_ != array.ncols_)) {
670 throw std::runtime_error("[Array multiply] Arrays have diffent shapes. ");
671 }
672
673 Array<T> result(nrows_, ncols_);
674
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);
678 }
679 }
680
681 return result;
682 }
683
684 /// @brief Divide one array by another component-wise.
685 /// C = A / B
686 //
687 Array<T> operator / (const Array<T>& array) const
688 {
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.");
692 }
693
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);
697 }
698 }
699 return result;
700 }
701
702 /// @brief Compound add assignment.
703 //
704 Array<T> operator+=(const Array<T>& array) const
705 {
706 for (int j = 0; j < ncols_; j++) {
707 for (int i = 0; i < nrows_; i++) {
708 data_[i + j*nrows_] += array(i,j);
709 }
710 }
711 return *this;
712 }
713
714 /// @brief Compound subtract assignment.
715 //
716 Array<T> operator-=(const Array<T>& array) const
717 {
718 for (int j = 0; j < ncols_; j++) {
719 for (int i = 0; i < nrows_; i++) {
720 data_[i + j*nrows_] -= array(i,j);
721 }
722 }
723 return *this;
724 }
725
726 /// @brief Compound multiply assignment.
727 //
728 Array<T> operator*=(const Array<T>& array) const
729 {
730 for (int j = 0; j < ncols_; j++) {
731 for (int i = 0; i < nrows_; i++) {
732 data_[i + j*nrows_] *= array(i,j);
733 }
734 }
735 return *this;
736 }
737
738 /// @brief Multiply by a scalar.
739 //
740 Array<T> operator*(const T value) const
741 {
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_];
746 }
747 }
748 return result;
749 }
750
751 friend const Array<T> operator*(const T value, const Array& rhs)
752 {
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_];
757 }
758 }
759 return result;
760 }
761
762 /// @brief Divide by a scalar.
763 /// A / s
764 //
765 Array<T> operator / (const T value) const
766 {
767 if (value == 0.0) {
768 throw std::runtime_error(+"Array Divide by zero.");
769 }
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;
774 }
775 }
776 return result;
777 }
778
779 /// @brief Divide scalar by array.
780 /// s / A
781 //
782 friend const Array<T> operator / (const T value, const Array& rhs)
783 {
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_];
788 }
789 }
790 return result;
791 }
792
793 /// @brief Subtract a scalar.
794 /// A - s
795 //
796 Array<T> operator-(const T value) const
797 {
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;
802 }
803 }
804 return result;
805 }
806
807 /// @brief Compound add assignment.
808 //
809 Array<T> operator+=(const T value) const
810 {
811 for (int j = 0; j < ncols_; j++) {
812 for (int i = 0; i < nrows_; i++) {
813 data_[i + j*nrows_] += value;
814 }
815 }
816 return *this;
817 }
818
819 /// @brief negate
820 //
821 Array<T> operator-() const
822 {
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_]);
827 }
828 }
829 return result;
830 }
831
832 /// @brief Compound subtract assignment.
833 //
834 Array<T> operator-=(const T value) const
835 {
836 for (int j = 0; j < ncols_; j++) {
837 for (int i = 0; i < nrows_; i++) {
838 data_[i + j*nrows_] -= value;
839 }
840 }
841 return *this;
842 }
843
844 /// @brief Subtract a scalar.
845 /// s - A
846 //
847 friend const Array<T> operator-(const T value, const Array& rhs)
848 {
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_];
853 }
854 }
855 return result;
856 }
857
858 /// @brief absolute value
859 //
860 friend Array<T> abs(const Array& rhs)
861 {
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_]);
866 }
867 }
868 return result;
869 }
870
871 /// @brief maximum
872 //
873 friend T max(const Array& arg)
874 {
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];
879 }
880 }
881 return max_v;
882 }
883
884 /// @brief square root
885 //
886 friend Array<T> sqrt(const Array& arg)
887 {
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_]);
892 }
893 }
894 return result;
895 }
896
897 /// @brief Compute the sum of a row of valuesr
898 //
899 T sum_row(const int row) const
900 {
901 #ifdef Array_check_enabled
902 check_index(row, 0);
903 #endif
904 T sum {};
905 for (int col = 0; col < ncols_; col++) {
906 sum += data_[row + col*nrows_];
907 }
908 return sum;
909 }
910
911 T* data() const {
912 return data_;
913 }
914
915 private:
916
917 /// @brief Allocate memory for array data.
918 //
919 void allocate(const int num_rows, const int num_cols)
920 {
921 data_reference_ = false;
922 nrows_ = num_rows;
923 ncols_ = num_cols;
924 size_ = nrows_ * ncols_;
925 #if Array_gather_stats
926 memory_in_use += sizeof(T)*size_;
927 #endif
928
929 if (data_ != nullptr) {
930 //throw std::runtime_error(+"[Array] Allocating when data is not nullptr.");
931 }
932
933 if (size_ != 0) {
934 data_ = new T [size_];
935 memset(data_, 0, sizeof(T)*size_);
936 }
937 }
938
939 /// @brief Get a value from data_[].
940 //
941 inline T value(const int row, const int col) const
942 {
943 return data_[row + col*nrows_];
944 }
945
946 void check_index(const int row, const int col) const
947 {
948 if (data_ == nullptr) {
949 //throw std::runtime_error(+"Accessing null data in Array.");
950 return;
951 }
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 " +
958 dims + " array.");
959 }
960 }
961
962 //-------------
963 // Member data
964 //-------------
965 //
966 int nrows_ = 0;
967 int ncols_ = 0;
968 int size_ = 0;
969 bool data_reference_ = false;
970 T *data_ = nullptr;
971};
972
973#endif
974
The Vector template class is used for storing int and double data.
Definition Vector.h:23