FasTC/Base/include/MatrixSquare.h
Pavel Krajcevski 479ba8e76d Fix a bunch of MSVC compiler warnings and errors.
Most notably, we need to actually fix a bug in MSVC that doesn't know how to properly instantiate
enums in partial template specialization. There are more details outlined here:

http://stackoverflow.com/questions/15466594/why-does-msvc-fail-to-compile-this-template-function

The fix in this commit closes #10

Also in this commit is a hacky way to allow GL defines. Apparently "LoadImage" is defined as a
macro even with WIN32_LEAN_AND_MEAN. This means that we have to #undef the code that includes
it, meaning that we also need to make sure not to actually mix GLDefines.h with any file that needs
to use the functions from Windows.h
2014-03-12 02:43:09 -04:00

124 lines
3.6 KiB
C++

/*******************************************************************************
* Copyright (c) 2012 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_MATRIXSQUARE_H_
#define BASE_INCLUDE_MATRIXSQUARE_H_
#include "MatrixBase.h"
#include <cstdlib>
#include <ctime>
namespace FasTC {
template <typename T, const int N>
class MatrixSquare : public MatrixBase<T, N, N> {
public:
// Constructors
MatrixSquare() { }
MatrixSquare(const MatrixSquare<T, N> &other)
: MatrixBase<T, N, N>(other) { }
MatrixSquare(const 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.
// Returns them in eigVec and eigVal after kMaxNumIterations
int PowerMethod(VectorBase<T, N> &eigVec,
T *eigVal = NULL,
const int kMaxNumIterations = 200,
const unsigned int kSeed = time(NULL)) {
srand(kSeed);
int numIterations = 0;
VectorBase<T, N> b;
for(int i = 0; i < N; i++)
b[i] = static_cast<T>(rand());
b.Normalize();
bool badEigenValue = false;
bool fixed = false;
numIterations = 0;
while(!fixed && ++numIterations < kMaxNumIterations) {
VectorBase<T, N> newB = (*this) * b;
// !HACK! If the principal eigenvector of the matrix
// converges to zero, that could mean that there is no
// principal eigenvector. However, that may be due to
// poor initialization of the random vector, so rerandomize
// and try again.
const T newBlen = newB.Length();
if(newBlen < 1e-10) {
if(badEigenValue) {
eigVec = b;
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;
}
// Normalize
newB.Normalize();
// 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;
// Save and continue.
b = newB;
}
// 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;
}
private:
};
REGISTER_ONE_TEMPLATE_MATRIX_SIZED_TYPE(MatrixSquare);
};
#endif // BASE_INCLUDE_MATRIXSQUARE_H_