1 // Matrix.java
2 // a simple java file for a standard class
3
4 package math.utils;
5
6 // Imports
7
8 /**
9 * class Matrix
10 */
11 public class Matrix {
12
13 // ===================================================================
14 // constants
15
16 // ===================================================================
17 // class variables
18
19 /** the number of rows. */
20 private int nRows;
21 /** the number of columns. */
22 private int nCols;
23
24 /** the element array of the matrix. */
25 private double[][] el;
26
27 // ===================================================================
28 // constructors
29
30 /** Main constructor */
31
32 /**
33 * Construct a new Matrix, with 1 row and 1 column, initialized to 1.
34 */
35 public Matrix() {
36 this(1, 1);
37 }
38
39 /** init a new Matrix with nbRows rows, and nbCols columns. */
40 public Matrix(int nbRows, int nbCols) {
41 nRows = nbRows;
42 nCols = nbCols;
43 el = new double[nRows][nCols];
44 setToIdentity();
45 }
46
47 /**
48 * Construct a new Matrix, initialized with the given coefficients.
49 */
50 public Matrix(double[][] coef) {
51 if (coef==null) {
52 nRows = 1;
53 nCols = 1;
54 el = new double[nRows][nCols];
55 setToIdentity();
56 return;
57 }
58
59 nRows = coef.length;
60 nCols = coef[0].length;
61 el = new double[nRows][nCols];
62 for (int r = 0; r<nRows; r++)
63 for (int c = 0; c<nCols; c++)
64 el[r][c] = coef[r][c];
65 }
66
67 // ===================================================================
68 // accessors
69
70 /**
71 * return the coef. row and col are between 1 and the number of rows and
72 * columns.
73 */
74 public double getCoef(int row, int col) {
75 return el[row-1][col-1];
76 }
77
78 /** return the number of rows. */
79 public int getRows() {
80 return nRows;
81 }
82
83 /** return the number of columns. */
84 public int getColumns() {
85 return nCols;
86 }
87
88 /**
89 * return true if the matrix is square, i.e. the number of rows equals the
90 * number of columns.
91 */
92 public boolean isSquare() {
93 return (nCols==nRows);
94 }
95
96 // ===================================================================
97 // modifiers
98
99 /**
100 * set the coef to the given value. row and col are between 1 and the number
101 * of rows and columns.
102 */
103 public void setCoef(int row, int col, double coef) {
104 el[row-1][col-1] = coef;
105 }
106
107 // ===================================================================
108 // computation methods
109
110 /**
111 * return the result of the multiplication of the matriux with another one.
112 * The content of the matrix is not modified.
113 */
114 public Matrix multiplyWith(Matrix matrix) {
115
116 // check sizes of the matrices
117 if (nCols!=matrix.nRows) {
118 System.out.println("Matrices size don't match !");
119 return null;
120 }
121 double sum;
122
123 Matrix m = new Matrix(nRows, matrix.nCols);
124
125 for (int r = 0; r<m.nRows; r++)
126 for (int c = 0; c<m.nCols; c++) {
127 sum = 0;
128 for (int i = 0; i<nCols; i++)
129 sum += el[r][i]*matrix.el[i][c];
130 m.el[r][c] = sum;
131 }
132
133 return m;
134 }
135
136 /**
137 * return the result of the multiplication of the matrix with the given
138 * vector. The content of the matrix is not modified.
139 */
140 public double[] multiplyWith(double[] coefs) {
141
142 if (coefs==null) {
143 System.out.println("no data to compute");
144 return null;
145 }
146
147 // check sizes of matrix and vector
148 if (coefs.length!=nCols) {
149 System.out.println("Matrices size don't match !");
150 return null;
151 }
152 double sum;
153 double[] res = new double[nRows];
154
155 for (int r = 0; r<nRows; r++) {
156 sum = 0;
157 for (int c = 0; c<nCols; c++)
158 sum += el[r][c]*coefs[c];
159 res[r] = sum;
160 }
161 return res;
162 }
163
164 /**
165 * return the result of the multiplication of the matrix with the given
166 * vector. The content of the matrix is not modified.
167 */
168 public double[] multiplyWith(double[] src, double[] res) {
169
170 if (src==null) {
171 System.out.println("no data to compute");
172 return null;
173 }
174
175 // check sizes of matrix and vector
176 if (src.length!=nCols) {
177 System.out.println("Matrices size don't match !");
178 return null;
179 }
180 if (src.length!=res.length)
181 res = new double[nRows];
182
183 double sum;
184
185 for (int r = 0; r<nRows; r++) {
186 sum = 0;
187 for (int c = 0; c<nCols; c++)
188 sum += el[r][c]*src[c];
189 res[r] = sum;
190 }
191 return res;
192 }
193
194 /** transpose the matrix, changing the inner coefficients. */
195 public void transpose() {
196 int tmp = nCols;
197 nCols = nRows;
198 nRows = tmp;
199 double[][] oldData = el;
200 el = new double[nRows][nCols];
201
202 for (int r = 0; r<nRows; r++)
203 for (int c = 0; c<nCols; c++)
204 el[r][c] = oldData[c][r];
205 }
206
207 /**
208 * get the transposed matrix, without changing the inner coefficients of the
209 * original matrix.
210 */
211 public Matrix getTranspose() {
212 Matrix mat = new Matrix(nCols, nRows);
213
214 for (int r = 0; r<nRows; r++)
215 for (int c = 0; c<nCols; c++)
216 mat.el[c][r] = el[r][c];
217 return mat;
218 }
219
220 /**
221 * compute the solution of a linear system, using the Gauss-Jordan
222 * algorithm. The inner coefficients of the matrix are not modified.
223 */
224 public double[] solve(double vector[]) {
225
226 if (vector==null)
227 throw new NullPointerException();
228 if (vector.length!=nRows) {
229 System.out.println("matrix and vector dimensions do not match!");
230 return null;
231 }
232 if (nCols!=nRows) {
233 System.out.println("Try to invert non square Matrix.");
234 return null;
235 }
236
237 double[] res = new double[vector.length];
238 for (int i = 0; i<nRows; i++)
239 res[i] = vector[i];
240
241 Matrix mat = new Matrix(el);
242
243 int r, c; // row and column indices
244 int p, r2; // pivot index, and secondary row index
245 double pivot, tmp;
246
247 // for each line of the matrix
248 for (r = 0; r<nRows; r++) {
249
250 p = r;
251 // look for the first non-null pivot
252 while ((Math.abs(mat.el[p][r])<1e-15)&&(p<=nRows))
253 p++;
254
255 if (p==nRows) {
256 System.out.println("Degenerated linear system :");
257 return null;
258 }
259
260 // swap the current line and the pivot
261 for (c = 0; c<nRows; c++) {
262 tmp = mat.el[r][c];
263 mat.el[r][c] = mat.el[p][c];
264 mat.el[p][c] = tmp;
265 }
266
267 // swap the corresponding values in the vector
268 tmp = res[r];
269 res[r] = res[p];
270 res[p] = tmp;
271
272 pivot = mat.el[r][r];
273
274 // divide elements of the current line by the pivot
275 for (c = r+1; c<nRows; c++)
276 mat.el[r][c] /= pivot;
277 res[r] /= pivot;
278 mat.el[r][r] = 1;
279
280 // update other lines, before current line...
281 for (r2 = 0; r2<r; r2++) {
282 pivot = mat.el[r2][r];
283 for (c = r+1; c<nRows; c++)
284 mat.el[r2][c] -= pivot*mat.el[r][c];
285 res[r2] -= pivot*res[r];
286 mat.el[r2][r] = 0;
287 }
288
289 // and after current line
290 for (r2 = r+1; r2<nRows; r2++) {
291 pivot = mat.el[r2][r];
292 for (c = r+1; c<nRows; c++)
293 mat.el[r2][c] -= pivot*mat.el[r][c];
294 res[r2] -= pivot*res[r];
295 mat.el[r2][r] = 0;
296 }
297 }
298
299 return res;
300 }
301
302 // ===================================================================
303 // general methods
304
305 /**
306 * Fill the matrix with zeros everywhere, except on the main diagonal,
307 * filled with ones.
308 */
309 public void setToIdentity() {
310 for (int r = 0; r<nRows; r++)
311 for (int c = 0; c<nCols; c++)
312 el[r][c] = 0;
313 for (int i = Math.min(nRows, nCols)-1; i>=0; i--)
314 el[i][i] = 1;
315 }
316
317 /**
318 * return a String representation of the elements of the Matrix
319 */
320 @Override
321 public String toString() {
322 String res = new String("");
323 res = res.concat("Matrix size : "+Integer.toString(nRows)+" rows and "
324 +Integer.toString(nCols)+" columns.\n");
325 for (int r = 0; r<nRows; r++) {
326 for (int c = 0; c<nCols; c++)
327 res = res.concat(Double.toString(el[r][c])).concat(" ");
328 res = res.concat(new String("\n"));
329 }
330 return res;
331 }
332 }