Fix Clang 15 test build errors

Fixes for compiler errors when building the tests using Clang 15,
including:

    * Use explicit cast to silence Wimplicit-int-float-conversion
      warning for conversion of spin count in implementation of
      glm::slerp.
    * Use GLM_FORCE_MESSAGES instead of removed GLM_MESSAGES for
      messages in glm/gtx/hash.hpp, avoiding Wundef warning.
    * Encode en dash in URL for Gram-Schmit Process wikipedia page and
      replace similar en dashes in comments with regular dashes, to
      avoid Winvalid-utf8 warnings in glm/gtx/matrix_factorisation.inl.
    * Replace degree sign symbol with text "degrees" to avoid
      Winvalid-utf8 warnings in test/gtc/gtc_quaternion.cpp.
    * When using Clang, build tests with -Wno-float-equal to silence
      Wfloat-equal warning in implementation of glm::vec<L,T,Q>::equal.
    * For performance tests in test/gtx/gtx_fast_trigonometry.cpp, add
      statement explicitly casting result to void, to silence
      Wunused-but-set-variable warnings.
    * Add newline at end of test/gtx/gtx_hash.cpp to silence
      Wnewline-eof warning.
    * Rename namespace _1aga to agarose in test/gtx/gtx_pca.cpp to
      avoid Wreserved-identifier warning.
This commit is contained in:
Mark Sheppard 2023-03-31 17:39:53 +01:00
parent efec5db081
commit 3cb568cd37
8 changed files with 47 additions and 34 deletions

View File

@ -104,7 +104,7 @@ namespace glm
{ {
// Graphics Gems III, page 96 // Graphics Gems III, page 96
T angle = acos(cosTheta); T angle = acos(cosTheta);
T phi = angle + k * glm::pi<T>(); T phi = angle + static_cast<T>(k) * glm::pi<T>();
return (sin(angle - a * phi)* x + sin(a * phi) * z) / sin(angle); return (sin(angle - a * phi)* x + sin(a * phi) * z) / sin(angle);
} }
} }

View File

@ -12,7 +12,7 @@
#pragma once #pragma once
#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) #if defined(GLM_FORCE_MESSAGES) && !defined(GLM_EXT_INCLUDED)
# ifndef GLM_ENABLE_EXPERIMENTAL # ifndef GLM_ENABLE_EXPERIMENTAL
# pragma message("GLM: GLM_GTX_hash is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") # pragma message("GLM: GLM_GTX_hash is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.")
# else # else

View File

