mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
templateLapack_test.cpp
Go to the documentation of this file.
1/** \file templateLapack_test.cpp
2 * \brief Tests the typed LAPACK wrappers.
3 * \ingroup templateLapack_unit_tests
4 */
5
6#include "../../catch2/catch.hpp"
7
9
10#include <array>
11#include <cmath>
12#include <limits>
13
14/// Verify typed lamch wrappers for supported real precisions.
15/**
16 * \ingroup templateLapack_unit_tests
17 */
18TEST_CASE( "getting lamch values", "[templateLapack]" )
19{
20 GIVEN( "a precision" )
21 {
22
23 WHEN( "precision is float" )
24 {
25 // This is just a compilation test.
26 float ch = mx::math::lamch<float>( 'E' );
27 REQUIRE( ch > 0 );
28 }
29 WHEN( "precision is double" )
30 {
31 // This is just a compilation test.
32 double ch = mx::math::lamch<double>( 'E' );
33 REQUIRE( ch > 0 );
34 }
35 }
36}
37
38/// solving a rank-one secular equation with laed9
39/**
40 * The mx::math::laed9<float>() and mx::math::laed9<double>() wrappers are applied to a two-dimensional
41 * diagonal-plus-rank-one eigenproblem with an analytic spectrum.
42 *
43 * \ingroup templateLapack_unit_tests
44 */
45TEST_CASE( "solving a rank-one secular equation with laed9", "[templateLapack]" )
46{
47 SECTION( "float" )
48 {
49 std::array<float, 2> eigenvalues{};
50 std::array<float, 4> workspace{};
51 std::array<float, 4> eigenvectors{};
52 std::array<float, 2> poles{ 1.0F, 3.0F };
53 std::array<float, 2> update{ 0.6F, 0.8F };
54
55 const MXLAPACK_INT info = mx::math::laed9<float>( eigenvalues.data(),
56 workspace.data(),
57 eigenvectors.data(),
58 2,
59 1,
60 2,
61 2,
62 2,
63 2.0F,
64 poles.data(),
65 update.data(),
66 2 );
67
68 const float tolerance = 64.0F * std::numeric_limits<float>::epsilon();
69 REQUIRE( info == 0 );
70 REQUIRE( std::abs( eigenvalues[0] - 1.4F ) <= tolerance );
71 REQUIRE( std::abs( eigenvalues[1] - 4.6F ) <= tolerance );
72 for( std::size_t column = 0; column < 2; ++column )
73 {
74 const float first = eigenvectors[2 * column];
75 const float second = eigenvectors[2 * column + 1];
76 const float firstResidual = 1.72F * first + 0.96F * second - eigenvalues[column] * first;
77 const float secondResidual = 0.96F * first + 4.28F * second - eigenvalues[column] * second;
78 CAPTURE( column, firstResidual, secondResidual );
79 REQUIRE( std::hypot( firstResidual, secondResidual ) <= tolerance );
80 REQUIRE( std::abs( std::hypot( first, second ) - 1.0F ) <= tolerance );
81 }
82 REQUIRE( std::abs( eigenvectors[0] * eigenvectors[2] + eigenvectors[1] * eigenvectors[3] ) <= tolerance );
83 }
84
85 SECTION( "double" )
86 {
87 std::array<double, 2> eigenvalues{};
88 std::array<double, 4> workspace{};
89 std::array<double, 4> eigenvectors{};
90 std::array<double, 2> poles{ 1.0, 3.0 };
91 std::array<double, 2> update{ 0.6, 0.8 };
92
93 const MXLAPACK_INT info = mx::math::laed9<double>( eigenvalues.data(),
94 workspace.data(),
95 eigenvectors.data(),
96 2,
97 1,
98 2,
99 2,
100 2,
101 2.0,
102 poles.data(),
103 update.data(),
104 2 );
105
106 const double tolerance = 64.0 * std::numeric_limits<double>::epsilon();
107 REQUIRE( info == 0 );
108 REQUIRE( std::abs( eigenvalues[0] - 1.4 ) <= tolerance );
109 REQUIRE( std::abs( eigenvalues[1] - 4.6 ) <= tolerance );
110 for( std::size_t column = 0; column < 2; ++column )
111 {
112 const double first = eigenvectors[2 * column];
113 const double second = eigenvectors[2 * column + 1];
114 const double firstResidual = 1.72 * first + 0.96 * second - eigenvalues[column] * first;
115 const double secondResidual = 0.96 * first + 4.28 * second - eigenvalues[column] * second;
116 CAPTURE( column, firstResidual, secondResidual );
117 REQUIRE( std::hypot( firstResidual, secondResidual ) <= tolerance );
118 REQUIRE( std::abs( std::hypot( first, second ) - 1.0 ) <= tolerance );
119 }
120 REQUIRE( std::abs( eigenvectors[0] * eigenvectors[2] + eigenvectors[1] * eigenvectors[3] ) <= tolerance );
121 }
122}
TEST_CASE("getting lamch values", "[templateLapack]")
Verify typed lamch wrappers for supported real precisions.
dataT lamch(char CMACH)
Determine machine parameters.
MXLAPACK_INT laed9(dataT *D, dataT *Q, dataT *S, MXLAPACK_INT K, MXLAPACK_INT KSTART, MXLAPACK_INT KSTOP, MXLAPACK_INT N, MXLAPACK_INT LDQ, dataT RHO, dataT *DLAMDA, dataT *W, MXLAPACK_INT LDS)
Solve selected roots of a diagonal-plus-rank-one secular equation and form its eigenvectors.
Declares and defines templatized wrappers for the Lapack library.