1 package org.djunits.value.vfloat.matrix.base;
2
3 import java.lang.reflect.Array;
4
5 import org.djunits.Throw;
6 import org.djunits.unit.Unit;
7 import org.djunits.value.Absolute;
8 import org.djunits.value.AbstractIndexedValue;
9 import org.djunits.value.ValueRuntimeException;
10 import org.djunits.value.formatter.Format;
11 import org.djunits.value.storage.StorageType;
12 import org.djunits.value.util.ValueUtil;
13 import org.djunits.value.vfloat.function.FloatFunction;
14 import org.djunits.value.vfloat.function.FloatMathFunctions;
15 import org.djunits.value.vfloat.matrix.data.FloatMatrixData;
16 import org.djunits.value.vfloat.scalar.base.AbstractFloatScalar;
17 import org.djunits.value.vfloat.scalar.base.FloatScalar;
18 import org.djunits.value.vfloat.vector.base.AbstractFloatVector;
19 import org.djunits.value.vfloat.vector.data.FloatVectorData;
20 import org.ojalgo.matrix.PrimitiveMatrix;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public abstract class AbstractFloatMatrix<U extends Unit<U>, S extends AbstractFloatScalar<U, S>,
37 V extends AbstractFloatVector<U, S, V>, M extends AbstractFloatMatrix<U, S, V, M>>
38 extends AbstractIndexedValue<U, S, M, FloatMatrixData> implements FloatMatrixInterface<U, S, V, M>
39 {
40
41 private static final long serialVersionUID = 20161015L;
42
43
44 @SuppressWarnings("checkstyle:visibilitymodifier")
45 protected FloatMatrixData data;
46
47
48
49
50
51
52 AbstractFloatMatrix(final FloatMatrixData data, final U unit)
53 {
54 super(unit);
55 Throw.whenNull(data, "data cannot be null");
56 this.data = data;
57 }
58
59
60 @Override
61 protected final FloatMatrixData getData()
62 {
63 return this.data;
64 }
65
66
67 @Override
68 protected void setData(final FloatMatrixData data)
69 {
70 this.data = data;
71 }
72
73
74 @Override
75 public float getSI(final int row, final int column) throws ValueRuntimeException
76 {
77 checkIndex(row, column);
78 return this.data.getSI(row, column);
79 }
80
81
82 @Override
83 public float getInUnit(final int row, final int column) throws ValueRuntimeException
84 {
85 checkIndex(row, column);
86 return (float) ValueUtil.expressAsUnit(this.data.getSI(row, column), getDisplayUnit());
87 }
88
89
90 @Override
91 public float getInUnit(final int row, final int column, final U targetUnit) throws ValueRuntimeException
92 {
93 checkIndex(row, column);
94 return (float) ValueUtil.expressAsUnit(this.data.getSI(row, column), targetUnit);
95 }
96
97
98 @Override
99 public void setSI(final int row, final int column, final float valueSI) throws ValueRuntimeException
100 {
101 checkIndex(row, column);
102 checkCopyOnWrite();
103 this.data.setSI(row, column, valueSI);
104 }
105
106
107 @Override
108 public void setInUnit(final int row, final int column, final float valueInUnit) throws ValueRuntimeException
109 {
110 setSI(row, column, (float) ValueUtil.expressAsSIUnit(valueInUnit, getDisplayUnit()));
111 }
112
113
114 @Override
115 public void setInUnit(final int row, final int column, final float valueInUnit, final U valueUnit)
116 throws ValueRuntimeException
117 {
118 setSI(row, column, (float) ValueUtil.expressAsSIUnit(valueInUnit, valueUnit));
119 }
120
121
122 @Override
123 public void set(final int row, final int column, final S value) throws ValueRuntimeException
124 {
125 setSI(row, column, value.si);
126 }
127
128
129 @Override
130 public float[] getRowSI(final int row) throws ValueRuntimeException
131 {
132 checkRowIndex(row);
133 float[] result = new float[this.data.cols()];
134 for (int col = 0; col < result.length; col++)
135 {
136 result[col] = this.data.getSI(row, col);
137 }
138 return result;
139 }
140
141
142 @Override
143 public float[] getColumnSI(final int column) throws ValueRuntimeException
144 {
145 checkColumnIndex(column);
146 float[] result = new float[this.data.rows()];
147 for (int row = 0; row < result.length; row++)
148 {
149 result[row] = this.data.getSI(row, column);
150 }
151 return result;
152 }
153
154
155 @Override
156 public float[] getDiagonalSI() throws ValueRuntimeException
157 {
158 checkSquare();
159 float[] result = new float[this.data.rows()];
160 for (int row = 0; row < result.length; row++)
161 {
162 result[row] = this.data.getSI(row, row);
163 }
164 return result;
165 }
166
167
168 @Override
169 public final float[][] getValuesSI()
170 {
171 return this.data.getDenseMatrixSI();
172 }
173
174
175 @Override
176 public final float[][] getValuesInUnit()
177 {
178 return getValuesInUnit(getDisplayUnit());
179 }
180
181
182 @Override
183 public final float[][] getValuesInUnit(final U targetUnit)
184 {
185 float[][] values = getValuesSI();
186 for (int i = values.length; --i >= 0;)
187 {
188 for (int j = values[i].length; --j >= 0;)
189 {
190 values[i][j] = (float) ValueUtil.expressAsUnit(values[i][j], targetUnit);
191 }
192 }
193 return values;
194 }
195
196
197 @Override
198 public int rows()
199 {
200 return this.data.rows();
201 }
202
203
204 @Override
205 public int cols()
206 {
207 return this.data.cols();
208 }
209
210
211 @SuppressWarnings("unchecked")
212 @Override
213 public S[][] getScalars()
214 {
215 S[][] array = (S[][]) Array.newInstance(getScalarClass(), rows(), cols());
216 for (int i = 0; i < rows(); i++)
217 {
218 S[] row = (S[]) Array.newInstance(getScalarClass(), cols());
219 array[i] = row;
220 for (int j = 0; j < cols(); j++)
221 {
222 row[j] = get(i, j);
223 }
224 }
225 return array;
226 }
227
228
229 @Override
230 public S get(final int row, final int column) throws ValueRuntimeException
231 {
232 checkIndex(row, column);
233 return FloatScalar.instantiateSI(getSI(row, column), getDisplayUnit());
234 }
235
236
237 @Override
238 public V getRow(final int row) throws ValueRuntimeException
239 {
240 checkRowIndex(row);
241 FloatVectorData dvd =
242 FloatVectorData.instantiate(getRowSI(row), getDisplayUnit().getStandardUnit().getScale(), getStorageType());
243 return instantiateVector(dvd, getDisplayUnit());
244 }
245
246
247 @Override
248 public V getColumn(final int column) throws ValueRuntimeException
249 {
250 checkColumnIndex(column);
251 FloatVectorData dvd = FloatVectorData.instantiate(getColumnSI(column), getDisplayUnit().getStandardUnit().getScale(),
252 getStorageType());
253 return instantiateVector(dvd, getDisplayUnit());
254 }
255
256
257 @Override
258 public V getDiagonal() throws ValueRuntimeException
259 {
260 checkSquare();
261 FloatVectorData dvd =
262 FloatVectorData.instantiate(getDiagonalSI(), getDisplayUnit().getStandardUnit().getScale(), getStorageType());
263 return instantiateVector(dvd, getDisplayUnit());
264
265 }
266
267
268 @SuppressWarnings("unchecked")
269 @Override
270 public S[] getRowScalars(final int row) throws ValueRuntimeException
271 {
272 checkRowIndex(row);
273 S[] array = (S[]) Array.newInstance(getScalarClass(), cols());
274 for (int col = 0; col < cols(); col++)
275 {
276 array[col] = get(row, col);
277 }
278 return array;
279 }
280
281
282 @SuppressWarnings("unchecked")
283 @Override
284 public S[] getColumnScalars(final int col) throws ValueRuntimeException
285 {
286 checkColumnIndex(col);
287 S[] array = (S[]) Array.newInstance(getScalarClass(), rows());
288 for (int row = 0; row < rows(); row++)
289 {
290 array[row] = get(row, col);
291 }
292 return array;
293 }
294
295
296 @SuppressWarnings("unchecked")
297 @Override
298 public S[] getDiagonalScalars() throws ValueRuntimeException
299 {
300 checkSquare();
301 S[] array = (S[]) Array.newInstance(getScalarClass(), rows());
302 for (int row = 0; row < rows(); row++)
303 {
304 array[row] = get(row, row);
305 }
306 return array;
307 }
308
309
310 @SuppressWarnings("unchecked")
311 @Override
312 public M toSparse()
313 {
314 M result;
315 if (getStorageType().equals(StorageType.SPARSE))
316 {
317 result = (M) this;
318 result.setDisplayUnit(getDisplayUnit());
319 }
320 else
321 {
322 result = instantiateMatrix(this.data.toSparse(), getDisplayUnit());
323 }
324 result.setDisplayUnit(getDisplayUnit());
325 return result;
326 }
327
328
329 @SuppressWarnings("unchecked")
330 @Override
331 public M toDense()
332 {
333 M result;
334 if (getStorageType().equals(StorageType.DENSE))
335 {
336 result = (M) this;
337 result.setDisplayUnit(getDisplayUnit());
338 }
339 else
340 {
341 result = instantiateMatrix(this.data.toDense(), getDisplayUnit());
342 }
343 return result;
344 }
345
346
347 @SuppressWarnings("unchecked")
348 @Override
349 public final M assign(final FloatFunction floatFunction)
350 {
351 checkCopyOnWrite();
352 this.data.assign(floatFunction);
353 return (M) this;
354 }
355
356
357 @Override
358 public final M abs()
359 {
360 return assign(FloatMathFunctions.ABS);
361 }
362
363
364 @Override
365 public final M ceil()
366 {
367 return assign(FloatMathFunctions.CEIL);
368 }
369
370
371 @Override
372 public final M floor()
373 {
374 return assign(FloatMathFunctions.FLOOR);
375 }
376
377
378 @Override
379 public final M neg()
380 {
381 return assign(FloatMathFunctions.NEG);
382 }
383
384
385 @Override
386 public final M rint()
387 {
388 return assign(FloatMathFunctions.RINT);
389 }
390
391
392 @Override
393 public String toString()
394 {
395 return toString(getDisplayUnit(), false, true);
396 }
397
398
399 @Override
400 public String toString(final U displayUnit)
401 {
402 return toString(displayUnit, false, true);
403 }
404
405
406 @Override
407 public String toString(final boolean verbose, final boolean withUnit)
408 {
409 return toString(getDisplayUnit(), verbose, withUnit);
410 }
411
412
413 @Override
414 public String toString(final U displayUnit, final boolean verbose, final boolean withUnit)
415 {
416 StringBuffer buf = new StringBuffer();
417 if (verbose)
418 {
419 String ab = this instanceof Absolute ? "Abs " : "Rel ";
420 String ds = this.data.isDense() ? "Dense " : this.data.isSparse() ? "Sparse " : "?????? ";
421 if (isMutable())
422 {
423 buf.append("Mutable " + ab + ds);
424 }
425 else
426 {
427 buf.append("Immutable " + ab + ds);
428 }
429 }
430 for (int row = 0; row < rows(); row++)
431 {
432 buf.append("\r\n\t");
433 for (int col = 0; col < cols(); col++)
434 {
435 try
436 {
437 float d = (float) ValueUtil.expressAsUnit(getSI(row, col), displayUnit);
438 buf.append(" " + Format.format(d));
439 }
440 catch (ValueRuntimeException ve)
441 {
442 buf.append(" " + "********************".substring(0, Format.DEFAULTSIZE));
443 }
444 }
445 }
446 buf.append("\n");
447 if (withUnit)
448 {
449 buf.append(displayUnit.getDefaultDisplayAbbreviation());
450 }
451 return buf.toString();
452 }
453
454
455
456
457
458
459
460 protected final void checkIndex(final int row, final int col) throws ValueRuntimeException
461 {
462 if (row < 0 || row >= rows() || col < 0 || col >= cols())
463 {
464 throw new ValueRuntimeException("index out of range (valid range is 0.." + (rows() - 1) + ", 0.." + (cols() - 1)
465 + ", got " + row + ", " + col + ")");
466 }
467 }
468
469
470
471
472
473
474 protected final void checkRowIndex(final int row) throws ValueRuntimeException
475 {
476 if (row < 0 || row >= rows())
477 {
478 throw new ValueRuntimeException("row index out of range (valid range is 0.." + (rows() - 1) + ", got " + row + ")");
479 }
480 }
481
482
483
484
485
486
487 protected final void checkColumnIndex(final int col) throws ValueRuntimeException
488 {
489 if (col < 0 || col >= cols())
490 {
491 throw new ValueRuntimeException(
492 "column index out of range (valid range is 0.." + (cols() - 1) + ", got " + col + ")");
493 }
494 }
495
496
497
498
499
500 protected final void checkSquare() throws ValueRuntimeException
501 {
502 Throw.when(rows() != cols(), ValueRuntimeException.class, "Matrix is not square, rows=%d, cols=%d", rows(), cols());
503 }
504
505
506 @Override
507 public final float determinant() throws ValueRuntimeException
508 {
509 try
510 {
511 final PrimitiveMatrix.Factory matrixFactory = PrimitiveMatrix.FACTORY;
512 final PrimitiveMatrix m = matrixFactory.rows(this.data.getDoubleDenseMatrixSI());
513 if (!m.isSquare())
514 {
515 throw new IllegalArgumentException("Matrix is not square -- determinant cannot be calculated.");
516 }
517 return m.getDeterminant().floatValue();
518 }
519 catch (IllegalArgumentException exception)
520 {
521 throw new ValueRuntimeException(exception);
522 }
523 }
524
525
526 @Override
527 @SuppressWarnings("checkstyle:designforextension")
528 public int hashCode()
529 {
530 final int prime = 31;
531 int result = getDisplayUnit().getStandardUnit().hashCode();
532 result = prime * result + ((this.data == null) ? 0 : this.data.hashCode());
533 return result;
534 }
535
536
537 @Override
538 @SuppressWarnings({"checkstyle:designforextension", "checkstyle:needbraces"})
539 public boolean equals(final Object obj)
540 {
541 if (this == obj)
542 return true;
543 if (obj == null)
544 return false;
545 if (getClass() != obj.getClass())
546 return false;
547 AbstractFloatMatrix<?, ?, ?, ?> other = (AbstractFloatMatrix<?, ?, ?, ?>) obj;
548 if (!getDisplayUnit().getStandardUnit().equals(other.getDisplayUnit().getStandardUnit()))
549 return false;
550 if (this.data == null)
551 {
552 if (other.data != null)
553 return false;
554 }
555 else if (!this.data.equals(other.data))
556 return false;
557 return true;
558 }
559 }