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 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
... ...