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