2020-12-26 14:12:05 -08:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2021-05-01 15:53:30 +00:00
|
|
|
package edu.wpi.first.math;
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2021-05-01 15:53:30 +00:00
|
|
|
import edu.wpi.first.math.numbers.N1;
|
|
|
|
|
import edu.wpi.first.math.numbers.N2;
|
|
|
|
|
import edu.wpi.first.math.numbers.N3;
|
|
|
|
|
import edu.wpi.first.math.numbers.N4;
|
2020-12-29 22:45:16 -08:00
|
|
|
import org.ejml.data.SingularMatrixException;
|
|
|
|
|
import org.junit.jupiter.api.Test;
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2021-12-09 12:20:08 -08:00
|
|
|
class MatrixTest {
|
2019-08-18 18:00:40 -04:00
|
|
|
@Test
|
|
|
|
|
void testMatrixMultiplication() {
|
2020-12-29 22:45:16 -08:00
|
|
|
var mat1 = Matrix.mat(Nat.N2(), Nat.N2()).fill(2.0, 1.0, 0.0, 1.0);
|
|
|
|
|
var mat2 = Matrix.mat(Nat.N2(), Nat.N2()).fill(3.0, 0.0, 0.0, 2.5);
|
2019-08-18 18:00:40 -04:00
|
|
|
|
|
|
|
|
Matrix<N2, N2> result = mat1.times(mat2);
|
|
|
|
|
|
2020-08-14 23:40:33 -07:00
|
|
|
assertEquals(result, Matrix.mat(Nat.N2(), Nat.N2()).fill(6.0, 2.5, 0.0, 2.5));
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
var mat3 = Matrix.mat(Nat.N2(), Nat.N3()).fill(1.0, 3.0, 0.5, 2.0, 4.3, 1.2);
|
|
|
|
|
var mat4 =
|
|
|
|
|
Matrix.mat(Nat.N3(), Nat.N4())
|
|
|
|
|
.fill(3.0, 1.5, 2.0, 4.5, 2.3, 1.0, 1.6, 3.1, 5.2, 2.1, 2.0, 1.0);
|
2019-08-18 18:00:40 -04:00
|
|
|
|
|
|
|
|
Matrix<N2, N4> result2 = mat3.times(mat4);
|
|
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
assertTrue(
|
|
|
|
|
Matrix.mat(Nat.N2(), Nat.N4())
|
|
|
|
|
.fill(12.5, 5.55, 7.8, 14.3, 22.13, 9.82, 13.28, 23.53)
|
|
|
|
|
.isEqual(result2, 1E-9));
|
2019-08-18 18:00:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void testMatrixVectorMultiplication() {
|
2020-12-29 22:45:16 -08:00
|
|
|
var mat = Matrix.mat(Nat.N2(), Nat.N2()).fill(1.0, 1.0, 0.0, 1.0);
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-08-14 23:40:33 -07:00
|
|
|
var vec = VecBuilder.fill(3.0, 2.0);
|
2019-08-18 18:00:40 -04:00
|
|
|
|
|
|
|
|
Matrix<N2, N1> result = mat.times(vec);
|
2020-08-14 23:40:33 -07:00
|
|
|
assertEquals(VecBuilder.fill(5.0, 2.0), result);
|
2019-08-18 18:00:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void testTranspose() {
|
2020-12-29 22:45:16 -08:00
|
|
|
Matrix<N3, N1> vec = VecBuilder.fill(1.0, 2.0, 3.0);
|
2019-08-18 18:00:40 -04:00
|
|
|
|
|
|
|
|
Matrix<N1, N3> transpose = vec.transpose();
|
|
|
|
|
|
2020-08-14 23:40:33 -07:00
|
|
|
assertEquals(Matrix.mat(Nat.N1(), Nat.N3()).fill(1.0, 2.0, 3.0), transpose);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void testSolve() {
|
|
|
|
|
var mat1 = Matrix.mat(Nat.N2(), Nat.N2()).fill(1.0, 2.0, 3.0, 4.0);
|
|
|
|
|
var vec1 = VecBuilder.fill(1.0, 2.0);
|
|
|
|
|
|
|
|
|
|
var solve1 = mat1.solve(vec1);
|
|
|
|
|
|
|
|
|
|
assertEquals(VecBuilder.fill(0.0, 0.5), solve1);
|
|
|
|
|
|
|
|
|
|
var mat2 = Matrix.mat(Nat.N3(), Nat.N2()).fill(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
|
|
|
|
|
var vec2 = VecBuilder.fill(1.0, 2.0, 3.0);
|
|
|
|
|
|
|
|
|
|
var solve2 = mat2.solve(vec2);
|
|
|
|
|
|
|
|
|
|
assertEquals(VecBuilder.fill(0.0, 0.5), solve2);
|
2019-08-18 18:00:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void testInverse() {
|
2020-12-29 22:45:16 -08:00
|
|
|
var mat = Matrix.mat(Nat.N3(), Nat.N3()).fill(1.0, 3.0, 2.0, 5.0, 2.0, 1.5, 0.0, 1.3, 2.5);
|
2019-08-18 18:00:40 -04:00
|
|
|
|
|
|
|
|
var inv = mat.inv();
|
|
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
assertTrue(Matrix.eye(Nat.N3()).isEqual(mat.times(inv), 1E-9));
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
assertTrue(Matrix.eye(Nat.N3()).isEqual(inv.times(mat), 1E-9));
|
2019-08-18 18:00:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void testUninvertableMatrix() {
|
2020-12-29 22:45:16 -08:00
|
|
|
var singularMatrix = Matrix.mat(Nat.N2(), Nat.N2()).fill(2.0, 1.0, 2.0, 1.0);
|
2019-08-18 18:00:40 -04:00
|
|
|
|
|
|
|
|
assertThrows(SingularMatrixException.class, singularMatrix::inv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void testMatrixScalarArithmetic() {
|
2020-12-29 22:45:16 -08:00
|
|
|
var mat = Matrix.mat(Nat.N2(), Nat.N2()).fill(1.0, 2.0, 3.0, 4.0);
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-08-14 23:40:33 -07:00
|
|
|
assertEquals(Matrix.mat(Nat.N2(), Nat.N2()).fill(3.0, 4.0, 5.0, 6.0), mat.plus(2.0));
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-08-14 23:40:33 -07:00
|
|
|
assertEquals(Matrix.mat(Nat.N2(), Nat.N2()).fill(0.0, 1.0, 2.0, 3.0), mat.minus(1.0));
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
assertEquals(Matrix.mat(Nat.N2(), Nat.N2()).fill(2.0, 4.0, 6.0, 8.0), mat.times(2.0));
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
assertTrue(Matrix.mat(Nat.N2(), Nat.N2()).fill(0.5, 1.0, 1.5, 2.0).isEqual(mat.div(2.0), 1E-3));
|
2019-08-18 18:00:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void testMatrixMatrixArithmetic() {
|
2020-12-29 22:45:16 -08:00
|
|
|
var mat1 = Matrix.mat(Nat.N2(), Nat.N2()).fill(1.0, 2.0, 3.0, 4.0);
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
var mat2 = Matrix.mat(Nat.N2(), Nat.N2()).fill(5.0, 6.0, 7.0, 8.0);
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
assertEquals(Matrix.mat(Nat.N2(), Nat.N2()).fill(-4.0, -4.0, -4.0, -4.0), mat1.minus(mat2));
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
assertEquals(Matrix.mat(Nat.N2(), Nat.N2()).fill(6.0, 8.0, 10.0, 12.0), mat1.plus(mat2));
|
2019-08-18 18:00:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void testMatrixExponential() {
|
2020-08-14 23:40:33 -07:00
|
|
|
var matrix = Matrix.eye(Nat.N2());
|
|
|
|
|
var result = matrix.exp();
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-08-14 23:40:33 -07:00
|
|
|
assertTrue(result.isEqual(Matrix.mat(Nat.N2(), Nat.N2()).fill(Math.E, 0, 0, Math.E), 1E-9));
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-08-14 23:40:33 -07:00
|
|
|
matrix = Matrix.mat(Nat.N2(), Nat.N2()).fill(1, 2, 3, 4);
|
|
|
|
|
result = matrix.times(0.01).exp();
|
2019-08-18 18:00:40 -04:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
assertTrue(
|
|
|
|
|
result.isEqual(
|
|
|
|
|
Matrix.mat(Nat.N2(), Nat.N2()).fill(1.01035625, 0.02050912, 0.03076368, 1.04111993),
|
|
|
|
|
1E-8));
|
2019-08-18 18:00:40 -04:00
|
|
|
}
|
|
|
|
|
}
|