41 #ifdef ENABLE_ARRAY_INDEX_CHECKING
42 #define Array3_check_enabled
55 static int num_allocated;
57 static bool show_index_check_message;
58 static double memory_in_use;
59 static double memory_returned;
60 static bool write_enabled;
61 static void memory(
const std::string& prefix=
"");
62 static void stats(
const std::string& prefix=
"");
76 Array3(
const int num_rows,
const int num_cols,
const int num_slices,
bool row_major=
true)
81 nslices_ = num_slices;
83 if ((num_rows <= 0) || (num_cols <= 0) || (num_slices <= 0)) {
88 allocate(num_rows, num_cols, num_slices, row_major);
96 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0) || (rhs.nslices_ <= 0)) {
100 allocate(rhs.nrows_, rhs.ncols_, rhs.nslices_);
101 memcpy(data_, rhs.data_, size_*
sizeof(T));
108 if (data_ !=
nullptr) {
109 memory_in_use -=
sizeof(T) * size_;;
110 memory_returned +=
sizeof(T) * size_;;
117 int ncols()
const {
return ncols_; }
118 int nrows()
const {
return nrows_; }
119 int nslices()
const {
return nslices_; }
121 void allocate(
const int num_rows,
const int num_cols,
const int num_slices,
const bool row_major=
true)
125 nslices_ = num_slices;
126 slice_size_ = ncols_ * nrows_;
127 size_ = nrows_ * ncols_ * nslices_;
128 data_ =
new T [size_];
129 memset(data_, 0,
sizeof(T)*size_);
130 memory_in_use +=
sizeof(T) * size_;;
133 void check_index(
const int i,
const int j,
const int k)
const
135 if (show_index_check_message) {
136 std::cout <<
"[Array3] **********************************" << std::endl;
137 std::cout <<
"[Array3] WARNING: Index checking is enabled " << std::endl;
138 std::cout <<
"[Array3] **********************************" << std::endl;
139 show_index_check_message =
false;
142 if (data_ ==
nullptr) {
143 throw std::runtime_error(+
"Accessing null data in Array3.");
146 if ((i < 0) || (i >= nrows_) or (j < 0) || (j >= ncols_) or (k < 0) || (k >= nslices_)) {
147 auto i_str = std::to_string(nrows_);
148 auto j_str = std::to_string(ncols_);
149 auto k_str = std::to_string(nslices_);
150 auto dims = i_str +
" x " + j_str +
" x " + k_str;
151 auto index_str =
" " + std::to_string(i) +
"," + std::to_string(j) +
"," + std::to_string(k) +
" ";
152 throw std::runtime_error(
"Index (i,j,k)=" + index_str +
" is out of bounds for " + dims +
" array.");
156 friend std::ostream& operator << (std::ostream& out,
const Array3<T>& lhs)
158 if (lhs.data_ ==
nullptr) {
159 throw std::runtime_error(
"[Array3] Accessing null data in ostream.");
162 for (
int i = 0; i < lhs.size(); i++) {
164 if (i != lhs.size()-1) {
176 if (data_ !=
nullptr) {
178 memory_in_use -=
sizeof(T) * size_;;
179 memory_returned +=
sizeof(T) * size_;;
195 #ifdef Array3_check_enabled
196 check_index(0, 0,
slice);
199 Array<T> array_slice(nrows_, ncols_, &data_[
slice*slice_size_]);
204 T* slice_data(
const int slice) {
205 return &data_[
slice*slice_size_];
208 void print(
const std::string& label)
210 printf(
"%s (%d): \n", label.c_str(), size_);
211 for (
int i = 0; i < size_; i++) {
212 if (data_[i] != 0.0) {
213 printf(
"%s %d %g\n", label.c_str(), i+1, data_[i]);
221 #ifdef Array3_check_enabled
222 check_index(0, 0,
slice);
224 Array<T> array_slice(nrows_, ncols_);
226 for (
int col = 0; col < ncols_; col++) {
227 for (
int row = 0; row < nrows_; row++) {
228 array_slice(row, col) = data_[row + col*nrows_ +
slice*slice_size_];
235 void set_row(
const int col,
const int slice,
const std::vector<T>& values)
const
237 #ifdef Array3_check_enabled
238 check_index(0, col,
slice);
240 for (
int row = 0; row < values.size(); row++) {
241 data_[row + col*nrows_ +
slice*slice_size_] = values[row];
245 void set_slice(
const int slice,
const Array<T>& values)
const
247 #ifdef Array3_check_enabled
248 check_index(0, 0,
slice);
250 for (
int col = 0; col < ncols_; col++) {
251 for (
int row = 0; row < nrows_; row++) {
252 data_[row + col*nrows_ +
slice*slice_size_] = values(row,col);
267 if ((nrows_ > 0) || (ncols_ > 0) || nslices_ > 0) {
276 return size_ *
sizeof(T);
280 void resize(
const int num_rows,
const int num_cols,
const int num_slices)
285 nslices_ = num_slices;
287 if ((num_rows <= 0) || (num_cols <= 0) || (num_slices <= 0)) {
291 if (data_ !=
nullptr) {
293 memory_in_use -=
sizeof(T) * size_;;
294 memory_returned +=
sizeof(T) * size_;;
298 allocate(num_rows, num_cols, num_slices);
306 int rhs_size = rhs.size();
308 if (size_ != rhs_size) {
309 throw std::runtime_error(
"The RHS size " + std::to_string(rhs_size) +
" does not have the same size " +
310 std::to_string(size_) +
" of this array.");
313 auto rhs_data = rhs.data();
315 for (
int i = 0; i < size_; i++) {
316 data_[i] = rhs_data[i];
320 void read(
const std::string& file_name)
322 auto fp = fopen(file_name.c_str(),
"rb");
323 fread(&size_,
sizeof(
int), 1, fp);
324 fread(data_,
sizeof(
double), size_, fp);
328 void write(
const std::string& label,
bool memory=
true)
330 if (!write_enabled) {
334 auto file_prefix = build_file_prefix(label);
335 auto file_name = file_prefix +
"_cm.bin";
338 auto fp = fopen(file_name.c_str(),
"wb");
339 fwrite(&size_,
sizeof(
int), 1, fp);
340 fwrite(data_,
sizeof(
double), size_, fp);
344 void append(
const std::string& label,
bool memory=
true)
346 if (!write_enabled) {
350 auto file_prefix = build_file_prefix(label);
351 auto file_name = file_prefix +
"_cm.bin";
354 auto fp = fopen(file_name.c_str(),
"ab");
355 fwrite(data_,
sizeof(
double), size_, fp);
368 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0) || (rhs.nslices_ <= 0)) {
372 if (rhs.data_ ==
nullptr) {
373 throw std::runtime_error(+
"RHS has null data.");
380 if (size_ != rhs.size_) {
382 allocate(rhs.nrows_, rhs.ncols_, rhs.nslices_);
385 memcpy(data_, rhs.data_,
sizeof(T) * size_);
393 #ifdef Array3_check_enabled
394 check_index(row, col,
slice);
396 return data_[row + col*nrows_ +
slice*slice_size_];
402 #ifdef Array3_check_enabled
403 check_index(row, col,
slice);
405 return data_[row + col*nrows_ +
slice*slice_size_];
410 for (
int i = 0; i < size_; i++) {
423 Array3<T> result(nrows_, ncols_, nslices_);
424 for (
int i = 0; i < size_; i++) {
425 result.data_[i] = value * data_[i];
432 for (
int i = 0; i < size_; i++) {
440 if (rhs.data_ ==
nullptr) {
441 throw std::runtime_error(
"Null data for rhs Array3.");
443 Array3<T> result(rhs.nrows_, rhs.ncols_, rhs.nslices_);
444 for (
int i = 0; i < rhs.size_; i++) {
445 result.data_[i] = value * rhs.data_[i];
The Array3 template class implements a simple interface to 3D arrays.
Definition: Array3.h:52
const T & operator()(const int row, const int col, const int slice) const
Get the array value at (row,col).
Definition: Array3.h:391
void clear()
Free the array data.
Definition: Array3.h:174
Array< T > slice(const int slice) const
Get a slice.
Definition: Array3.h:219
Array3 & operator=(const Array3 &rhs)
Array assignment.
Definition: Array3.h:366
void set_values(Array< T > &rhs)
Set the array values from an Array with the equivalent number of values.
Definition: Array3.h:304
Array< T > rslice(const int slice) const
rslice
Definition: Array3.h:193
void resize(const int num_rows, const int num_cols, const int num_slices)
Resize the array.
Definition: Array3.h:280
bool allocated()
Test if an array has rows or columns or slices set but no data.
Definition: Array3.h:265
Array3< T > operator*(const T value) const
Multiply by a scalar.
Definition: Array3.h:421
T & operator()(const int row, const int col, const int slice)
Set the array value at (row,col).
Definition: Array3.h:400
Array3(const Array3 &rhs)
Array copy.
Definition: Array3.h:94