5package org.wpilib.math.linalg;
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;
49 Objects.requireNonNull(rows).getNum(), Objects.requireNonNull(columns).getNum());
61 this.m_storage =
new SimpleMatrix(rows.
getNum(), columns.
getNum(),
true, storage);
74 public Matrix(SimpleMatrix storage) {
75 this.m_storage = Objects.requireNonNull(storage);
84 this.m_storage = Objects.requireNonNull(other).getStorage().copy();
106 return this.m_storage.getNumCols();
115 return this.m_storage.getNumRows();
125 public final double get(
int row,
int col) {
126 return this.m_storage.get(row, col);
136 public final void set(
int row,
int col,
double value) {
137 this.m_storage.set(row, col, value);
147 this.m_storage.setRow(row, 0, Objects.requireNonNull(val).m_storage.getDDRM().getData());
157 this.m_storage.setColumn(column, 0, Objects.requireNonNull(val).m_storage.getDDRM().getData());
165 public void fill(
double value) {
166 this.m_storage.fill(value);
174 public final double max() {
175 return CommonOps_DDRM.elementMax(this.m_storage.getDDRM());
184 return CommonOps_DDRM.elementMaxAbs(this.m_storage.getDDRM());
193 return CommonOps_DDRM.elementMin(this.m_storage.getDDRM());
202 return this.
elementSum() / this.m_storage.getNumElements();
217 return new Matrix<>(this.m_storage.mult(Objects.requireNonNull(other).m_storage));
227 return new Matrix<>(this.m_storage.scale(value));
240 return new Matrix<>(this.m_storage.elementMult(Objects.requireNonNull(other).m_storage));
250 return new Matrix<>(this.m_storage.minus(value));
260 return new Matrix<>(this.m_storage.minus(Objects.requireNonNull(value).m_storage));
270 return new Matrix<>(this.m_storage.plus(value));
280 return new Matrix<>(this.m_storage.plus(Objects.requireNonNull(value).m_storage));
290 return new Matrix<>(this.m_storage.divide(value));
300 return new Matrix<>(this.m_storage.divide(value));
309 return new Matrix<>(this.m_storage.transpose());
318 return new Matrix<>(this.m_storage.copy());
328 return new Matrix<>(this.m_storage.invert());
337 return new Matrix<>(this.m_storage.pseudoInverse());
351 return new Matrix<>(this.m_storage.solve(Objects.requireNonNull(b).m_storage));
362 throw new MatrixDimensionException(
363 "Non-square matrices cannot be exponentiated! "
371 this.m_storage.getDDRM().getData(),
386 throw new MatrixDimensionException(
387 "Non-square matrices cannot be raised to a power! "
395 this.m_storage.getDDRM().getData(),
407 public final double det() {
408 return this.m_storage.determinant();
419 return this.m_storage.normF();
430 return NormOps_DDRM.inducedP1(this.m_storage.getDDRM());
439 return this.m_storage.elementSum();
448 return this.m_storage.trace();
460 return new Matrix<>(this.m_storage.elementPower(b));
472 return new Matrix<>(this.m_storage.elementPower(b));
482 return new Matrix<>(this.m_storage.extractVector(
true, row));
492 return new Matrix<>(this.m_storage.extractVector(
false, column));
507 Nat<R2> height,
Nat<C2> width,
int startingRow,
int startingCol) {
509 this.m_storage.extractMatrix(
511 startingRow + Objects.requireNonNull(height).getNum(),
513 startingCol + Objects.requireNonNull(width).getNum()));
528 int height,
int width,
int startingRow,
int startingCol) {
530 this.m_storage.extractMatrix(
531 startingRow, startingRow + height, startingCol, startingCol + width));
543 public <R2 extends Num, C2 extends Num>
void assignBlock(
545 this.m_storage.insertIntoThis(
546 startingRow, startingCol, Objects.requireNonNull(other).m_storage);
559 public <R2 extends Num, C2 extends Num>
void extractFrom(
561 CommonOps_DDRM.extract(
562 other.m_storage.getDDRM(), startingRow, startingCol,
this.m_storage.getDDRM());
577 CholeskyDecomposition_F64<DMatrixRMaj> chol =
578 DecompositionFactory_DDRM.chol(temp.getNumRows(), lowerTriangular);
579 if (!chol.decompose(temp.getMatrix())) {
582 var matData = temp.getDDRM().data;
584 for (
double matDatum : matData) {
585 isZeros &= Math.abs(matDatum) < 1e-6;
588 return new Matrix<>(
new SimpleMatrix(temp.getNumRows(), temp.getNumCols()));
591 throw new RuntimeException(
"Cholesky decomposition failed! Input matrix:\n" +
m_storage);
594 return new Matrix<>(SimpleMatrix.wrap(chol.getT(
null)));
614 return new Matrix<>(SimpleMatrix.identity(Objects.requireNonNull(dim).getNum()));
625 return new Matrix<>(SimpleMatrix.identity(Objects.requireNonNull(dim).getNum()));
660 return MatrixFeatures_DDRM.isIdentical(
661 this.m_storage.getDDRM(), other.
m_storage.getDDRM(), tolerance);
677 return MatrixFeatures_DDRM.isEquals(
678 this.m_storage.getDDRM(), other.
m_storage.getDDRM(), tolerance);
696 public String toString() {
712 && !MatrixFeatures_DDRM.hasUncountable(matrix.m_storage.getDDRM())
713 && MatrixFeatures_DDRM.isEquals(this.m_storage.getDDRM(), matrix.m_storage.getDDRM());
717 public int hashCode() {
final< R2 extends Num, C2 extends Num > Matrix< R2, C2 > block(Nat< R2 > height, Nat< C2 > width, int startingRow, int startingCol)
final Matrix< R, C > minus(double value)
Matrix< R, C > lltDecompose(boolean lowerTriangular)
final Matrix< R, C > plus(Matrix< R, C > value)
boolean isEqual(Matrix<?, ?> other, double tolerance)
Matrix< R, C > times(double value)
final Matrix< C, R > pseudoInverse()
final Matrix< R, C > exp()
static< R extends Num, C extends Num > MatrixProto< R, C > getProto(Nat< R > rows, Nat< C > cols)
static< D extends Num > Matrix< D, D > eye(D dim)
SimpleMatrix getStorage()
final void setColumn(int column, Matrix< R, N1 > val)
Matrix(SimpleMatrix storage)
final Matrix< R, N1 > extractColumnVector(int column)
Matrix(Nat< R > rows, Nat< C > columns, double[] storage)
static< R1 extends Num, C1 extends Num > Matrix< R1, C1 > changeBoundsUnchecked(Matrix<?, ?> mat)
final Matrix< R, C > copy()
final< C2 extends Num > Matrix< R, C2 > times(Matrix< C, C2 > other)
Matrix(Matrix< R, C > other)
static< R extends Num, C extends Num > MatrixStruct< R, C > getStruct(Nat< R > rows, Nat< C > cols)
final Matrix< C, R > transpose()
final Matrix< R, C > minus(Matrix< R, C > value)
final< R2 extends Num, C2 extends Num > Matrix< R2, C2 > block(int height, int width, int startingRow, int startingCol)
boolean equals(Object other)
final double elementSum()
final SimpleMatrix m_storage
final Matrix< R, C > plus(double value)
final Matrix< R, C > elementTimes(Matrix< R, C > other)
final Matrix< R, C > pow(double exponent)
final< C2 extends Num > Matrix< C, C2 > solve(Matrix< R, C2 > b)
final double minInternal()
Matrix(Nat< R > rows, Nat< C > columns)
final Matrix< R, C > inv()
Matrix< R, C > div(int value)
final Matrix< N1, C > extractRowVector(int row)
final void setRow(int row, Matrix< N1, C > val)
boolean isIdentical(Matrix<?, ?> other, double tolerance)
final Matrix< R, C > elementPower(int b)
void rankUpdate(Matrix< R, N1 > v, double sigma, boolean lowerTriangular)
Matrix< R, C > div(double value)
static< D extends Num > Matrix< D, D > eye(Nat< D > dim)
final Matrix< R, C > elementPower(double b)
MatrixProto(Nat< R > rows, Nat< C > cols)
MatrixStruct(Nat< R > rows, Nat< C > cols)