PSCF v1.1
DMatrix.h
1#ifndef UTIL_D_MATRIX_H
2#define UTIL_D_MATRIX_H
3
4/*
5* Util Package - C++ Utilities for Scientific Computation
6*
7* Copyright 2010 - 2017, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include <util/containers/Matrix.h>
12#include <util/misc/Memory.h>
13#include <util/global.h>
14
15namespace Util
16{
17
23 template <typename Data>
24 class DMatrix : public Matrix<Data>
25 {
26
27 using Matrix<Data>::data_;
28 using Matrix<Data>::capacity1_;
29 using Matrix<Data>::capacity2_;
30
31 public:
32
37
41 DMatrix(DMatrix<Data> const & other);
42
49
56
64
70 void deallocate();
71
75 bool isAllocated() const;
76
83 template <class Archive>
84 void serialize(Archive& ar, const unsigned int version);
85
86 };
87
88 // Method definitions
89
90 /*
91 * Default constructor.
92 */
93 template <typename Data>
95 Matrix<Data>()
96 {}
97
98 /*
99 * Copy constructor.
100 */
101 template <typename Data>
103 : Matrix<Data>()
104 {
105 // Precondition
106 if (other.data_ == 0) {
107 UTIL_THROW("Other DMatrix must be allocated");
108 }
109
110 // Allocate and copy elements
111 allocate(other.capacity1_, other.capacity2_);
112 for (int i = 0; i < capacity1_*capacity2_; ++i) {
113 data_[i] = other.data_[i];
114 }
115 }
116
117 /*
118 * Assignment.
119 */
120 template <typename Data>
122 {
123 // Check for self assignment.
124 if (this == &other) return *this;
125
126 // Precondition
127 if (other.data_ == 0) {
128 UTIL_THROW("RHS DMatrix must be allocated before assignment");
129 }
130
131 if (data_ == 0) {
132 // If this DMatrix if not allocated, allocate now.
133 allocate(other.capacity1_, other.capacity2_);
134 } else {
135 // If this is allocated, check that capacities are equal.
136 if (capacity1_ != other.capacity1_ ||
137 capacity2_ != other.capacity2_) {
138 UTIL_THROW("Unequal capacities in assignment");
139 }
140 }
141
142 // Copy elements
143 for (int i = 0; i < capacity1_*capacity2_; ++i) {
144 data_[i] = other.data_[i];
145 }
146
147 return *this;
148 }
149
150 /*
151 * Destructor.
152 *
153 * If allocated, deallocate.
154 */
155 template <typename Data>
157 {
158 if (data_) {
159 Memory::deallocate<Data>(data_, capacity1_*capacity2_);
160 }
161 }
162
163 /*
164 * Allocate memory for a matrix.
165 *
166 * \param capacity1 number of rows (range of first index)
167 * \param capacity2 number of columns (range of second index)
168 */
169 template <typename Data>
170 void DMatrix<Data>::allocate(int capacity1, int capacity2)
171 {
172 // Preconditions
173 if (capacity1 <= 0) UTIL_THROW("Capacity1 must be positive");
174 if (capacity2 <= 0) UTIL_THROW("Capacity2 must be positive");
175 if (data_ != 0) UTIL_THROW("Attempt to re-allocate a Matrix");
176
177 Memory::allocate<Data>(data_, capacity1*capacity2);
178 capacity1_ = capacity1;
179 capacity2_ = capacity2;
180 }
181
182 /*
183 * Deallocate the underlying C array.
184 *
185 * Throw an Exception if this DMatrix is not allocated.
186 */
187 template <class Data>
189 {
190 if (!isAllocated()) {
191 UTIL_THROW("Array is not allocated");
192 }
193 Memory::deallocate<Data>(data_, capacity1_*capacity2_);
194 capacity1_ = 0;
195 capacity2_ = 0;
196 }
197
198 /*
199 * Return true if the DMatrix has been allocated, false otherwise.
200 */
201 template <class Data>
202 inline bool DMatrix<Data>::isAllocated() const
203 { return !(data_ == 0); }
204
205 /*
206 * Serialize a DMatrix to/from an Archive.
207 */
208 template <class Data>
209 template <class Archive>
210 void DMatrix<Data>::serialize(Archive& ar, const unsigned int version)
211 {
212 int capacity1, capacity2;
213 if (Archive::is_saving()) {
214 if (!isAllocated()) {
215 UTIL_THROW("Cannot save unallocated DMatrix.");
216 }
217 capacity1 = capacity1_;
218 capacity2 = capacity2_;
219 }
220 ar & capacity1;
221 ar & capacity2;
222 if (Archive::is_loading()) {
223 if (!isAllocated()) {
224 if (capacity1 > 0 && capacity2 > 0) {
225 allocate(capacity1, capacity2);
226 } else {
227 UTIL_THROW("Unallocated DMatrix, invalid capacity values");
228 }
229 } else {
230 if (capacity1 != capacity1_) {
231 UTIL_THROW("Inconsistent DMatrix capacity1 values");
232 }
233 if (capacity2 != capacity2_) {
234 UTIL_THROW("Inconsistent DMatrix capacity2 values");
235 }
236 }
237 }
238 for (int i = 0; i < capacity1_*capacity2_; ++i) {
239 ar & data_[i];
240 }
241 }
242
243}
244#endif
Dynamically allocated Matrix.
Definition: DMatrix.h:25
void serialize(Archive &ar, const unsigned int version)
Serialize a DMatrix to/from an Archive.
Definition: DMatrix.h:210
DMatrix< Data > & operator=(DMatrix< Data > const &other)
Assignment.
Definition: DMatrix.h:121
void allocate(int capacity1, int capacity2)
Allocate memory for a matrix.
Definition: DMatrix.h:170
DMatrix()
Constructor.
Definition: DMatrix.h:94
bool isAllocated() const
Return true if the DMatrix has been allocated, false otherwise.
Definition: DMatrix.h:202
void deallocate()
Deallocate the underlying memory block.
Definition: DMatrix.h:188
DMatrix(DMatrix< Data > const &other)
Copy constructor.
Definition: DMatrix.h:102
~DMatrix()
Destructor.
Definition: DMatrix.h:156
Two-dimensional array container template (abstract).
Definition: Matrix.h:32
int capacity2() const
Get number of columns (range of the second array index).
Definition: Matrix.h:143
Data * data_
Pointer to 1D C array of all elements.
Definition: Matrix.h:84
int capacity2_
Number of columns (range of first index).
Definition: Matrix.h:90
int capacity1_
Number of rows (range of first index).
Definition: Matrix.h:87
int capacity1() const
Get number of rows (range of the first array index).
Definition: Matrix.h:136
File containing preprocessor macros for error handling.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
Utility classes for scientific computation.
Definition: accumulators.mod:1