Got coverage working for templates.

This commit is contained in:
jgoppert
2015-11-04 12:11:32 -05:00
parent bf6de4b710
commit 18f80462b7
13 changed files with 243 additions and 201 deletions
+2 -162
View File
@@ -151,7 +151,8 @@ public:
self = self - other;
}
void operator*=(const Matrix<Type, M, N> &other)
template<size_t P>
void operator*=(const Matrix<Type, N, P> &other)
{
Matrix<Type, M, N> &self = *this;
self = self * other;
@@ -247,42 +248,6 @@ public:
return transpose();
}
Matrix<Type, M, M> expm(float dt, size_t n) const
{
Matrix<float, M, M> res;
res.setIdentity();
Matrix<float, M, M> A_pow = *this;
float k_fact = 1;
size_t k = 1;
while (k < n) {
res += A_pow * (float(pow(dt, k)) / k_fact);
if (k == n) {
break;
}
A_pow *= A_pow;
k_fact *= k;
k++;
}
return res;
}
Vector<Type, M> diagonal() const
{
Vector<Type, M> res;
// force square for now
const Matrix<Type, M, M> &self = *this;
for (size_t i = 0; i < M; i++) {
res(i) = self(i, i);
}
return res;
}
void setZero()
{
memset(_data, 0, sizeof(_data));
@@ -328,133 +293,8 @@ public:
}
}
/**
* inverse based on LU factorization with partial pivotting
*/
Matrix <Type, M, M> inverse() const
{
Matrix<Type, M, M> L;
L.setIdentity();
const Matrix<Type, M, M> &A = (*this);
Matrix<Type, M, M> U = A;
Matrix<Type, M, M> P;
P.setIdentity();
//printf("A:\n"); A.print();
// for all diagonal elements
for (size_t n = 0; n < N; n++) {
// if diagonal is zero, swap with row below
if (fabsf(U(n, n)) < 1e-8f) {
//printf("trying pivot for row %d\n",n);
for (size_t i = 0; i < N; i++) {
if (i == n) {
continue;
}
//printf("\ttrying row %d\n",i);
if (fabsf(U(i, n)) > 1e-8f) {
//printf("swapped %d\n",i);
U.swapRows(i, n);
P.swapRows(i, n);
}
}
}
#ifdef MATRIX_ASSERT
//printf("A:\n"); A.print();
//printf("U:\n"); U.print();
//printf("P:\n"); P.print();
//fflush(stdout);
ASSERT(fabsf(U(n, n)) > 1e-8f);
#endif
// failsafe, return zero matrix
if (fabsf(U(n, n)) < 1e-8f) {
Matrix<Type, M, M> zero;
zero.setZero();
return zero;
}
// for all rows below diagonal
for (size_t i = (n + 1); i < N; i++) {
L(i, n) = U(i, n) / U(n, n);
// add i-th row and n-th row
// multiplied by: -a(i,n)/a(n,n)
for (size_t k = n; k < N; k++) {
U(i, k) -= L(i, n) * U(n, k);
}
}
}
//printf("L:\n"); L.print();
//printf("U:\n"); U.print();
// solve LY=P*I for Y by forward subst
Matrix<Type, M, M> Y = P;
// for all columns of Y
for (size_t c = 0; c < N; c++) {
// for all rows of L
for (size_t i = 0; i < N; i++) {
// for all columns of L
for (size_t j = 0; j < i; j++) {
// for all existing y
// subtract the component they
// contribute to the solution
Y(i, c) -= L(i, j) * Y(j, c);
}
// divide by the factor
// on current
// term to be solved
// Y(i,c) /= L(i,i);
// but L(i,i) = 1.0
}
}
//printf("Y:\n"); Y.print();
// solve Ux=y for x by back subst
Matrix<Type, M, M> X = Y;
// for all columns of X
for (size_t c = 0; c < N; c++) {
// for all rows of U
for (size_t k = 0; k < N; k++) {
// have to go in reverse order
size_t i = N - 1 - k;
// for all columns of U
for (size_t j = i + 1; j < N; j++) {
// for all existing x
// subtract the component they
// contribute to the solution
X(i, c) -= U(i, j) * X(j, c);
}
// divide by the factor
// on current
// term to be solved
X(i, c) /= U(i, i);
}
}
//printf("X:\n"); X.print();
return X;
}
// inverse alias
inline Matrix<Type, N, M> I() const
{
return inverse();
}
};
typedef Matrix<float, 3, 3> Matrix3f;
}; // namespace matrix
+207
View File
@@ -0,0 +1,207 @@
/**
* @file SquareMatrix.hpp
*
* A square matrix
*
* @author James Goppert <james.goppert@gmail.com>
*/
#pragma once
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "Matrix.hpp"
namespace matrix
{
template <typename Type, size_t M, size_t N>
class Matrix;
template<typename Type, size_t M>
class SquareMatrix : public Matrix<Type, M, M>
{
public:
SquareMatrix() :
Matrix<Type, M, M>()
{
}
SquareMatrix(const Type *data) :
Matrix<Type, M, M>(data)
{
}
SquareMatrix(const Matrix<float, M, M> &other) :
Matrix<Type, M, M>(other)
{
}
/**
* inverse based on LU factorization with partial pivotting
*/
SquareMatrix <Type, M> inverse() const
{
SquareMatrix<Type, M> L;
L.setIdentity();
const SquareMatrix<Type, M> &A = (*this);
SquareMatrix<Type, M> U = A;
SquareMatrix<Type, M> P;
P.setIdentity();
//printf("A:\n"); A.print();
// for all diagonal elements
for (size_t n = 0; n < M; n++) {
// if diagonal is zero, swap with row below
if (fabsf(U(n, n)) < 1e-8f) {
//printf("trying pivot for row %d\n",n);
for (size_t i = 0; i < M; i++) {
if (i == n) {
continue;
}
//printf("\ttrying row %d\n",i);
if (fabsf(U(i, n)) > 1e-8f) {
//printf("swapped %d\n",i);
U.swapRows(i, n);
P.swapRows(i, n);
}
}
}
#ifdef MATRIX_ASSERT
//printf("A:\n"); A.print();
//printf("U:\n"); U.print();
//printf("P:\n"); P.print();
//fflush(stdout);
ASSERT(fabsf(U(n, n)) > 1e-8f);
#endif
// failsafe, return zero matrix
if (fabsf(U(n, n)) < 1e-8f) {
SquareMatrix<Type, M> zero;
zero.setZero();
return zero;
}
// for all rows below diagonal
for (size_t i = (n + 1); i < M; i++) {
L(i, n) = U(i, n) / U(n, n);
// add i-th row and n-th row
// multiplied by: -a(i,n)/a(n,n)
for (size_t k = n; k < M; k++) {
U(i, k) -= L(i, n) * U(n, k);
}
}
}
//printf("L:\n"); L.print();
//printf("U:\n"); U.print();
// solve LY=P*I for Y by forward subst
SquareMatrix<Type, M> Y = P;
// for all columns of Y
for (size_t c = 0; c < M; c++) {
// for all rows of L
for (size_t i = 0; i < M; i++) {
// for all columns of L
for (size_t j = 0; j < i; j++) {
// for all existing y
// subtract the component they
// contribute to the solution
Y(i, c) -= L(i, j) * Y(j, c);
}
// divide by the factor
// on current
// term to be solved
// Y(i,c) /= L(i,i);
// but L(i,i) = 1.0
}
}
//printf("Y:\n"); Y.print();
// solve Ux=y for x by back subst
SquareMatrix<Type, M> X = Y;
// for all columns of X
for (size_t c = 0; c < M; c++) {
// for all rows of U
for (size_t k = 0; k < M; k++) {
// have to go in reverse order
size_t i = M - 1 - k;
// for all columns of U
for (size_t j = i + 1; j < M; j++) {
// for all existing x
// subtract the component they
// contribute to the solution
X(i, c) -= U(i, j) * X(j, c);
}
// divide by the factor
// on current
// term to be solved
X(i, c) /= U(i, i);
}
}
//printf("X:\n"); X.print();
return X;
}
// inverse alias
inline SquareMatrix<Type, M> I() const
{
return inverse();
}
Vector<Type, M> diagonal() const
{
Vector<Type, M> res;
const SquareMatrix<Type, M> &self = *this;
for (size_t i = 0; i < M; i++) {
res(i) = self(i, i);
}
return res;
}
SquareMatrix<Type, M> expm(float dt, size_t n) const
{
SquareMatrix<float, M> res;
res.setIdentity();
SquareMatrix<float, M> A_pow = *this;
float k_fact = 1;
size_t k = 1;
while (k < n) {
res += A_pow * (float(pow(dt, k)) / k_fact);
if (k == n) {
break;
}
A_pow *= A_pow;
k_fact *= k;
k++;
}
return res;
}
};
typedef SquareMatrix<float, 3> SquareMatrix3f;
}; // namespace matrix
/* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */