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