1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package p3j.misc.math;
17
18 import james.SimSystem;
19
20 import java.util.List;
21 import java.util.logging.Level;
22
23 import cern.colt.matrix.impl.DenseDoubleMatrix2D;
24
25
26
27
28
29
30
31
32
33
34 public class Matrix2D extends DenseDoubleMatrix2D {
35
36
37 private static final long serialVersionUID = 8686379106612322945L;
38
39
40 static final long OFFSET_ROW = 1000L;
41
42
43 static final long OFFSET_HASH = 1000000L;
44
45
46 static final String ERR_MSG_COL_STORE = "Matrix operation error: Can't store to column with index ";
47
48
49 static final String ERR_MSG_SOURCE_MATRIX = "Matrix operation error: source matrix has ";
50
51
52 static final String ERR_MSG_CANNOT_READ = " cannot be read.";
53
54
55 static final String ERR_MSG_COL = ", so column with index ";
56
57
58 private String rowLabel = "";
59
60
61 private String columnLabel = "";
62
63
64
65
66
67
68
69
70
71
72
73 public Matrix2D(double[][] values, String rLabel, String cLabel) {
74 super(values);
75 this.rowLabel = rLabel;
76 this.columnLabel = cLabel;
77 }
78
79
80
81
82 public Matrix2D() {
83 super(new double[0][0]);
84 }
85
86
87
88
89
90
91
92
93
94 public Matrix2D(int rows, int columns) {
95 super(rows, columns);
96 }
97
98
99
100
101
102
103
104
105
106 public void assignColumn(int index, double[] values) {
107
108 if (index >= this.columns) {
109 throw new IllegalArgumentException(ERR_MSG_COL_STORE + index
110 + " - matrix only has " + this.columns + " columns");
111 }
112
113 if (values.length != this.rows) {
114 throw new IllegalArgumentException("Matrix operation error: Can't store "
115 + values.length + " - value vector to matrix with " + this.rows
116 + " rows");
117 }
118
119 for (int i = 0; i < this.rows; i++) {
120 this.setQuick(i, index, values[i]);
121 }
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135 public void assignColumn(int indexSourceColumn, Matrix2D source,
136 int indexTargetColumn) {
137
138 if (source.rows != this.rows) {
139 throw new IllegalArgumentException(ERR_MSG_SOURCE_MATRIX + source.rows
140 + "rows, while this matrix has " + this.rows + ".");
141 }
142
143 if (indexSourceColumn >= source.columns) {
144 throw new IllegalArgumentException(ERR_MSG_SOURCE_MATRIX + source.columns
145 + ERR_MSG_COL + indexSourceColumn + ERR_MSG_CANNOT_READ);
146 }
147
148 if (indexTargetColumn >= this.columns) {
149 throw new IllegalArgumentException(
150 "Matrix operation error: target matrix has " + this.columns
151 + ERR_MSG_COL + indexTargetColumn + ERR_MSG_CANNOT_READ);
152 }
153
154 for (int i = 0; i < this.rows; i++) {
155 this.setQuick(i, indexTargetColumn, source.getQuick(i, indexSourceColumn));
156 }
157 }
158
159 @Override
160 public Matrix2D copy() {
161 return new Matrix2D(this.getContent().toArray(), this.getRowLabel(),
162 this.getColumnLabel());
163 }
164
165
166
167
168
169
170
171
172 public static long calculateHashCode(Matrix2D val) {
173
174 long result = 0;
175 result *= OFFSET_HASH;
176 result += OFFSET_ROW * val.rows() + val.columns();
177 return result;
178 }
179
180 @Override
181 public boolean equals(Object o) {
182 if (!(o instanceof Matrix2D)) {
183 return false;
184 }
185 if (!super.equals(o)) {
186 return false;
187 }
188 Matrix2D val = (Matrix2D) o;
189 return rowLabel.equals(val.getRowLabel())
190 && columnLabel.equals(val.getColumnLabel());
191 }
192
193 @Override
194 public int hashCode() {
195 return (int) calculateHashCode(this);
196 }
197
198
199
200
201
202
203
204
205
206 public static void subMatrix(Matrix2D source, Matrix2D target) {
207 for (int i = 0; i < Math.min(source.rows, target.rows); i++) {
208 for (int j = 0; j < Math.min(source.columns, target.columns); j++) {
209 target.setQuick(i, j, source.get(i, j));
210 }
211 }
212 }
213
214 public String getColumnLabel() {
215 return columnLabel;
216 }
217
218 public void setColumnLabel(String columnLabel) {
219 this.columnLabel = columnLabel;
220 }
221
222 public String getRowLabel() {
223 return rowLabel;
224 }
225
226 public void setRowLabel(String rowLabel) {
227 this.rowLabel = rowLabel;
228 }
229
230
231
232
233
234
235
236
237 public static Matrix2D add(List<Matrix2D> addList) {
238 Matrix2D[] list = addList.toArray(new Matrix2D[0]);
239 Matrix2D result = list[0].copy();
240 for (int i = 0; i < result.rows(); i++) {
241 for (int j = 0; j < result.columns(); j++) {
242 double res = result.getQuick(i, j);
243 for (int k = 1; k < list.length; k++) {
244 res += list[k].getQuick(i, j);
245 }
246 result.setQuick(i, j, res);
247 }
248 }
249 return result;
250 }
251
252
253
254
255
256
257
258
259 public static Matrix2D sumRows(Matrix2D mat) {
260 return sumRows(mat, null, null);
261 }
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 public static Matrix2D sumRows(Matrix2D mat, Integer lowerBorder,
277 Integer upperBorder) {
278 Matrix2D result = new Matrix2D(1, mat.columns);
279 int lowB = lowerBorder == null ? 0 : lowerBorder;
280 int upB = upperBorder == null ? mat.rows : upperBorder;
281 for (int i = 0; i < mat.columns(); i++) {
282 double res = 0.0;
283 for (int j = lowB; j < upB; j++) {
284 res += mat.getQuick(j, i);
285 }
286 result.setQuick(0, i, res);
287 }
288 return result;
289 }
290
291
292
293
294
295
296
297
298
299 public Matrix2D sub(List<Matrix2D> subList) {
300 Matrix2D result = copy();
301 for (int i = 0; i < result.rows(); i++) {
302 for (int j = 0; j < result.columns(); j++) {
303 double sub = 0.0;
304 for (Matrix2D subMat : subList) {
305 sub += subMat.getQuick(i, j);
306 }
307 result.setQuick(i, j, result.getQuick(i, j) - sub);
308 }
309 }
310 return result;
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324 public Matrix2D getResizedMatrix(int newRows, int newCols) {
325 if (newRows <= 0 || newCols <= 0) {
326 SimSystem.report(Level.WARNING, "Resize to " + newRows + " x " + newCols
327 + " matrix not supported - matrix must not be empty.");
328 return copy();
329 }
330 Matrix2D result = new Matrix2D(newRows, newCols);
331 result.setRowLabel(rowLabel);
332 result.setColumnLabel(columnLabel);
333 int minRows = Math.min(rows, newRows);
334 int minCols = Math.min(columns, newCols);
335
336 for (int row = 0; row < minRows; row++) {
337 for (int col = 0; col < minCols; col++) {
338 result.setQuick(row, col, getQuick(row, col));
339 }
340 }
341 return result;
342 }
343
344 }