OpenRadioss 2025.1.11
OpenRadioss project
Loading...
Searching...
No Matches
cgelss.f
Go to the documentation of this file.
1*> \brief <b> CGELSS solves overdetermined or underdetermined systems for GE matrices</b>
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download CGELSS + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cgelss.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cgelss.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgelss.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18* Definition:
19* ===========
20*
21* SUBROUTINE CGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
22* WORK, LWORK, RWORK, INFO )
23*
24* .. Scalar Arguments ..
25* INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
26* REAL RCOND
27* ..
28* .. Array Arguments ..
29* REAL RWORK( * ), S( * )
30* COMPLEX A( LDA, * ), B( LDB, * ), WORK( * )
31* ..
32*
33*
34*> \par Purpose:
35* =============
36*>
37*> \verbatim
38*>
39*> CGELSS computes the minimum norm solution to a complex linear
40*> least squares problem:
41*>
42*> Minimize 2-norm(| b - A*x |).
43*>
44*> using the singular value decomposition (SVD) of A. A is an M-by-N
45*> matrix which may be rank-deficient.
46*>
47*> Several right hand side vectors b and solution vectors x can be
48*> handled in a single call; they are stored as the columns of the
49*> M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix
50*> X.
51*>
52*> The effective rank of A is determined by treating as zero those
53*> singular values which are less than RCOND times the largest singular
54*> value.
55*> \endverbatim
56*
57* Arguments:
58* ==========
59*
60*> \param[in] M
61*> \verbatim
62*> M is INTEGER
63*> The number of rows of the matrix A. M >= 0.
64*> \endverbatim
65*>
66*> \param[in] N
67*> \verbatim
68*> N is INTEGER
69*> The number of columns of the matrix A. N >= 0.
70*> \endverbatim
71*>
72*> \param[in] NRHS
73*> \verbatim
74*> NRHS is INTEGER
75*> The number of right hand sides, i.e., the number of columns
76*> of the matrices B and X. NRHS >= 0.
77*> \endverbatim
78*>
79*> \param[in,out] A
80*> \verbatim
81*> A is COMPLEX array, dimension (LDA,N)
82*> On entry, the M-by-N matrix A.
83*> On exit, the first min(m,n) rows of A are overwritten with
84*> its right singular vectors, stored rowwise.
85*> \endverbatim
86*>
87*> \param[in] LDA
88*> \verbatim
89*> LDA is INTEGER
90*> The leading dimension of the array A. LDA >= max(1,M).
91*> \endverbatim
92*>
93*> \param[in,out] B
94*> \verbatim
95*> B is COMPLEX array, dimension (LDB,NRHS)
96*> On entry, the M-by-NRHS right hand side matrix B.
97*> On exit, B is overwritten by the N-by-NRHS solution matrix X.
98*> If m >= n and RANK = n, the residual sum-of-squares for
99*> the solution in the i-th column is given by the sum of
100*> squares of the modulus of elements n+1:m in that column.
101*> \endverbatim
102*>
103*> \param[in] LDB
104*> \verbatim
105*> LDB is INTEGER
106*> The leading dimension of the array B. LDB >= max(1,M,N).
107*> \endverbatim
108*>
109*> \param[out] S
110*> \verbatim
111*> S is REAL array, dimension (min(M,N))
112*> The singular values of A in decreasing order.
113*> The condition number of A in the 2-norm = S(1)/S(min(m,n)).
114*> \endverbatim
115*>
116*> \param[in] RCOND
117*> \verbatim
118*> RCOND is REAL
119*> RCOND is used to determine the effective rank of A.
120*> Singular values S(i) <= RCOND*S(1) are treated as zero.
121*> If RCOND < 0, machine precision is used instead.
122*> \endverbatim
123*>
124*> \param[out] RANK
125*> \verbatim
126*> RANK is INTEGER
127*> The effective rank of A, i.e., the number of singular values
128*> which are greater than RCOND*S(1).
129*> \endverbatim
130*>
131*> \param[out] WORK
132*> \verbatim
133*> WORK is COMPLEX array, dimension (MAX(1,LWORK))
134*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
135*> \endverbatim
136*>
137*> \param[in] LWORK
138*> \verbatim
139*> LWORK is INTEGER
140*> The dimension of the array WORK. LWORK >= 1, and also:
141*> LWORK >= 2*min(M,N) + max(M,N,NRHS)
142*> For good performance, LWORK should generally be larger.
143*>
144*> If LWORK = -1, then a workspace query is assumed; the routine
145*> only calculates the optimal size of the WORK array, returns
146*> this value as the first entry of the WORK array, and no error
147*> message related to LWORK is issued by XERBLA.
148*> \endverbatim
149*>
150*> \param[out] RWORK
151*> \verbatim
152*> RWORK is REAL array, dimension (5*min(M,N))
153*> \endverbatim
154*>
155*> \param[out] INFO
156*> \verbatim
157*> INFO is INTEGER
158*> = 0: successful exit
159*> < 0: if INFO = -i, the i-th argument had an illegal value.
160*> > 0: the algorithm for computing the SVD failed to converge;
161*> if INFO = i, i off-diagonal elements of an intermediate
162*> bidiagonal form did not converge to zero.
163*> \endverbatim
164*
165* Authors:
166* ========
167*
168*> \author Univ. of Tennessee
169*> \author Univ. of California Berkeley
170*> \author Univ. of Colorado Denver
171*> \author NAG Ltd.
172*
173*> \ingroup complexGEsolve
174*
175* =====================================================================
176 SUBROUTINE cgelss( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,
177 $ WORK, LWORK, RWORK, INFO )
178*
179* -- LAPACK driver routine --
180* -- LAPACK is a software package provided by Univ. of Tennessee, --
181* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
182*
183* .. Scalar Arguments ..
184 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
185 REAL RCOND
186* ..
187* .. Array Arguments ..
188 REAL RWORK( * ), S( * )
189 COMPLEX A( LDA, * ), B( LDB, * ), WORK( * )
190* ..
191*
192* =====================================================================
193*
194* .. Parameters ..
195 REAL ZERO, ONE
196 parameter( zero = 0.0e+0, one = 1.0e+0 )
197 COMPLEX CZERO, CONE
198 parameter( czero = ( 0.0e+0, 0.0e+0 ),
199 $ cone = ( 1.0e+0, 0.0e+0 ) )
200* ..
201* .. Local Scalars ..
202 LOGICAL LQUERY
203 INTEGER BL, CHUNK, I, IASCL, IBSCL, IE, IL, IRWORK,
204 $ itau, itaup, itauq, iwork, ldwork, maxmn,
205 $ maxwrk, minmn, minwrk, mm, mnthr
206 INTEGER LWORK_CGEQRF, LWORK_CUNMQR, LWORK_CGEBRD,
207 $ lwork_cunmbr, lwork_cungbr, lwork_cunmlq,
208 $ lwork_cgelqf
209 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
210* ..
211* .. Local Arrays ..
212 COMPLEX DUM( 1 )
213* ..
214* .. External Subroutines ..
215 EXTERNAL cbdsqr, ccopy, cgebrd, cgelqf, cgemm, cgemv,
218 $ xerbla
219* ..
220* .. External Functions ..
221 INTEGER ILAENV
222 REAL CLANGE, SLAMCH
223 EXTERNAL ilaenv, clange, slamch
224* ..
225* .. Intrinsic Functions ..
226 INTRINSIC max, min
227* ..
228* .. Executable Statements ..
229*
230* Test the input arguments
231*
232 info = 0
233 minmn = min( m, n )
234 maxmn = max( m, n )
235 lquery = ( lwork.EQ.-1 )
236 IF( m.LT.0 ) THEN
237 info = -1
238 ELSE IF( n.LT.0 ) THEN
239 info = -2
240 ELSE IF( nrhs.LT.0 ) THEN
241 info = -3
242 ELSE IF( lda.LT.max( 1, m ) ) THEN
243 info = -5
244 ELSE IF( ldb.LT.max( 1, maxmn ) ) THEN
245 info = -7
246 END IF
247*
248* Compute workspace
249* (Note: Comments in the code beginning "Workspace:" describe the
250* minimal amount of workspace needed at that point in the code,
251* as well as the preferred amount for good performance.
252* CWorkspace refers to complex workspace, and RWorkspace refers
253* to real workspace. NB refers to the optimal block size for the
254* immediately following subroutine, as returned by ILAENV.)
255*
256 IF( info.EQ.0 ) THEN
257 minwrk = 1
258 maxwrk = 1
259 IF( minmn.GT.0 ) THEN
260 mm = m
261 mnthr = ilaenv( 6, 'CGELSS', ' ', m, n, nrhs, -1 )
262 IF( m.GE.n .AND. m.GE.mnthr ) THEN
263*
264* Path 1a - overdetermined, with many more rows than
265* columns
266*
267* Compute space needed for CGEQRF
268 CALL cgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
269 lwork_cgeqrf = real( dum(1) )
270* Compute space needed for CUNMQR
271 CALL cunmqr( 'L', 'C', m, nrhs, n, a, lda, dum(1), b,
272 $ ldb, dum(1), -1, info )
273 lwork_cunmqr = real( dum(1) )
274 mm = n
275 maxwrk = max( maxwrk, n + n*ilaenv( 1, 'CGEQRF', ' ', m,
276 $ n, -1, -1 ) )
277 maxwrk = max( maxwrk, n + nrhs*ilaenv( 1, 'CUNMQR', 'LC',
278 $ m, nrhs, n, -1 ) )
279 END IF
280 IF( m.GE.n ) THEN
281*
282* Path 1 - overdetermined or exactly determined
283*
284* Compute space needed for CGEBRD
285 CALL cgebrd( mm, n, a, lda, s, s, dum(1), dum(1), dum(1),
286 $ -1, info )
287 lwork_cgebrd = real( dum(1) )
288* Compute space needed for CUNMBR
289 CALL cunmbr( 'Q', 'L', 'C', mm, nrhs, n, a, lda, dum(1),
290 $ b, ldb, dum(1), -1, info )
291 lwork_cunmbr = real( dum(1) )
292* Compute space needed for CUNGBR
293 CALL cungbr( 'P', n, n, n, a, lda, dum(1),
294 $ dum(1), -1, info )
295 lwork_cungbr = real( dum(1) )
296* Compute total workspace needed
297 maxwrk = max( maxwrk, 2*n + lwork_cgebrd )
298 maxwrk = max( maxwrk, 2*n + lwork_cunmbr )
299 maxwrk = max( maxwrk, 2*n + lwork_cungbr )
300 maxwrk = max( maxwrk, n*nrhs )
301 minwrk = 2*n + max( nrhs, m )
302 END IF
303 IF( n.GT.m ) THEN
304 minwrk = 2*m + max( nrhs, n )
305 IF( n.GE.mnthr ) THEN
306*
307* Path 2a - underdetermined, with many more columns
308* than rows
309*
310* Compute space needed for CGELQF
311 CALL cgelqf( m, n, a, lda, dum(1), dum(1),
312 $ -1, info )
313 lwork_cgelqf = real( dum(1) )
314* Compute space needed for CGEBRD
315 CALL cgebrd( m, m, a, lda, s, s, dum(1), dum(1),
316 $ dum(1), -1, info )
317 lwork_cgebrd = real( dum(1) )
318* Compute space needed for CUNMBR
319 CALL cunmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda,
320 $ dum(1), b, ldb, dum(1), -1, info )
321 lwork_cunmbr = real( dum(1) )
322* Compute space needed for CUNGBR
323 CALL cungbr( 'P', m, m, m, a, lda, dum(1),
324 $ dum(1), -1, info )
325 lwork_cungbr = real( dum(1) )
326* Compute space needed for CUNMLQ
327 CALL cunmlq( 'L', 'C', n, nrhs, m, a, lda, dum(1),
328 $ b, ldb, dum(1), -1, info )
329 lwork_cunmlq = real( dum(1) )
330* Compute total workspace needed
331 maxwrk = m + lwork_cgelqf
332 maxwrk = max( maxwrk, 3*m + m*m + lwork_cgebrd )
333 maxwrk = max( maxwrk, 3*m + m*m + lwork_cunmbr )
334 maxwrk = max( maxwrk, 3*m + m*m + lwork_cungbr )
335 IF( nrhs.GT.1 ) THEN
336 maxwrk = max( maxwrk, m*m + m + m*nrhs )
337 ELSE
338 maxwrk = max( maxwrk, m*m + 2*m )
339 END IF
340 maxwrk = max( maxwrk, m + lwork_cunmlq )
341 ELSE
342*
343* Path 2 - underdetermined
344*
345* Compute space needed for CGEBRD
346 CALL cgebrd( m, n, a, lda, s, s, dum(1), dum(1),
347 $ dum(1), -1, info )
348 lwork_cgebrd = real( dum(1) )
349* Compute space needed for CUNMBR
350 CALL cunmbr( 'Q', 'L', 'C', m, nrhs, m, a, lda,
351 $ dum(1), b, ldb, dum(1), -1, info )
352 lwork_cunmbr = real( dum(1) )
353* Compute space needed for CUNGBR
354 CALL cungbr( 'P', m, n, m, a, lda, dum(1),
355 $ dum(1), -1, info )
356 lwork_cungbr = real( dum(1) )
357 maxwrk = 2*m + lwork_cgebrd
358 maxwrk = max( maxwrk, 2*m + lwork_cunmbr )
359 maxwrk = max( maxwrk, 2*m + lwork_cungbr )
360 maxwrk = max( maxwrk, n*nrhs )
361 END IF
362 END IF
363 maxwrk = max( minwrk, maxwrk )
364 END IF
365 work( 1 ) = maxwrk
366*
367 IF( lwork.LT.minwrk .AND. .NOT.lquery )
368 $ info = -12
369 END IF
370*
371 IF( info.NE.0 ) THEN
372 CALL xerbla( 'CGELSS', -info )
373 RETURN
374 ELSE IF( lquery ) THEN
375 RETURN
376 END IF
377*
378* Quick return if possible
379*
380 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
381 rank = 0
382 RETURN
383 END IF
384*
385* Get machine parameters
386*
387 eps = slamch( 'P' )
388 sfmin = slamch( 'S' )
389 smlnum = sfmin / eps
390 bignum = one / smlnum
391 CALL slabad( smlnum, bignum )
392*
393* Scale A if max element outside range [SMLNUM,BIGNUM]
394*
395 anrm = clange( 'M', m, n, a, lda, rwork )
396 iascl = 0
397 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
398*
399* Scale matrix norm up to SMLNUM
400*
401 CALL clascl( 'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
402 iascl = 1
403 ELSE IF( anrm.GT.bignum ) THEN
404*
405* Scale matrix norm down to BIGNUM
406*
407 CALL clascl( 'G', 0, 0, anrm, bignum, m, n, a, lda, info )
408 iascl = 2
409 ELSE IF( anrm.EQ.zero ) THEN
410*
411* Matrix all zero. Return zero solution.
412*
413 CALL claset( 'F', max( m, n ), nrhs, czero, czero, b, ldb )
414 CALL slaset( 'F', minmn, 1, zero, zero, s, minmn )
415 rank = 0
416 GO TO 70
417 END IF
418*
419* Scale B if max element outside range [SMLNUM,BIGNUM]
420*
421 bnrm = clange( 'm', M, NRHS, B, LDB, RWORK )
422 IBSCL = 0
423.GT..AND..LT. IF( BNRMZERO BNRMSMLNUM ) THEN
424*
425* Scale matrix norm up to SMLNUM
426*
427 CALL CLASCL( 'g', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
428 IBSCL = 1
429.GT. ELSE IF( BNRMBIGNUM ) THEN
430*
431* Scale matrix norm down to BIGNUM
432*
433 CALL CLASCL( 'g', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
434 IBSCL = 2
435 END IF
436*
437* Overdetermined case
438*
439.GE. IF( MN ) THEN
440*
441* Path 1 - overdetermined or exactly determined
442*
443 MM = M
444.GE. IF( MMNTHR ) THEN
445*
446* Path 1a - overdetermined, with many more rows than columns
447*
448 MM = N
449 ITAU = 1
450 IWORK = ITAU + N
451*
452* Compute A=Q*R
453* (CWorkspace: need 2*N, prefer N+N*NB)
454* (RWorkspace: none)
455*
456 CALL CGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
457 $ LWORK-IWORK+1, INFO )
458*
459* Multiply B by transpose(Q)
460* (CWorkspace: need N+NRHS, prefer N+NRHS*NB)
461* (RWorkspace: none)
462*
463 CALL CUNMQR( 'l', 'c', M, NRHS, N, A, LDA, WORK( ITAU ), B,
464 $ LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
465*
466* Zero out below R
467*
468.GT. IF( N1 )
469 $ CALL CLASET( 'l', N-1, N-1, CZERO, CZERO, A( 2, 1 ),
470 $ LDA )
471 END IF
472*
473 IE = 1
474 ITAUQ = 1
475 ITAUP = ITAUQ + N
476 IWORK = ITAUP + N
477*
478* Bidiagonalize R in A
479* (CWorkspace: need 2*N+MM, prefer 2*N+(MM+N)*NB)
480* (RWorkspace: need N)
481*
482 CALL CGEBRD( MM, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ),
483 $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,
484 $ INFO )
485*
486* Multiply B by transpose of left bidiagonalizing vectors of R
487* (CWorkspace: need 2*N+NRHS, prefer 2*N+NRHS*NB)
488* (RWorkspace: none)
489*
490 CALL CUNMBR( 'q', 'l', 'c', MM, NRHS, N, A, LDA, WORK( ITAUQ ),
491 $ B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )
492*
493* Generate right bidiagonalizing vectors of R in A
494* (CWorkspace: need 3*N-1, prefer 2*N+(N-1)*NB)
495* (RWorkspace: none)
496*
497 CALL CUNGBR( 'p', N, N, N, A, LDA, WORK( ITAUP ),
498 $ WORK( IWORK ), LWORK-IWORK+1, INFO )
499 IRWORK = IE + N
500*
501* Perform bidiagonal QR iteration
502* multiply B by transpose of left singular vectors
503* compute right singular vectors in A
504* (CWorkspace: none)
505* (RWorkspace: need BDSPAC)
506*
507 CALL CBDSQR( 'u', N, N, 0, NRHS, S, RWORK( IE ), A, LDA, DUM,
508 $ 1, B, LDB, RWORK( IRWORK ), INFO )
509.NE. IF( INFO0 )
510 $ GO TO 70
511*
512* Multiply B by reciprocals of singular values
513*
514 THR = MAX( RCOND*S( 1 ), SFMIN )
515.LT. IF( RCONDZERO )
516 $ THR = MAX( EPS*S( 1 ), SFMIN )
517 RANK = 0
518 DO 10 I = 1, N
519.GT. IF( S( I )THR ) THEN
520 CALL CSRSCL( NRHS, S( I ), B( I, 1 ), LDB )
521 RANK = RANK + 1
522 ELSE
523 CALL CLASET( 'f', 1, NRHS, CZERO, CZERO, B( I, 1 ), LDB )
524 END IF
525 10 CONTINUE
526*
527* Multiply B by right singular vectors
528* (CWorkspace: need N, prefer N*NRHS)
529* (RWorkspace: none)
530*
531.GE..AND..GT. IF( LWORKLDB*NRHS NRHS1 ) THEN
532 CALL CGEMM( 'c', 'n', N, NRHS, N, CONE, A, LDA, B, LDB,
533 $ CZERO, WORK, LDB )
534 CALL CLACPY( 'g', N, NRHS, WORK, LDB, B, LDB )
535.GT. ELSE IF( NRHS1 ) THEN
536 CHUNK = LWORK / N
537 DO 20 I = 1, NRHS, CHUNK
538 BL = MIN( NRHS-I+1, CHUNK )
539 CALL CGEMM( 'c', 'n', N, BL, N, CONE, A, LDA, B( 1, I ),
540 $ LDB, CZERO, WORK, N )
541 CALL CLACPY( 'g', N, BL, WORK, N, B( 1, I ), LDB )
542 20 CONTINUE
543 ELSE
544 CALL CGEMV( 'c', N, N, CONE, A, LDA, B, 1, CZERO, WORK, 1 )
545 CALL CCOPY( N, WORK, 1, B, 1 )
546 END IF
547*
548.GE..AND..GE. ELSE IF( NMNTHR LWORK3*M+M*M+MAX( M, NRHS, N-2*M ) )
549 $ THEN
550*
551* Underdetermined case, M much less than N
552*
553* Path 2a - underdetermined, with many more columns than rows
554* and sufficient workspace for an efficient algorithm
555*
556 LDWORK = M
557.GE. IF( LWORK3*M+M*LDA+MAX( M, NRHS, N-2*M ) )
558 $ LDWORK = LDA
559 ITAU = 1
560 IWORK = M + 1
561*
562* Compute A=L*Q
563* (CWorkspace: need 2*M, prefer M+M*NB)
564* (RWorkspace: none)
565*
566 CALL CGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),
567 $ LWORK-IWORK+1, INFO )
568 IL = IWORK
569*
570* Copy L to WORK(IL), zeroing out above it
571*
572 CALL CLACPY( 'l', M, M, A, LDA, WORK( IL ), LDWORK )
573 CALL CLASET( 'u', M-1, M-1, CZERO, CZERO, WORK( IL+LDWORK ),
574 $ LDWORK )
575 IE = 1
576 ITAUQ = IL + LDWORK*M
577 ITAUP = ITAUQ + M
578 IWORK = ITAUP + M
579*
580* Bidiagonalize L in WORK(IL)
581* (CWorkspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)
582* (RWorkspace: need M)
583*
584 CALL CGEBRD( M, M, WORK( IL ), LDWORK, S, RWORK( IE ),
585 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( IWORK ),
586 $ LWORK-IWORK+1, INFO )
587*
588* Multiply B by transpose of left bidiagonalizing vectors of L
589* (CWorkspace: need M*M+3*M+NRHS, prefer M*M+3*M+NRHS*NB)
590* (RWorkspace: none)
591*
592 CALL CUNMBR( 'q', 'l', 'c', M, NRHS, M, WORK( IL ), LDWORK,
593 $ WORK( ITAUQ ), B, LDB, WORK( IWORK ),
594 $ LWORK-IWORK+1, INFO )
595*
596* Generate right bidiagonalizing vectors of R in WORK(IL)
597* (CWorkspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB)
598* (RWorkspace: none)
599*
600 CALL CUNGBR( 'p', M, M, M, WORK( IL ), LDWORK, WORK( ITAUP ),
601 $ WORK( IWORK ), LWORK-IWORK+1, INFO )
602 IRWORK = IE + M
603*
604* Perform bidiagonal QR iteration, computing right singular
605* vectors of L in WORK(IL) and multiplying B by transpose of
606* left singular vectors
607* (CWorkspace: need M*M)
608* (RWorkspace: need BDSPAC)
609*
610 CALL CBDSQR( 'u', M, M, 0, NRHS, S, RWORK( IE ), WORK( IL ),
611 $ LDWORK, A, LDA, B, LDB, RWORK( IRWORK ), INFO )
612.NE. IF( INFO0 )
613 $ GO TO 70
614*
615* Multiply B by reciprocals of singular values
616*
617 THR = MAX( RCOND*S( 1 ), SFMIN )
618.LT. IF( RCONDZERO )
619 $ THR = MAX( EPS*S( 1 ), SFMIN )
620 RANK = 0
621 DO 30 I = 1, M
622.GT. IF( S( I )THR ) THEN
623 CALL CSRSCL( NRHS, S( I ), B( I, 1 ), LDB )
624 RANK = RANK + 1
625 ELSE
626 CALL CLASET( 'f', 1, NRHS, CZERO, CZERO, B( I, 1 ), LDB )
627 END IF
628 30 CONTINUE
629 IWORK = IL + M*LDWORK
630*
631* Multiply B by right singular vectors of L in WORK(IL)
632* (CWorkspace: need M*M+2*M, prefer M*M+M+M*NRHS)
633* (RWorkspace: none)
634*
635.GE..AND..GT. IF( LWORKLDB*NRHS+IWORK-1 NRHS1 ) THEN
636 CALL CGEMM( 'c', 'n', M, NRHS, M, CONE, WORK( IL ), LDWORK,
637 $ B, LDB, CZERO, WORK( IWORK ), LDB )
638 CALL CLACPY( 'g', M, NRHS, WORK( IWORK ), LDB, B, LDB )
639.GT. ELSE IF( NRHS1 ) THEN
640 CHUNK = ( LWORK-IWORK+1 ) / M
641 DO 40 I = 1, NRHS, CHUNK
642 BL = MIN( NRHS-I+1, CHUNK )
643 CALL CGEMM( 'c', 'n', M, BL, M, CONE, WORK( IL ), LDWORK,
644 $ B( 1, I ), LDB, CZERO, WORK( IWORK ), M )
645 CALL CLACPY( 'g', M, BL, WORK( IWORK ), M, B( 1, I ),
646 $ LDB )
647 40 CONTINUE
648 ELSE
649 CALL CGEMV( 'c', M, M, CONE, WORK( IL ), LDWORK, B( 1, 1 ),
650 $ 1, CZERO, WORK( IWORK ), 1 )
651 CALL CCOPY( M, WORK( IWORK ), 1, B( 1, 1 ), 1 )
652 END IF
653*
654* Zero out below first M rows of B
655*
656 CALL CLASET( 'f', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB )
657 IWORK = ITAU + M
658*
659* Multiply transpose(Q) by B
660* (CWorkspace: need M+NRHS, prefer M+NHRS*NB)
661* (RWorkspace: none)
662*
663 CALL CUNMLQ( 'l', 'c', n, nrhs, m, a, lda, work( itau ), b,
664 $ ldb, work( iwork ), lwork-iwork+1, info )
665*
666 ELSE
667*
668* Path 2 - remaining underdetermined cases
669*
670 ie = 1
671 itauq = 1
672 itaup = itauq + m
673 iwork = itaup + m
674*
675* Bidiagonalize A
676* (CWorkspace: need 3*M, prefer 2*M+(M+N)*NB)
677* (RWorkspace: need N)
678*
679 CALL cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),
680 $ work( itaup ), work( iwork ), lwork-iwork+1,
681 $ info )
682*
683* Multiply B by transpose of left bidiagonalizing vectors
684* (CWorkspace: need 2*M+NRHS, prefer 2*M+NRHS*NB)
685* (RWorkspace: none)
686*
687 CALL cunmbr( 'Q', 'L', 'C', m, nrhs, n, a, lda, work( itauq ),
688 $ b, ldb, work( iwork ), lwork-iwork+1, info )
689*
690* Generate right bidiagonalizing vectors in A
691* (CWorkspace: need 3*M, prefer 2*M+M*NB)
692* (RWorkspace: none)
693*
694 CALL cungbr( 'P', m, n, m, a, lda, work( itaup ),
695 $ work( iwork ), lwork-iwork+1, info )
696 irwork = ie + m
697*
698* Perform bidiagonal QR iteration,
699* computing right singular vectors of A in A and
700* multiplying B by transpose of left singular vectors
701* (CWorkspace: none)
702* (RWorkspace: need BDSPAC)
703*
704 CALL cbdsqr( 'L', m, n, 0, nrhs, s, rwork( ie ), a, lda, dum,
705 $ 1, b, ldb, rwork( irwork ), info )
706 IF( info.NE.0 )
707 $ GO TO 70
708*
709* Multiply B by reciprocals of singular values
710*
711 thr = max( rcond*s( 1 ), sfmin )
712 IF( rcond.LT.zero )
713 $ thr = max( eps*s( 1 ), sfmin )
714 rank = 0
715 DO 50 i = 1, m
716 IF( s( i ).GT.thr ) THEN
717 CALL csrscl( nrhs, s( i ), b( i, 1 ), ldb )
718 rank = rank + 1
719 ELSE
720 CALL claset( 'F', 1, nrhs, czero, czero, b( i, 1 ), ldb )
721 END IF
722 50 CONTINUE
723*
724* Multiply B by right singular vectors of A
725* (CWorkspace: need N, prefer N*NRHS)
726* (RWorkspace: none)
727*
728 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
729 CALL cgemm( 'C', 'N', n, nrhs, m, cone, a, lda, b, ldb,
730 $ czero, work, ldb )
731 CALL clacpy( 'G', n, nrhs, work, ldb, b, ldb )
732 ELSE IF( nrhs.GT.1 ) THEN
733 chunk = lwork / n
734 DO 60 i = 1, nrhs, chunk
735 bl = min( nrhs-i+1, chunk )
736 CALL cgemm( 'C', 'N', n, bl, m, cone, a, lda, b( 1, i ),
737 $ ldb, czero, work, n )
738 CALL clacpy( 'F', n, bl, work, n, b( 1, i ), ldb )
739 60 CONTINUE
740 ELSE
741 CALL cgemv( 'C', m, n, cone, a, lda, b, 1, czero, work, 1 )
742 CALL ccopy( n, work, 1, b, 1 )
743 END IF
744 END IF
745*
746* Undo scaling
747*
748 IF( iascl.EQ.1 ) THEN
749 CALL clascl( 'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
750 CALL slascl( 'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
751 $ info )
752 ELSE IF( iascl.EQ.2 ) THEN
753 CALL clascl( 'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
754 CALL slascl( 'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
755 $ info )
756 END IF
757 IF( ibscl.EQ.1 ) THEN
758 CALL clascl( 'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
759 ELSE IF( ibscl.EQ.2 ) THEN
760 CALL clascl( 'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
761 END IF
762 70 CONTINUE
763 work( 1 ) = maxwrk
764 RETURN
765*
766* End of CGELSS
767*
768 END
subroutine slabad(small, large)
SLABAD
Definition slabad.f:74
subroutine slaset(uplo, m, n, alpha, beta, a, lda)
SLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition slaset.f:110
subroutine slascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
SLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition slascl.f:143
subroutine xerbla(srname, info)
XERBLA
Definition xerbla.f:60
subroutine cungbr(vect, m, n, k, a, lda, tau, work, lwork, info)
CUNGBR
Definition cungbr.f:157
subroutine cgeqrf(m, n, a, lda, tau, work, lwork, info)
CGEQRF
Definition cgeqrf.f:146
subroutine cgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
CGEBRD
Definition cgebrd.f:206
subroutine cgelqf(m, n, a, lda, tau, work, lwork, info)
CGELQF
Definition cgelqf.f:143
subroutine cgelss(m, n, nrhs, a, lda, b, ldb, s, rcond, rank, work, lwork, rwork, info)
CGELSS solves overdetermined or underdetermined systems for GE matrices
Definition cgelss.f:178
subroutine clascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
CLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition clascl.f:143
subroutine clacpy(uplo, m, n, a, lda, b, ldb)
CLACPY copies all or part of one two-dimensional array to another.
Definition clacpy.f:103
subroutine claset(uplo, m, n, alpha, beta, a, lda)
CLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition claset.f:106
subroutine csrscl(n, sa, sx, incx)
CSRSCL multiplies a vector by the reciprocal of a real scalar.
Definition csrscl.f:84
subroutine cunmqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
CUNMQR
Definition cunmqr.f:168
subroutine cbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, rwork, info)
CBDSQR
Definition cbdsqr.f:222
subroutine cunmlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
CUNMLQ
Definition cunmlq.f:168
subroutine cunmbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
CUNMBR
Definition cunmbr.f:197
subroutine ccopy(n, cx, incx, cy, incy)
CCOPY
Definition ccopy.f:81
subroutine cgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
CGEMV
Definition cgemv.f:158
subroutine cgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
CGEMM
Definition cgemm.f:187
#define min(a, b)
Definition macros.h:20
#define max(a, b)
Definition macros.h:21