RobotCore 1.0
WPILib port to raspberry Pi
Loading...
Searching...
No Matches
Matrix.java
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5package org.wpilib.math.linalg;
6
7import java.util.Objects;
8import org.ejml.MatrixDimensionException;
9import org.ejml.data.DMatrixRMaj;
10import org.ejml.dense.row.CommonOps_DDRM;
11import org.ejml.dense.row.MatrixFeatures_DDRM;
12import org.ejml.dense.row.NormOps_DDRM;
13import org.ejml.dense.row.factory.DecompositionFactory_DDRM;
14import org.ejml.interfaces.decomposition.CholeskyDecomposition_F64;
15import org.ejml.simple.SimpleMatrix;
16import org.wpilib.math.jni.EigenJNI;
17import org.wpilib.math.linalg.proto.MatrixProto;
18import org.wpilib.math.linalg.struct.MatrixStruct;
19import org.wpilib.math.numbers.N1;
20import org.wpilib.math.util.Nat;
21import org.wpilib.math.util.Num;
22import org.wpilib.util.protobuf.Protobuf;
23import org.wpilib.util.protobuf.ProtobufSerializable;
24import org.wpilib.util.struct.Struct;
25import org.wpilib.util.struct.StructSerializable;
26
35public class Matrix<R extends Num, C extends Num>
38 protected final SimpleMatrix m_storage;
39
46 public Matrix(Nat<R> rows, Nat<C> columns) {
47 this.m_storage =
48 new SimpleMatrix(
49 Objects.requireNonNull(rows).getNum(), Objects.requireNonNull(columns).getNum());
50 }
51
60 public Matrix(Nat<R> rows, Nat<C> columns, double[] storage) {
61 this.m_storage = new SimpleMatrix(rows.getNum(), columns.getNum(), true, storage);
62 }
63
74 public Matrix(SimpleMatrix storage) {
75 this.m_storage = Objects.requireNonNull(storage);
76 }
77
83 public Matrix(Matrix<R, C> other) {
84 this.m_storage = Objects.requireNonNull(other).getStorage().copy();
85 }
86
96 public SimpleMatrix getStorage() {
97 return m_storage;
98 }
99
105 public final int getNumCols() {
106 return this.m_storage.getNumCols();
107 }
108
114 public final int getNumRows() {
115 return this.m_storage.getNumRows();
116 }
117
125 public final double get(int row, int col) {
126 return this.m_storage.get(row, col);
127 }
128
136 public final void set(int row, int col, double value) {
137 this.m_storage.set(row, col, value);
138 }
139
146 public final void setRow(int row, Matrix<N1, C> val) {
147 this.m_storage.setRow(row, 0, Objects.requireNonNull(val).m_storage.getDDRM().getData());
148 }
149
156 public final void setColumn(int column, Matrix<R, N1> val) {
157 this.m_storage.setColumn(column, 0, Objects.requireNonNull(val).m_storage.getDDRM().getData());
158 }
159
165 public void fill(double value) {
166 this.m_storage.fill(value);
167 }
168
174 public final double max() {
175 return CommonOps_DDRM.elementMax(this.m_storage.getDDRM());
176 }
177
183 public final double maxAbs() {
184 return CommonOps_DDRM.elementMaxAbs(this.m_storage.getDDRM());
185 }
186
192 public final double minInternal() {
193 return CommonOps_DDRM.elementMin(this.m_storage.getDDRM());
194 }
195
201 public final double mean() {
202 return this.elementSum() / this.m_storage.getNumElements();
203 }
204
216 public final <C2 extends Num> Matrix<R, C2> times(Matrix<C, C2> other) {
217 return new Matrix<>(this.m_storage.mult(Objects.requireNonNull(other).m_storage));
218 }
219
226 public Matrix<R, C> times(double value) {
227 return new Matrix<>(this.m_storage.scale(value));
228 }
229
240 return new Matrix<>(this.m_storage.elementMult(Objects.requireNonNull(other).m_storage));
241 }
242
249 public final Matrix<R, C> minus(double value) {
250 return new Matrix<>(this.m_storage.minus(value));
251 }
252
259 public final Matrix<R, C> minus(Matrix<R, C> value) {
260 return new Matrix<>(this.m_storage.minus(Objects.requireNonNull(value).m_storage));
261 }
262
269 public final Matrix<R, C> plus(double value) {
270 return new Matrix<>(this.m_storage.plus(value));
271 }
272
279 public final Matrix<R, C> plus(Matrix<R, C> value) {
280 return new Matrix<>(this.m_storage.plus(Objects.requireNonNull(value).m_storage));
281 }
282
289 public Matrix<R, C> div(int value) {
290 return new Matrix<>(this.m_storage.divide(value));
291 }
292
299 public Matrix<R, C> div(double value) {
300 return new Matrix<>(this.m_storage.divide(value));
301 }
302
308 public final Matrix<C, R> transpose() {
309 return new Matrix<>(this.m_storage.transpose());
310 }
311
317 public final Matrix<R, C> copy() {
318 return new Matrix<>(this.m_storage.copy());
319 }
320
327 public final Matrix<R, C> inv() {
328 return new Matrix<>(this.m_storage.invert());
329 }
330
337 return new Matrix<>(this.m_storage.pseudoInverse());
338 }
339
350 public final <C2 extends Num> Matrix<C, C2> solve(Matrix<R, C2> b) {
351 return new Matrix<>(this.m_storage.solve(Objects.requireNonNull(b).m_storage));
352 }
353
360 public final Matrix<R, C> exp() {
361 if (this.getNumRows() != this.getNumCols()) {
362 throw new MatrixDimensionException(
363 "Non-square matrices cannot be exponentiated! "
364 + "This matrix is "
365 + this.getNumRows()
366 + " x "
367 + this.getNumCols());
368 }
369 Matrix<R, C> toReturn = new Matrix<>(new SimpleMatrix(this.getNumRows(), this.getNumCols()));
370 EigenJNI.exp(
371 this.m_storage.getDDRM().getData(),
372 this.getNumRows(),
373 toReturn.m_storage.getDDRM().getData());
374 return toReturn;
375 }
376
384 public final Matrix<R, C> pow(double exponent) {
385 if (this.getNumRows() != this.getNumCols()) {
386 throw new MatrixDimensionException(
387 "Non-square matrices cannot be raised to a power! "
388 + "This matrix is "
389 + this.getNumRows()
390 + " x "
391 + this.getNumCols());
392 }
393 Matrix<R, C> toReturn = new Matrix<>(new SimpleMatrix(this.getNumRows(), this.getNumCols()));
394 EigenJNI.pow(
395 this.m_storage.getDDRM().getData(),
396 this.getNumRows(),
397 exponent,
398 toReturn.m_storage.getDDRM().getData());
399 return toReturn;
400 }
401
407 public final double det() {
408 return this.m_storage.determinant();
409 }
410
418 public final double normF() {
419 return this.m_storage.normF();
420 }
421
429 public final double normIndP1() {
430 return NormOps_DDRM.inducedP1(this.m_storage.getDDRM());
431 }
432
438 public final double elementSum() {
439 return this.m_storage.elementSum();
440 }
441
447 public final double trace() {
448 return this.m_storage.trace();
449 }
450
459 public final Matrix<R, C> elementPower(double b) {
460 return new Matrix<>(this.m_storage.elementPower(b));
461 }
462
471 public final Matrix<R, C> elementPower(int b) {
472 return new Matrix<>(this.m_storage.elementPower(b));
473 }
474
481 public final Matrix<N1, C> extractRowVector(int row) {
482 return new Matrix<>(this.m_storage.extractVector(true, row));
483 }
484
491 public final Matrix<R, N1> extractColumnVector(int column) {
492 return new Matrix<>(this.m_storage.extractVector(false, column));
493 }
494
506 public final <R2 extends Num, C2 extends Num> Matrix<R2, C2> block(
507 Nat<R2> height, Nat<C2> width, int startingRow, int startingCol) {
508 return new Matrix<>(
509 this.m_storage.extractMatrix(
510 startingRow,
511 startingRow + Objects.requireNonNull(height).getNum(),
512 startingCol,
513 startingCol + Objects.requireNonNull(width).getNum()));
514 }
515
527 public final <R2 extends Num, C2 extends Num> Matrix<R2, C2> block(
528 int height, int width, int startingRow, int startingCol) {
529 return new Matrix<>(
530 this.m_storage.extractMatrix(
531 startingRow, startingRow + height, startingCol, startingCol + width));
532 }
533
543 public <R2 extends Num, C2 extends Num> void assignBlock(
544 int startingRow, int startingCol, Matrix<R2, C2> other) {
545 this.m_storage.insertIntoThis(
546 startingRow, startingCol, Objects.requireNonNull(other).m_storage);
547 }
548
559 public <R2 extends Num, C2 extends Num> void extractFrom(
560 int startingRow, int startingCol, Matrix<R2, C2> other) {
561 CommonOps_DDRM.extract(
562 other.m_storage.getDDRM(), startingRow, startingCol, this.m_storage.getDDRM());
563 }
564
574 public Matrix<R, C> lltDecompose(boolean lowerTriangular) {
575 SimpleMatrix temp = m_storage.copy();
576
577 CholeskyDecomposition_F64<DMatrixRMaj> chol =
578 DecompositionFactory_DDRM.chol(temp.getNumRows(), lowerTriangular);
579 if (!chol.decompose(temp.getMatrix())) {
580 // check that the input is not all zeros -- if they are, we special case and return all
581 // zeros.
582 var matData = temp.getDDRM().data;
583 var isZeros = true;
584 for (double matDatum : matData) {
585 isZeros &= Math.abs(matDatum) < 1e-6;
586 }
587 if (isZeros) {
588 return new Matrix<>(new SimpleMatrix(temp.getNumRows(), temp.getNumCols()));
589 }
590
591 throw new RuntimeException("Cholesky decomposition failed! Input matrix:\n" + m_storage);
592 }
593
594 return new Matrix<>(SimpleMatrix.wrap(chol.getT(null)));
595 }
596
602 public double[] getData() {
603 return m_storage.getDDRM().getData();
604 }
605
613 public static <D extends Num> Matrix<D, D> eye(Nat<D> dim) {
614 return new Matrix<>(SimpleMatrix.identity(Objects.requireNonNull(dim).getNum()));
615 }
616
624 public static <D extends Num> Matrix<D, D> eye(D dim) {
625 return new Matrix<>(SimpleMatrix.identity(Objects.requireNonNull(dim).getNum()));
626 }
627
637 public static <R1 extends Num, C1 extends Num> Matrix<R1, C1> changeBoundsUnchecked(
638 Matrix<?, ?> mat) {
639 return new Matrix<>(mat.m_storage);
640 }
641
659 public boolean isIdentical(Matrix<?, ?> other, double tolerance) {
660 return MatrixFeatures_DDRM.isIdentical(
661 this.m_storage.getDDRM(), other.m_storage.getDDRM(), tolerance);
662 }
663
676 public boolean isEqual(Matrix<?, ?> other, double tolerance) {
677 return MatrixFeatures_DDRM.isEquals(
678 this.m_storage.getDDRM(), other.m_storage.getDDRM(), tolerance);
679 }
680
691 public void rankUpdate(Matrix<R, N1> v, double sigma, boolean lowerTriangular) {
692 EigenJNI.rankUpdate(this.getData(), this.getNumRows(), v.getData(), sigma, lowerTriangular);
693 }
694
695 @Override
696 public String toString() {
697 return m_storage.toString();
698 }
699
708 @Override
709 public boolean equals(Object other) {
710 return this == other
711 || other instanceof Matrix<?, ?> matrix
712 && !MatrixFeatures_DDRM.hasUncountable(matrix.m_storage.getDDRM())
713 && MatrixFeatures_DDRM.isEquals(this.m_storage.getDDRM(), matrix.m_storage.getDDRM());
714 }
715
716 @Override
717 public int hashCode() {
718 return Objects.hash(m_storage);
719 }
720
730 public static <R extends Num, C extends Num> MatrixProto<R, C> getProto(
731 Nat<R> rows, Nat<C> cols) {
732 return new MatrixProto<>(rows, cols);
733 }
734
744 public static <R extends Num, C extends Num> MatrixStruct<R, C> getStruct(
745 Nat<R> rows, Nat<C> cols) {
746 return new MatrixStruct<>(rows, cols);
747 }
748}
final< R2 extends Num, C2 extends Num > Matrix< R2, C2 > block(Nat< R2 > height, Nat< C2 > width, int startingRow, int startingCol)
Definition Matrix.java:506
final Matrix< R, C > minus(double value)
Definition Matrix.java:249
Matrix< R, C > lltDecompose(boolean lowerTriangular)
Definition Matrix.java:574
final Matrix< R, C > plus(Matrix< R, C > value)
Definition Matrix.java:279
boolean isEqual(Matrix<?, ?> other, double tolerance)
Definition Matrix.java:676
Matrix< R, C > times(double value)
Definition Matrix.java:226
final Matrix< C, R > pseudoInverse()
Definition Matrix.java:336
final Matrix< R, C > exp()
Definition Matrix.java:360
static< R extends Num, C extends Num > MatrixProto< R, C > getProto(Nat< R > rows, Nat< C > cols)
Definition Matrix.java:730
static< D extends Num > Matrix< D, D > eye(D dim)
Definition Matrix.java:624
SimpleMatrix getStorage()
Definition Matrix.java:96
final void setColumn(int column, Matrix< R, N1 > val)
Definition Matrix.java:156
Matrix(SimpleMatrix storage)
Definition Matrix.java:74
final Matrix< R, N1 > extractColumnVector(int column)
Definition Matrix.java:491
Matrix(Nat< R > rows, Nat< C > columns, double[] storage)
Definition Matrix.java:60
static< R1 extends Num, C1 extends Num > Matrix< R1, C1 > changeBoundsUnchecked(Matrix<?, ?> mat)
Definition Matrix.java:637
final Matrix< R, C > copy()
Definition Matrix.java:317
final< C2 extends Num > Matrix< R, C2 > times(Matrix< C, C2 > other)
Definition Matrix.java:216
Matrix(Matrix< R, C > other)
Definition Matrix.java:83
static< R extends Num, C extends Num > MatrixStruct< R, C > getStruct(Nat< R > rows, Nat< C > cols)
Definition Matrix.java:744
final Matrix< C, R > transpose()
Definition Matrix.java:308
final Matrix< R, C > minus(Matrix< R, C > value)
Definition Matrix.java:259
final< R2 extends Num, C2 extends Num > Matrix< R2, C2 > block(int height, int width, int startingRow, int startingCol)
Definition Matrix.java:527
boolean equals(Object other)
Definition Matrix.java:709
final SimpleMatrix m_storage
Definition Matrix.java:38
final Matrix< R, C > plus(double value)
Definition Matrix.java:269
final Matrix< R, C > elementTimes(Matrix< R, C > other)
Definition Matrix.java:239
final Matrix< R, C > pow(double exponent)
Definition Matrix.java:384
final< C2 extends Num > Matrix< C, C2 > solve(Matrix< R, C2 > b)
Definition Matrix.java:350
Matrix(Nat< R > rows, Nat< C > columns)
Definition Matrix.java:46
final Matrix< R, C > inv()
Definition Matrix.java:327
Matrix< R, C > div(int value)
Definition Matrix.java:289
void fill(double value)
Definition Matrix.java:165
final Matrix< N1, C > extractRowVector(int row)
Definition Matrix.java:481
final void setRow(int row, Matrix< N1, C > val)
Definition Matrix.java:146
boolean isIdentical(Matrix<?, ?> other, double tolerance)
Definition Matrix.java:659
final Matrix< R, C > elementPower(int b)
Definition Matrix.java:471
void rankUpdate(Matrix< R, N1 > v, double sigma, boolean lowerTriangular)
Definition Matrix.java:691
Matrix< R, C > div(double value)
Definition Matrix.java:299
static< D extends Num > Matrix< D, D > eye(Nat< D > dim)
Definition Matrix.java:613
final Matrix< R, C > elementPower(double b)
Definition Matrix.java:459
MatrixProto(Nat< R > rows, Nat< C > cols)
MatrixStruct(Nat< R > rows, Nat< C > cols)