Corrected errors on Xcode C++98 pure related to language extensions accidentially used.

master
SGrottel ago%!(EXTRA string=4 years)
parent b8adc27808
commit 0f5b544d5d
  1. 4
      glm/gtx/pca.inl
  2. 173
      test/gtx/gtx_pca.cpp

@ -70,7 +70,7 @@ namespace glm {
GLM_INLINE T transferSign(T const& v, T const& s) GLM_INLINE T transferSign(T const& v, T const& s)
{ {
return ((s) >= 0 ? glm::abs(v) : -glm::abs(v)); return ((s) >= 0 ? glm::abs(v) : -glm::abs(v));
}; }
template<typename T> template<typename T>
GLM_INLINE T pythag(T const& a, T const& b) { GLM_INLINE T pythag(T const& a, T const& b) {
@ -86,7 +86,7 @@ namespace glm {
absa /= absb; absa /= absb;
absa *= absa; absa *= absa;
return absb * glm::sqrt(static_cast<T>(1) + absa); return absb * glm::sqrt(static_cast<T>(1) + absa);
}; }
} }

@ -6,6 +6,33 @@
#include <vector> #include <vector>
#include <random> #include <random>
template<glm::length_t D, typename T, glm::qualifier Q>
bool vectorEpsilonEqual(glm::vec<D, T, Q> const& a, glm::vec<D, T, Q> const& b)
{
for (int c = 0; c < D; ++c)
if (!glm::epsilonEqual(a[c], b[c], static_cast<T>(0.000001)))
return false;
return true;
}
template<glm::length_t D, typename T, glm::qualifier Q>
bool matrixEpsilonEqual(glm::mat<D, D, T, Q> const& a, glm::mat<D, D, T, Q> const& b)
{
for (int c = 0; c < D; ++c)
for (int r = 0; r < D; ++r)
if (!glm::epsilonEqual(a[c][r], b[c][r], static_cast<T>(0.000001)))
return false;
return true;
}
template<typename T>
T failReport(T line)
{
printf("Failed in line %d\n", static_cast<int>(line));
fprintf(stderr, "Failed in line %d\n", static_cast<int>(line));
return line;
}
// Test data: 1AGA 'agarose double helix' // Test data: 1AGA 'agarose double helix'
// https://www.rcsb.org/structure/1aga // https://www.rcsb.org/structure/1aga
// The fourth coordinate is randomized // The fourth coordinate is randomized
@ -147,11 +174,11 @@ namespace _1aga
3.830, 3.522, 5.367, -0.302, 3.830, 3.522, 5.367, -0.302,
5.150, 4.461, 2.116, -1.615 5.150, 4.461, 2.116, -1.615
}; };
static const size_t _1agaSize = sizeof(_1aga) / (4 * sizeof(double)); static const glm::length_t _1agaSize = sizeof(_1aga) / (4 * sizeof(double));
outTestData.resize(_1agaSize); outTestData.resize(_1agaSize);
for(size_t i = 0; i < _1agaSize; ++i) for(glm::length_t i = 0; i < _1agaSize; ++i)
for(size_t d = 0; d < static_cast<size_t>(vec::length()); ++d) for(glm::length_t d = 0; d < static_cast<glm::length_t>(vec::length()); ++d)
outTestData[i][d] = static_cast<typename vec::value_type>(_1aga[i * 4 + d]); outTestData[i][d] = static_cast<typename vec::value_type>(_1aga[i * 4 + d]);
} }
@ -182,10 +209,10 @@ namespace _1aga
{ {
const T* expectedCovarData = nullptr; const T* expectedCovarData = nullptr;
getExpectedCovarDataPtr(expectedCovarData); getExpectedCovarDataPtr(expectedCovarData);
for(size_t x = 0; x < D; ++x) for(glm::length_t x = 0; x < D; ++x)
for(size_t y = 0; y < D; ++y) for(glm::length_t y = 0; y < D; ++y)
if(!glm::equal(covarMat[y][x], expectedCovarData[x * 4 + y], static_cast<T>(0.000001))) if(!glm::equal(covarMat[y][x], expectedCovarData[x * 4 + y], static_cast<T>(0.000001)))
return 1; return failReport(__LINE__);
return 0; return 0;
} }
@ -280,12 +307,12 @@ namespace _1aga
for(int i = 0; i < D; ++i) for(int i = 0; i < D; ++i)
if(!glm::equal(evals[i], expectedEvals[i], static_cast<T>(0.000001))) if(!glm::equal(evals[i], expectedEvals[i], static_cast<T>(0.000001)))
return 1; return failReport(__LINE__);
for (int i = 0; i < D; ++i) for (int i = 0; i < D; ++i)
for (int d = 0; d < D; ++d) for (int d = 0; d < D; ++d)
if (!glm::equal(evecs[i][d], expectedEvecs[i * D + d], static_cast<T>(0.000001))) if (!glm::equal(evecs[i][d], expectedEvecs[i * D + d], static_cast<T>(0.000001)))
return 1; return failReport(__LINE__);
return 0; return 0;
} }
@ -296,29 +323,20 @@ namespace _1aga
template<typename vec> template<typename vec>
vec computeCenter(const std::vector<vec>& testData) vec computeCenter(const std::vector<vec>& testData)
{ {
double c[vec::length()]; double c[4];
std::fill(c, c + vec::length(), 0.0); std::fill(c, c + vec::length(), 0.0);
for(vec const& v : testData) typename std::vector<vec>::const_iterator e = testData.end();
for(size_t d = 0; d < static_cast<size_t>(vec::length()); ++d) for(typename std::vector<vec>::const_iterator i = testData.begin(); i != e; ++i)
c[d] += static_cast<double>(v[d]); for(glm::length_t d = 0; d < static_cast<glm::length_t>(vec::length()); ++d)
c[d] += static_cast<double>((*i)[d]);
vec cVec; vec cVec(0);
for(size_t d = 0; d < static_cast<size_t>(vec::length()); ++d) for(glm::length_t d = 0; d < static_cast<glm::length_t>(vec::length()); ++d)
cVec[d] = static_cast<typename vec::value_type>(c[d] / static_cast<double>(testData.size())); cVec[d] = static_cast<typename vec::value_type>(c[d] / static_cast<double>(testData.size()));
return cVec; return cVec;
} }
template<glm::length_t D, typename T, glm::qualifier Q>
bool matrixEpsilonEqual(glm::mat<D, D, T, Q> const& a, glm::mat<D, D, T, Q> const& b)
{
for (int c = 0; c < D; ++c)
for (int r = 0; r < D; ++r)
if (!glm::epsilonEqual(a[c][r], b[c][r], static_cast<T>(0.000001)))
return false;
return true;
}
// Test sorting of Eigenvalue&Eigenvector lists. Use exhaustive search. // Test sorting of Eigenvalue&Eigenvector lists. Use exhaustive search.
template<glm::length_t D, typename T, glm::qualifier Q> template<glm::length_t D, typename T, glm::qualifier Q>
int testEigenvalueSort() int testEigenvalueSort()
@ -339,8 +357,7 @@ int testEigenvalueSort()
) )
); );
// Permutations of test input data for exhaustive check, based on `D` (1 <= D <= 4) // Permutations of test input data for exhaustive check, based on `D` (1 <= D <= 4)
static const int permutationCount[] static const int permutationCount[] = {
{
0, 0,
1, 1,
2, 2,
@ -348,8 +365,7 @@ int testEigenvalueSort()
24 24
}; };
// The permutations t perform, based on `D` (1 <= D <= 4) // The permutations t perform, based on `D` (1 <= D <= 4)
static const glm::ivec4 permutation[] static const glm::ivec4 permutation[] = {
{
{ 0, 1, 2, 3 }, { 0, 1, 2, 3 },
{ 1, 0, 2, 3 }, // last for D = 2 { 1, 0, 2, 3 }, // last for D = 2
{ 0, 2, 1, 3 }, { 0, 2, 1, 3 },
@ -377,10 +393,10 @@ int testEigenvalueSort()
}; };
// initial sanity check // initial sanity check
if(!glm::all(glm::epsilonEqual(refVal, refVal, static_cast<T>(0.000001)))) if(!vectorEpsilonEqual(refVal, refVal))
return 1; return failReport(__LINE__);
if(!matrixEpsilonEqual(refVec, refVec)) if(!matrixEpsilonEqual(refVec, refVec))
return 1; return failReport(__LINE__);
// Exhaustive search through all permutations // Exhaustive search through all permutations
for(int p = 0; p < permutationCount[D]; ++p) for(int p = 0; p < permutationCount[D]; ++p)
@ -395,10 +411,10 @@ int testEigenvalueSort()
glm::sortEigenvalues(testVal, testVec); glm::sortEigenvalues(testVal, testVec);
if (!glm::all(glm::epsilonEqual(testVal, refVal, static_cast<T>(0.000001)))) if (!vectorEpsilonEqual(testVal, refVal))
return 2 + p * 2; return failReport(__LINE__);
if (!matrixEpsilonEqual(testVec, refVec)) if (!matrixEpsilonEqual(testVec, refVec))
return 2 + 1 + p * 2; return failReport(__LINE__);
} }
return 0; return 0;
@ -406,7 +422,7 @@ int testEigenvalueSort()
// Test covariance matrix creation functions // Test covariance matrix creation functions
template<glm::length_t D, typename T, glm::qualifier Q> template<glm::length_t D, typename T, glm::qualifier Q>
int testCovar(unsigned int dataSize, unsigned int randomEngineSeed) int testCovar(glm::length_t dataSize, unsigned int randomEngineSeed)
{ {
typedef glm::vec<D, T, Q> vec; typedef glm::vec<D, T, Q> vec;
typedef glm::mat<D, D, T, Q> mat; typedef glm::mat<D, D, T, Q> mat;
@ -420,7 +436,7 @@ int testCovar(unsigned int dataSize, unsigned int randomEngineSeed)
mat covarMat = glm::computeCovarianceMatrix(testData.data(), testData.size(), center); mat covarMat = glm::computeCovarianceMatrix(testData.data(), testData.size(), center);
if(_1aga::checkCovarMat(covarMat)) if(_1aga::checkCovarMat(covarMat))
return 1; return failReport(__LINE__);
// #2: test function variant consitency with random data // #2: test function variant consitency with random data
std::default_random_engine rndEng(randomEngineSeed); std::default_random_engine rndEng(randomEngineSeed);
@ -428,18 +444,19 @@ int testCovar(unsigned int dataSize, unsigned int randomEngineSeed)
testData.resize(dataSize); testData.resize(dataSize);
// some common offset of all data // some common offset of all data
T offset[D]; T offset[D];
for(size_t d = 0; d < D; ++d) for(glm::length_t d = 0; d < D; ++d)
offset[d] = normalDist(rndEng); offset[d] = normalDist(rndEng);
// init data // init data
for(size_t i = 0; i < dataSize; ++i) for(glm::length_t i = 0; i < dataSize; ++i)
for(size_t d = 0; d < D; ++d) for(glm::length_t d = 0; d < D; ++d)
testData[i][d] = offset[d] + normalDist(rndEng); testData[i][d] = offset[d] + normalDist(rndEng);
center = computeCenter(testData); center = computeCenter(testData);
std::vector<vec> centeredTestData; std::vector<vec> centeredTestData;
centeredTestData.reserve(testData.size()); centeredTestData.reserve(testData.size());
for(vec const& v : testData) std::vector<vec>::const_iterator e = testData.end();
centeredTestData.push_back(v - center); for(std::vector<vec>::const_iterator i = testData.begin(); i != e; ++i)
centeredTestData.push_back((*i) - center);
mat c1 = glm::computeCovarianceMatrix(centeredTestData.data(), centeredTestData.size()); mat c1 = glm::computeCovarianceMatrix(centeredTestData.data(), centeredTestData.size());
mat c2 = glm::computeCovarianceMatrix<D, T, Q>(centeredTestData.begin(), centeredTestData.end()); mat c2 = glm::computeCovarianceMatrix<D, T, Q>(centeredTestData.begin(), centeredTestData.end());
@ -447,11 +464,11 @@ int testCovar(unsigned int dataSize, unsigned int randomEngineSeed)
mat c4 = glm::computeCovarianceMatrix<D, T, Q>(testData.rbegin(), testData.rend(), center); mat c4 = glm::computeCovarianceMatrix<D, T, Q>(testData.rbegin(), testData.rend(), center);
if(!matrixEpsilonEqual(c1, c2)) if(!matrixEpsilonEqual(c1, c2))
return 1; return failReport(__LINE__);
if(!matrixEpsilonEqual(c1, c3)) if(!matrixEpsilonEqual(c1, c3))
return 1; return failReport(__LINE__);
if(!matrixEpsilonEqual(c1, c4)) if(!matrixEpsilonEqual(c1, c4))
return 1; return failReport(__LINE__);
return 0; return 0;
} }
@ -471,11 +488,11 @@ int testEigenvectors()
mat eigenvectors; mat eigenvectors;
unsigned int c = glm::findEigenvaluesSymReal(covarMat, eigenvalues, eigenvectors); unsigned int c = glm::findEigenvaluesSymReal(covarMat, eigenvalues, eigenvectors);
if(c != D) if(c != D)
return 1; return failReport(__LINE__);
glm::sortEigenvalues(eigenvalues, eigenvectors); glm::sortEigenvalues(eigenvalues, eigenvectors);
if(_1aga::checkEigenvaluesEigenvectors(eigenvalues, eigenvectors) != 0) if(_1aga::checkEigenvaluesEigenvectors(eigenvalues, eigenvectors) != 0)
return 1; return failReport(__LINE__);
return 0; return 0;
} }
@ -501,7 +518,7 @@ int smokeTest()
vec3 eVal; vec3 eVal;
int eCnt = glm::findEigenvaluesSymReal(covar, eVal, eVec); int eCnt = glm::findEigenvaluesSymReal(covar, eVal, eVec);
if(eCnt != 3) if(eCnt != 3)
return 1; return failReport(__LINE__);
// sort eVec by decending eVal // sort eVec by decending eVal
if(eVal[0] < eVal[1]) if(eVal[0] < eVal[1])
@ -520,12 +537,12 @@ int smokeTest()
std::swap(eVec[1], eVec[2]); std::swap(eVec[1], eVec[2]);
} }
if(!glm::all(glm::equal(glm::abs(eVec[0]), vec3(0, 1, 0)))) if(!vectorEpsilonEqual(glm::abs(eVec[0]), vec3(0, 1, 0)))
return 2; return failReport(__LINE__);
if(!glm::all(glm::equal(glm::abs(eVec[1]), vec3(1, 0, 0)))) if(!vectorEpsilonEqual(glm::abs(eVec[1]), vec3(1, 0, 0)))
return 3; return failReport(__LINE__);
if(!glm::all(glm::equal(glm::abs(eVec[2]), vec3(0, 0, 1)))) if(!vectorEpsilonEqual(glm::abs(eVec[2]), vec3(0, 0, 1)))
return 4; return failReport(__LINE__);
return 0; return 0;
} }
@ -586,7 +603,7 @@ int rndTest(unsigned int randomEngineSeed)
glm::dmat3 evecs; glm::dmat3 evecs;
int evcnt = glm::findEigenvaluesSymReal(covarMat, evals, evecs); int evcnt = glm::findEigenvaluesSymReal(covarMat, evals, evecs);
if(evcnt != 3) if(evcnt != 3)
return 1; return failReport(__LINE__);
glm::sortEigenvalues(evals, evecs); glm::sortEigenvalues(evals, evecs);
//printf("\n"); //printf("\n");
@ -595,11 +612,11 @@ int rndTest(unsigned int randomEngineSeed)
//printf("evec1: %.10lf, %.10lf, %.10lf\n", evecs[1].x, evecs[1].y, evecs[1].z); //printf("evec1: %.10lf, %.10lf, %.10lf\n", evecs[1].x, evecs[1].y, evecs[1].z);
if(glm::length(glm::abs(x) - glm::abs(evecs[0])) > 0.000001) if(glm::length(glm::abs(x) - glm::abs(evecs[0])) > 0.000001)
return 1; return failReport(__LINE__);
if(glm::length(glm::abs(y) - glm::abs(evecs[2])) > 0.000001) if(glm::length(glm::abs(y) - glm::abs(evecs[2])) > 0.000001)
return 1; return failReport(__LINE__);
if(glm::length(glm::abs(z) - glm::abs(evecs[1])) > 0.000001) if(glm::length(glm::abs(z) - glm::abs(evecs[1])) > 0.000001)
return 1; return failReport(__LINE__);
return 0; return 0;
} }
@ -609,56 +626,56 @@ int main()
// A small smoke test to fail early with most problems // A small smoke test to fail early with most problems
if(smokeTest()) if(smokeTest())
return __LINE__; return failReport(__LINE__);
// test sorting utility. // test sorting utility.
if(testEigenvalueSort<2, float, glm::defaultp>() != 0) if(testEigenvalueSort<2, float, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
if(testEigenvalueSort<2, double, glm::defaultp>() != 0) if(testEigenvalueSort<2, double, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
if(testEigenvalueSort<3, float, glm::defaultp>() != 0) if(testEigenvalueSort<3, float, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
if(testEigenvalueSort<3, double, glm::defaultp>() != 0) if(testEigenvalueSort<3, double, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
if(testEigenvalueSort<4, float, glm::defaultp>() != 0) if(testEigenvalueSort<4, float, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
if(testEigenvalueSort<4, double, glm::defaultp>() != 0) if(testEigenvalueSort<4, double, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
// Note: the random engine uses a fixed seed to create consistent and reproducible test data // Note: the random engine uses a fixed seed to create consistent and reproducible test data
// test covariance matrix computation from different data sources // test covariance matrix computation from different data sources
if(testCovar<2, float, glm::defaultp>(100, 12345) != 0) if(testCovar<2, float, glm::defaultp>(100, 12345) != 0)
return __LINE__; return failReport(__LINE__);
if(testCovar<2, double, glm::defaultp>(100, 42) != 0) if(testCovar<2, double, glm::defaultp>(100, 42) != 0)
return __LINE__; return failReport(__LINE__);
if(testCovar<3, float, glm::defaultp>(100, 2021) != 0) if(testCovar<3, float, glm::defaultp>(100, 2021) != 0)
return __LINE__; return failReport(__LINE__);
if(testCovar<3, double, glm::defaultp>(100, 815) != 0) if(testCovar<3, double, glm::defaultp>(100, 815) != 0)
return __LINE__; return failReport(__LINE__);
if(testCovar<4, float, glm::defaultp>(100, 3141) != 0) if(testCovar<4, float, glm::defaultp>(100, 3141) != 0)
return __LINE__; return failReport(__LINE__);
if(testCovar<4, double, glm::defaultp>(100, 174) != 0) if(testCovar<4, double, glm::defaultp>(100, 174) != 0)
return __LINE__; return failReport(__LINE__);
// test PCA eigen vector reconstruction // test PCA eigen vector reconstruction
if(testEigenvectors<2, float, glm::defaultp>() != 0) if(testEigenvectors<2, float, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
if(testEigenvectors<2, double, glm::defaultp>() != 0) if(testEigenvectors<2, double, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
if(testEigenvectors<3, float, glm::defaultp>() != 0) if(testEigenvectors<3, float, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
if(testEigenvectors<3, double, glm::defaultp>() != 0) if(testEigenvectors<3, double, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
if (testEigenvectors<4, float, glm::defaultp>() != 0) if (testEigenvectors<4, float, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
if (testEigenvectors<4, double, glm::defaultp>() != 0) if (testEigenvectors<4, double, glm::defaultp>() != 0)
return __LINE__; return failReport(__LINE__);
// Final tests with randomized data // Final tests with randomized data
if(rndTest(12345) != 0) if(rndTest(12345) != 0)
return __LINE__; return failReport(__LINE__);
if(rndTest(42) != 0) if(rndTest(42) != 0)
return __LINE__; return failReport(__LINE__);
return 0; return 0;
} }

Loading…
Cancel
Save