Commit 65c1aac005cfcc806e62502c6eabc4ec83352fc8
1 parent
c495d065
fixed memory leaks in stim::matrix
Showing
1 changed file
with
150 additions
and
34 deletions
Show diff stats
stim/math/matrix.h
... | ... | @@ -17,42 +17,79 @@ class matrix { |
17 | 17 | size_t R; //number of rows |
18 | 18 | size_t C; //number of colums |
19 | 19 | |
20 | - void init(size_t rows, size_t cols){ | |
20 | + /*void init(size_t rows, size_t cols){ | |
21 | 21 | R = rows; |
22 | 22 | C = cols; |
23 | - M = (T*) malloc (R * C * sizeof(T)); //allocate space for the matrix | |
23 | + if (R == 0 || C == 0) M = NULL; | |
24 | + else | |
25 | + M = (T*)malloc(R * C * sizeof(T)); //allocate space for the matrix | |
26 | + }*/ | |
27 | + | |
28 | + T get(const size_t row, const size_t col) const { | |
29 | + if (row >= R || col >= C) { | |
30 | + std::cout << "ERROR: row or column out of range." << std::endl; | |
31 | + exit(1); | |
32 | + } | |
33 | + return M[col * R + row]; | |
24 | 34 | } |
25 | 35 | |
26 | 36 | T& at(size_t row, size_t col){ |
37 | + if (row >= R || col >= C) { | |
38 | + std::cout << "ERROR: row or column out of range." << std::endl; | |
39 | + exit(1); | |
40 | + } | |
27 | 41 | return M[col * R + row]; |
28 | 42 | } |
29 | 43 | |
30 | 44 | public: |
31 | - | |
45 | + matrix() { | |
46 | + R = 0; | |
47 | + C = 0; | |
48 | + M = NULL; | |
49 | + } | |
50 | + | |
32 | 51 | matrix(size_t rows, size_t cols) { |
33 | - init(rows, cols); //initialize memory | |
52 | + R = rows; | |
53 | + C = cols; | |
54 | + if (R * C == 0) | |
55 | + M = NULL; | |
56 | + else | |
57 | + M = new T[R * C]; | |
34 | 58 | } |
35 | 59 | |
36 | 60 | matrix(size_t rows, size_t cols, T* data) { |
37 | - init(rows, cols); | |
61 | + R = rows; | |
62 | + C = cols; | |
63 | + if (R * C == 0) | |
64 | + M = NULL; | |
65 | + else | |
66 | + M = new T[R * C]; | |
38 | 67 | memcpy(M, data, R * C * sizeof(T)); |
39 | 68 | } |
40 | 69 | |
41 | 70 | matrix(const matrix<T>& cpy){ |
42 | - init(cpy.R, cpy.C); | |
43 | - memcpy(M, cpy.M, R * C * sizeof(T)); | |
71 | + | |
72 | + if (cpy.R * cpy.C == 0) | |
73 | + M = NULL; | |
74 | + else | |
75 | + M = new T[cpy.R * cpy.C]; | |
76 | + memcpy(M, cpy.M, cpy.R * cpy.C * sizeof(T)); | |
77 | + | |
78 | + R = cpy.R; | |
79 | + C = cpy.C; | |
44 | 80 | } |
45 | 81 | |
46 | 82 | ~matrix() { |
47 | - R = C = 0; | |
48 | 83 | if(M) free(M); |
84 | + M = NULL; | |
85 | + R = C = 0; | |
49 | 86 | } |
50 | 87 | |
51 | - size_t rows(){ | |
88 | + size_t rows() const { | |
52 | 89 | return R; |
53 | 90 | } |
54 | 91 | |
55 | - size_t cols(){ | |
92 | + size_t cols() const { | |
56 | 93 | return C; |
57 | 94 | } |
58 | 95 | |
... | ... | @@ -60,10 +97,8 @@ public: |
60 | 97 | return at(row, col); |
61 | 98 | } |
62 | 99 | |
63 | - matrix<T> operator=(T rhs) { | |
64 | - if (&rhs == this) | |
65 | - return *this; | |
66 | - init(R, C); | |
100 | + matrix<T>& operator=(const T rhs) { | |
101 | + //init(R, C); | |
67 | 102 | size_t N = R * C; |
68 | 103 | for(size_t n=0; n<N; n++) |
69 | 104 | M[n] = rhs; |
... | ... | @@ -71,14 +106,21 @@ public: |
71 | 106 | return *this; |
72 | 107 | } |
73 | 108 | |
74 | - matrix<T>& operator=(matrix<T> rhs){ | |
75 | - init(rhs.R, rhs.C); | |
76 | - memcpy(M, rhs.M, R * C * sizeof(T)); | |
109 | + matrix<T>& operator=(const matrix<T>& rhs){ | |
110 | + if (this != &rhs) { //if the matrix isn't self-assigned | |
111 | + T* new_matrix = new T[rhs.R * rhs.C]; //allocate new resources | |
112 | + memcpy(new_matrix, rhs.M, rhs.R * rhs.C * sizeof(T)); //copy the matrix | |
113 | + | |
114 | + delete[] M; //delete the previous array | |
115 | + M = new_matrix; | |
116 | + R = rhs.R; | |
117 | + C = rhs.C; | |
118 | + } | |
77 | 119 | return *this; |
78 | 120 | } |
79 | 121 | |
80 | 122 | //element-wise operations |
81 | - matrix<T> operator+(T rhs) { | |
123 | + matrix<T> operator+(const T rhs) const { | |
82 | 124 | matrix<T> result(R, C); //create a result matrix |
83 | 125 | size_t N = R * C; |
84 | 126 | |
... | ... | @@ -88,11 +130,39 @@ public: |
88 | 130 | return result; |
89 | 131 | } |
90 | 132 | |
91 | - matrix<T> operator-(T rhs) { | |
133 | + matrix<T> operator+(const matrix<T> rhs) const { | |
134 | + if (R != rhs.R || C != rhs.C) { | |
135 | + std::cout << "ERROR: addition is only defined for matrices that are the same size." << std::endl; | |
136 | + exit(1); | |
137 | + } | |
138 | + matrix<T> result(R, C); //create a result matrix | |
139 | + size_t N = R * C; | |
140 | + | |
141 | + for (int i = 0; i < N; i++) | |
142 | + result.M[i] = M[i] + rhs.M[i]; //calculate the operation and assign to result | |
143 | + | |
144 | + return result; | |
145 | + } | |
146 | + | |
147 | + matrix<T> operator-(const T rhs) const { | |
92 | 148 | return operator+(-rhs); //add the negative of rhs |
93 | 149 | } |
94 | 150 | |
95 | - matrix<T> operator*(T rhs) { | |
151 | + matrix<T> operator-(const matrix<T> rhs) const { | |
152 | + return operator+(-rhs); | |
153 | + } | |
154 | + | |
155 | + matrix<T> operator-() const { | |
156 | + matrix<T> result(R, C); //create a result matrix | |
157 | + size_t N = R * C; | |
158 | + | |
159 | + for (int i = 0; i < N; i++) | |
160 | + result.M[i] = -M[i]; //calculate the operation and assign to result | |
161 | + | |
162 | + return result; | |
163 | + } | |
164 | + | |
165 | + matrix<T> operator*(const T rhs) const { | |
96 | 166 | matrix<T> result(R, C); //create a result matrix |
97 | 167 | size_t N = R * C; |
98 | 168 | |
... | ... | @@ -102,7 +172,7 @@ public: |
102 | 172 | return result; |
103 | 173 | } |
104 | 174 | |
105 | - matrix<T> operator/(T rhs) { | |
175 | + matrix<T> operator/(const T rhs) const { | |
106 | 176 | matrix<T> result(R, C); //create a result matrix |
107 | 177 | size_t N = R * C; |
108 | 178 | |
... | ... | @@ -113,7 +183,7 @@ public: |
113 | 183 | } |
114 | 184 | |
115 | 185 | //matrix multiplication |
116 | - matrix<T> operator*(matrix<T> rhs){ | |
186 | + matrix<T> operator*(const matrix<T> rhs) const { | |
117 | 187 | if(C != rhs.R){ |
118 | 188 | std::cout<<"ERROR: matrix multiplication is undefined for matrices of size "; |
119 | 189 | std::cout<<"[ "<<R<<" x "<<C<<" ] and [ "<<rhs.R<<" x "<<rhs.C<<"]"<<std::endl; |
... | ... | @@ -127,7 +197,7 @@ public: |
127 | 197 | for(r = 0; r < R; r++){ |
128 | 198 | inner = (T)0; |
129 | 199 | for(i = 0; i < C; i++){ |
130 | - inner += at(r, i) * rhs.at(i, c); | |
200 | + inner += get(r, i) * rhs.get(i, c); | |
131 | 201 | } |
132 | 202 | result.M[c * R + r] = inner; |
133 | 203 | } |
... | ... | @@ -141,7 +211,7 @@ public: |
141 | 211 | } |
142 | 212 | |
143 | 213 | //return a transposed matrix |
144 | - matrix<T> transpose(){ | |
214 | + matrix<T> transpose() const { | |
145 | 215 | matrix<T> result(C, R); |
146 | 216 | size_t c, r; |
147 | 217 | for(c = 0; c < C; c++){ |
... | ... | @@ -152,8 +222,31 @@ public: |
152 | 222 | return result; |
153 | 223 | } |
154 | 224 | |
225 | + ///Calculate and return the determinant of the matrix | |
226 | + T det() const { | |
227 | + if (R != C) { | |
228 | + std::cout << "ERROR: a determinant can only be calculated for a square matrix." << std::endl; | |
229 | + exit(1); | |
230 | + } | |
231 | + if (R == 1) return M[0]; //if the matrix only contains one value, return it | |
232 | + | |
233 | + int r, c, ri, cia, cib; | |
234 | + T a = 0; | |
235 | + T b = 0; | |
236 | + for (c = 0; c < C; c++) { | |
237 | + for (r = 0; r < R; r++) { | |
238 | + ri = r; | |
239 | + cia = (r + c) % C; | |
240 | + cib = (C - 1 - r) % C; | |
241 | + a += get(ri, cia); | |
242 | + b += get(ri, cib); | |
243 | + } | |
244 | + } | |
245 | + return a - b; | |
246 | + } | |
247 | + | |
155 | 248 | /// Sort rows of the matrix by the specified indices |
156 | - matrix<T> sort_rows(size_t* idx) { | |
249 | + matrix<T> sort_rows(size_t* idx) const { | |
157 | 250 | matrix<T> result(C, R); //create the output matrix |
158 | 251 | size_t r, c; |
159 | 252 | for (c = 0; c < C; c++) { //for each column |
... | ... | @@ -165,7 +258,7 @@ public: |
165 | 258 | } |
166 | 259 | |
167 | 260 | /// Sort columns of the matrix by the specified indices |
168 | - matrix<T> sort_cols(size_t* idx) { | |
261 | + matrix<T> sort_cols(size_t* idx) const { | |
169 | 262 | matrix<T> result(C, R); |
170 | 263 | size_t c; |
171 | 264 | for (c = 0; c < C; c++) { //for each column |
... | ... | @@ -174,7 +267,7 @@ public: |
174 | 267 | return result; |
175 | 268 | } |
176 | 269 | |
177 | - std::string toStr() { | |
270 | + std::string toStr() const { | |
178 | 271 | std::stringstream ss; |
179 | 272 | |
180 | 273 | for(int r = 0; r < R; r++) { |
... | ... | @@ -187,25 +280,35 @@ public: |
187 | 280 | return ss.str(); |
188 | 281 | } |
189 | 282 | |
190 | - std::string csv() { | |
191 | - std::stringstream csvss; | |
283 | + void csv(std::ostream& out) const { | |
284 | + //std::stringstream csvss; | |
192 | 285 | for (size_t i = 0; i < R; i++) { |
193 | - csvss << M[i]; | |
194 | - for (size_t j = 0; j < C; j++) csvss << ", " << M[j * R + i]; | |
195 | - csvss << std::endl; | |
286 | + out << std::fixed << M[i]; | |
287 | + for (size_t j = 1; j < C; j++) | |
288 | + out << ", " << std::fixed << M[j * R + i]; | |
289 | + out << std::endl; | |
196 | 290 | } |
291 | + //return csvss.str(); | |
292 | + } | |
293 | + | |
294 | + std::string csv() const { | |
295 | + std::stringstream csvss; | |
296 | + int digits = std::numeric_limits<double>::max_digits10; | |
297 | + csvss.precision(digits); | |
298 | + csv(csvss); | |
197 | 299 | return csvss.str(); |
198 | 300 | } |
199 | 301 | |
302 | + | |
303 | + | |
200 | 304 | //save the data as a CSV file |
201 | - void csv(std::string filename) { | |
305 | + void csv(std::string filename) const { | |
202 | 306 | ofstream basisfile(filename.c_str()); |
203 | 307 | basisfile << csv(); |
204 | 308 | basisfile.close(); |
205 | 309 | } |
206 | 310 | |
207 | 311 | static matrix<T> I(size_t N) { |
208 | - | |
209 | 312 | matrix<T> result(N, N); //create the identity matrix |
210 | 313 | memset(result.M, 0, N * N * sizeof(T)); //set the entire matrix to zero |
211 | 314 | for (size_t n = 0; n < N; n++) { |
... | ... | @@ -214,6 +317,19 @@ public: |
214 | 317 | return result; |
215 | 318 | } |
216 | 319 | |
320 | + //loads a matrix from a stream in CSV format | |
321 | + void csv(std::istream& in) { | |
322 | + size_t c, r; | |
323 | + T v; | |
324 | + for (r = 0; r < R; r++) { | |
325 | + for (c = 0; c < C; c++) { | |
326 | + in >> v; | |
327 | + if (in.peek() == ',') in.seekg(1, std::ios::cur); | |
328 | + at(r, c) = v;; | |
329 | + } | |
330 | + } | |
331 | + } | |
332 | + | |
217 | 333 | }; |
218 | 334 | |
219 | 335 | } //end namespace rts | ... | ... |