diff --git a/src/Magnum/Math/Algorithms/CMakeLists.txt b/src/Magnum/Math/Algorithms/CMakeLists.txt index 06c46f8bf..cfddc216e 100644 --- a/src/Magnum/Math/Algorithms/CMakeLists.txt +++ b/src/Magnum/Math/Algorithms/CMakeLists.txt @@ -26,6 +26,7 @@ set(MagnumMathAlgorithms_HEADERS GaussJordan.h GramSchmidt.h + Qr.h Svd.h) # Force IDEs to display all header files in project view diff --git a/src/Magnum/Math/Algorithms/Qr.h b/src/Magnum/Math/Algorithms/Qr.h new file mode 100644 index 000000000..7ddfe91b4 --- /dev/null +++ b/src/Magnum/Math/Algorithms/Qr.h @@ -0,0 +1,59 @@ +#ifndef Magnum_Math_Algorithms_Qr_h +#define Magnum_Math_Algorithms_Qr_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Function @ref Magnum::Math::Algorithms::qr() + */ + +#include "Magnum/Math/Matrix.h" + +namespace Magnum { namespace Math { namespace Algorithms { + +/** +@brief QR decomposition + +Calculated using classic Gram-Schmidt process. +*/ +template std::pair, Matrix> qr(const Matrix& matrix) { + Matrix q, r; + + for(std::size_t k = 0; k != size; ++k) { + Vector p = matrix[k]; + for(std::size_t j = 0; j != k; ++j) { + r[k][j] = Math::dot(p, q[j]); + p -= q[j]*r[k][j]; + } + r[k][k] = p.length(); + q[k] = p/r[k][k]; + } + + return {q, r}; +} + +}}} + +#endif diff --git a/src/Magnum/Math/Algorithms/Test/CMakeLists.txt b/src/Magnum/Math/Algorithms/Test/CMakeLists.txt index 5ab52b53b..926d21613 100644 --- a/src/Magnum/Math/Algorithms/Test/CMakeLists.txt +++ b/src/Magnum/Math/Algorithms/Test/CMakeLists.txt @@ -25,4 +25,5 @@ corrade_add_test(MathAlgorithmsGaussJordanTest GaussJordanTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathAlgorithmsGramSchmidtTest GramSchmidtTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(MathAlgorithmsQrTest QrTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathAlgorithmsSvdTest SvdTest.cpp LIBRARIES MagnumMathTestLib) diff --git a/src/Magnum/Math/Algorithms/Test/QrTest.cpp b/src/Magnum/Math/Algorithms/Test/QrTest.cpp new file mode 100644 index 000000000..272bfa466 --- /dev/null +++ b/src/Magnum/Math/Algorithms/Test/QrTest.cpp @@ -0,0 +1,69 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include + +#include "Magnum/Math/Matrix3.h" +#include "Magnum/Math/Algorithms/Qr.h" + +namespace Magnum { namespace Math { namespace Algorithms { namespace Test { + +struct QrTest: Corrade::TestSuite::Tester { + explicit QrTest(); + + void test(); +}; + +typedef Matrix3 Matrix3; + +QrTest::QrTest() { + addTests({&QrTest::test}); +} + +void QrTest::test() { + Matrix3 a{{ 0.0f, 3.0f, 4.0f}, + {-20.0f, 27.0f, 11.0f}, + {-14.0f, -4.0f, -2.0f}}; + + Matrix3 q, r; + std::tie(q, r) = Algorithms::qr(a); + + CORRADE_COMPARE(q*r, a); + + Matrix3 qExpected = Matrix3{{ 0.0f, 15.0f, 20.0f}, + {-20.0f, 12.0f, -9.0f}, + {-15.0f, -16.0f, 12.0f}}/25.0f; + CORRADE_COMPARE(q, qExpected); + + Matrix3 rExpected{{ 5.0f, 0.0f, 0.0f}, + {25.0f, 25.0f, 0.0f}, + {-4.0f, 10.0f, 10.0f}}; + CORRADE_COMPARE(r, rExpected); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Math::Algorithms::Test::QrTest)