20#include <boost/test/unit_test.hpp>
21#include <boost/test/data/test_case.hpp>
28#include <ql/math/comparison.hpp>
29#include <ql/math/randomnumbers/mt19937uniformrng.hpp>
31#include <boost/make_shared.hpp>
32#include <boost/timer/timer.hpp>
37using namespace boost::unit_test_framework;
42BOOST_AUTO_TEST_SUITE(BlockMatrixInverseTest)
45void check(
const Matrix res,
const Matrix ex) {
46 QL_REQUIRE(res.rows() == ex.rows(),
"different number of rows (" << res.rows() <<
", expected " << ex.rows());
47 QL_REQUIRE(res.columns() == ex.columns(),
48 "different number of columns (" << res.columns() <<
", expected " << ex.columns());
50 for (Size i = 0; i < res.rows(); ++i) {
51 for (Size j = 0; j < res.columns(); ++j) {
52 if (std::abs(ex[i][j]) < 1E-5)
53 BOOST_CHECK_SMALL(std::abs(res[i][j] - ex[i][j]), 1E-10);
55 BOOST_CHECK_CLOSE(res[i][j], ex[i][j], 1E-10);
62 BOOST_TEST_MESSAGE(
"Test block matrix inversion with single block matrix");
65 std::vector<Real> data = { 1.0, 2.0, 2.0,
71 std::copy(data.begin(), data.end(), m.begin());
73 std::vector<Size> indices = {3};
81 BOOST_TEST_MESSAGE(
"Test block matrix inversion with two blocks");
84 std::vector<Real> data = { 1.0, 2.0, 2.0, 3.0,
87 3.0, 1.0, -1.0, -1.0};
91 std::copy(data.begin(), data.end(), m.begin());
93 std::vector<Size> indices = {2, 4};
101 BOOST_TEST_MESSAGE(
"Test block matrix inversion with three blocks");
104 std::vector<Real> data = { 1.0, 2.0, 2.0, 3.0,
106 -2.0, 0.5, 4.0, -2.0,
107 3.0, 1.0, -1.0, -1.0};
111 std::copy(data.begin(), data.end(), m.begin());
113 std::vector<Size> indices = {1, 2, 4};
121 BOOST_TEST_MESSAGE(
"Test block matrix inversion with four blocks big matrix");
123 Matrix m(300, 300, 0.0);
125 std::vector<Size> indices = {50, 100, 280, 300};
127 MersenneTwisterUniformRng mt(42);
128 for (Size i = 0; i < indices.size(); ++i) {
129 Size a0 = (i == 0 ? 0 : indices[i - 1]);
130 Size a1 = indices[i];
131 for (Size ii = a0; ii < a1; ++ii) {
132 for (Size jj = a0; jj < a1; ++jj) {
133 m[ii][jj] = mt.nextReal();
138 boost::timer::cpu_timer timer;
141 BOOST_TEST_MESSAGE(
"block matrix inversion: " << timer.elapsed().wall * 1e-6 <<
" ms");
145 BOOST_TEST_MESSAGE(
"plain matrix inversion: " << timer.elapsed().wall * 1e-6 <<
" ms");
150 BOOST_TEST_MESSAGE(
"Test block matrix inversion with ten blocks big matrix");
152 Matrix m(500, 500, 0.0);
154 std::vector<Size> indices = {30, 80, 130, 150, 200, 280, 370, 420, 430, 500};
156 MersenneTwisterUniformRng mt(42);
157 for (Size i = 0; i < indices.size(); ++i) {
158 Size a0 = (i == 0 ? 0 : indices[i - 1]);
159 Size a1 = indices[i];
160 for (Size ii = a0; ii < a1; ++ii) {
161 for (Size jj = a0; jj < a1; ++jj) {
162 m[ii][jj] = mt.nextReal();
167 boost::timer::cpu_timer timer;
170 BOOST_TEST_MESSAGE(
"block matrix inversion: " << timer.elapsed().wall * 1e-6 <<
" ms");
174 BOOST_TEST_MESSAGE(
"plain matrix inversion: " << timer.elapsed().wall * 1e-6 <<
" ms");
179 BOOST_TEST_MESSAGE(
"Test sparse matrix with two blocks");
182 std::vector<Real> data = { 1.0, 2.0, 0.0, 3.0,
184 -2.0, 0.0, 4.0, -2.0,
185 3.0, 1.0, -1.0, -1.0};
189 std::copy(data.begin(), data.end(), m.begin());
191 SparseMatrix sm(4, 4);
192 for (Size i = 0; i < 4; ++i) {
193 for (Size j = 0; j < 4; ++j) {
194 Real tmp = data[i * 4 + j];
200 std::vector<Size> indices = {2, 4};
206 for (Size i = 0; i < 4; ++i) {
207 for (Size j = 0; j < 4; ++j) {
208 res2[i][j] = res(i, j);
216BOOST_AUTO_TEST_SUITE_END()
218BOOST_AUTO_TEST_SUITE_END()
inverse of a matrix using a block formula
QuantLib::SparseMatrix inverse(QuantLib::SparseMatrix m)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
Matrix blockMatrixInverse(const Matrix &A, const std::vector< Size > &blockIndices)
BOOST_AUTO_TEST_CASE(testSingleBlock)
Fixture that can be used at top level.