1 /* ../netlib/dggsvd.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib;
2  on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */
3 #include "FLA_f2c.h" /* Table of constant values */
4 static integer c__1 = 1;
5 /* > \brief <b> DGGSVD computes the singular value decomposition (SVD) for OTHER matrices</b> */
6 /* =========== DOCUMENTATION =========== */
7 /* Online html documentation available at */
8 /* http://www.netlib.org/lapack/explore-html/ */
9 /* > \htmlonly */
10 /* > Download DGGSVD + dependencies */
11 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dggsvd. f"> */
12 /* > [TGZ]</a> */
13 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dggsvd. f"> */
14 /* > [ZIP]</a> */
15 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggsvd. f"> */
16 /* > [TXT]</a> */
17 /* > \endhtmlonly */
18 /* Definition: */
19 /* =========== */
20 /* SUBROUTINE DGGSVD( JOBU, JOBV, JOBQ, M, N, P, K, L, A, LDA, B, */
21 /* LDB, ALPHA, BETA, U, LDU, V, LDV, Q, LDQ, WORK, */
22 /* IWORK, INFO ) */
23 /* .. Scalar Arguments .. */
24 /* CHARACTER JOBQ, JOBU, JOBV */
25 /* INTEGER INFO, K, L, LDA, LDB, LDQ, LDU, LDV, M, N, P */
26 /* .. */
27 /* .. Array Arguments .. */
28 /* INTEGER IWORK( * ) */
29 /* DOUBLE PRECISION A( LDA, * ), ALPHA( * ), B( LDB, * ), */
30 /* $ BETA( * ), Q( LDQ, * ), U( LDU, * ), */
31 /* $ V( LDV, * ), WORK( * ) */
32 /* .. */
33 /* > \par Purpose: */
34 /* ============= */
35 /* > */
36 /* > \verbatim */
37 /* > */
38 /* > DGGSVD computes the generalized singular value decomposition (GSVD) */
39 /* > of an M-by-N real matrix A and P-by-N real matrix B: */
40 /* > */
41 /* > U**T*A*Q = D1*( 0 R ), V**T*B*Q = D2*( 0 R ) */
42 /* > */
43 /* > where U, V and Q are orthogonal matrices. */
44 /* > Let K+L = the effective numerical rank of the matrix (A**T,B**T)**T, */
45 /* > then R is a K+L-by-K+L nonsingular upper triangular matrix, D1 and */
46 /* > D2 are M-by-(K+L) and P-by-(K+L) "diagonal" matrices and of the */
47 /* > following structures, respectively: */
48 /* > */
49 /* > If M-K-L >= 0, */
50 /* > */
51 /* > K L */
52 /* > D1 = K ( I 0 ) */
53 /* > L ( 0 C ) */
54 /* > M-K-L ( 0 0 ) */
55 /* > */
56 /* > K L */
57 /* > D2 = L ( 0 S ) */
58 /* > P-L ( 0 0 ) */
59 /* > */
60 /* > N-K-L K L */
61 /* > ( 0 R ) = K ( 0 R11 R12 ) */
62 /* > L ( 0 0 R22 ) */
63 /* > */
64 /* > where */
65 /* > */
66 /* > C = diag( ALPHA(K+1), ... , ALPHA(K+L) ), */
67 /* > S = diag( BETA(K+1), ... , BETA(K+L) ), */
68 /* > C**2 + S**2 = I. */
69 /* > */
70 /* > R is stored in A(1:K+L,N-K-L+1:N) on exit. */
71 /* > */
72 /* > If M-K-L < 0, */
73 /* > */
74 /* > K M-K K+L-M */
75 /* > D1 = K ( I 0 0 ) */
76 /* > M-K ( 0 C 0 ) */
77 /* > */
78 /* > K M-K K+L-M */
79 /* > D2 = M-K ( 0 S 0 ) */
80 /* > K+L-M ( 0 0 I ) */
81 /* > P-L ( 0 0 0 ) */
82 /* > */
83 /* > N-K-L K M-K K+L-M */
84 /* > ( 0 R ) = K ( 0 R11 R12 R13 ) */
85 /* > M-K ( 0 0 R22 R23 ) */
86 /* > K+L-M ( 0 0 0 R33 ) */
87 /* > */
88 /* > where */
89 /* > */
90 /* > C = diag( ALPHA(K+1), ... , ALPHA(M) ), */
91 /* > S = diag( BETA(K+1), ... , BETA(M) ), */
92 /* > C**2 + S**2 = I. */
93 /* > */
94 /* > (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N), and R33 is stored */
95 /* > ( 0 R22 R23 ) */
96 /* > in B(M-K+1:L,N+M-K-L+1:N) on exit. */
97 /* > */
98 /* > The routine computes C, S, R, and optionally the orthogonal */
99 /* > transformation matrices U, V and Q. */
100 /* > */
101 /* > In particular, if B is an N-by-N nonsingular matrix, then the GSVD of */
102 /* > A and B implicitly gives the SVD of A*inv(B): */
103 /* > A*inv(B) = U*(D1*inv(D2))*V**T. */
104 /* > If ( A**T,B**T)**T has orthonormal columns, then the GSVD of A and B is */
105 /* > also equal to the CS decomposition of A and B. Furthermore, the GSVD */
106 /* > can be used to derive the solution of the eigenvalue problem: */
107 /* > A**T*A x = lambda* B**T*B x. */
108 /* > In some literature, the GSVD of A and B is presented in the form */
109 /* > U**T*A*X = ( 0 D1 ), V**T*B*X = ( 0 D2 ) */
110 /* > where U and V are orthogonal and X is nonsingular, D1 and D2 are */
111 /* > ``diagonal''. The former GSVD form can be converted to the latter */
112 /* > form by taking the nonsingular matrix X as */
113 /* > */
114 /* > X = Q*( I 0 ) */
115 /* > ( 0 inv(R) ). */
116 /* > \endverbatim */
117 /* Arguments: */
118 /* ========== */
119 /* > \param[in] JOBU */
120 /* > \verbatim */
121 /* > JOBU is CHARACTER*1 */
122 /* > = 'U': Orthogonal matrix U is computed;
123 */
124 /* > = 'N': U is not computed. */
125 /* > \endverbatim */
126 /* > */
127 /* > \param[in] JOBV */
128 /* > \verbatim */
129 /* > JOBV is CHARACTER*1 */
130 /* > = 'V': Orthogonal matrix V is computed;
131 */
132 /* > = 'N': V is not computed. */
133 /* > \endverbatim */
134 /* > */
135 /* > \param[in] JOBQ */
136 /* > \verbatim */
137 /* > JOBQ is CHARACTER*1 */
138 /* > = 'Q': Orthogonal matrix Q is computed;
139 */
140 /* > = 'N': Q is not computed. */
141 /* > \endverbatim */
142 /* > */
143 /* > \param[in] M */
144 /* > \verbatim */
145 /* > M is INTEGER */
146 /* > The number of rows of the matrix A. M >= 0. */
147 /* > \endverbatim */
148 /* > */
149 /* > \param[in] N */
150 /* > \verbatim */
151 /* > N is INTEGER */
152 /* > The number of columns of the matrices A and B. N >= 0. */
153 /* > \endverbatim */
154 /* > */
155 /* > \param[in] P */
156 /* > \verbatim */
157 /* > P is INTEGER */
158 /* > The number of rows of the matrix B. P >= 0. */
159 /* > \endverbatim */
160 /* > */
161 /* > \param[out] K */
162 /* > \verbatim */
163 /* > K is INTEGER */
164 /* > \endverbatim */
165 /* > */
166 /* > \param[out] L */
167 /* > \verbatim */
168 /* > L is INTEGER */
169 /* > */
170 /* > On exit, K and L specify the dimension of the subblocks */
171 /* > described in Purpose. */
172 /* > K + L = effective numerical rank of (A**T,B**T)**T. */
173 /* > \endverbatim */
174 /* > */
175 /* > \param[in,out] A */
176 /* > \verbatim */
177 /* > A is DOUBLE PRECISION array, dimension (LDA,N) */
178 /* > On entry, the M-by-N matrix A. */
179 /* > On exit, A contains the triangular matrix R, or part of R. */
180 /* > See Purpose for details. */
181 /* > \endverbatim */
182 /* > */
183 /* > \param[in] LDA */
184 /* > \verbatim */
185 /* > LDA is INTEGER */
186 /* > The leading dimension of the array A. LDA >= max(1,M). */
187 /* > \endverbatim */
188 /* > */
189 /* > \param[in,out] B */
190 /* > \verbatim */
191 /* > B is DOUBLE PRECISION array, dimension (LDB,N) */
192 /* > On entry, the P-by-N matrix B. */
193 /* > On exit, B contains the triangular matrix R if M-K-L < 0. */
194 /* > See Purpose for details. */
195 /* > \endverbatim */
196 /* > */
197 /* > \param[in] LDB */
198 /* > \verbatim */
199 /* > LDB is INTEGER */
200 /* > The leading dimension of the array B. LDB >= max(1,P). */
201 /* > \endverbatim */
202 /* > */
203 /* > \param[out] ALPHA */
204 /* > \verbatim */
205 /* > ALPHA is DOUBLE PRECISION array, dimension (N) */
206 /* > \endverbatim */
207 /* > */
208 /* > \param[out] BETA */
209 /* > \verbatim */
210 /* > BETA is DOUBLE PRECISION array, dimension (N) */
211 /* > */
212 /* > On exit, ALPHA and BETA contain the generalized singular */
213 /* > value pairs of A and B;
214 */
215 /* > ALPHA(1:K) = 1, */
216 /* > BETA(1:K) = 0, */
217 /* > and if M-K-L >= 0, */
218 /* > ALPHA(K+1:K+L) = C, */
219 /* > BETA(K+1:K+L) = S, */
220 /* > or if M-K-L < 0, */
221 /* > ALPHA(K+1:M)=C, ALPHA(M+1:K+L)=0 */
222 /* > BETA(K+1:M) =S, BETA(M+1:K+L) =1 */
223 /* > and */
224 /* > ALPHA(K+L+1:N) = 0 */
225 /* > BETA(K+L+1:N) = 0 */
226 /* > \endverbatim */
227 /* > */
228 /* > \param[out] U */
229 /* > \verbatim */
230 /* > U is DOUBLE PRECISION array, dimension (LDU,M) */
231 /* > If JOBU = 'U', U contains the M-by-M orthogonal matrix U. */
232 /* > If JOBU = 'N', U is not referenced. */
233 /* > \endverbatim */
234 /* > */
235 /* > \param[in] LDU */
236 /* > \verbatim */
237 /* > LDU is INTEGER */
238 /* > The leading dimension of the array U. LDU >= max(1,M) if */
239 /* > JOBU = 'U';
240 LDU >= 1 otherwise. */
241 /* > \endverbatim */
242 /* > */
243 /* > \param[out] V */
244 /* > \verbatim */
245 /* > V is DOUBLE PRECISION array, dimension (LDV,P) */
246 /* > If JOBV = 'V', V contains the P-by-P orthogonal matrix V. */
247 /* > If JOBV = 'N', V is not referenced. */
248 /* > \endverbatim */
249 /* > */
250 /* > \param[in] LDV */
251 /* > \verbatim */
252 /* > LDV is INTEGER */
253 /* > The leading dimension of the array V. LDV >= max(1,P) if */
254 /* > JOBV = 'V';
255 LDV >= 1 otherwise. */
256 /* > \endverbatim */
257 /* > */
258 /* > \param[out] Q */
259 /* > \verbatim */
260 /* > Q is DOUBLE PRECISION array, dimension (LDQ,N) */
261 /* > If JOBQ = 'Q', Q contains the N-by-N orthogonal matrix Q. */
262 /* > If JOBQ = 'N', Q is not referenced. */
263 /* > \endverbatim */
264 /* > */
265 /* > \param[in] LDQ */
266 /* > \verbatim */
267 /* > LDQ is INTEGER */
268 /* > The leading dimension of the array Q. LDQ >= max(1,N) if */
269 /* > JOBQ = 'Q';
270 LDQ >= 1 otherwise. */
271 /* > \endverbatim */
272 /* > */
273 /* > \param[out] WORK */
274 /* > \verbatim */
275 /* > WORK is DOUBLE PRECISION array, */
276 /* > dimension (max(3*N,M,P)+N) */
277 /* > \endverbatim */
278 /* > */
279 /* > \param[out] IWORK */
280 /* > \verbatim */
281 /* > IWORK is INTEGER array, dimension (N) */
282 /* > On exit, IWORK stores the sorting information. More */
283 /* > precisely, the following loop will sort ALPHA */
284 /* > for I = K+1, min(M,K+L) */
285 /* > swap ALPHA(I) and ALPHA(IWORK(I)) */
286 /* > endfor */
287 /* > such that ALPHA(1) >= ALPHA(2) >= ... >= ALPHA(N). */
288 /* > \endverbatim */
289 /* > */
290 /* > \param[out] INFO */
291 /* > \verbatim */
292 /* > INFO is INTEGER */
293 /* > = 0: successful exit */
294 /* > < 0: if INFO = -i, the i-th argument had an illegal value. */
295 /* > > 0: if INFO = 1, the Jacobi-type procedure failed to */
296 /* > converge. For further details, see subroutine DTGSJA. */
297 /* > \endverbatim */
298 /* > \par Internal Parameters: */
299 /* ========================= */
300 /* > */
301 /* > \verbatim */
302 /* > TOLA DOUBLE PRECISION */
303 /* > TOLB DOUBLE PRECISION */
304 /* > TOLA and TOLB are the thresholds to determine the effective */
305 /* > rank of (A',B')**T. Generally, they are set to */
306 /* > TOLA = MAX(M,N)*norm(A)*MAZHEPS, */
307 /* > TOLB = MAX(P,N)*norm(B)*MAZHEPS. */
308 /* > The size of TOLA and TOLB may affect the size of backward */
309 /* > errors of the decomposition. */
310 /* > \endverbatim */
311 /* Authors: */
312 /* ======== */
313 /* > \author Univ. of Tennessee */
314 /* > \author Univ. of California Berkeley */
315 /* > \author Univ. of Colorado Denver */
316 /* > \author NAG Ltd. */
317 /* > \date November 2011 */
318 /* > \ingroup doubleOTHERsing */
319 /* > \par Contributors: */
320 /* ================== */
321 /* > */
322 /* > Ming Gu and Huan Ren, Computer Science Division, University of */
323 /* > California at Berkeley, USA */
324 /* > */
325 /* ===================================================================== */
326 /* Subroutine */
dggsvd_(char * jobu,char * jobv,char * jobq,integer * m,integer * n,integer * p,integer * k,integer * l,doublereal * a,integer * lda,doublereal * b,integer * ldb,doublereal * alpha,doublereal * beta,doublereal * u,integer * ldu,doublereal * v,integer * ldv,doublereal * q,integer * ldq,doublereal * work,integer * iwork,integer * info)327 int dggsvd_(char *jobu, char *jobv, char *jobq, integer *m, integer *n, integer *p, integer *k, integer *l, doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *alpha, doublereal *beta, doublereal *u, integer *ldu, doublereal *v, integer *ldv, doublereal *q, integer *ldq, doublereal *work, integer *iwork, integer *info)
328 {
329     /* System generated locals */
330     integer a_dim1, a_offset, b_dim1, b_offset, q_dim1, q_offset, u_dim1, u_offset, v_dim1, v_offset, i__1, i__2;
331     /* Local variables */
332     integer i__, j;
333     doublereal ulp;
334     integer ibnd;
335     doublereal tola;
336     integer isub;
337     doublereal tolb, unfl, temp, smax;
338     extern logical lsame_(char *, char *);
339     doublereal anorm, bnorm;
340     extern /* Subroutine */
341     int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *);
342     logical wantq, wantu, wantv;
343     extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *);
344     extern /* Subroutine */
345     int dtgsja_(char *, char *, char *, integer *, integer *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *);
346     integer ncycle;
347     extern /* Subroutine */
348     int xerbla_(char *, integer *), dggsvp_( char *, char *, char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, doublereal *, doublereal *, integer *);
349     /* -- LAPACK driver routine (version 3.4.0) -- */
350     /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */
351     /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */
352     /* November 2011 */
353     /* .. Scalar Arguments .. */
354     /* .. */
355     /* .. Array Arguments .. */
356     /* .. */
357     /* ===================================================================== */
358     /* .. Local Scalars .. */
359     /* .. */
360     /* .. External Functions .. */
361     /* .. */
362     /* .. External Subroutines .. */
363     /* .. */
364     /* .. Intrinsic Functions .. */
365     /* .. */
366     /* .. Executable Statements .. */
367     /* Test the input parameters */
368     /* Parameter adjustments */
369     a_dim1 = *lda;
370     a_offset = 1 + a_dim1;
371     a -= a_offset;
372     b_dim1 = *ldb;
373     b_offset = 1 + b_dim1;
374     b -= b_offset;
375     --alpha;
376     --beta;
377     u_dim1 = *ldu;
378     u_offset = 1 + u_dim1;
379     u -= u_offset;
380     v_dim1 = *ldv;
381     v_offset = 1 + v_dim1;
382     v -= v_offset;
383     q_dim1 = *ldq;
384     q_offset = 1 + q_dim1;
385     q -= q_offset;
386     --work;
387     --iwork;
388     /* Function Body */
389     wantu = lsame_(jobu, "U");
390     wantv = lsame_(jobv, "V");
391     wantq = lsame_(jobq, "Q");
392     *info = 0;
393     if (! (wantu || lsame_(jobu, "N")))
394     {
395         *info = -1;
396     }
397     else if (! (wantv || lsame_(jobv, "N")))
398     {
399         *info = -2;
400     }
401     else if (! (wantq || lsame_(jobq, "N")))
402     {
403         *info = -3;
404     }
405     else if (*m < 0)
406     {
407         *info = -4;
408     }
409     else if (*n < 0)
410     {
411         *info = -5;
412     }
413     else if (*p < 0)
414     {
415         *info = -6;
416     }
417     else if (*lda < max(1,*m))
418     {
419         *info = -10;
420     }
421     else if (*ldb < max(1,*p))
422     {
423         *info = -12;
424     }
425     else if (*ldu < 1 || wantu && *ldu < *m)
426     {
427         *info = -16;
428     }
429     else if (*ldv < 1 || wantv && *ldv < *p)
430     {
431         *info = -18;
432     }
433     else if (*ldq < 1 || wantq && *ldq < *n)
434     {
435         *info = -20;
436     }
437     if (*info != 0)
438     {
439         i__1 = -(*info);
440         xerbla_("DGGSVD", &i__1);
441         return 0;
442     }
443     /* Compute the Frobenius norm of matrices A and B */
444     anorm = dlange_("1", m, n, &a[a_offset], lda, &work[1]);
445     bnorm = dlange_("1", p, n, &b[b_offset], ldb, &work[1]);
446     /* Get machine precision and set up threshold for determining */
447     /* the effective numerical rank of the matrices A and B. */
448     ulp = dlamch_("Precision");
449     unfl = dlamch_("Safe Minimum");
450     tola = max(*m,*n) * max(anorm,unfl) * ulp;
451     tolb = max(*p,*n) * max(bnorm,unfl) * ulp;
452     /* Preprocessing */
453     dggsvp_(jobu, jobv, jobq, m, p, n, &a[a_offset], lda, &b[b_offset], ldb, & tola, &tolb, k, l, &u[u_offset], ldu, &v[v_offset], ldv, &q[ q_offset], ldq, &iwork[1], &work[1], &work[*n + 1], info);
454     /* Compute the GSVD of two upper "triangular" matrices */
455     dtgsja_(jobu, jobv, jobq, m, p, n, k, l, &a[a_offset], lda, &b[b_offset], ldb, &tola, &tolb, &alpha[1], &beta[1], &u[u_offset], ldu, &v[ v_offset], ldv, &q[q_offset], ldq, &work[1], &ncycle, info);
456     /* Sort the singular values and store the pivot indices in IWORK */
457     /* Copy ALPHA to WORK, then sort ALPHA in WORK */
458     dcopy_(n, &alpha[1], &c__1, &work[1], &c__1);
459     /* Computing MIN */
460     i__1 = *l;
461     i__2 = *m - *k; // , expr subst
462     ibnd = min(i__1,i__2);
463     i__1 = ibnd;
464     for (i__ = 1;
465             i__ <= i__1;
466             ++i__)
467     {
468         /* Scan for largest ALPHA(K+I) */
469         isub = i__;
470         smax = work[*k + i__];
471         i__2 = ibnd;
472         for (j = i__ + 1;
473                 j <= i__2;
474                 ++j)
475         {
476             temp = work[*k + j];
477             if (temp > smax)
478             {
479                 isub = j;
480                 smax = temp;
481             }
482             /* L10: */
483         }
484         if (isub != i__)
485         {
486             work[*k + isub] = work[*k + i__];
487             work[*k + i__] = smax;
488             iwork[*k + i__] = *k + isub;
489         }
490         else
491         {
492             iwork[*k + i__] = *k + i__;
493         }
494         /* L20: */
495     }
496     return 0;
497     /* End of DGGSVD */
498 }
499 /* dggsvd_ */
500