mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2025-01-08 05:55:35 +00:00
Finish matrix unit tests
This commit is contained in:
parent
8b9e8cd9b5
commit
ba0b5df59e
47
Base/include/Matrix2x2.h
Normal file
47
Base/include/Matrix2x2.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2014 Pavel Krajcevski
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef BASE_INCLUDE_MATRIX2X2_H_
|
||||||
|
#define BASE_INCLUDE_MATRIX2X2_H_
|
||||||
|
|
||||||
|
#include "MatrixSquare.h"
|
||||||
|
|
||||||
|
namespace FasTC {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Matrix2x2 : public MatrixSquare<T, 2> {
|
||||||
|
public:
|
||||||
|
// Constructors
|
||||||
|
Matrix2x2() { }
|
||||||
|
Matrix2x2(const Matrix2x2<T> &other)
|
||||||
|
: MatrixSquare<T, 2>(other) { }
|
||||||
|
Matrix2x2(const MatrixSquare<T, 2> &other)
|
||||||
|
: MatrixSquare<T, 2>(other) { }
|
||||||
|
Matrix2x2(const MatrixBase<T, 2, 2> &other)
|
||||||
|
: MatrixSquare<T, 2>(other) { }
|
||||||
|
};
|
||||||
|
REGISTER_ONE_TEMPLATE_MATRIX_TYPE(Matrix2x2);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BASE_INCLUDE_MATRIX2X2_H_
|
|
@ -31,17 +31,17 @@ namespace FasTC {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Matrix3x3 : public MatrixSquare<T, 3> {
|
class Matrix3x3 : public MatrixSquare<T, 3> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
Matrix3x3() { }
|
Matrix3x3() { }
|
||||||
Matrix3x3(const MatrixSquare<T, 3> &other) {
|
Matrix3x3(const Matrix3x3<T> &other)
|
||||||
for(int i = 0; i < kNumElements; i++) {
|
: MatrixSquare<T, 3>(other) { }
|
||||||
mat[i] = other[i];
|
Matrix3x3(const MatrixSquare<T, 3> &other)
|
||||||
}
|
: MatrixSquare<T, 3>(other) { }
|
||||||
}
|
Matrix3x3(const MatrixBase<T, 3, 3> &other)
|
||||||
|
: MatrixSquare<T, 3>(other) { }
|
||||||
};
|
};
|
||||||
|
REGISTER_ONE_TEMPLATE_MATRIX_TYPE(Matrix3x3);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BASE_INCLUDE_MATRIX3X3_H_
|
#endif // BASE_INCLUDE_MATRIX3X3_H_
|
||||||
|
|
|
@ -59,17 +59,17 @@ namespace FasTC {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Matrix4x4 : public MatrixSquare<T, 4> {
|
class Matrix4x4 : public MatrixSquare<T, 4> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
Matrix4x4() { }
|
Matrix4x4() { }
|
||||||
|
Matrix4x4(const Matrix4x4<T> &other)
|
||||||
|
: MatrixSquare<T, 4>(other) { }
|
||||||
Matrix4x4(const MatrixSquare<T, 4> &other)
|
Matrix4x4(const MatrixSquare<T, 4> &other)
|
||||||
: MatrixSquare<T, 4>(other) { }
|
: MatrixSquare<T, 4>(other) { }
|
||||||
|
|
||||||
Matrix4x4(const MatrixBase<T, 4, 4> &other)
|
Matrix4x4(const MatrixBase<T, 4, 4> &other)
|
||||||
: MatrixSquare<T, 4>(other) { }
|
: MatrixSquare<T, 4>(other) { }
|
||||||
};
|
};
|
||||||
|
REGISTER_ONE_TEMPLATE_MATRIX_TYPE(Matrix4x4);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BASE_INCLUDE_MATRIX3X3_H_
|
#endif // BASE_INCLUDE_MATRIX3X3_H_
|
||||||
|
|
|
@ -158,6 +158,13 @@ namespace FasTC {
|
||||||
static const EVectorType kVectorType = eVectorType_Matrix; \
|
static const EVectorType kVectorType = eVectorType_Matrix; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define REGISTER_ONE_TEMPLATE_MATRIX_SIZED_TYPE(TYPE) \
|
||||||
|
template<typename T, const int SIZE> \
|
||||||
|
class VectorTraits< TYPE <T, SIZE> > { \
|
||||||
|
public: \
|
||||||
|
static const EVectorType kVectorType = eVectorType_Matrix; \
|
||||||
|
}
|
||||||
|
|
||||||
// Define matrix multiplication for * operator
|
// Define matrix multiplication for * operator
|
||||||
template<typename TypeOne, typename TypeTwo>
|
template<typename TypeOne, typename TypeTwo>
|
||||||
class MultSwitch<
|
class MultSwitch<
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#define BASE_INCLUDE_MATRIXSQUARE_H_
|
#define BASE_INCLUDE_MATRIXSQUARE_H_
|
||||||
|
|
||||||
#include "MatrixBase.h"
|
#include "MatrixBase.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
namespace FasTC {
|
namespace FasTC {
|
||||||
|
|
||||||
|
@ -40,54 +42,82 @@ namespace FasTC {
|
||||||
MatrixSquare(const MatrixBase<T, N, N> &other)
|
MatrixSquare(const MatrixBase<T, N, N> &other)
|
||||||
: MatrixBase<T, N, N>(other) { }
|
: MatrixBase<T, N, N>(other) { }
|
||||||
|
|
||||||
|
MatrixSquare<T, N> Transpose() const {
|
||||||
|
return MatrixBase<T, N, N>::Transpose();
|
||||||
|
}
|
||||||
|
|
||||||
// Does power iteration to determine the principal eigenvector and eigenvalue.
|
// Does power iteration to determine the principal eigenvector and eigenvalue.
|
||||||
// Returns them in eigVec and eigVal after kMaxNumIterations
|
// Returns them in eigVec and eigVal after kMaxNumIterations
|
||||||
int PowerMethod(VectorBase<T, N> &eigVec, T *eigVal = NULL,
|
int PowerMethod(VectorBase<T, N> &eigVec,
|
||||||
const int kMaxNumIterations = 200) {
|
T *eigVal = NULL,
|
||||||
|
const int kMaxNumIterations = 200,
|
||||||
|
const unsigned int kSeed = time(NULL)) {
|
||||||
|
|
||||||
|
srand(kSeed);
|
||||||
int numIterations = 0;
|
int numIterations = 0;
|
||||||
|
|
||||||
// !SPEED! Find eigenvectors by using the power method. This is good because the
|
|
||||||
// matrix is only 4x4, which allows us to use SIMD...
|
|
||||||
VectorBase<T, N> b;
|
VectorBase<T, N> b;
|
||||||
for(int i = 0; i < N; i++)
|
for(int i = 0; i < N; i++)
|
||||||
b[i] = T(1.0);
|
b[i] = static_cast<T>(rand());
|
||||||
|
b.Normalize();
|
||||||
b /= b.Length();
|
|
||||||
|
|
||||||
|
bool badEigenValue = false;
|
||||||
bool fixed = false;
|
bool fixed = false;
|
||||||
numIterations = 0;
|
numIterations = 0;
|
||||||
while(!fixed && ++numIterations < kMaxNumIterations) {
|
while(!fixed && ++numIterations < kMaxNumIterations) {
|
||||||
|
|
||||||
VectorBase<T, N> newB = (*this).operator*(b);
|
VectorBase<T, N> newB = (*this) * b;
|
||||||
|
|
||||||
// !HACK! If the principal eigenvector of the covariance matrix
|
// !HACK! If the principal eigenvector of the matrix
|
||||||
// converges to zero, that means that the points lie equally
|
// converges to zero, that could mean that there is no
|
||||||
// spaced on a sphere in this space. In this (extremely rare)
|
// principal eigenvector. However, that may be due to
|
||||||
// situation, just choose a point and use it as the principal
|
// poor initialization of the random vector, so rerandomize
|
||||||
// direction.
|
// and try again.
|
||||||
const float newBlen = newB.Length();
|
const float newBlen = newB.Length();
|
||||||
if(newBlen < 1e-10) {
|
if(newBlen < 1e-10) {
|
||||||
eigVec = b;
|
if(badEigenValue) {
|
||||||
if(eigVal) *eigVal = 0.0;
|
eigVec = b;
|
||||||
return numIterations;
|
if(eigVal) *eigVal = 0.0;
|
||||||
|
return numIterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorBase<T, N> b;
|
||||||
|
for(int i = 0; i < N; i++)
|
||||||
|
b[i] = static_cast<T>(rand());
|
||||||
|
|
||||||
|
b.Normalize();
|
||||||
|
badEigenValue = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
T len = newB.Length();
|
// Normalize
|
||||||
newB /= len;
|
newB.Normalize();
|
||||||
if(eigVal)
|
|
||||||
*eigVal = len;
|
|
||||||
|
|
||||||
if(fabs(1.0f - (b.Dot(newB))) < 1e-5)
|
// If the new eigenvector is close enough to the old one,
|
||||||
|
// then we've converged.
|
||||||
|
if(fabs(1.0f - (b.Dot(newB))) < 1e-8)
|
||||||
fixed = true;
|
fixed = true;
|
||||||
|
|
||||||
|
// Save and continue.
|
||||||
b = newB;
|
b = newB;
|
||||||
}
|
}
|
||||||
|
|
||||||
eigVec = b;
|
// Store the eigenvector in the proper variable.
|
||||||
|
eigVec = b;
|
||||||
|
|
||||||
|
// Store eigenvalue if it was requested
|
||||||
|
if(eigVal) {
|
||||||
|
VectorBase<T, N> result = (*this) * b;
|
||||||
|
*eigVal = result.Length() / b.Length();
|
||||||
|
}
|
||||||
|
|
||||||
return numIterations;
|
return numIterations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
REGISTER_ONE_TEMPLATE_MATRIX_SIZED_TYPE(MatrixSquare);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BASE_INCLUDE_MATRIXSQUARE_H_
|
#endif // BASE_INCLUDE_MATRIXSQUARE_H_
|
||||||
|
|
|
@ -123,7 +123,13 @@ TEST(MatrixBase, PointerConversion) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MatrixBase, CastVector) {
|
TEST(MatrixBase, CastVector) {
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
FasTC::MatrixBase<float, 3, 2> v3f;
|
FasTC::MatrixBase<float, 3, 2> v3f;
|
||||||
|
for(int i = 0; i < 6; i++) {
|
||||||
|
v3f[i] = static_cast<float>(rand());
|
||||||
|
}
|
||||||
|
|
||||||
FasTC::MatrixBase<double, 3, 2> v3d = v3f;
|
FasTC::MatrixBase<double, 3, 2> v3d = v3f;
|
||||||
FasTC::MatrixBase<int, 3, 2> v3i = v3f;
|
FasTC::MatrixBase<int, 3, 2> v3i = v3f;
|
||||||
for(int i = 0; i < 3*2; i++) {
|
for(int i = 0; i < 3*2; i++) {
|
||||||
|
@ -198,28 +204,137 @@ TEST(MatrixBase, VectorMultiplication) {
|
||||||
EXPECT_EQ(v[4], 0 + (3 * 2) + (5 * 3));
|
EXPECT_EQ(v[4], 0 + (3 * 2) + (5 * 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "MatrixSquare.h"
|
||||||
|
|
||||||
TEST(MatrixSquare, Constructors) {
|
TEST(MatrixSquare, Constructors) {
|
||||||
// Stub
|
FasTC::MatrixBase<int, 3, 3> m;
|
||||||
EXPECT_EQ(0, 1);
|
m(0, 0) = 1; m(0, 1) = 2; m(0, 2) = 3;
|
||||||
|
m(1, 0) = 2; m(1, 1) = 3; m(1, 2) = 4;
|
||||||
|
m(2, 0) = 3; m(2, 1) = 4; m(2, 2) = 5;
|
||||||
|
|
||||||
|
FasTC::MatrixSquare<int, 3> sqm (m);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_EQ(m[i], sqm[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::MatrixSquare<float, 3> fsqm(m);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_NEAR(m[i], fsqm[i], kEpsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::MatrixSquare<float, 3> fcsqm(sqm);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_NEAR(fcsqm[i], sqm[i], kEpsilon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MatrixSquare, EigenvalueCalculation) {
|
TEST(MatrixSquare, PowerMethod) {
|
||||||
// Stub
|
FasTC::MatrixSquare<double, 2> A;
|
||||||
EXPECT_EQ(0, 1);
|
A(0, 0) = 0.8f; A(0, 1) = 0.3f;
|
||||||
|
A(1, 0) = 0.2f; A(1, 1) = 0.7f;
|
||||||
|
|
||||||
|
double e;
|
||||||
|
FasTC::VectorBase<double, 2> x;
|
||||||
|
A.PowerMethod(x, &e, 20, 200);
|
||||||
|
|
||||||
|
EXPECT_NEAR(x[0], 0.83205f, 0.0001);
|
||||||
|
EXPECT_NEAR(x[1], 0.5547f, 0.0001);
|
||||||
|
|
||||||
|
EXPECT_NEAR(e, 1.f, 0.0001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Matrix2x2.h"
|
||||||
|
|
||||||
TEST(Matrix2x2, Constructors) {
|
TEST(Matrix2x2, Constructors) {
|
||||||
// Stub
|
FasTC::MatrixBase<int, 2, 2> m;
|
||||||
EXPECT_EQ(0, 1);
|
m(0, 0) = 1; m(0, 1) = 2;
|
||||||
|
m(1, 0) = 2; m(1, 1) = 3;
|
||||||
|
|
||||||
|
FasTC::MatrixSquare<int, 2> sqm (m);
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
EXPECT_EQ(m[i], sqm[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::Matrix2x2<int> tbtm (m);
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
EXPECT_EQ(m[i], tbtm[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::Matrix2x2<float> fsqm(m);
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
EXPECT_NEAR(m[i], fsqm[i], kEpsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::Matrix2x2<float> fcsqm(sqm);
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
EXPECT_NEAR(fcsqm[i], sqm[i], kEpsilon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Matrix3x3.h"
|
||||||
|
|
||||||
TEST(Matrix3x3, Constructors) {
|
TEST(Matrix3x3, Constructors) {
|
||||||
// Stub
|
FasTC::MatrixBase<int, 3, 3> m;
|
||||||
EXPECT_EQ(0, 1);
|
m(0, 0) = 1; m(0, 1) = 2; m(0, 2) = 3;
|
||||||
|
m(1, 0) = 2; m(1, 1) = 3; m(1, 2) = 4;
|
||||||
|
m(2, 0) = 3; m(2, 1) = 4; m(2, 2) = 5;
|
||||||
|
|
||||||
|
FasTC::MatrixSquare<int, 3> sqm (m);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_EQ(m[i], sqm[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::Matrix3x3<int> tbtm (m);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_EQ(m[i], tbtm[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::Matrix3x3<float> fsqm(m);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_NEAR(m[i], fsqm[i], kEpsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::Matrix3x3<float> fcsqm(sqm);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_NEAR(fcsqm[i], sqm[i], kEpsilon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Matrix4x4.h"
|
||||||
|
|
||||||
TEST(Matrix4x4, Constructors) {
|
TEST(Matrix4x4, Constructors) {
|
||||||
// Stub
|
FasTC::MatrixBase<int, 4, 4> m;
|
||||||
EXPECT_EQ(0, 1);
|
m(0, 0) = 1; m(0, 1) = 2; m(0, 2) = 3; m(0, 3) = 4;
|
||||||
|
m(1, 0) = 2; m(1, 1) = 3; m(1, 2) = 4; m(1, 3) = 5;
|
||||||
|
m(2, 0) = 3; m(2, 1) = 4; m(2, 2) = 5; m(2, 3) = 6;
|
||||||
|
m(3, 0) = 4; m(3, 1) = 5; m(3, 2) = 6; m(3, 3) = 7;
|
||||||
|
|
||||||
|
FasTC::MatrixSquare<int, 4> sqm (m);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_EQ(m[i], sqm[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::Matrix4x4<int> tbtm (m);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_EQ(m[i], tbtm[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::Matrix4x4<float> fsqm(m);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_NEAR(m[i], fsqm[i], kEpsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
FasTC::Matrix4x4<float> fcsqm(sqm);
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
EXPECT_NEAR(fcsqm[i], sqm[i], kEpsilon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue