diff --git a/src/Math/Algorithms/CMakeLists.txt b/src/Math/Algorithms/CMakeLists.txt index cb5121b20..0a54d2d3c 100644 --- a/src/Math/Algorithms/CMakeLists.txt +++ b/src/Math/Algorithms/CMakeLists.txt @@ -1,5 +1,6 @@ set(MagnumMathAlgorithms_HEADERS - GaussJordan.h) + GaussJordan.h + GramSchmidt.h) install(FILES ${MagnumMathAlgorithms_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Math/Algorithms) if(BUILD_TESTS) diff --git a/src/Math/Algorithms/GramSchmidt.h b/src/Math/Algorithms/GramSchmidt.h new file mode 100644 index 000000000..cbaa3d04c --- /dev/null +++ b/src/Math/Algorithms/GramSchmidt.h @@ -0,0 +1,51 @@ +#ifndef Magnum_Math_Algorithms_GramSchmidt_h +#define Magnum_Math_Algorithms_GramSchmidt_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Function Magnum::Math::Algorithms::gramSchmidtInPlace(), Magnum::Math::Algorithms::gramSchmidt() + */ + +#include "Math/Matrix.h" + +namespace Magnum { namespace Math { namespace Algorithms { + +/** +@brief Gram-schmidt matrix orthonormalization +@param[in,out] matrix Matrix to perform orthonormalization on +*/ +template void gramSchmidtInPlace(Matrix& matrix) { + for(std::size_t i = 0; i != size; ++i) { + matrix[i] = matrix[i].normalized(); + for(std::size_t j = i+1; j != size; ++j) + matrix[j] -= matrix[j].projected(matrix[i]); + } +} + +/** +@brief Gram-schmidt matrix orthonormalization + +Unlike gramSchmidtInPlace() returns the modified matrix instead of performing +the orthonormalization in-place. +*/ +template Matrix gramSchmidt(Matrix matrix) { + gramSchmidtInPlace(matrix); + return matrix; +} + +}}} + +#endif diff --git a/src/Math/Algorithms/Test/CMakeLists.txt b/src/Math/Algorithms/Test/CMakeLists.txt index 88eb779c5..e7e6975e0 100644 --- a/src/Math/Algorithms/Test/CMakeLists.txt +++ b/src/Math/Algorithms/Test/CMakeLists.txt @@ -1 +1,2 @@ corrade_add_test(MathAlgorithmsGaussJordanTest GaussJordanTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(MathAlgorithmsGramSchmidtTest GramSchmidtTest.cpp LIBRARIES MagnumMathTestLib) diff --git a/src/Math/Algorithms/Test/GramSchmidtTest.cpp b/src/Math/Algorithms/Test/GramSchmidtTest.cpp new file mode 100644 index 000000000..b7671eae9 --- /dev/null +++ b/src/Math/Algorithms/Test/GramSchmidtTest.cpp @@ -0,0 +1,60 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "GramSchmidtTest.h" + +#include "Math/Algorithms/GramSchmidt.h" + +CORRADE_TEST_MAIN(Magnum::Math::Algorithms::Test::GramSchmidtTest) + +namespace Magnum { namespace Math { namespace Algorithms { namespace Test { + +typedef Matrix<3, float> Matrix3; +typedef Vector<3, float> Vector3; + +GramSchmidtTest::GramSchmidtTest() { + addTests(&GramSchmidtTest::test); +} + +void GramSchmidtTest::test() { + Matrix3 m( + 3.0f, 5.0f, 8.0f, + 4.0f, 4.0f, 7.0f, + 7.0f, -1.0f, 8.0f + ); + + Matrix3 normalized = Algorithms::gramSchmidt(m); + + /* Verify the first vector is in direction of first original */ + CORRADE_COMPARE(normalized[0], m[0].normalized()); + + /* Verify the vectors have unit length */ + CORRADE_COMPARE(normalized[0].length(), 1.0f); + CORRADE_COMPARE(normalized[1].length(), 1.0f); + CORRADE_COMPARE(normalized[2].length(), 1.0f); + + /* Verify the vectors are orthogonal */ + CORRADE_COMPARE(Vector3::dot(normalized[0], normalized[1]), 0.0f); + CORRADE_COMPARE(Vector3::dot(normalized[0], normalized[2]), 0.0f); + CORRADE_COMPARE(Vector3::dot(normalized[1], normalized[2]), 0.0f); + + /* Just to be sure */ + Matrix3 expected( 0.303046f, 0.505076f, 0.808122f, + 0.928316f, -0.348119f, -0.130544f, + -0.215388f, -0.789754f, 0.574367f); + CORRADE_COMPARE(normalized, expected); +} + +}}}} diff --git a/src/Math/Algorithms/Test/GramSchmidtTest.h b/src/Math/Algorithms/Test/GramSchmidtTest.h new file mode 100644 index 000000000..c09df77d8 --- /dev/null +++ b/src/Math/Algorithms/Test/GramSchmidtTest.h @@ -0,0 +1,31 @@ +#ifndef Magnum_Math_Algorithms_Test_GramSchmidtTest_h +#define Magnum_Math_Algorithms_Test_GramSchmidtTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Math { namespace Algorithms { namespace Test { + +class GramSchmidtTest: public Corrade::TestSuite::Tester { + public: + GramSchmidtTest(); + + void test(); +}; + +}}}} + +#endif