Commit 65c1aac005cfcc806e62502c6eabc4ec83352fc8

Authored by David Mayerich
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,42 +17,79 @@ class matrix {
17 size_t R; //number of rows 17 size_t R; //number of rows
18 size_t C; //number of colums 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 R = rows; 21 R = rows;
22 C = cols; 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 T& at(size_t row, size_t col){ 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 return M[col * R + row]; 41 return M[col * R + row];
28 } 42 }
29 43
30 public: 44 public:
31 - 45 + matrix() {
  46 + R = 0;
  47 + C = 0;
  48 + M = NULL;
  49 + }
  50 +
32 matrix(size_t rows, size_t cols) { 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 matrix(size_t rows, size_t cols, T* data) { 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 memcpy(M, data, R * C * sizeof(T)); 67 memcpy(M, data, R * C * sizeof(T));
39 } 68 }
40 69
41 matrix(const matrix<T>& cpy){ 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 ~matrix() { 82 ~matrix() {
47 - R = C = 0;  
48 if(M) free(M); 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 return R; 89 return R;
53 } 90 }
54 91
55 - size_t cols(){ 92 + size_t cols() const {
56 return C; 93 return C;
57 } 94 }
58 95
@@ -60,10 +97,8 @@ public: @@ -60,10 +97,8 @@ public:
60 return at(row, col); 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 size_t N = R * C; 102 size_t N = R * C;
68 for(size_t n=0; n<N; n++) 103 for(size_t n=0; n<N; n++)
69 M[n] = rhs; 104 M[n] = rhs;
@@ -71,14 +106,21 @@ public: @@ -71,14 +106,21 @@ public:
71 return *this; 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 return *this; 119 return *this;
78 } 120 }
79 121
80 //element-wise operations 122 //element-wise operations
81 - matrix<T> operator+(T rhs) { 123 + matrix<T> operator+(const T rhs) const {
82 matrix<T> result(R, C); //create a result matrix 124 matrix<T> result(R, C); //create a result matrix
83 size_t N = R * C; 125 size_t N = R * C;
84 126
@@ -88,11 +130,39 @@ public: @@ -88,11 +130,39 @@ public:
88 return result; 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 return operator+(-rhs); //add the negative of rhs 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 matrix<T> result(R, C); //create a result matrix 166 matrix<T> result(R, C); //create a result matrix
97 size_t N = R * C; 167 size_t N = R * C;
98 168
@@ -102,7 +172,7 @@ public: @@ -102,7 +172,7 @@ public:
102 return result; 172 return result;
103 } 173 }
104 174
105 - matrix<T> operator/(T rhs) { 175 + matrix<T> operator/(const T rhs) const {
106 matrix<T> result(R, C); //create a result matrix 176 matrix<T> result(R, C); //create a result matrix
107 size_t N = R * C; 177 size_t N = R * C;
108 178
@@ -113,7 +183,7 @@ public: @@ -113,7 +183,7 @@ public:
113 } 183 }
114 184
115 //matrix multiplication 185 //matrix multiplication
116 - matrix<T> operator*(matrix<T> rhs){ 186 + matrix<T> operator*(const matrix<T> rhs) const {
117 if(C != rhs.R){ 187 if(C != rhs.R){
118 std::cout<<"ERROR: matrix multiplication is undefined for matrices of size "; 188 std::cout<<"ERROR: matrix multiplication is undefined for matrices of size ";
119 std::cout<<"[ "<<R<<" x "<<C<<" ] and [ "<<rhs.R<<" x "<<rhs.C<<"]"<<std::endl; 189 std::cout<<"[ "<<R<<" x "<<C<<" ] and [ "<<rhs.R<<" x "<<rhs.C<<"]"<<std::endl;
@@ -127,7 +197,7 @@ public: @@ -127,7 +197,7 @@ public:
127 for(r = 0; r < R; r++){ 197 for(r = 0; r < R; r++){
128 inner = (T)0; 198 inner = (T)0;
129 for(i = 0; i < C; i++){ 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 result.M[c * R + r] = inner; 202 result.M[c * R + r] = inner;
133 } 203 }
@@ -141,7 +211,7 @@ public: @@ -141,7 +211,7 @@ public:
141 } 211 }
142 212
143 //return a transposed matrix 213 //return a transposed matrix
144 - matrix<T> transpose(){ 214 + matrix<T> transpose() const {
145 matrix<T> result(C, R); 215 matrix<T> result(C, R);
146 size_t c, r; 216 size_t c, r;
147 for(c = 0; c < C; c++){ 217 for(c = 0; c < C; c++){
@@ -152,8 +222,31 @@ public: @@ -152,8 +222,31 @@ public:
152 return result; 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 /// Sort rows of the matrix by the specified indices 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 matrix<T> result(C, R); //create the output matrix 250 matrix<T> result(C, R); //create the output matrix
158 size_t r, c; 251 size_t r, c;
159 for (c = 0; c < C; c++) { //for each column 252 for (c = 0; c < C; c++) { //for each column
@@ -165,7 +258,7 @@ public: @@ -165,7 +258,7 @@ public:
165 } 258 }
166 259
167 /// Sort columns of the matrix by the specified indices 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 matrix<T> result(C, R); 262 matrix<T> result(C, R);
170 size_t c; 263 size_t c;
171 for (c = 0; c < C; c++) { //for each column 264 for (c = 0; c < C; c++) { //for each column
@@ -174,7 +267,7 @@ public: @@ -174,7 +267,7 @@ public:
174 return result; 267 return result;
175 } 268 }
176 269
177 - std::string toStr() { 270 + std::string toStr() const {
178 std::stringstream ss; 271 std::stringstream ss;
179 272
180 for(int r = 0; r < R; r++) { 273 for(int r = 0; r < R; r++) {
@@ -187,25 +280,35 @@ public: @@ -187,25 +280,35 @@ public:
187 return ss.str(); 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 for (size_t i = 0; i < R; i++) { 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 return csvss.str(); 299 return csvss.str();
198 } 300 }
199 301
  302 +
  303 +
200 //save the data as a CSV file 304 //save the data as a CSV file
201 - void csv(std::string filename) { 305 + void csv(std::string filename) const {
202 ofstream basisfile(filename.c_str()); 306 ofstream basisfile(filename.c_str());
203 basisfile << csv(); 307 basisfile << csv();
204 basisfile.close(); 308 basisfile.close();
205 } 309 }
206 310
207 static matrix<T> I(size_t N) { 311 static matrix<T> I(size_t N) {
208 -  
209 matrix<T> result(N, N); //create the identity matrix 312 matrix<T> result(N, N); //create the identity matrix
210 memset(result.M, 0, N * N * sizeof(T)); //set the entire matrix to zero 313 memset(result.M, 0, N * N * sizeof(T)); //set the entire matrix to zero
211 for (size_t n = 0; n < N; n++) { 314 for (size_t n = 0; n < N; n++) {
@@ -214,6 +317,19 @@ public: @@ -214,6 +317,19 @@ public:
214 return result; 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 } //end namespace rts 335 } //end namespace rts