1 /* linalg/test_qrc.c
2  *
3  * Copyright (C) 2020 Patrick Alken
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or (at
8  * your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 #include <config.h>
21 #include <stdlib.h>
22 #include <gsl/gsl_test.h>
23 #include <gsl/gsl_math.h>
24 #include <gsl/gsl_ieee_utils.h>
25 #include <gsl/gsl_permute_vector.h>
26 #include <gsl/gsl_blas.h>
27 #include <gsl/gsl_linalg.h>
28 #include <gsl/gsl_rng.h>
29 #include <gsl/gsl_permutation.h>
30 
31 static int
test_QRc_decomp_eps(const gsl_matrix_complex * m,const double eps,const char * desc)32 test_QRc_decomp_eps(const gsl_matrix_complex * m, const double eps, const char * desc)
33 {
34   int s = 0;
35   const size_t M = m->size1;
36   const size_t N = m->size2;
37   size_t i, j;
38 
39   gsl_matrix_complex * qr = gsl_matrix_complex_alloc(M, N);
40   gsl_matrix_complex * a  = gsl_matrix_complex_alloc(M, N);
41   gsl_matrix_complex * q  = gsl_matrix_complex_alloc(M, M);
42   gsl_matrix_complex * r  = gsl_matrix_complex_alloc(M, N);
43   gsl_vector_complex * d = gsl_vector_complex_alloc(N);
44 
45   gsl_matrix_complex_memcpy(qr, m);
46 
47   s += gsl_linalg_complex_QR_decomp(qr, d);
48   s += gsl_linalg_complex_QR_unpack(qr, d, q, r);
49 
50   /* compute a = q r */
51   gsl_blas_zgemm (CblasNoTrans, CblasNoTrans, GSL_COMPLEX_ONE, q, r, GSL_COMPLEX_ZERO, a);
52 
53   for (i = 0; i < M; i++) {
54     for (j = 0; j < N; j++) {
55       gsl_complex aij = gsl_matrix_complex_get(a, i, j);
56       gsl_complex mij = gsl_matrix_complex_get(m, i, j);
57       int foo_r = check(GSL_REAL(aij), GSL_REAL(mij), eps);
58       int foo_i = check(GSL_IMAG(aij), GSL_IMAG(mij), eps);
59       if (foo_r || foo_i)
60         {
61           printf("%s (%3lu,%3lu)[%lu,%lu]: %22.18g   %22.18g\n", desc, M, N, i, j, GSL_REAL(aij), GSL_REAL(mij));
62           printf("%s (%3lu,%3lu)[%lu,%lu]: %22.18g   %22.18g\n", desc, M, N, i, j, GSL_IMAG(aij), GSL_IMAG(mij));
63         }
64       s += foo_r + foo_i;
65     }
66   }
67 
68   gsl_vector_complex_free(d);
69   gsl_matrix_complex_free(qr);
70   gsl_matrix_complex_free(a);
71   gsl_matrix_complex_free(q);
72   gsl_matrix_complex_free(r);
73 
74   return s;
75 }
76 
77 static int
test_QRc_decomp(gsl_rng * r)78 test_QRc_decomp(gsl_rng * r)
79 {
80   int s = 0;
81   size_t N, M;
82 
83   /* test random matrices */
84   for (N = 1; N <= 20; ++N)
85     {
86       for (M = 1; M <= 20; ++M)
87         {
88           gsl_matrix_complex * A = gsl_matrix_complex_alloc(N, M);
89 
90           create_random_complex_matrix(A, r);
91           test_QRc_decomp_eps(A, 1.0e6 * GSL_MAX(N, M) * GSL_DBL_EPSILON, "complex_QR_decomp random");
92 
93           gsl_matrix_complex_free(A);
94         }
95     }
96 
97   return s;
98 }
99 
100 static int
test_QRc_solve_eps(const gsl_matrix_complex * A,const gsl_vector_complex * rhs,const gsl_vector_complex * sol,const double eps,const char * desc)101 test_QRc_solve_eps(const gsl_matrix_complex * A, const gsl_vector_complex * rhs, const gsl_vector_complex * sol,
102                    const double eps, const char * desc)
103 {
104   int s = 0;
105   const size_t M = A->size1;
106   const size_t N = A->size2;
107   size_t i;
108 
109   gsl_matrix_complex * QR = gsl_matrix_complex_alloc(M, N);
110   gsl_vector_complex * tau = gsl_vector_complex_alloc(N);
111   gsl_vector_complex * x  = gsl_vector_complex_alloc(N);
112 
113   gsl_matrix_complex_memcpy(QR, A);
114 
115   s += gsl_linalg_complex_QR_decomp(QR, tau);
116   s += gsl_linalg_complex_QR_solve(QR, tau, rhs, x);
117 
118   for (i = 0; i < M; i++)
119     {
120       gsl_complex xi = gsl_vector_complex_get(x, i);
121       gsl_complex yi = gsl_vector_complex_get(sol, i);
122 
123       gsl_test_rel(GSL_REAL(xi), GSL_REAL(yi), eps, "%s real (%3lu)[%lu]: %22.18g   %22.18g\n",
124                    desc, N, i, xi, yi);
125       gsl_test_rel(GSL_IMAG(xi), GSL_IMAG(yi), eps, "%s imag (%3lu)[%lu]: %22.18g   %22.18g\n",
126                    desc, N, i, xi, yi);
127     }
128 
129   gsl_matrix_complex_free(QR);
130   gsl_vector_complex_free(tau);
131   gsl_vector_complex_free(x);
132 
133   return s;
134 }
135 
136 static int
test_QRc_solve(gsl_rng * r)137 test_QRc_solve(gsl_rng * r)
138 {
139   int s = 0;
140   size_t N;
141 
142   for (N = 1; N <= 50; ++N)
143     {
144       gsl_matrix_complex * A = gsl_matrix_complex_alloc(N, N);
145       gsl_vector_complex * sol = gsl_vector_complex_alloc(N);
146       gsl_vector_complex * rhs = gsl_vector_complex_alloc(N);
147 
148       create_random_complex_matrix(A, r);
149       create_random_complex_vector(sol, r);
150       gsl_blas_zgemv(CblasNoTrans, GSL_COMPLEX_ONE, A, sol, GSL_COMPLEX_ZERO, rhs);
151 
152       s += test_QRc_solve_eps(A, rhs, sol, 1.0e5 * N * GSL_DBL_EPSILON, "complex QR_solve_r random");
153 
154       gsl_matrix_complex_free(A);
155       gsl_vector_complex_free(sol);
156       gsl_vector_complex_free(rhs);
157     }
158 
159   return s;
160 }
161 
162 static int
test_QRc_lssolve_eps(const gsl_matrix_complex * A,const gsl_vector_complex * rhs,const gsl_vector_complex * sol,const double eps,const char * desc)163 test_QRc_lssolve_eps(const gsl_matrix_complex * A, const gsl_vector_complex * rhs, const gsl_vector_complex * sol,
164                      const double eps, const char * desc)
165 {
166   int s = 0;
167   const size_t M = A->size1;
168   const size_t N = A->size2;
169   size_t i;
170 
171   gsl_matrix_complex * QR = gsl_matrix_complex_alloc(M, N);
172   gsl_vector_complex * tau = gsl_vector_complex_alloc(N);
173   gsl_vector_complex * x  = gsl_vector_complex_alloc(N);
174   gsl_vector_complex * r  = gsl_vector_complex_alloc(M);
175   gsl_vector_complex * r2  = gsl_vector_complex_alloc(M);
176 
177   gsl_matrix_complex_memcpy(QR, A);
178 
179   s += gsl_linalg_complex_QR_decomp(QR, tau);
180   s += gsl_linalg_complex_QR_lssolve(QR, tau, rhs, x, r);
181 
182   for (i = 0; i < N; i++)
183     {
184       gsl_complex xi = gsl_vector_complex_get(x, i);
185       gsl_complex yi = gsl_vector_complex_get(sol, i);
186 
187       gsl_test_rel(GSL_REAL(xi), GSL_REAL(yi), eps, "%s sol real (%3lu)[%lu]: %22.18g   %22.18g\n",
188                    desc, N, i, GSL_REAL(xi), GSL_REAL(yi));
189       gsl_test_rel(GSL_IMAG(xi), GSL_IMAG(yi), eps, "%s sol imag (%3lu)[%lu]: %22.18g   %22.18g\n",
190                    desc, N, i, GSL_IMAG(xi), GSL_IMAG(yi));
191     }
192 
193   /* compute residual and check */
194   gsl_vector_complex_memcpy(r2, rhs);
195   gsl_blas_zgemv(CblasNoTrans, GSL_COMPLEX_NEGONE, A, sol, GSL_COMPLEX_ONE, r2);
196 
197   for (i = 0; i < M; i++)
198     {
199       gsl_complex xi = gsl_vector_complex_get(r, i);
200       gsl_complex yi = gsl_vector_complex_get(r2, i);
201 
202       gsl_test_rel(GSL_REAL(xi), GSL_REAL(yi), eps, "%s res real (%3lu)[%lu]: %22.18g   %22.18g\n",
203                    desc, N, i, GSL_REAL(xi), GSL_REAL(yi));
204       gsl_test_rel(GSL_IMAG(xi), GSL_IMAG(yi), eps, "%s res imag (%3lu)[%lu]: %22.18g   %22.18g\n",
205                    desc, N, i, GSL_IMAG(xi), GSL_IMAG(yi));
206     }
207 
208   gsl_matrix_complex_free(QR);
209   gsl_vector_complex_free(tau);
210   gsl_vector_complex_free(x);
211   gsl_vector_complex_free(r);
212   gsl_vector_complex_free(r2);
213 
214   return s;
215 }
216 
217 static int
test_QRc_lssolve()218 test_QRc_lssolve()
219 {
220   int s = 0;
221   const double tol = 1.0e-10;
222 
223   {
224     const double A_data[] = { 6.70178096995592e-01, 2.51765675689489e-01, 7.18387884271362e-01, 3.61106008613644e-01,
225                               3.36342428526987e-02, 5.25755806084206e-01, 5.87596968507183e-01, 5.27700895952418e-01,
226                               6.85871226549483e-01, 3.71216051930735e-01, 4.40045953339814e-01, 2.08875308141557e-01,
227                               8.62676230425306e-01, 5.79995188556082e-01, 4.86983443637474e-02, 2.82915411954634e-01,
228                               2.92843706013013e-01, 5.61536446182319e-01, 6.85137614758495e-02, 8.90853425372411e-01,
229                               4.38527971314087e-01, 4.78136089625096e-01, 1.57942824868494e-01, 8.38451530279972e-01,
230                               6.36273325487226e-01, 7.74039464290391e-02, 5.45646256301364e-01, 7.80075219450629e-01,
231                               9.27400956530167e-01, 7.01700239834713e-02, 1.09682812589509e-01, 5.64047584357803e-01,
232                               4.46922541620762e-02, 3.03438549353353e-01, 8.09200219159660e-01, 1.44245237525133e-01 };
233     const double rhs_data[] = { 5.82246876454474e-01, 1.42259458199622e-02, 6.25588177982770e-01, 3.79195077388159e-01,
234                                 8.45448918385455e-02, 3.20808711881935e-01, 8.02701461544476e-01, 5.65141425118050e-01,
235                                 8.34227120735637e-01, 4.69005326248388e-01, 9.73712086117648e-01, 3.47197650692321e-01 };
236     const double sol_data[] = { -2.07103028285037e-01, -3.77392587461962e-01,
237                                  7.46590544020302e-01, -1.10976592416587e-01,
238                                  6.07653916072011e-01,  2.05471935567110e-01 };
239     gsl_matrix_complex_const_view A = gsl_matrix_complex_const_view_array(A_data, 6, 3);
240     gsl_vector_complex_const_view rhs = gsl_vector_complex_const_view_array(rhs_data, 6);
241     gsl_vector_complex_const_view sol = gsl_vector_complex_const_view_array(sol_data, 3);
242 
243     test_QRc_lssolve_eps(&A.matrix, &rhs.vector, &sol.vector, tol, "complex QR_lssolve test1");
244   }
245 
246   return s;
247 }
248 
249 static int
test_QRc_decomp_r_eps(const gsl_matrix_complex * m,const double eps,const char * desc)250 test_QRc_decomp_r_eps(const gsl_matrix_complex * m, const double eps, const char * desc)
251 {
252   int s = 0;
253   const size_t M = m->size1;
254   const size_t N = m->size2;
255   size_t i, j;
256 
257   gsl_matrix_complex * QR = gsl_matrix_complex_alloc(M, N);
258   gsl_matrix_complex * T = gsl_matrix_complex_alloc(N, N);
259   gsl_matrix_complex * A  = gsl_matrix_complex_alloc(M, N);
260   gsl_matrix_complex * R  = gsl_matrix_complex_alloc(N, N);
261   gsl_matrix_complex * Q  = gsl_matrix_complex_alloc(M, M);
262   gsl_matrix_complex_view Q1 = gsl_matrix_complex_submatrix(Q, 0, 0, M, N);
263   gsl_vector_complex_const_view tau = gsl_matrix_complex_const_diagonal(T);
264 
265   gsl_matrix_complex_memcpy(QR, m);
266 
267   s += gsl_linalg_complex_QR_decomp_r(QR, T);
268   s += gsl_linalg_complex_QR_unpack_r(QR, T, Q, R);
269 
270   /* compute A = Q R */
271   gsl_matrix_complex_memcpy(A, &Q1.matrix);
272   gsl_blas_ztrmm (CblasRight, CblasUpper, CblasNoTrans, CblasNonUnit, GSL_COMPLEX_ONE, R, A);
273 
274   for (i = 0; i < M; i++)
275     {
276       for (j = 0; j < N; j++)
277         {
278           gsl_complex aij = gsl_matrix_complex_get(A, i, j);
279           gsl_complex mij = gsl_matrix_complex_get(m, i, j);
280 
281           gsl_test_rel(GSL_REAL(aij), GSL_REAL(mij), eps, "%s real (%3lu,%3lu)[%lu,%lu]: %22.18g   %22.18g\n",
282                        desc, M, N, i,j, GSL_REAL(aij), GSL_REAL(mij));
283           gsl_test_rel(GSL_IMAG(aij), GSL_IMAG(mij), eps, "%s imag (%3lu,%3lu)[%lu,%lu]: %22.18g   %22.18g\n",
284                        desc, M, N, i,j, GSL_IMAG(aij), GSL_IMAG(mij));
285         }
286     }
287 
288   if (M > N)
289     {
290       gsl_matrix_complex * R_alt  = gsl_matrix_complex_alloc(M, N);
291       gsl_matrix_complex * Q_alt  = gsl_matrix_complex_alloc(M, M);
292 
293       /* test that Q2 was computed correctly by comparing with Level 2 algorithm */
294       gsl_linalg_complex_QR_unpack(QR, &tau.vector, Q_alt, R_alt);
295 
296       for (i = 0; i < M; i++)
297         {
298           for (j = 0; j < M; j++)
299             {
300               gsl_complex aij = gsl_matrix_complex_get(Q, i, j);
301               gsl_complex bij = gsl_matrix_complex_get(Q_alt, i, j);
302 
303               gsl_test_rel(GSL_REAL(aij), GSL_REAL(bij), eps, "%s real Q (%3lu,%3lu)[%lu,%lu]: %22.18g   %22.18g\n",
304                            desc, M, N, i, j, GSL_REAL(aij), GSL_REAL(bij));
305               gsl_test_rel(GSL_IMAG(aij), GSL_IMAG(bij), eps, "%s imag Q (%3lu,%3lu)[%lu,%lu]: %22.18g   %22.18g\n",
306                            desc, M, N, i, j, GSL_IMAG(aij), GSL_IMAG(bij));
307             }
308         }
309 
310       gsl_matrix_complex_free(R_alt);
311       gsl_matrix_complex_free(Q_alt);
312     }
313 
314   gsl_matrix_complex_free(QR);
315   gsl_matrix_complex_free(T);
316   gsl_matrix_complex_free(A);
317   gsl_matrix_complex_free(Q);
318   gsl_matrix_complex_free(R);
319 
320   return s;
321 }
322 
323 static int
test_QRc_decomp_r(gsl_rng * r)324 test_QRc_decomp_r(gsl_rng * r)
325 {
326   int s = 0;
327   size_t M, N;
328 
329   for (M = 1; M <= 50; ++M)
330     {
331       for (N = 1; N <= M; ++N)
332         {
333           gsl_matrix_complex * A = gsl_matrix_complex_alloc(M, N);
334 
335           create_random_complex_matrix(A, r);
336           s += test_QRc_decomp_r_eps(A, 1.0e6 * M * GSL_DBL_EPSILON, "complex_QR_decomp_r random");
337 
338           gsl_matrix_complex_free(A);
339         }
340     }
341 
342   return s;
343 }
344 
345 static int
test_QRc_solve_r_eps(const gsl_matrix_complex * A,const gsl_vector_complex * rhs,const gsl_vector_complex * sol,const double eps,const char * desc)346 test_QRc_solve_r_eps(const gsl_matrix_complex * A, const gsl_vector_complex * rhs, const gsl_vector_complex * sol,
347                      const double eps, const char * desc)
348 {
349   int s = 0;
350   const size_t M = A->size1;
351   const size_t N = A->size2;
352   size_t i;
353 
354   gsl_matrix_complex * QR = gsl_matrix_complex_alloc(M, N);
355   gsl_matrix_complex * T = gsl_matrix_complex_alloc(N, N);
356   gsl_vector_complex * x  = gsl_vector_complex_alloc(N);
357 
358   gsl_matrix_complex_memcpy(QR, A);
359 
360   s += gsl_linalg_complex_QR_decomp_r(QR, T);
361   s += gsl_linalg_complex_QR_solve_r(QR, T, rhs, x);
362 
363   for (i = 0; i < M; i++)
364     {
365       gsl_complex xi = gsl_vector_complex_get(x, i);
366       gsl_complex yi = gsl_vector_complex_get(sol, i);
367 
368       gsl_test_rel(GSL_REAL(xi), GSL_REAL(yi), eps, "%s real (%3lu)[%lu]: %22.18g   %22.18g\n",
369                    desc, N, i, GSL_REAL(xi), GSL_REAL(yi));
370       gsl_test_rel(GSL_IMAG(xi), GSL_IMAG(yi), eps, "%s imag (%3lu)[%lu]: %22.18g   %22.18g\n",
371                    desc, N, i, GSL_IMAG(xi), GSL_IMAG(yi));
372     }
373 
374   gsl_matrix_complex_free(QR);
375   gsl_matrix_complex_free(T);
376   gsl_vector_complex_free(x);
377 
378   return s;
379 }
380 
381 static int
test_QRc_solve_r(gsl_rng * r)382 test_QRc_solve_r(gsl_rng * r)
383 {
384   int s = 0;
385   size_t N;
386 
387   for (N = 1; N <= 50; ++N)
388     {
389       gsl_matrix_complex * A = gsl_matrix_complex_alloc(N, N);
390       gsl_vector_complex * sol = gsl_vector_complex_alloc(N);
391       gsl_vector_complex * rhs = gsl_vector_complex_alloc(N);
392 
393       create_random_complex_matrix(A, r);
394       create_random_complex_vector(sol, r);
395       gsl_blas_zgemv(CblasNoTrans, GSL_COMPLEX_ONE, A, sol, GSL_COMPLEX_ZERO, rhs);
396 
397       s += test_QRc_solve_r_eps(A, rhs, sol, 1.0e6 * N * GSL_DBL_EPSILON, "complex_QR_solve_r random");
398 
399       gsl_matrix_complex_free(A);
400       gsl_vector_complex_free(sol);
401       gsl_vector_complex_free(rhs);
402     }
403 
404   return s;
405 }
406 
407 static int
test_QRc_lssolve_r_eps(const gsl_matrix_complex * A,const gsl_vector_complex * rhs,const gsl_vector_complex * sol,const double eps,const char * desc)408 test_QRc_lssolve_r_eps(const gsl_matrix_complex * A, const gsl_vector_complex * rhs, const gsl_vector_complex * sol,
409                        const double eps, const char * desc)
410 {
411   int s = 0;
412   const size_t M = A->size1;
413   const size_t N = A->size2;
414   size_t i;
415 
416   gsl_matrix_complex * QR = gsl_matrix_complex_alloc(M, N);
417   gsl_matrix_complex * T = gsl_matrix_complex_alloc(N, N);
418   gsl_vector_complex * x  = gsl_vector_complex_alloc(M);
419   gsl_vector_complex * r  = gsl_vector_complex_alloc(M);
420   gsl_vector_complex * work = gsl_vector_complex_alloc(N);
421   gsl_vector_complex_const_view x1 = gsl_vector_complex_const_subvector(x, N, M - N);
422   double rnorm_expected, rnorm;
423 
424   gsl_matrix_complex_memcpy(QR, A);
425 
426   s += gsl_linalg_complex_QR_decomp_r(QR, T);
427   s += gsl_linalg_complex_QR_lssolve_r(QR, T, rhs, x, work);
428 
429   for (i = 0; i < N; i++)
430     {
431       gsl_complex xi = gsl_vector_complex_get(x, i);
432       gsl_complex yi = gsl_vector_complex_get(sol, i);
433 
434       gsl_test_rel(GSL_REAL(xi), GSL_REAL(yi), eps, "%s sol real (%3lu)[%lu]: %22.18g   %22.18g\n",
435                    desc, N, i, GSL_REAL(xi), GSL_REAL(yi));
436       gsl_test_rel(GSL_IMAG(xi), GSL_IMAG(yi), eps, "%s sol imag (%3lu)[%lu]: %22.18g   %22.18g\n",
437                    desc, N, i, GSL_IMAG(xi), GSL_IMAG(yi));
438     }
439 
440   /* compute residual and check */
441   gsl_vector_complex_memcpy(r, rhs);
442   gsl_blas_zgemv(CblasNoTrans, GSL_COMPLEX_NEGONE, A, sol, GSL_COMPLEX_ONE, r);
443 
444   rnorm_expected = gsl_blas_dznrm2(r);
445   rnorm = gsl_blas_dznrm2(&x1.vector);
446   gsl_test_rel(rnorm, rnorm_expected, eps, "%s rnorm (%3lu): %22.18g   %22.18g\n",
447                desc, N, rnorm, rnorm_expected);
448 
449   gsl_matrix_complex_free(QR);
450   gsl_matrix_complex_free(T);
451   gsl_vector_complex_free(x);
452   gsl_vector_complex_free(r);
453   gsl_vector_complex_free(work);
454 
455   return s;
456 }
457 
458 static int
test_QRc_lssolve_r()459 test_QRc_lssolve_r()
460 {
461   int s = 0;
462   const double tol = 1.0e-10;
463 
464   {
465     const double A_data[] = { 6.70178096995592e-01, 2.51765675689489e-01, 7.18387884271362e-01, 3.61106008613644e-01,
466                               3.36342428526987e-02, 5.25755806084206e-01, 5.87596968507183e-01, 5.27700895952418e-01,
467                               6.85871226549483e-01, 3.71216051930735e-01, 4.40045953339814e-01, 2.08875308141557e-01,
468                               8.62676230425306e-01, 5.79995188556082e-01, 4.86983443637474e-02, 2.82915411954634e-01,
469                               2.92843706013013e-01, 5.61536446182319e-01, 6.85137614758495e-02, 8.90853425372411e-01,
470                               4.38527971314087e-01, 4.78136089625096e-01, 1.57942824868494e-01, 8.38451530279972e-01,
471                               6.36273325487226e-01, 7.74039464290391e-02, 5.45646256301364e-01, 7.80075219450629e-01,
472                               9.27400956530167e-01, 7.01700239834713e-02, 1.09682812589509e-01, 5.64047584357803e-01,
473                               4.46922541620762e-02, 3.03438549353353e-01, 8.09200219159660e-01, 1.44245237525133e-01 };
474     const double rhs_data[] = { 5.82246876454474e-01, 1.42259458199622e-02, 6.25588177982770e-01, 3.79195077388159e-01,
475                                 8.45448918385455e-02, 3.20808711881935e-01, 8.02701461544476e-01, 5.65141425118050e-01,
476                                 8.34227120735637e-01, 4.69005326248388e-01, 9.73712086117648e-01, 3.47197650692321e-01 };
477     const double sol_data[] = { -2.07103028285037e-01, -3.77392587461962e-01,
478                                  7.46590544020302e-01, -1.10976592416587e-01,
479                                  6.07653916072011e-01,  2.05471935567110e-01 };
480     gsl_matrix_complex_const_view A = gsl_matrix_complex_const_view_array(A_data, 6, 3);
481     gsl_vector_complex_const_view rhs = gsl_vector_complex_const_view_array(rhs_data, 6);
482     gsl_vector_complex_const_view sol = gsl_vector_complex_const_view_array(sol_data, 3);
483 
484     test_QRc_lssolve_r_eps(&A.matrix, &rhs.vector, &sol.vector, tol, "complex_QR_lssolve_r test1");
485   }
486 
487   return s;
488 }
489