@ -28,7 +28,7 @@ namespace glm
GLM_FUNC_QUALIFIER void qr_decompose(mat<C, R, T, Q> const& in, mat<(C < R ? C : R), R, T, Q>& q, mat<C, (C < R ? C : R), T, Q>& r) GLM_FUNC_QUALIFIER void qr_decompose(mat<C, R, T, Q> const& in, mat<(C < R ? C : R), R, T, Q>& q, mat<C, (C < R ? C : R), T, Q>& r)
{ {
// Uses modified Gram-Schmidt method // Uses modified Gram-Schmidt method
// Source: https://en.wikipedia.org/wiki/GramSchmidt_process // Source: https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process
// And https://en.wikipedia.org/wiki/QR_decomposition // And https://en.wikipedia.org/wiki/QR_decomposition
//For all the linearly independs columns of the input... //For all the linearly independs columns of the input...
@ -64,8 +64,8 @@ namespace glm
{ {
// From https://en.wikipedia.org/wiki/QR_decomposition: // From https://en.wikipedia.org/wiki/QR_decomposition:
// The RQ decomposition transforms a matrix A into the product of an upper triangular matrix R (also known as right-triangular) and an orthogonal matrix Q. The only difference from QR decomposition is the order of these matrices. // The RQ decomposition transforms a matrix A into the product of an upper triangular matrix R (also known as right-triangular) and an orthogonal matrix Q. The only difference from QR decomposition is the order of these matrices.
// QR decomposition is GramSchmidt orthogonalization of columns of A, started from the first column. // QR decomposition is Gram-Schmidt orthogonalization of columns of A, started from the first column.
// RQ decomposition is GramSchmidt orthogonalization of rows of A, started from the last row. // RQ decomposition is Gram-Schmidt orthogonalization of rows of A, started from the last row.
mat<R, C, T, Q> tin = transpose(in); mat<R, C, T, Q> tin = transpose(in);
tin = fliplr(tin); tin = fliplr(tin);

View File

@ -199,7 +199,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Werror -Weverything) add_compile_options(-Werror -Weverything)
add_compile_options(-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++11-long-long -Wno-padded -Wno-gnu-anonymous-struct -Wno-nested-anon-types) add_compile_options(-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++11-long-long -Wno-padded -Wno-gnu-anonymous-struct -Wno-nested-anon-types)
add_compile_options(-Wno-undefined-reinterpret-cast -Wno-sign-conversion -Wno-unused-variable -Wno-missing-prototypes -Wno-unreachable-code -Wno-missing-variable-declarations -Wno-sign-compare -Wno-global-constructors -Wno-unused-macros -Wno-format-nonliteral) add_compile_options(-Wno-undefined-reinterpret-cast -Wno-sign-conversion -Wno-unused-variable -Wno-missing-prototypes -Wno-unreachable-code -Wno-missing-variable-declarations -Wno-sign-compare -Wno-global-constructors -Wno-unused-macros -Wno-format-nonliteral -Wno-float-equal)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if(NOT GLM_QUIET) if(NOT GLM_QUIET)

View File

@ -141,39 +141,39 @@ int test_quat_slerp()
Error += glm::all(glm::equal(id, id2, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(id, id2, Epsilon)) ? 0 : 1;
// Testing a == 1 // Testing a == 1
// Must be 90° rotation on Y : 0 0.7 0 0.7 // Must be 90 degrees rotation on Y : 0 0.7 0 0.7
glm::quat Y90rot2 = glm::slerp(id, Y90rot, 1.0f); glm::quat Y90rot2 = glm::slerp(id, Y90rot, 1.0f);
Error += glm::all(glm::equal(Y90rot, Y90rot2, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(Y90rot, Y90rot2, Epsilon)) ? 0 : 1;
// Testing standard, easy case // Testing standard, easy case
// Must be 45° rotation on Y : 0 0.38 0 0.92 // Must be 45 degrees rotation on Y : 0 0.38 0 0.92
glm::quat Y45rot1 = glm::slerp(id, Y90rot, 0.5f); glm::quat Y45rot1 = glm::slerp(id, Y90rot, 0.5f);
// Testing reverse case // Testing reverse case
// Must be 45° rotation on Y : 0 0.38 0 0.92 // Must be 45 degrees rotation on Y : 0 0.38 0 0.92
glm::quat Ym45rot2 = glm::slerp(Y90rot, id, 0.5f); glm::quat Ym45rot2 = glm::slerp(Y90rot, id, 0.5f);
// Testing against full circle around the sphere instead of shortest path // Testing against full circle around the sphere instead of shortest path
// Must be 45° rotation on Y // Must be 45 degrees rotation on Y
// certainly not a 135° rotation // certainly not a 135 degrees rotation
glm::quat Y45rot3 = glm::slerp(id , -Y90rot, 0.5f); glm::quat Y45rot3 = glm::slerp(id , -Y90rot, 0.5f);
float Y45angle3 = glm::angle(Y45rot3); float Y45angle3 = glm::angle(Y45rot3);
Error += glm::equal(Y45angle3, glm::pi<float>() * 0.25f, Epsilon) ? 0 : 1; Error += glm::equal(Y45angle3, glm::pi<float>() * 0.25f, Epsilon) ? 0 : 1;
Error += glm::all(glm::equal(Ym45rot2, Y45rot3, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(Ym45rot2, Y45rot3, Epsilon)) ? 0 : 1;
// Same, but inverted // Same, but inverted
// Must also be 45° rotation on Y : 0 0.38 0 0.92 // Must also be 45 degrees rotation on Y : 0 0.38 0 0.92
// -0 -0.38 -0 -0.92 is ok too // -0 -0.38 -0 -0.92 is ok too
glm::quat Y45rot4 = glm::slerp(-Y90rot, id, 0.5f); glm::quat Y45rot4 = glm::slerp(-Y90rot, id, 0.5f);
Error += glm::all(glm::equal(Ym45rot2, -Y45rot4, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(Ym45rot2, -Y45rot4, Epsilon)) ? 0 : 1;
// Testing q1 = q2 // Testing q1 = q2
// Must be 90° rotation on Y : 0 0.7 0 0.7 // Must be 90 degrees rotation on Y : 0 0.7 0 0.7
glm::quat Y90rot3 = glm::slerp(Y90rot, Y90rot, 0.5f); glm::quat Y90rot3 = glm::slerp(Y90rot, Y90rot, 0.5f);
Error += glm::all(glm::equal(Y90rot, Y90rot3, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(Y90rot, Y90rot3, Epsilon)) ? 0 : 1;
// Testing 180° rotation // Testing 180 degrees rotation
// Must be 90° rotation on almost any axis that is on the XZ plane // Must be 90 degrees rotation on almost any axis that is on the XZ plane
glm::quat XZ90rot = glm::slerp(id, -Y90rot, 0.5f); glm::quat XZ90rot = glm::slerp(id, -Y90rot, 0.5f);
float XZ90angle = glm::angle(XZ90rot); // Must be PI/4 = 0.78; float XZ90angle = glm::angle(XZ90rot); // Must be PI/4 = 0.78;
Error += glm::equal(XZ90angle, glm::pi<float>() * 0.25f, Epsilon) ? 0 : 1; Error += glm::equal(XZ90angle, glm::pi<float>() * 0.25f, Epsilon) ? 0 : 1;
@ -216,7 +216,7 @@ int test_quat_slerp_spins()
Error += glm::all(glm::equal(id, id3, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(id, id3, Epsilon)) ? 0 : 1;
// Testing a == 1, k == 1 // Testing a == 1, k == 1
// Must be 90° rotation on Y : 0 0.7 0 0.7 // Must be 90 degrees rotation on Y : 0 0.7 0 0.7
// Negative quaternion is representing same orientation // Negative quaternion is representing same orientation
glm::quat Y90rot2 = glm::slerp(id, Y90rot, 1.0f, 1); glm::quat Y90rot2 = glm::slerp(id, Y90rot, 1.0f, 1);
Error += glm::all(glm::equal(Y90rot, -Y90rot2, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(Y90rot, -Y90rot2, Epsilon)) ? 0 : 1;
@ -227,44 +227,44 @@ int test_quat_slerp_spins()
Error += glm::all(glm::equal(id, Y90rot3, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(id, Y90rot3, Epsilon)) ? 0 : 1;
// Testing a == 1, k == 1 // Testing a == 1, k == 1
// Must be 90° rotation on Y : 0 0.7 0 0.7 // Must be 90 degrees rotation on Y : 0 0.7 0 0.7
glm::quat Y90rot4 = glm::slerp(id, Y90rot, 0.2f, 1); glm::quat Y90rot4 = glm::slerp(id, Y90rot, 0.2f, 1);
Error += glm::all(glm::equal(Y90rot, Y90rot4, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(Y90rot, Y90rot4, Epsilon)) ? 0 : 1;
// Testing reverse case // Testing reverse case
// Must be 45° rotation on Y : 0 0.38 0 0.92 // Must be 45 degrees rotation on Y : 0 0.38 0 0.92
// Negative quaternion is representing same orientation // Negative quaternion is representing same orientation
glm::quat Ym45rot2 = glm::slerp(Y90rot, id, 0.9f, 1); glm::quat Ym45rot2 = glm::slerp(Y90rot, id, 0.9f, 1);
glm::quat Ym45rot3 = glm::slerp(Y90rot, id, 0.5f); glm::quat Ym45rot3 = glm::slerp(Y90rot, id, 0.5f);
Error += glm::all(glm::equal(-Ym45rot2, Ym45rot3, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(-Ym45rot2, Ym45rot3, Epsilon)) ? 0 : 1;
// Testing against full circle around the sphere instead of shortest path // Testing against full circle around the sphere instead of shortest path
// Must be 45° rotation on Y // Must be 45 degrees rotation on Y
// certainly not a 135° rotation // certainly not a 135 degrees rotation
glm::quat Y45rot3 = glm::slerp(id, -Y90rot, 0.5f, 0); glm::quat Y45rot3 = glm::slerp(id, -Y90rot, 0.5f, 0);
float Y45angle3 = glm::angle(Y45rot3); float Y45angle3 = glm::angle(Y45rot3);
Error += glm::equal(Y45angle3, glm::pi<float>() * 0.25f, Epsilon) ? 0 : 1; Error += glm::equal(Y45angle3, glm::pi<float>() * 0.25f, Epsilon) ? 0 : 1;
Error += glm::all(glm::equal(Ym45rot3, Y45rot3, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(Ym45rot3, Y45rot3, Epsilon)) ? 0 : 1;
// Same, but inverted // Same, but inverted
// Must also be 45° rotation on Y : 0 0.38 0 0.92 // Must also be 45 degrees rotation on Y : 0 0.38 0 0.92
// -0 -0.38 -0 -0.92 is ok too // -0 -0.38 -0 -0.92 is ok too
glm::quat Y45rot4 = glm::slerp(-Y90rot, id, 0.5f, 0); glm::quat Y45rot4 = glm::slerp(-Y90rot, id, 0.5f, 0);
Error += glm::all(glm::equal(Ym45rot2, Y45rot4, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(Ym45rot2, Y45rot4, Epsilon)) ? 0 : 1;
// Testing q1 = q2 k == 2 // Testing q1 = q2 k == 2
// Must be 90° rotation on Y : 0 0.7 0 0.7 // Must be 90 degrees rotation on Y : 0 0.7 0 0.7
glm::quat Y90rot5 = glm::slerp(Y90rot, Y90rot, 0.5f, 2); glm::quat Y90rot5 = glm::slerp(Y90rot, Y90rot, 0.5f, 2);
Error += glm::all(glm::equal(Y90rot, Y90rot5, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(Y90rot, Y90rot5, Epsilon)) ? 0 : 1;
// Testing 180° rotation // Testing 180 degrees rotation
// Must be 90° rotation on almost any axis that is on the XZ plane // Must be 90 degrees rotation on almost any axis that is on the XZ plane
glm::quat XZ90rot = glm::slerp(id, -Y90rot, 0.5f, 1); glm::quat XZ90rot = glm::slerp(id, -Y90rot, 0.5f, 1);
float XZ90angle = glm::angle(XZ90rot); // Must be PI/4 = 0.78; float XZ90angle = glm::angle(XZ90rot); // Must be PI/4 = 0.78;
Error += glm::equal(XZ90angle, glm::pi<float>() * 1.25f, Epsilon) ? 0 : 1; Error += glm::equal(XZ90angle, glm::pi<float>() * 1.25f, Epsilon) ? 0 : 1;
// Testing rotation over long arc // Testing rotation over long arc
// Distance from id to 90° is 270°, so 2/3 of it should be 180° // Distance from id to 90 degrees is 270 degrees, so 2/3 of it should be 180 degrees
// Negative quaternion is representing same orientation // Negative quaternion is representing same orientation
glm::quat Neg90rot = glm::slerp(id, Y90rot, 2.0f / 3.0f, -1); glm::quat Neg90rot = glm::slerp(id, Y90rot, 2.0f / 3.0f, -1);
Error += glm::all(glm::equal(Y180rot, -Neg90rot, Epsilon)) ? 0 : 1; Error += glm::all(glm::equal(Y180rot, -Neg90rot, Epsilon)) ? 0 : 1;

View File

@ -35,6 +35,8 @@ namespace fastCos
std::printf("fastCos Time %d clocks\n", static_cast<int>(time_fast)); std::printf("fastCos Time %d clocks\n", static_cast<int>(time_fast));
std::printf("cos Time %d clocks\n", static_cast<int>(time_default)); std::printf("cos Time %d clocks\n", static_cast<int>(time_default));
(void) result; // Silence set but not used warning
return time_fast <= time_default ? 0 : 1; return time_fast <= time_default ? 0 : 1;
} }
}//namespace fastCos }//namespace fastCos
@ -69,6 +71,8 @@ namespace fastSin
std::printf("fastSin Time %d clocks\n", static_cast<int>(time_fast)); std::printf("fastSin Time %d clocks\n", static_cast<int>(time_fast));
std::printf("sin Time %d clocks\n", static_cast<int>(time_default)); std::printf("sin Time %d clocks\n", static_cast<int>(time_default));
(void) result; // Silence set but not used warning
return time_fast <= time_default ? 0 : 1; return time_fast <= time_default ? 0 : 1;
} }
}//namespace fastSin }//namespace fastSin
@ -95,6 +99,8 @@ namespace fastTan
std::printf("fastTan Time %d clocks\n", static_cast<int>(time_fast)); std::printf("fastTan Time %d clocks\n", static_cast<int>(time_fast));
std::printf("tan Time %d clocks\n", static_cast<int>(time_default)); std::printf("tan Time %d clocks\n", static_cast<int>(time_default));
(void) result; // Silence set but not used warning
return time_fast <= time_default ? 0 : 1; return time_fast <= time_default ? 0 : 1;
} }
}//namespace fastTan }//namespace fastTan
@ -122,6 +128,8 @@ namespace fastAcos
std::printf("fastAcos Time %d clocks\n", static_cast<int>(time_fast)); std::printf("fastAcos Time %d clocks\n", static_cast<int>(time_fast));
std::printf("acos Time %d clocks\n", static_cast<int>(time_default)); std::printf("acos Time %d clocks\n", static_cast<int>(time_default));
(void) result; // Silence set but not used warning
return time_fast <= time_default ? 0 : 1; return time_fast <= time_default ? 0 : 1;
} }
}//namespace fastAcos }//namespace fastAcos
@ -145,6 +153,8 @@ namespace fastAsin
std::printf("fastAsin Time %d clocks\n", static_cast<int>(time_fast)); std::printf("fastAsin Time %d clocks\n", static_cast<int>(time_fast));
std::printf("asin Time %d clocks\n", static_cast<int>(time_default)); std::printf("asin Time %d clocks\n", static_cast<int>(time_default));
(void) result; // Silence set but not used warning
return time_fast <= time_default ? 0 : 1; return time_fast <= time_default ? 0 : 1;
} }
}//namespace fastAsin }//namespace fastAsin
@ -168,6 +178,8 @@ namespace fastAtan
std::printf("fastAtan Time %d clocks\n", static_cast<int>(time_fast)); std::printf("fastAtan Time %d clocks\n", static_cast<int>(time_fast));
std::printf("atan Time %d clocks\n", static_cast<int>(time_default)); std::printf("atan Time %d clocks\n", static_cast<int>(time_default));
(void) result; // Silence set but not used warning
return time_fast <= time_default ? 0 : 1; return time_fast <= time_default ? 0 : 1;
} }
}//namespace fastAtan }//namespace fastAtan

