Skip to content

Commit a5271aa

Browse files
Tests: check for inaccurate 2x1 CS decomposition
The problem was fixed in pull request Reference-LAPACK#928.
1 parent 6092fde commit a5271aa

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

TESTING/cpp/xUNCSD2BY1_tests.cpp

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020-2021 Christoph Conrads
2+
* Copyright (c) 2020-2021, 2023 Christoph Conrads
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
3232
#include <cstddef>
3333
#include <boost/assert.hpp>
3434
#include <boost/numeric/ublas/matrix.hpp>
35+
#include <boost/numeric/ublas/matrix_proxy.hpp>
3536
#include <boost/numeric/ublas/vector.hpp>
3637
#include <boost/test/unit_test.hpp>
3738

@@ -267,3 +268,69 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(
267268
{
268269
xUNCSD2BY1_regression_20211024_impl(Number{});
269270
}
271+
272+
273+
BOOST_AUTO_TEST_CASE(xUNCSD2BY1_regression_20231026)
274+
{
275+
using Number = float;
276+
using Real = typename tools::real_from<Number>::type;
277+
using Matrix = ublas::matrix<Number, ublas::column_major>;
278+
279+
auto m = std::size_t{2};
280+
auto n = std::size_t{2};
281+
auto p = std::size_t{1};
282+
auto ldq = m + p;
283+
auto Q = Matrix(ldq, n);
284+
Q(0, 0) = -2.0392263e-01; Q(0, 1) = -9.7898704e-01;
285+
Q(1, 0) = 1.1427624e-08; Q(1, 1) = 9.2925374e-09;
286+
Q(2, 0) = 9.7898704e-01; Q(2, 1) = -2.0392257e-01;
287+
288+
BOOST_VERIFY( tools::is_almost_isometric(Q) );
289+
290+
auto nan = tools::not_a_number<Number>::value;
291+
auto real_nan = tools::not_a_number<Real>::value;
292+
auto theta = ublas::vector<Real>(n, real_nan);
293+
auto Q_copy = Matrix(Q);
294+
auto U1 = Matrix(m, m, nan);
295+
auto U2 = Matrix(p, p, nan);
296+
auto V = Matrix(n, n, nan);
297+
auto lwork = 32 * ldq;
298+
auto work = ublas::vector<Number>(lwork, nan);
299+
auto iwork = ublas::vector<Integer>(m + p, -1);
300+
auto ret = lapack::xUNCSD2BY1(
301+
'Y', 'Y', 'Y',
302+
m + p, m, n,
303+
&Q_copy(0, 0), ldq, &Q_copy(m, 0), ldq,
304+
&theta(0),
305+
&U1(0, 0), m, &U2(0, 0), p, &V(0, 0), n,
306+
&work(0), lwork, &iwork(0)
307+
);
308+
309+
BOOST_REQUIRE_EQUAL( ret, 0 );
310+
BOOST_CHECK( tools::is_almost_isometric(U1) );
311+
BOOST_CHECK( tools::is_almost_isometric(U2) );
312+
BOOST_CHECK( tools::is_almost_isometric(V) );
313+
314+
auto sigma_1 = Matrix(m, n);
315+
auto sigma_2 = Matrix(p, n);
316+
317+
std::fill(sigma_1.data().begin(), sigma_1.data().end(), 0.0);
318+
sigma_1(0, 0) = 1.0;
319+
sigma_1(1, 1) = std::cos(theta(0));
320+
sigma_2(0, 0) = 0.0;
321+
sigma_2(0, 1) = std::sin(theta(0));
322+
323+
auto almost_Q = Matrix(m + p, n);
324+
325+
std::fill(almost_Q.data().begin(), almost_Q.data().end(), nan);
326+
ublas::subrange(almost_Q, 0, m, 0, n) = prod(U1, Matrix(prod(sigma_1, V)));
327+
ublas::subrange(almost_Q, m, m + p, 0, n) = prod(U2, Matrix(prod(sigma_2, V)));
328+
329+
BOOST_CHECK( tools::is_almost_isometric(almost_Q) );
330+
331+
auto eps = std::numeric_limits<Real>::epsilon();
332+
333+
BOOST_CHECK_LE(
334+
ublas::norm_frobenius(Q - almost_Q), 2 * eps * ublas::norm_frobenius(Q)
335+
);
336+
}

0 commit comments

Comments
 (0)