Line data Source code
1 : #include <gmock/gmock.h>
2 : #include <gtest/gtest.h>
3 : #include <cfloat>
4 : #include <vector>
5 :
6 : #include "qrfactorization.hpp"
7 :
8 : using namespace std;
9 : using namespace testing;
10 :
11 : class TestThatCPPQR : public Test
12 : {
13 : public:
14 : int m{3}, n{3};
15 : double epsilon{DBL_EPSILON};
16 :
17 10 : void SetUp() override {}
18 :
19 10 : void TearDown() override {}
20 : };
21 :
22 2 : TEST_F(TestThatCPPQR, CanAccessTheQRFactorizationMethod)
23 : {
24 1 : matrix<double> a(m, n);
25 1 : vectorf<double> x(n);
26 1 : vectorf<double> b(m);
27 1 : a(1, 1) = 2.0, a(1, 2) = -1.0, a(1, 3) = 0.0;
28 1 : a(2, 1) = -1.0, a(2, 2) = 2.0, a(2, 3) = -1.0;
29 1 : a(3, 1) = 0.0, a(3, 2) = -1.0, a(3, 3) = 2.0;
30 1 : b(1) = -1.0;
31 1 : b(2) = -1.0;
32 1 : b(3) = -1.0;
33 1 : ASSERT_THAT(qr(m, n, a, b, x), Eq(0));
34 : }
35 :
36 2 : TEST_F(TestThatCPPQR, WillThrowQRFactorizationErrorFromQRF)
37 : {
38 1 : matrix<double> a(m, n, vector<double>(m * n, 0.0));
39 1 : vectorf<double> x(n);
40 1 : vectorf<double> b(m);
41 : // This throw comes from qrf finding a zero pivot
42 : //
43 : // Once there is a zero pivot found in qrf, the method qr
44 : // throws an error and returns.
45 : //
46 : // qrs will fail for the same reason. A zero pivot is the
47 : // only reason for a fail in qrs. The QRSolver error
48 : // throw is redundant. Code coverate should discover this.
49 2 : ASSERT_THROW(qr(m, n, a, b, x), std::exception);
50 : }
51 :
52 2 : TEST_F(TestThatCPPQR, WillReturnACorrectSolution)
53 : {
54 2 : matrix<double> a(m, n);
55 2 : vectorf<double> x(n);
56 2 : vectorf<double> b(m);
57 1 : a(1, 1) = 2.0, a(1, 2) = -1.0, a(1, 3) = 0.0;
58 1 : a(2, 1) = -1.0, a(2, 2) = 2.0, a(2, 3) = -1.0;
59 1 : a(3, 1) = 0.0, a(3, 2) = -1.0, a(3, 3) = 2.0;
60 1 : b(1) = -1.0;
61 1 : b(2) = -1.0;
62 1 : b(3) = -1.0;
63 1 : qr(m, n, a, b, x);
64 1 : EXPECT_THAT(x(1), DoubleNear(-1.5, 8.88179e-16));
65 1 : EXPECT_THAT(x(2), DoubleNear(-2.0, epsilon));
66 1 : EXPECT_THAT(x(3), DoubleNear(-1.5, 8.88178e-16));
67 1 : }
68 :
69 2 : TEST_F(TestThatCPPQR, QRCanResolveAOneDimensionalSystem)
70 : {
71 1 : matrix<double> a(1, 1);
72 1 : vectorf<double> x(1);
73 1 : vectorf<double> b(1);
74 1 : a(1, 1) = 2.0;
75 1 : b(1) = -1.0;
76 :
77 1 : qr(1, 1, a, b, x);
78 :
79 1 : ASSERT_THAT(x(1), DoubleNear(-0.5, epsilon));
80 : }
81 :
82 2 : TEST_F(TestThatCPPQR, QRFailsOnSingularOneDimensionalSystem)
83 : {
84 1 : matrix<double> a(1, 1);
85 1 : vectorf<double> x(1);
86 1 : vectorf<double> b(1);
87 1 : a(1, 1) = 0.0;
88 1 : b(1) = -1.0;
89 :
90 2 : ASSERT_THROW(qr(1, 1, a, b, x), std::exception);
91 : }
92 :
93 2 : TEST_F(TestThatCPPQR, FactorFailsOnSingularOneDimensionalSystem)
94 : {
95 1 : matrix<double> a(1, 1, vector<double>{0.0});
96 1 : vectorf<double> tau(1);
97 1 : vectorf<int> ipiv(1);
98 :
99 2 : ASSERT_THROW(factor(1, 1, a, tau, ipiv), std::exception);
100 : }
101 :
102 2 : TEST_F(TestThatCPPQR, FactorFailsOnSingularMultiDimensionalSystem)
103 : {
104 1 : matrix<double> a(m, n);
105 1 : vectorf<double> tau(n);
106 1 : vectorf<int> ipiv(n);
107 1 : a(1, 1) = 2.0, a(1, 2) = -1.0, a(1, 3) = 0.0;
108 1 : a(2, 1) = -1.0, a(2, 2) = 2.0, a(2, 3) = -1.0;
109 1 : a(3, 1) = 0.0, a(3, 2) = 0.0, a(3, 3) = 0.0;
110 :
111 2 : ASSERT_THROW(factor(m, n, a, tau, ipiv), std::exception);
112 : }
113 :
114 2 : TEST_F(TestThatCPPQR, SolveFailsOnSingularOneDimensionalSystem)
115 : {
116 1 : matrix<double> a(1, 1, vector<double>{0.0});
117 1 : vectorf<double> tau(1);
118 1 : vectorf<double> b(1);
119 1 : vectorf<double> x(1);
120 :
121 2 : ASSERT_THROW(solve(1, 1, a, tau, b, x), std::exception);
122 : }
123 :
124 2 : TEST_F(TestThatCPPQR, SolveFailsOnSingularMultiDimensionalSystem)
125 : {
126 1 : matrix<double> a(m, n);
127 1 : vectorf<double> tau(n);
128 1 : vectorf<double> b(m);
129 1 : vectorf<double> x(n);
130 1 : a(1, 1) = 1.0, a(1, 2) = 0.0, a(1, 3) = 0.0;
131 1 : a(2, 1) = 0.0, a(2, 2) = 1.0, a(2, 3) = 0.0;
132 1 : a(3, 1) = 0.0, a(3, 2) = 0.0, a(3, 3) = 0.0;
133 :
134 2 : ASSERT_THROW(solve(m, n, a, tau, b, x), std::exception);
135 : }
136 :
137 2 : TEST_F(TestThatCPPQR, PermutesASolutionNVector)
138 : {
139 2 : vectorf<int> ipiv(3);
140 2 : vectorf<double> wrk(3);
141 2 : vectorf<double> x(3);
142 1 : ipiv(1) = 3;
143 1 : ipiv(2) = 1;
144 1 : ipiv(3) = 2;
145 1 : x(1) = 2.0;
146 1 : x(2) = 3.0;
147 1 : x(3) = 1.0;
148 :
149 1 : permute(3, x, ipiv, wrk);
150 1 : EXPECT_THAT(x(1), DoubleNear(1.0, epsilon));
151 1 : EXPECT_THAT(x(2), DoubleNear(2.0, epsilon));
152 1 : EXPECT_THAT(x(3), DoubleNear(3.0, epsilon));
153 1 : }
|