View File

@ -52,4 +52,5 @@ int main()
Error += test_compile(); Error += test_compile();
return Error; return Error;
} }

View File

@ -68,7 +68,7 @@ T failReport(T 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
namespace _1aga namespace agarose
{ {
// Fills `outTestData` with hard-coded atom positions from 1AGA // Fills `outTestData` with hard-coded atom positions from 1AGA
@ -216,7 +216,7 @@ namespace _1aga
// All reference values computed separately using symbolic precision // All reference values computed separately using symbolic precision
// https://github.com/sgrottel/exp-pca-precision // https://github.com/sgrottel/exp-pca-precision
// This applies to all functions named: `_1aga::expected*()` // This applies to all functions named: `agarose::expected*()`
GLM_INLINE glm::dmat4 const& expectedCovarData() GLM_INLINE glm::dmat4 const& expectedCovarData()
{ {
@ -333,7 +333,7 @@ namespace _1aga
return evecs4; return evecs4;
} }
} // namespace _1aga } // namespace agarose
// Compute center of gravity // Compute center of gravity
template<typename vec> template<typename vec>
@ -451,13 +451,13 @@ int testCovar(
// #1: test expected result with fixed data set // #1: test expected result with fixed data set
std::vector<vec> testData; std::vector<vec> testData;
_1aga::fillTestData(testData); agarose::fillTestData(testData);
// compute center of gravity // compute center of gravity
vec center = computeCenter(testData); vec center = computeCenter(testData);
mat covarMat = glm::computeCovarianceMatrix(testData.data(), testData.size(), center); mat covarMat = glm::computeCovarianceMatrix(testData.data(), testData.size(), center);
if(!matrixEpsilonEqual(covarMat, mat(_1aga::expectedCovarData()), myEpsilon<T>())) if(!matrixEpsilonEqual(covarMat, mat(agarose::expectedCovarData()), myEpsilon<T>()))
{ {
fprintf(stderr, "Reconstructed covarMat:\n%s\n", glm::to_string(covarMat).c_str()); fprintf(stderr, "Reconstructed covarMat:\n%s\n", glm::to_string(covarMat).c_str());
return failReport(__LINE__); return failReport(__LINE__);
@ -508,7 +508,7 @@ int testEigenvectors(T epsilon)
// test expected result with fixed data set // test expected result with fixed data set
std::vector<vec> testData; std::vector<vec> testData;
mat covarMat(_1aga::expectedCovarData()); mat covarMat(agarose::expectedCovarData());
vec eigenvalues; vec eigenvalues;
mat eigenvectors; mat eigenvectors;
@ -517,13 +517,13 @@ int testEigenvectors(T epsilon)
return failReport(__LINE__); return failReport(__LINE__);
glm::sortEigenvalues(eigenvalues, eigenvectors); glm::sortEigenvalues(eigenvalues, eigenvectors);
if (!vectorEpsilonEqual(eigenvalues, vec(_1aga::expectedEigenvalues<D>()), epsilon)) if (!vectorEpsilonEqual(eigenvalues, vec(agarose::expectedEigenvalues<D>()), epsilon))
return failReport(__LINE__); return failReport(__LINE__);
for (int i = 0; i < D; ++i) for (int i = 0; i < D; ++i)
{ {
vec act = glm::normalize(eigenvectors[i]); vec act = glm::normalize(eigenvectors[i]);
vec exp = glm::normalize(_1aga::expectedEigenvectors<D>()[i]); vec exp = glm::normalize(agarose::expectedEigenvectors<D>()[i]);
if (!sameSign(act[0], exp[0])) exp = -exp; if (!sameSign(act[0], exp[0])) exp = -exp;
if (!vectorEpsilonEqual(act, exp, epsilon)) if (!vectorEpsilonEqual(act, exp, epsilon))
return failReport(__LINE__); return failReport(__LINE__);