Line data Source code
1 : #include <gmock/gmock.h>
2 : #include <gtest/gtest.h>
3 : #include <cassert>
4 : #include <cfloat>
5 :
6 : extern "C"
7 : {
8 : #include "dist.h"
9 : #include "qrfactorization.h"
10 : }
11 :
12 : #define DOUBLE_NEAR(x) DoubleNear((x), 4.0 * DBL_EPSILON)
13 : #define DOUBLE_NEAR_MULTIPLIER(x, multiplier) \
14 : DoubleNear((x), (multiplier)*DBL_EPSILON)
15 : #define map(i, j) ((j)-1) * lda + ((i)-1)
16 : #define a(i, j) a[ map(i, j) ]
17 : #define q(i, j) q[ map(i, j) ]
18 : #define r(i, j) r[ map(i, j) ]
19 : #define map1(i) (i) - 1
20 : #define x(i) x[ map1(i) ]
21 : #define y(i) y[ map1(i) ]
22 : #define ipiv(i) ipiv[ map1(i) ]
23 : #define wrk(i) wrk[ map1(i) ]
24 : #define tau(i) tau[ map1(i) ]
25 :
26 : using namespace std;
27 : using namespace testing;
28 :
29 : class TestThatHouseholderG : public Test
30 : {
31 : public:
32 : int n = 10, incx = 1;
33 : double alpha = 2.0;
34 : double tau = 2.0;
35 : double *xvector = NULL;
36 : double epmach = DBL_EPSILON;
37 : double safmin = DBL_MIN;
38 : const double cutlo = 4.44089e-16;
39 : const double cuthi = 1.30438e19;
40 :
41 10 : void SetUp() override
42 : {
43 10 : xvector = (double *)calloc((size_t)n, (size_t)sizeof(double));
44 : // if (xvector == NULL)
45 : //{
46 : // printf("Failed to allocate xvector memory!\n");
47 : // assert(xvector);
48 : //}
49 10 : }
50 :
51 10 : void TearDown() override { free(xvector); }
52 : };
53 :
54 2 : TEST_F(TestThatHouseholderG, CanAccessEPMACHandSAFMIN)
55 : {
56 1 : EXPECT_THAT(0.2220446049250313E-15, DOUBLE_NEAR(epmach));
57 1 : EXPECT_THAT(0.2225073858507201E-307, DOUBLE_NEAR(safmin));
58 1 : }
59 :
60 2 : TEST_F(TestThatHouseholderG, CanAccessTheHouseholderReflectorMethod)
61 : {
62 1 : ASSERT_THAT(housg(n, &alpha, xvector, incx, &tau, safmin), Eq(0));
63 : }
64 :
65 2 : TEST_F(TestThatHouseholderG, IsDefinedForINCXEqualsZeroButFlagsNegativeTwo)
66 : {
67 1 : int myIncx = 0;
68 1 : EXPECT_THAT(housg(n, &alpha, xvector, myIncx, &tau, safmin), Eq(-2));
69 1 : EXPECT_THAT(tau, DoubleEq(0.0));
70 1 : }
71 :
72 2 : TEST_F(TestThatHouseholderG, IsDefinedForNegativeDimensionsButFlagsNegativeOne)
73 : {
74 1 : int dim = -10;
75 1 : EXPECT_THAT(housg(dim, &alpha, xvector, incx, &tau, safmin), Eq(-1));
76 1 : EXPECT_THAT(tau, DoubleEq(0.0));
77 1 : }
78 :
79 2 : TEST_F(TestThatHouseholderG, IsIdentityForOneDimensionalApplications)
80 : {
81 1 : int dim = 1;
82 1 : EXPECT_THAT(housg(dim, &alpha, xvector, incx, &tau, safmin), Eq(0));
83 1 : EXPECT_THAT(tau, DoubleEq(0.0));
84 1 : }
85 :
86 2 : TEST_F(TestThatHouseholderG, IsIdentityForXEqualsZero)
87 : {
88 1 : EXPECT_THAT(housg(n, &alpha, xvector, incx, &tau, safmin), Eq(0));
89 1 : EXPECT_THAT(tau, DoubleEq(0.0));
90 1 : }
91 :
92 2 : TEST_F(TestThatHouseholderG, ProductOfHTransposeHIsIdentityAndVerifyNorm)
93 : {
94 1 : xvector[ 0 ] = 1.0;
95 1 : xvector[ 1 ] = 1.0;
96 1 : xvector[ 2 ] = 1.0;
97 1 : xvector[ 3 ] = 1.0;
98 1 : xvector[ 4 ] = 1.0;
99 1 : xvector[ 5 ] = 1.0;
100 1 : xvector[ 6 ] = 1.0;
101 1 : xvector[ 7 ] = 1.0;
102 1 : xvector[ 8 ] = 1.0;
103 1 : EXPECT_THAT(ddist2(n - 1, xvector, incx, xvector, incx, 1), DOUBLE_NEAR(3.0));
104 :
105 1 : EXPECT_THAT(housg(n, &alpha, xvector, incx, &tau, safmin), Eq(0));
106 1 : double vnorm = ddist2(n - 1, xvector, incx, xvector, incx, 1);
107 1 : EXPECT_THAT(-2.0 * tau + tau * tau * (1.0 + vnorm * vnorm), DOUBLE_NEAR(0.0));
108 1 : }
109 :
110 2 : TEST_F(TestThatHouseholderG,
111 : ProductOfHTransposeHIsIdentityAndVerifyNormNoUnderflow)
112 : {
113 1 : xvector[ 0 ] = cutlo / 9;
114 1 : xvector[ 1 ] = cutlo / 8;
115 1 : xvector[ 2 ] = cutlo / 7;
116 1 : xvector[ 3 ] = cutlo / 6;
117 1 : xvector[ 4 ] = cutlo / 5;
118 1 : xvector[ 5 ] = cutlo / 4;
119 1 : xvector[ 6 ] = cutlo / 3;
120 1 : xvector[ 7 ] = cutlo / 2;
121 1 : xvector[ 8 ] = cutlo;
122 1 : EXPECT_THAT(ddist2(n - 1, xvector, incx, xvector, incx, 1),
123 : DOUBLE_NEAR(5.510583948830441e-16));
124 :
125 1 : EXPECT_THAT(housg(n, &alpha, xvector, incx, &tau, safmin), Eq(0));
126 1 : double vnorm = ddist2(n - 1, xvector, incx, xvector, incx, 1);
127 1 : EXPECT_THAT(-2.0 * tau + tau * tau * (1.0 + vnorm * vnorm), DOUBLE_NEAR(0.0));
128 1 : }
129 :
130 2 : TEST_F(TestThatHouseholderG,
131 : ProductOfHTransposeHIsIdentityAndVerifyNormNoOverflow)
132 : {
133 1 : xvector[ 0 ] = cuthi * 2;
134 1 : xvector[ 1 ] = cuthi * 3;
135 1 : xvector[ 2 ] = cuthi * 4;
136 1 : xvector[ 3 ] = cuthi * 5;
137 1 : xvector[ 4 ] = cuthi * 6;
138 1 : xvector[ 5 ] = cuthi * 7;
139 1 : xvector[ 6 ] = cuthi * 8;
140 1 : xvector[ 7 ] = cuthi * 9;
141 1 : xvector[ 8 ] = cuthi * 10;
142 1 : EXPECT_THAT(ddist2(n - 1, xvector, incx, xvector, incx, 1),
143 : DOUBLE_NEAR(2.556052344553217e+20 + 32768));
144 :
145 1 : EXPECT_THAT(housg(n, &alpha, xvector, incx, &tau, safmin), Eq(0));
146 1 : double vnorm = ddist2(n - 1, xvector, incx, xvector, incx, 1);
147 1 : EXPECT_THAT(-2.0 * tau + tau * tau * (1.0 + vnorm * vnorm), DOUBLE_NEAR(0.0));
148 1 : }
149 :
150 2 : TEST_F(TestThatHouseholderG,
151 : ProductOfHTransposeHIsIdentityAndVerifyNormNoUnderflowNoOverflow)
152 : {
153 1 : xvector[ 0 ] = 1.0;
154 1 : xvector[ 1 ] = 1.0;
155 1 : xvector[ 2 ] = cutlo;
156 1 : xvector[ 3 ] = 1.0;
157 1 : xvector[ 4 ] = 1.0;
158 1 : xvector[ 5 ] = cuthi;
159 1 : xvector[ 6 ] = 1.0;
160 1 : xvector[ 7 ] = cutlo;
161 1 : xvector[ 8 ] = 1.0;
162 1 : EXPECT_THAT(ddist2(n - 1, xvector, incx, xvector, incx, 1),
163 : DOUBLE_NEAR(1.304380000000000e+19));
164 :
165 1 : EXPECT_THAT(housg(n, &alpha, xvector, incx, &tau, safmin), Eq(0));
166 1 : double vnorm = ddist2(n - 1, xvector, incx, xvector, incx, 1);
167 1 : EXPECT_THAT(-2.0 * tau + tau * tau * (1.0 + vnorm * vnorm), DOUBLE_NEAR(0.0));
168 1 : }
169 :
170 : class TestThatHouseholderL : public Test
171 : {
172 : public:
173 : int m = 4, lda = 4, n = 3, ier = 0, incx = 1;
174 : double tau = 2.0;
175 : double *a = NULL;
176 : double *r = NULL;
177 : double *xvector = NULL;
178 : double epmach = DBL_EPSILON;
179 : double safmin = DBL_MIN;
180 :
181 10 : void SetUp() override
182 : {
183 10 : xvector = (double *)calloc((size_t)m, (size_t)sizeof(double));
184 : // if (xvector == NULL)
185 : //{
186 : // printf("Failed to allocate xvector memory!\n");
187 : // assert(xvector);
188 : //}
189 :
190 10 : a = (double *)calloc((size_t)(lda * n), (size_t)sizeof(double));
191 : // if (a == NULL)
192 : //{
193 : // printf("Failed to allocate matrix A memory!\n");
194 : // assert(a);
195 : //}
196 :
197 10 : a(1, 1) = 1.0, a(1, 2) = 2.0, a(1, 3) = 3.0;
198 10 : a(2, 1) = 1.0, a(2, 2) = 5.0, a(2, 3) = 6.0;
199 10 : a(3, 1) = 1.0, a(3, 2) = 8.0, a(3, 3) = 9.0;
200 10 : a(4, 1) = 1.0, a(4, 2) = 11.0, a(4, 3) = 12.0;
201 :
202 10 : r = (double *)calloc((size_t)(lda * n), (size_t)sizeof(double));
203 : // if (r == NULL)
204 : //{
205 : // printf("Failed to allocate space for result r!\n");
206 : // assert(r);
207 : //}
208 10 : }
209 :
210 10 : void TearDown() override
211 : {
212 10 : free(r);
213 10 : free(a);
214 10 : free(xvector);
215 10 : }
216 : };
217 :
218 2 : TEST_F(TestThatHouseholderL, CanAccessTheHouseholderLeftMultiplyMethod)
219 : {
220 1 : ASSERT_THAT(housl(m, n, xvector, incx, tau, a, lda, &ier), Eq(0));
221 : }
222 :
223 2 : TEST_F(TestThatHouseholderL, IsNotDefinedForNegativeRowDimensionM)
224 : {
225 1 : m = -1;
226 1 : EXPECT_THAT(housl(m, n, xvector, incx, tau, a, lda, &ier), Eq(1));
227 1 : EXPECT_THAT(ier, Eq(1));
228 1 : }
229 :
230 2 : TEST_F(TestThatHouseholderL, IsNotDefinedForNegativeColumnDimensionN)
231 : {
232 1 : n = -1;
233 1 : EXPECT_THAT(housl(m, n, xvector, incx, tau, a, lda, &ier), Eq(1));
234 1 : EXPECT_THAT(ier, Eq(1));
235 1 : }
236 :
237 2 : TEST_F(TestThatHouseholderL, IsNotDefinedForINCXEqualsZero)
238 : {
239 1 : incx = 0;
240 1 : EXPECT_THAT(housl(m, n, xvector, incx, tau, a, lda, &ier), Eq(1));
241 1 : EXPECT_THAT(ier, Eq(1));
242 1 : }
243 :
244 2 : TEST_F(TestThatHouseholderL,
245 : IsNotDefinedForLeadingDimensionLDALessThanNumberOfRowsM)
246 : {
247 1 : lda = 1;
248 1 : EXPECT_THAT(housl(m, n, xvector, incx, tau, a, lda, &ier), Eq(1));
249 1 : EXPECT_THAT(ier, Eq(1));
250 1 : }
251 :
252 2 : TEST_F(TestThatHouseholderL, IsDefinedForRowDimensionMEqualsZero)
253 : {
254 1 : m = 0;
255 1 : EXPECT_THAT(housl(m, n, xvector, incx, tau, a, lda, &ier), Eq(0));
256 1 : EXPECT_THAT(ier, Eq(0));
257 1 : }
258 :
259 2 : TEST_F(TestThatHouseholderL, IsDefinedForColumnDimensionNEqualsZero)
260 : {
261 1 : n = 0;
262 1 : EXPECT_THAT(housl(m, n, xvector, incx, tau, a, lda, &ier), Eq(0));
263 1 : EXPECT_THAT(ier, Eq(0));
264 1 : }
265 :
266 2 : TEST_F(TestThatHouseholderL, IsDefinedForTAUEqualsZero)
267 : {
268 1 : tau = 0.0;
269 1 : EXPECT_THAT(housl(m, n, xvector, incx, tau, a, lda, &ier), Eq(0));
270 1 : EXPECT_THAT(ier, Eq(0));
271 1 : }
272 :
273 2 : TEST_F(TestThatHouseholderL, ImplementsHouseholderMultiplicationOnLeft)
274 : {
275 1 : xvector[ 0 ] = a(1, 1);
276 1 : xvector[ 1 ] = a(2, 1);
277 1 : xvector[ 2 ] = a(3, 1);
278 1 : xvector[ 3 ] = a(4, 1);
279 :
280 1 : double *alpha = xvector;
281 1 : double *v = xvector + 1;
282 :
283 : // On input of housg, alpha is the first component of xvector
284 1 : EXPECT_THAT(*alpha, DoubleEq(xvector[ 0 ]));
285 : // On input of housg, v is components 2:m of xvector
286 4 : for (int row = 0; row < m - 1; row++)
287 3 : EXPECT_THAT(*(v + row), DoubleEq(xvector[ row + 1 ]));
288 :
289 1 : EXPECT_THAT(housg(m, alpha, v, incx, &tau, safmin), Eq(0));
290 :
291 : // On output of housg, beta is stored in alpha
292 1 : double beta = *alpha;
293 : // On output of housg, beta is stored in the first component of xvector
294 1 : EXPECT_THAT(beta, DoubleEq(xvector[ 0 ]));
295 : // On output of housg, xvector is components 2:m of v
296 4 : for (int row = 0; row < m - 1; row++)
297 3 : EXPECT_THAT(*(v + row), DoubleEq(xvector[ row + 1 ]));
298 :
299 1 : int i = 1;
300 1 : EXPECT_THAT(
301 : housl(m - i + 1, n - i, xvector, incx, tau, a + map(i, i + 1), lda, &ier),
302 : Eq(0));
303 :
304 : // First column remains a(:,1) here which does not hold (beta v)
305 1 : r(1, 1) = 1.0, r(1, 2) = -13.0, r(1, 3) = -15.0;
306 1 : r(2, 1) = 1.0, r(2, 2) = 0.0, r(2, 3) = 0.0;
307 1 : r(3, 1) = 1.0, r(3, 2) = 3.0, r(3, 3) = 3.0;
308 1 : r(4, 1) = 1.0, r(4, 2) = 6.0, r(4, 3) = 6.0;
309 :
310 4 : for (int col = 1; col <= n; col++)
311 15 : for (int row = 1; row <= m; row++)
312 12 : EXPECT_THAT(a(row, col), DOUBLE_NEAR_MULTIPLIER(r(row, col), 100));
313 1 : }
314 :
315 2 : TEST_F(TestThatHouseholderL,
316 : ImplementsHouseholderMultiplicationOnLeftWithoutAdditionalStorage)
317 : {
318 1 : double *alpha = a + map(1, 1);
319 1 : double *v = a + map(2, 1);
320 :
321 : // On input of housg, alpha is the first component of xvector
322 1 : EXPECT_THAT(*alpha, DoubleEq(a(1, 1)));
323 : // On input of housg, v is components 2:m of xvector
324 4 : for (int row = 0; row < m - 1; row++)
325 3 : EXPECT_THAT(*(v + row), DoubleEq(a(row + 2, 1)));
326 :
327 1 : EXPECT_THAT(housg(m, alpha, v, incx, &tau, safmin), Eq(0));
328 :
329 : // On output of housg, beta is stored in alpha
330 1 : double beta = *alpha;
331 : // On output of housg, beta is stored in the first component of xvector
332 1 : EXPECT_THAT(beta, DoubleEq(a(1, 1)));
333 : // On output of housg, xvector is components 2:m of v
334 4 : for (int row = 0; row < m - 1; row++)
335 3 : EXPECT_THAT(*(v + row), DoubleEq(a(row + 2, 1)));
336 :
337 1 : int i = 1;
338 1 : EXPECT_THAT(housl(m - i + 1, n - i, a + map(i, i), incx, tau,
339 : a + map(i, i + 1), lda, &ier),
340 : Eq(0));
341 :
342 : // First column remains a(:,1) holds (beta v)
343 1 : r(1, 1) = beta, r(1, 2) = -13.0, r(1, 3) = -15.0;
344 1 : r(2, 1) = *(v + 0), r(2, 2) = 0.0, r(2, 3) = 0.0;
345 1 : r(3, 1) = *(v + 1), r(3, 2) = 3.0, r(3, 3) = 3.0;
346 1 : r(4, 1) = *(v + 2), r(4, 2) = 6.0, r(4, 3) = 6.0;
347 :
348 4 : for (int col = 1; col <= n; col++)
349 15 : for (int row = 1; row <= m; row++)
350 12 : EXPECT_THAT(a(row, col), DOUBLE_NEAR_MULTIPLIER(r(row, col), 100));
351 1 : }
352 :
353 : class TestThatQRF : public Test
354 : {
355 : public:
356 : int m = 4, lda = 4, n = 3, min_m_n = 0, ier = 0;
357 : double *a = NULL;
358 : int *ipiv = NULL;
359 : double *tau = NULL;
360 : double *wrk = NULL;
361 : double *r = NULL;
362 : double epmach = DBL_EPSILON;
363 : double safmin = DBL_MIN;
364 :
365 7 : void SetUp() override
366 : {
367 7 : a = (double *)calloc((size_t)(lda * n), (size_t)sizeof(double));
368 : // if (a == NULL)
369 : //{
370 : // printf("Failed to allocate matrix A memory!\n");
371 : // assert(a);
372 : //}
373 :
374 7 : a(1, 1) = 1.0, a(1, 2) = 2.0, a(1, 3) = 3.0;
375 7 : a(2, 1) = 1.0, a(2, 2) = 5.0, a(2, 3) = 6.0;
376 7 : a(3, 1) = 1.0, a(3, 2) = 8.0, a(3, 3) = 9.0;
377 7 : a(4, 1) = 1.0, a(4, 2) = 11.0, a(4, 3) = 12.0;
378 :
379 7 : min_m_n = (m < n) ? m : n;
380 :
381 7 : tau = (double *)calloc((size_t)min_m_n, (size_t)sizeof(double));
382 : // if (tau == NULL)
383 : //{
384 : // printf("Failed to allocate tau memory!\n");
385 : // assert(tau);
386 : //}
387 :
388 7 : wrk = (double *)calloc((size_t)n, (size_t)sizeof(double));
389 : // if (wrk == NULL)
390 : //{
391 : // printf("Failed to allocate wrk memory!\n");
392 : // assert(wrk);
393 : //}
394 :
395 7 : ipiv = (int *)calloc((size_t)n, (size_t)sizeof(int));
396 : // if (ipiv == NULL)
397 : //{
398 : // printf("Failed to allocate ipiv memory!\n");
399 : // assert(ipiv);
400 : //}
401 :
402 7 : r = (double *)calloc((size_t)(lda * n), (size_t)sizeof(double));
403 : // if (r == NULL)
404 : //{
405 : // printf("Failed to allocate space for result r!\n");
406 : // assert(r);
407 : //}
408 7 : }
409 :
410 7 : void TearDown() override
411 : {
412 7 : free(r);
413 7 : free(ipiv);
414 7 : free(wrk);
415 7 : free(tau);
416 7 : free(a);
417 7 : }
418 : };
419 :
420 2 : TEST_F(TestThatQRF, CanAccessTheQRFactorizationMethod)
421 : {
422 1 : ASSERT_THAT(qrf(m, n, a, lda, ipiv, tau, wrk, safmin, &ier), Eq(0));
423 : }
424 :
425 2 : TEST_F(TestThatQRF, IsNotDefinedForNegativeRowDimensionM)
426 : {
427 1 : m = -1;
428 1 : EXPECT_THAT(qrf(m, n, a, lda, ipiv, tau, wrk, safmin, &ier), Eq(1));
429 1 : EXPECT_THAT(ier, Eq(1));
430 1 : }
431 :
432 2 : TEST_F(TestThatQRF, IsNotDefinedForNegativeColumnDimensionN)
433 : {
434 1 : n = -1;
435 1 : EXPECT_THAT(qrf(m, n, a, lda, ipiv, tau, wrk, safmin, &ier), Eq(1));
436 1 : EXPECT_THAT(ier, Eq(1));
437 1 : }
438 :
439 2 : TEST_F(TestThatQRF, IsNotDefinedForLeadingDimensionLDALessThanNumberOfRowsM)
440 : {
441 1 : lda = 1;
442 1 : EXPECT_THAT(qrf(m, n, a, lda, ipiv, tau, wrk, safmin, &ier), Eq(1));
443 1 : EXPECT_THAT(ier, Eq(1));
444 1 : }
445 :
446 2 : TEST_F(TestThatQRF, IsDefinedForRowDimensionMEqualsZero)
447 : {
448 1 : m = 0;
449 1 : EXPECT_THAT(qrf(m, n, a, lda, ipiv, tau, wrk, safmin, &ier), Eq(0));
450 1 : EXPECT_THAT(ier, Eq(0));
451 1 : }
452 :
453 2 : TEST_F(TestThatQRF, IsDefinedForColumnDimensionNEqualsZero)
454 : {
455 1 : n = 0;
456 1 : EXPECT_THAT(qrf(m, n, a, lda, ipiv, tau, wrk, safmin, &ier), Eq(0));
457 1 : EXPECT_THAT(ier, Eq(0));
458 1 : }
459 :
460 2 : TEST_F(TestThatQRF, WillQRFactorA)
461 : {
462 1 : EXPECT_THAT(qrf(m, n, a, lda, ipiv, tau, wrk, safmin, &ier), Eq(0));
463 1 : EXPECT_THAT(ier, Eq(0));
464 :
465 : // >> M = [[1 2 3];[1 5 6];[1 8 9];[1 11 12]]
466 : // M =
467 : // 1 2 3
468 : // 1 5 6
469 : // 1 8 9
470 : // 1 11 12
471 : // >> [Q,R,E] = qr(M)
472 : // Q =
473 : // Columns 1 through 3
474 : // -1.825741858350554e-01 -8.164965809277261e-01 5.477210117775342e-01
475 : // -3.651483716701108e-01 -4.082482904638630e-01 -7.312645785255080e-01
476 : // -5.477225575051662e-01 -8.814441016525298e-17 -1.806338782815866e-01
477 : // -7.302967433402215e-01 4.082482904638629e-01 3.641774450295606e-01
478 : // Column 4
479 : // 1.301252240837732e-03
480 : // 4.065121353587260e-01
481 : // -8.169280274399654e-01
482 : // 4.091146398404016e-01
483 : // R =
484 : // -1.643167672515498e+01 -1.825741858350554e+00 -1.460593486680443e+01
485 : // 0 -8.164965809277261e-01 8.164965809277228e-01
486 : // 0 0 2.174446367394293e-15
487 : // 0 0 0
488 : // E =
489 : // 0 1 0
490 : // 0 0 1
491 : // 1 0 0
492 : // >> transpose(Q)*Q
493 : // ans =
494 : // Columns 1 through 3
495 : // 1.000000000000000e+00 1.110223024625157e-16 -7.307522642552300e-17
496 : // 1.110223024625157e-16 1.000000000000000e+00 -1.110223024625157e-16
497 : // -7.307522642552300e-17 -1.110223024625157e-16 1.000000000000000e+00
498 : // 0 8.283304597789254e-17 8.326672684688674e-17
499 : // Column 4
500 : // 0
501 : // 8.283304597789254e-17
502 : // 8.326672684688674e-17
503 : // 9.999999999999999e-01
504 : // >> Q*R-M*E
505 : // ans =
506 : // -4.440892098500626e-16 0 4.440892098500626e-15
507 : // 0 0 8.881784197001252e-16
508 : // 0 0 1.776356839400250e-15
509 : // 0 0 1.776356839400250e-15
510 : // Check R
511 1 : r(1, 1) = -1.643167672515498e+01;
512 1 : r(1, 2) = -1.825741858350554e+00;
513 1 : r(1, 3) = -1.460593486680443e+01;
514 1 : r(2, 1) = 0;
515 1 : r(2, 2) = -8.164965809277261e-01;
516 1 : r(2, 3) = 8.164965809277228e-01;
517 1 : r(3, 1) = 0;
518 1 : r(3, 2) = 0;
519 1 : r(3, 3) = 2.174446367394293e-15;
520 1 : r(4, 1) = 0;
521 1 : r(4, 2) = 0;
522 1 : r(4, 3) = 0;
523 4 : for (int col = 1; col <= n; col++)
524 9 : for (int row = 1; row <= col; row++)
525 6 : EXPECT_THAT(a(row, col), DOUBLE_NEAR_MULTIPLIER(r(row, col), 100));
526 : // Check E
527 1 : EXPECT_THAT(ipiv[ 0 ], Eq(3));
528 1 : EXPECT_THAT(ipiv[ 1 ], Eq(1));
529 1 : EXPECT_THAT(ipiv[ 2 ], Eq(2));
530 1 : }
531 :
532 : class TestThatQRS : public Test
533 : {
534 : public:
535 : int m = 4, lda = 4, n = 2, min_m_n = 0, ier = 0;
536 : double *a = NULL;
537 : int *ipiv = NULL;
538 : double *tau = NULL;
539 : double *wrk = NULL;
540 : double *r = NULL;
541 : double *x = NULL;
542 : double *y = NULL;
543 : double epmach = DBL_EPSILON;
544 : double safmin = DBL_MIN;
545 :
546 8 : void SetUp() override
547 : {
548 8 : a = (double *)calloc((size_t)(lda * n), (size_t)sizeof(double));
549 : // if (a == NULL)
550 : //{
551 : // printf("Failed to allocate matrix A memory!\n");
552 : // assert(a);
553 : //}
554 :
555 8 : a(1, 1) = 1.0, a(1, 2) = 2.0;
556 8 : a(2, 1) = 1.0, a(2, 2) = 5.0;
557 8 : a(3, 1) = 1.0, a(3, 2) = 8.0;
558 8 : a(4, 1) = 1.0, a(4, 2) = 11.0;
559 :
560 8 : min_m_n = (m < n) ? m : n;
561 :
562 8 : tau = (double *)calloc((size_t)min_m_n, (size_t)sizeof(double));
563 : // if (tau == NULL)
564 : //{
565 : // printf("Failed to allocate tau memory!\n");
566 : // assert(tau);
567 : //}
568 :
569 8 : wrk = (double *)calloc((size_t)n, (size_t)sizeof(double));
570 : // if (wrk == NULL)
571 : //{
572 : // printf("Failed to allocate wrk memory!\n");
573 : // assert(wrk);
574 : //}
575 :
576 8 : ipiv = (int *)calloc((size_t)n, (size_t)sizeof(int));
577 : // if (ipiv == NULL)
578 : //{
579 : // printf("Failed to allocate ipiv memory!\n");
580 : // assert(ipiv);
581 : //}
582 :
583 8 : r = (double *)calloc((size_t)(lda * n), (size_t)sizeof(double));
584 : // if (r == NULL)
585 : //{
586 : // printf("Failed to allocate space for result r!\n");
587 : // assert(r);
588 : //}
589 :
590 8 : x = (double *)calloc((size_t)n, (size_t)sizeof(double));
591 : // if (x == NULL)
592 : //{
593 : // printf("Failed to allocate space for result x!\n");
594 : // assert(x);
595 : //}
596 :
597 8 : y = (double *)calloc((size_t)m, (size_t)sizeof(double));
598 : // if (y == NULL)
599 : //{
600 : // printf("Failed to allocate space for result y!\n");
601 : // assert(y);
602 : //}
603 8 : }
604 :
605 8 : void TearDown() override
606 : {
607 8 : free(y);
608 8 : free(x);
609 8 : free(r);
610 8 : free(ipiv);
611 8 : free(wrk);
612 8 : free(tau);
613 8 : free(a);
614 8 : }
615 : };
616 :
617 2 : TEST_F(TestThatQRS, CanAccessTheLeastSquaredSolutionMethod)
618 : {
619 1 : EXPECT_THAT(qrs(m, n, a, lda, tau, y, x, &ier), Eq(0));
620 1 : EXPECT_THAT(ier, Eq(0));
621 1 : }
622 :
623 2 : TEST_F(TestThatQRS, IsNotDefinedForNegativeRowDimensionM)
624 : {
625 1 : m = -1;
626 1 : EXPECT_THAT(qrs(m, n, a, lda, tau, y, x, &ier), Eq(1));
627 1 : EXPECT_THAT(ier, Eq(1));
628 1 : }
629 :
630 2 : TEST_F(TestThatQRS, IsNotDefinedForNegativeColumnDimensionN)
631 : {
632 1 : n = -1;
633 1 : EXPECT_THAT(qrs(m, n, a, lda, tau, y, x, &ier), Eq(1));
634 1 : EXPECT_THAT(ier, Eq(1));
635 1 : }
636 :
637 2 : TEST_F(TestThatQRS, IsNotDefinedForRowDimensionMLessThanNumberColumnDimensionN)
638 : {
639 1 : m = 1;
640 1 : n = 2;
641 1 : EXPECT_THAT(qrs(m, n, a, lda, tau, y, x, &ier), Eq(1));
642 1 : EXPECT_THAT(ier, Eq(1));
643 1 : }
644 :
645 2 : TEST_F(TestThatQRS, IsNotDefinedForLeadingDimensionLDALessThanNumberOfRowsM)
646 : {
647 1 : lda = 1;
648 1 : EXPECT_THAT(qrs(m, n, a, lda, tau, y, x, &ier), Eq(1));
649 1 : EXPECT_THAT(ier, Eq(1));
650 1 : }
651 :
652 2 : TEST_F(TestThatQRS, IsDefinedForRowDimensionMEqualsZero)
653 : {
654 1 : m = 0;
655 1 : n = 0;
656 1 : EXPECT_THAT(qrs(m, n, a, lda, tau, y, x, &ier), Eq(0));
657 1 : EXPECT_THAT(ier, Eq(0));
658 1 : }
659 :
660 2 : TEST_F(TestThatQRS, IsDefinedForColumnDimensionNEqualsZero)
661 : {
662 1 : n = 0;
663 1 : EXPECT_THAT(qrs(m, n, a, lda, tau, y, x, &ier), Eq(0));
664 1 : EXPECT_THAT(ier, Eq(0));
665 1 : }
666 :
667 2 : TEST_F(TestThatQRS, WillQRFactorANDComputeLinearLeastSquarsSolution)
668 : {
669 1 : EXPECT_THAT(qrf(m, n, a, lda, ipiv, tau, wrk, safmin, &ier), Eq(0));
670 1 : EXPECT_THAT(ier, Eq(0));
671 1 : y(1) = 3.0;
672 1 : y(2) = 5.0;
673 1 : y(3) = 2.0;
674 1 : y(4) = 1.0;
675 1 : EXPECT_THAT(qrs(m, n, a, lda, tau, y, x, &ier), Eq(0));
676 1 : EXPECT_THAT(ier, Eq(0));
677 1 : EXPECT_THAT(x(ipiv(1)), DOUBLE_NEAR_MULTIPLIER(4.7, 100.0));
678 1 : EXPECT_THAT(x(ipiv(2)), DOUBLE_NEAR_MULTIPLIER(-0.3, 100.0));
679 1 : }
680 :
681 : class TestThatQR : public Test
682 : {
683 : public:
684 : int m{3}, lda{3}, n{3}, min_m_n{0}, ier{0}, ldq{3};
685 : vector<int> ipiv{0, 0, 0};
686 : vector<double> a{2.0, -1.0, 0.0, -1.0, 2.0, -1.0, 0.0, -1.0, 2.0};
687 : vector<double> q{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
688 : vector<double> tau{0.0, 0.0, 0.0};
689 : vector<double> wrk{0.0, 0.0, 0.0};
690 : vector<double> x{0.0, 0.0, 0.0};
691 : vector<double> y{-1.0, -1.0, -1.0};
692 : double epmach{DBL_EPSILON};
693 : double safmin{DBL_MIN};
694 :
695 : vector<double> a_check{
696 : 2.4494897427831783, -0.57979589711327117, 0.28989794855663559,
697 : -1.6329931618554516, -1.5275252316519461, -0.39985928207919952,
698 : -1.6329931618554518, 1.0910894511799623, 1.0690449676496974};
699 : vector<double> q_check{
700 : -0.40824829046386291, 0.81649658092772592, -0.40824829046386296,
701 : -0.87287156094396945, -0.21821789023599258, 0.43643578047198495,
702 : 0.26726124191242445, 0.53452248382484879, 0.80178372573727308};
703 : vector<int> ipiv_check{2, 1, 3};
704 : vector<double> x_check{-1.5, -2, -1.5};
705 :
706 9 : void SetUp() override { min_m_n = (m < n) ? m : n; }
707 :
708 9 : void TearDown() override {}
709 : };
710 :
711 4 : inline void EXPECT_DARRAY_EQ(const int n, double *expected, double *actual)
712 : {
713 40 : for (int i = 0; i < n; i++)
714 : {
715 36 : EXPECT_THAT(*(actual + i), DOUBLE_NEAR_MULTIPLIER(*(expected + i), 100.0));
716 : }
717 4 : }
718 :
719 1 : inline void EXPECT_IARRAY_EQ(const int n, int *expected, int *actual)
720 : {
721 4 : for (int i = 0; i < n; i++)
722 : {
723 3 : EXPECT_THAT(*(actual + i), Eq(*(expected + i)));
724 : }
725 1 : }
726 :
727 2 : TEST_F(TestThatQR, WillFactorANDComputeSolutionForSquareSystem)
728 : {
729 1 : EXPECT_THAT(
730 : qrf(m, n, &a[ 0 ], lda, &ipiv[ 0 ], &tau[ 0 ], &wrk[ 0 ], safmin, &ier),
731 : Eq(0));
732 1 : EXPECT_THAT(ier, Eq(0));
733 :
734 1 : EXPECT_DARRAY_EQ(m * n, &a[ 0 ], &a_check[ 0 ]);
735 1 : EXPECT_IARRAY_EQ(m, &ipiv[ 0 ], &ipiv_check[ 0 ]);
736 :
737 1 : EXPECT_THAT(qorg(m, n, 1, m, &a[ 0 ], lda, &tau[ 0 ], &q[ 0 ], ldq, &ier),
738 : Eq(0));
739 1 : EXPECT_THAT(ier, Eq(0));
740 :
741 1 : EXPECT_DARRAY_EQ(m * n, &a[ 0 ], &a_check[ 0 ]);
742 1 : EXPECT_DARRAY_EQ(m * n, &q[ 0 ], &q_check[ 0 ]);
743 :
744 1 : EXPECT_THAT(qrs(m, n, &a[ 0 ], lda, &tau[ 0 ], &y[ 0 ], &x[ 0 ], &ier),
745 : Eq(0));
746 1 : EXPECT_THAT(ier, Eq(0));
747 :
748 1 : EXPECT_DARRAY_EQ(m * n, &a[ 0 ], &a_check[ 0 ]);
749 4 : for (int i = 0; i < n; i++)
750 : {
751 3 : EXPECT_THAT(x[ ipiv[ i ] - 1 ],
752 : DOUBLE_NEAR_MULTIPLIER(x_check[ i ], 100.0));
753 : }
754 1 : }
755 :
756 2 : TEST_F(TestThatQR, WillProvideOrthogonalMartixQUnlessMLessThanZero)
757 : {
758 1 : int ier{0};
759 1 : int m{-1};
760 1 : int n{2};
761 1 : int k{1};
762 1 : int ell{m};
763 1 : int lda{1};
764 1 : int ldq{2};
765 : // All matricies not accessed in this test
766 1 : EXPECT_THAT(qorg(m, n, k, ell, &a[ 0 ], lda, &tau[ 0 ], &q[ 0 ], ldq, &ier),
767 : Eq(1));
768 1 : }
769 :
770 2 : TEST_F(TestThatQR, WillProvideOrthogonalMartixQUnlessNLessThanZero)
771 : {
772 1 : int ier{0};
773 1 : int m{2};
774 1 : int n{-1};
775 1 : int k{1};
776 1 : int ell{m};
777 1 : int lda{1};
778 1 : int ldq{2};
779 : // All matricies not accessed in this test
780 1 : EXPECT_THAT(qorg(m, n, k, ell, &a[ 0 ], lda, &tau[ 0 ], &q[ 0 ], ldq, &ier),
781 : Eq(1));
782 1 : }
783 :
784 2 : TEST_F(TestThatQR, WillProvideOrthogonalMartixQUnlessMLessThanN)
785 : {
786 1 : int ier{0};
787 1 : int m{2};
788 1 : int n{3};
789 1 : int k{1};
790 1 : int ell{m};
791 1 : int lda{m};
792 1 : int ldq{m};
793 : // All matricies not accessed in this test
794 1 : EXPECT_THAT(qorg(m, n, k, ell, &a[ 0 ], lda, &tau[ 0 ], &q[ 0 ], ldq, &ier),
795 : Eq(1));
796 1 : }
797 :
798 2 : TEST_F(TestThatQR, WillProvideOrthogonalMartixQUnlessKGreaterThanL)
799 : {
800 1 : int ier{0};
801 1 : int m{3};
802 1 : int n{2};
803 1 : int k{m + 1};
804 1 : int ell{m};
805 1 : int lda{m};
806 1 : int ldq{m};
807 : // All matricies not accessed in this test
808 1 : EXPECT_THAT(qorg(m, n, k, ell, &a[ 0 ], lda, &tau[ 0 ], &q[ 0 ], ldq, &ier),
809 : Eq(1));
810 1 : }
811 :
812 2 : TEST_F(TestThatQR, WillProvideOrthogonalMartixQUnlessLDALessThanM)
813 : {
814 1 : int ier{0};
815 1 : int m{3};
816 1 : int n{2};
817 1 : int k{m};
818 1 : int ell{m};
819 1 : int lda{m - 1};
820 1 : int ldq{m};
821 : // All matricies not accessed in this test
822 1 : EXPECT_THAT(qorg(m, n, k, ell, &a[ 0 ], lda, &tau[ 0 ], &q[ 0 ], ldq, &ier),
823 : Eq(1));
824 1 : }
825 :
826 2 : TEST_F(TestThatQR, WillProvideOrthogonalMartixQUnlessLDQLessThanOne)
827 : {
828 1 : int ier{0};
829 1 : int m{3};
830 1 : int n{2};
831 1 : int k{m};
832 1 : int ell{m};
833 1 : int lda{m};
834 1 : int ldq{0};
835 : // All matricies not accessed in this test
836 1 : EXPECT_THAT(qorg(m, n, k, ell, &a[ 0 ], lda, &tau[ 0 ], &q[ 0 ], ldq, &ier),
837 : Eq(1));
838 1 : }
839 :
840 2 : TEST_F(TestThatQR, WillProvideOrthogonalMartixQWithQuickReturnNEqualsZero)
841 : {
842 1 : int ier{0};
843 1 : int m{3};
844 1 : int n{0};
845 1 : int k{m};
846 1 : int ell{m};
847 1 : int lda{m};
848 1 : int ldq{m};
849 : // All matricies not accessed in this test
850 1 : EXPECT_THAT(qorg(m, n, k, ell, &a[ 0 ], lda, &tau[ 0 ], &q[ 0 ], ldq, &ier),
851 : Eq(0));
852 1 : }
853 :
854 2 : TEST_F(TestThatQR,
855 : WillProvideOrthogonalMartixQWithQuickReturnNEqualsZeroANDMEqualsZero)
856 : {
857 1 : int ier{0};
858 1 : int m{0};
859 1 : int n{0};
860 1 : int k{m};
861 1 : int ell{m};
862 1 : int lda{1};
863 1 : int ldq{1};
864 : // All matricies not accessed in this test
865 1 : EXPECT_THAT(qorg(m, n, k, ell, &a[ 0 ], lda, &tau[ 0 ], &q[ 0 ], ldq, &ier),
866 : Eq(0));
867 1 : }
|