54 static int num_allocated;
56 static double memory_in_use;
57 static double memory_returned;
58 static bool write_enabled;
59 static void memory(
const std::string& prefix=
"");
60 static void stats(
const std::string& prefix=
"");
74 Array3(
const int num_rows,
const int num_cols,
const int num_slices,
bool row_major=
true)
79 nslices_ = num_slices;
81 if ((num_rows <= 0) || (num_cols <= 0) || (num_slices <= 0)) {
86 allocate(num_rows, num_cols, num_slices, row_major);
94 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0) || (rhs.nslices_ <= 0)) {
98 allocate(rhs.nrows_, rhs.ncols_, rhs.nslices_);
99 memcpy(data_, rhs.data_, size_*
sizeof(T));
106 if (data_ !=
nullptr) {
107 memory_in_use -=
sizeof(T) * size_;;
108 memory_returned +=
sizeof(T) * size_;;
115 int ncols()
const {
return ncols_; }
116 int nrows()
const {
return nrows_; }
117 int nslices()
const {
return nslices_; }
119 void allocate(
const int num_rows,
const int num_cols,
const int num_slices,
const bool row_major=
true)
123 nslices_ = num_slices;
124 slice_size_ = ncols_ * nrows_;
125 size_ = nrows_ * ncols_ * nslices_;
126 data_ =
new T [size_];
127 memset(data_, 0,
sizeof(T)*size_);
128 memory_in_use +=
sizeof(T) * size_;;
131 void check_index(
const int i,
const int j,
const int k)
const
133 if (data_ ==
nullptr) {
134 throw std::runtime_error(+
"Accessing null data in Array3.");
137 if ((i < 0) || (i >= nrows_) or (j < 0) || (j >= ncols_) or (k < 0) || (k >= nslices_)) {
138 auto i_str = std::to_string(nrows_);
139 auto j_str = std::to_string(ncols_);
140 auto k_str = std::to_string(nslices_);
141 auto dims = i_str +
" x " + j_str +
" x " + k_str;
142 auto index_str =
" " + std::to_string(i) +
"," + std::to_string(j) +
"," + std::to_string(k) +
" ";
143 throw std::runtime_error(
"Index (i,j,k)=" + index_str +
" is out of bounds for " + dims +
" array.");
147 friend std::ostream& operator << (std::ostream& out,
const Array3<T>& lhs)
149 if (lhs.data_ ==
nullptr) {
150 throw std::runtime_error(
"[Array3] Accessing null data in ostream.");
153 for (
int i = 0; i < lhs.size(); i++) {
155 if (i != lhs.size()-1) {
167 if (data_ !=
nullptr) {
169 memory_in_use -=
sizeof(T) * size_;;
170 memory_returned +=
sizeof(T) * size_;;
186 #ifdef Array3_check_enabled
187 check_index(0, 0,
slice);
190 Array<T> array_slice(nrows_, ncols_, &data_[
slice*slice_size_]);
195 T* slice_data(
const int slice) {
196 return &data_[
slice*slice_size_];
199 void print(
const std::string& label)
201 printf(
"%s (%d): \n", label.c_str(), size_);
202 for (
int i = 0; i < size_; i++) {
203 if (data_[i] != 0.0) {
204 printf(
"%s %d %g\n", label.c_str(), i+1, data_[i]);
212 #ifdef Array3_check_enabled
213 check_index(0, 0,
slice);
215 Array<T> array_slice(nrows_, ncols_);
217 for (
int col = 0; col < ncols_; col++) {
218 for (
int row = 0; row < nrows_; row++) {
219 array_slice(row, col) = data_[row + col*nrows_ +
slice*slice_size_];
226 void set_row(
const int col,
const int slice,
const std::vector<T>& values)
const
228 #ifdef Array3_check_enabled
229 check_index(0, col,
slice);
231 for (
int row = 0; row < values.size(); row++) {
232 data_[row + col*nrows_ +
slice*slice_size_] = values[row];
236 void set_slice(
const int slice,
const Array<T>& values)
const
238 #ifdef Array3_check_enabled
239 check_index(0, 0,
slice);
241 for (
int col = 0; col < ncols_; col++) {
242 for (
int row = 0; row < nrows_; row++) {
243 data_[row + col*nrows_ +
slice*slice_size_] = values(row,col);
258 if ((nrows_ > 0) || (ncols_ > 0) || nslices_ > 0) {
267 return size_ *
sizeof(T);
271 void resize(
const int num_rows,
const int num_cols,
const int num_slices)
276 nslices_ = num_slices;
278 if ((num_rows <= 0) || (num_cols <= 0) || (num_slices <= 0)) {
282 if (data_ !=
nullptr) {
284 memory_in_use -=
sizeof(T) * size_;;
285 memory_returned +=
sizeof(T) * size_;;
289 allocate(num_rows, num_cols, num_slices);
297 int rhs_size = rhs.size();
299 if (size_ != rhs_size) {
300 throw std::runtime_error(
"The RHS size " + std::to_string(rhs_size) +
" does not have the same size " +
301 std::to_string(size_) +
" of this array.");
304 auto rhs_data = rhs.data();
306 for (
int i = 0; i < size_; i++) {
307 data_[i] = rhs_data[i];
311 void read(
const std::string& file_name)
313 auto fp = fopen(file_name.c_str(),
"rb");
314 fread(&size_,
sizeof(
int), 1, fp);
315 fread(data_,
sizeof(
double), size_, fp);
319 void write(
const std::string& label,
bool memory=
true)
321 if (!write_enabled) {
325 auto file_prefix = build_file_prefix(label);
326 auto file_name = file_prefix +
"_cm.bin";
329 auto fp = fopen(file_name.c_str(),
"wb");
330 fwrite(&size_,
sizeof(
int), 1, fp);
331 fwrite(data_,
sizeof(
double), size_, fp);
335 void append(
const std::string& label,
bool memory=
true)
337 if (!write_enabled) {
341 auto file_prefix = build_file_prefix(label);
342 auto file_name = file_prefix +
"_cm.bin";
345 auto fp = fopen(file_name.c_str(),
"ab");
346 fwrite(data_,
sizeof(
double), size_, fp);
359 if ((rhs.nrows_ <= 0) || (rhs.ncols_ <= 0) || (rhs.nslices_ <= 0)) {
363 if (rhs.data_ ==
nullptr) {
364 throw std::runtime_error(+
"RHS has null data.");
371 if (size_ != rhs.size_) {
373 allocate(rhs.nrows_, rhs.ncols_, rhs.nslices_);
376 memcpy(data_, rhs.data_,
sizeof(T) * size_);
384 #ifdef Array3_check_enabled
385 check_index(row, col,
slice);
387 return data_[row + col*nrows_ +
slice*slice_size_];
393 #ifdef Array3_check_enabled
394 check_index(row, col,
slice);
396 return data_[row + col*nrows_ +
slice*slice_size_];
401 for (
int i = 0; i < size_; i++) {
414 Array3<T> result(nrows_, ncols_, nslices_);
415 for (
int i = 0; i < size_; i++) {
416 result.data_[i] = value * data_[i];
423 for (
int i = 0; i < size_; i++) {
431 if (rhs.data_ ==
nullptr) {
432 throw std::runtime_error(
"Null data for rhs Array3.");
434 Array3<T> result(rhs.nrows_, rhs.ncols_, rhs.nslices_);
435 for (
int i = 0; i < rhs.size_; i++) {
436 result.data_[i] = value * rhs.data_[i];
The Array3 template class implements a simple interface to 3D arrays.
Definition: Array3.h:51
const T & operator()(const int row, const int col, const int slice) const
Get the array value at (row,col).
Definition: Array3.h:382
void clear()
Free the array data.
Definition: Array3.h:165
Array< T > slice(const int slice) const
Get a slice.
Definition: Array3.h:210
Array3 & operator=(const Array3 &rhs)
Array assignment.
Definition: Array3.h:357
void set_values(Array< T > &rhs)
Set the array values from an Array with the equivalent number of values.
Definition: Array3.h:295
Array< T > rslice(const int slice) const
rslice
Definition: Array3.h:184
void resize(const int num_rows, const int num_cols, const int num_slices)
Resize the array.
Definition: Array3.h:271
bool allocated()
Test if an array has rows or columns or slices set but no data.
Definition: Array3.h:256
Array3< T > operator*(const T value) const
Multiply by a scalar.
Definition: Array3.h:412
T & operator()(const int row, const int col, const int slice)
Set the array value at (row,col).
Definition: Array3.h:391
Array3(const Array3 &rhs)
Array copy.
Definition: Array3.h:92