]> gitweb.fperrin.net Git - GpsPrune.git/blob - src/tim/prune/function/estimate/jama/Matrix.java
Moved source into separate src directory due to popular request
[GpsPrune.git] / src / tim / prune / function / estimate / jama / Matrix.java
1 package tim.prune.function.estimate.jama;\r
2 \r
3 /**\r
4  * The Java Matrix Class provides the fundamental operations of numerical linear algebra.\r
5  * Original authors The MathWorks, Inc. and the National Institute of Standards and Technology\r
6  * The original public domain code has now been modified and reduced to only contain\r
7  * the use of QR Decomposition of rectangular matrices, to solve least squares regression,\r
8  * and is placed under GPL2 with the rest of the GpsPrune code.\r
9  */\r
10 public class Matrix\r
11 {\r
12 \r
13         /** Array for internal storage of elements */\r
14         private double[][] _matrix;\r
15 \r
16         /** Row and column dimensions */\r
17         private int _m, _n;\r
18 \r
19 \r
20         /**\r
21          * Construct an m-by-n matrix of zeros\r
22          * @param inM  Number of rows\r
23          * @param inN  Number of colums\r
24          */\r
25         public Matrix(int inM, int inN)\r
26         {\r
27                 _m = inM;\r
28                 _n = inN;\r
29                 _matrix = new double[inM][inN];\r
30         }\r
31 \r
32         /**\r
33          * Construct a matrix from a 2-D array\r
34          * @param A   Two-dimensional array of doubles.\r
35          * @exception IllegalArgumentException All rows must have the same length\r
36          */\r
37         public Matrix(double[][] A)\r
38         {\r
39                 _m = A.length;\r
40                 _n = A[0].length;\r
41                 for (int i = 0; i < _m; i++) {\r
42                         if (A[i].length != _n) {\r
43                                 throw new IllegalArgumentException("All rows must have the same length.");\r
44                         }\r
45                 }\r
46                 _matrix = A;\r
47         }\r
48 \r
49         /**\r
50          * Construct a matrix quickly without checking arguments.\r
51          * @param inA   Two-dimensional array of doubles.\r
52          * @param inM   Number of rows\r
53          * @param inN   Number of columns\r
54          */\r
55         public Matrix(double[][] inA, int inM, int inN)\r
56         {\r
57                 _matrix = inA;\r
58                 _m = inM;\r
59                 _n = inN;\r
60         }\r
61 \r
62         /*\r
63          * ------------------------ Public Methods ------------------------\r
64          */\r
65 \r
66 \r
67         /**\r
68          * Set a value in a cell of the matrix\r
69          * @param inRow row index\r
70          * @param inCol column index\r
71          * @param inValue value to set\r
72          */\r
73         public void setValue(int inRow, int inCol, double inValue)\r
74         {\r
75                 _matrix[inRow][inCol] = inValue;\r
76         }\r
77 \r
78         /**\r
79          * Access the internal two-dimensional array.\r
80          * @return Pointer to the two-dimensional array of matrix elements.\r
81          */\r
82         public double[][] getArray() {\r
83                 return _matrix;\r
84         }\r
85 \r
86         /**\r
87          * Copy the internal two-dimensional array.\r
88          * @return Two-dimensional array copy of matrix elements.\r
89          */\r
90         public double[][] getArrayCopy()\r
91         {\r
92                 double[][] C = new double[_m][_n];\r
93                 for (int i = 0; i < _m; i++) {\r
94                         for (int j = 0; j < _n; j++) {\r
95                                 C[i][j] = _matrix[i][j];\r
96                         }\r
97                 }\r
98                 return C;\r
99         }\r
100 \r
101         /**\r
102          * Get a single element.\r
103          * @param inRow   Row index\r
104          * @param inCol   Column index\r
105          * @return A(inRow,inCol)\r
106          * @exception ArrayIndexOutOfBoundsException\r
107          */\r
108         public double get(int inRow, int inCol) {\r
109                 return _matrix[inRow][inCol];\r
110         }\r
111 \r
112         /** @return number of rows _m */\r
113         public int getNumRows() {\r
114                 return _m;\r
115         }\r
116 \r
117         /** @return number of columns _n */\r
118         public int getNumColumns() {\r
119                 return _n;\r
120         }\r
121 \r
122         /**\r
123          * Get a submatrix\r
124          * @param i0  Initial row index\r
125          * @param i1  Final row index\r
126          * @param j0  Initial column index\r
127          * @param j1  Final column index\r
128          * @return A(i0:i1,j0:j1)\r
129          * @exception ArrayIndexOutOfBoundsException\r
130          */\r
131         public Matrix getMatrix(int i0, int i1, int j0, int j1)\r
132         {\r
133                 Matrix X = new Matrix(i1 - i0 + 1, j1 - j0 + 1);\r
134                 double[][] B = X.getArray();\r
135                 try {\r
136                         for (int i = i0; i <= i1; i++) {\r
137                                 for (int j = j0; j <= j1; j++) {\r
138                                         B[i - i0][j - j0] = _matrix[i][j];\r
139                                 }\r
140                         }\r
141                 } catch (ArrayIndexOutOfBoundsException e) {\r
142                         throw new ArrayIndexOutOfBoundsException("Submatrix indices");\r
143                 }\r
144                 return X;\r
145         }\r
146 \r
147 \r
148         /**\r
149          * Linear algebraic matrix multiplication, A * B\r
150          * @param B   another matrix\r
151          * @return Matrix product, A * B\r
152          * @exception IllegalArgumentException if matrix dimensions don't agree\r
153          */\r
154         public Matrix times(Matrix B)\r
155         {\r
156                 if (B._m != _n) {\r
157                         throw new IllegalArgumentException("Matrix inner dimensions must agree.");\r
158                 }\r
159                 Matrix X = new Matrix(_m, B._n);\r
160                 double[][] C = X.getArray();\r
161                 double[] Bcolj = new double[_n];\r
162                 for (int j = 0; j < B._n; j++) {\r
163                         for (int k = 0; k < _n; k++) {\r
164                                 Bcolj[k] = B._matrix[k][j];\r
165                         }\r
166                         for (int i = 0; i < _m; i++) {\r
167                                 double[] Arowi = _matrix[i];\r
168                                 double s = 0;\r
169                                 for (int k = 0; k < _n; k++) {\r
170                                         s += Arowi[k] * Bcolj[k];\r
171                                 }\r
172                                 C[i][j] = s;\r
173                         }\r
174                 }\r
175                 return X;\r
176         }\r
177 \r
178         /**\r
179          * Subtract the other matrix from this one\r
180          * @param B   another matrix\r
181          * @return difference this - B\r
182          * @exception IllegalArgumentException if matrix dimensions don't agree\r
183          */\r
184         public Matrix minus(Matrix B)\r
185         {\r
186                 if (B._m != _m || B._n != _n) {\r
187                         throw new IllegalArgumentException("Matrix dimensions must agree.");\r
188                 }\r
189                 Matrix result = new Matrix(_m, _n);\r
190                 for (int i = 0; i < _m; i++) {\r
191                         for (int j = 0; j < _n; j++) {\r
192                                 result.setValue(i, j, get(i, j) - B.get(i, j));\r
193                         }\r
194                 }\r
195                 return result;\r
196         }\r
197 \r
198         /**\r
199          * Divide each element of this matrix by the corresponding element in the other one\r
200          * @param B   another matrix\r
201          * @return this[i,j]/other[i,j]\r
202          * @exception IllegalArgumentException if matrix dimensions don't agree\r
203          */\r
204         public Matrix divideEach(Matrix B)\r
205         {\r
206                 if (B._m != _m || B._n != _n) {\r
207                         throw new IllegalArgumentException("Matrix dimensions must agree.");\r
208                 }\r
209                 Matrix result = new Matrix(_m, _n);\r
210                 for (int i = 0; i < _m; i++) {\r
211                         for (int j = 0; j < _n; j++) {\r
212                                 result.setValue(i, j, get(i, j) / B.get(i, j));\r
213                         }\r
214                 }\r
215                 return result;\r
216         }\r
217 \r
218         /**\r
219          * Solve A*X = B\r
220          * @param B   right hand side\r
221          * @return least squares solution\r
222          */\r
223         public Matrix solve(Matrix B) {\r
224                 return new QRDecomposition(this).solve(B);\r
225         }\r
226 \r
227         /**\r
228          * @return the average absolute value of all the elements in the matrix\r
229          */\r
230         public double getAverageAbsValue()\r
231         {\r
232                 double total = 0.0;\r
233                 for (int i = 0; i < _m; i++) {\r
234                         for (int j = 0; j < _n; j++) {\r
235                                 total += Math.abs(_matrix[i][j]);\r
236                         }\r
237                 }\r
238                 return total / _m / _n;\r
239         }\r
240 \r
241         /**\r
242          * Primitive output for debugging\r
243          */\r
244         public String toString()\r
245         {\r
246                 StringBuilder builder = new StringBuilder();\r
247                 builder.append('(');\r
248                 for (int i = 0; i < _m; i++) {\r
249                         builder.append('(');\r
250                         for (int j = 0; j < _n; j++) {\r
251                                 builder.append((_matrix[i][j]));\r
252                                 builder.append(", ");\r
253                         }\r
254                         builder.append(") ");\r
255                 }\r
256                 builder.append(')');\r
257                 return builder.toString();\r
258         }\r
259 }\r