LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
sgelsy.f
Go to the documentation of this file.
1*> \brief <b> SGELSY 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*> Download SGELSY + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sgelsy.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sgelsy.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgelsy.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE SGELSY( M, N, NRHS, A, LDA, B, LDB, JPVT, RCOND, RANK,
20* WORK, LWORK, INFO )
21*
22* .. Scalar Arguments ..
23* INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
24* REAL RCOND
25* ..
26* .. Array Arguments ..
27* INTEGER JPVT( * )
28* REAL A( LDA, * ), B( LDB, * ), WORK( * )
29* ..
30*
31*
32*> \par Purpose:
33* =============
34*>
35*> \verbatim
36*>
37*> SGELSY computes the minimum-norm solution to a real linear least
38*> squares problem:
39*> minimize || A * X - B ||
40*> using a complete orthogonal factorization of A. A is an M-by-N
41*> matrix which may be rank-deficient.
42*>
43*> Several right hand side vectors b and solution vectors x can be
44*> handled in a single call; they are stored as the columns of the
45*> M-by-NRHS right hand side matrix B and the N-by-NRHS solution
46*> matrix X.
47*>
48*> The routine first computes a QR factorization with column pivoting:
49*> A * P = Q * [ R11 R12 ]
50*> [ 0 R22 ]
51*> with R11 defined as the largest leading submatrix whose estimated
52*> condition number is less than 1/RCOND. The order of R11, RANK,
53*> is the effective rank of A.
54*>
55*> Then, R22 is considered to be negligible, and R12 is annihilated
56*> by orthogonal transformations from the right, arriving at the
57*> complete orthogonal factorization:
58*> A * P = Q * [ T11 0 ] * Z
59*> [ 0 0 ]
60*> The minimum-norm solution is then
61*> X = P * Z**T [ inv(T11)*Q1**T*B ]
62*> [ 0 ]
63*> where Q1 consists of the first RANK columns of Q.
64*>
65*> This routine is basically identical to the original xGELSX except
66*> three differences:
67*> o The call to the subroutine xGEQPF has been substituted by the
68*> the call to the subroutine xGEQP3. This subroutine is a Blas-3
69*> version of the QR factorization with column pivoting.
70*> o Matrix B (the right hand side) is updated with Blas-3.
71*> o The permutation of matrix B (the right hand side) is faster and
72*> more simple.
73*> \endverbatim
74*
75* Arguments:
76* ==========
77*
78*> \param[in] M
79*> \verbatim
80*> M is INTEGER
81*> The number of rows of the matrix A. M >= 0.
82*> \endverbatim
83*>
84*> \param[in] N
85*> \verbatim
86*> N is INTEGER
87*> The number of columns of the matrix A. N >= 0.
88*> \endverbatim
89*>
90*> \param[in] NRHS
91*> \verbatim
92*> NRHS is INTEGER
93*> The number of right hand sides, i.e., the number of
94*> columns of matrices B and X. NRHS >= 0.
95*> \endverbatim
96*>
97*> \param[in,out] A
98*> \verbatim
99*> A is REAL array, dimension (LDA,N)
100*> On entry, the M-by-N matrix A.
101*> On exit, A has been overwritten by details of its
102*> complete orthogonal factorization.
103*> \endverbatim
104*>
105*> \param[in] LDA
106*> \verbatim
107*> LDA is INTEGER
108*> The leading dimension of the array A. LDA >= max(1,M).
109*> \endverbatim
110*>
111*> \param[in,out] B
112*> \verbatim
113*> B is REAL array, dimension (LDB,NRHS)
114*> On entry, the M-by-NRHS right hand side matrix B.
115*> On exit, the N-by-NRHS solution matrix X.
116*> If M = 0 or N = 0, B is not referenced.
117*> \endverbatim
118*>
119*> \param[in] LDB
120*> \verbatim
121*> LDB is INTEGER
122*> The leading dimension of the array B. LDB >= max(1,M,N).
123*> \endverbatim
124*>
125*> \param[in,out] JPVT
126*> \verbatim
127*> JPVT is INTEGER array, dimension (N)
128*> On entry, if JPVT(i) .ne. 0, the i-th column of A is permuted
129*> to the front of AP, otherwise column i is a free column.
130*> On exit, if JPVT(i) = k, then the i-th column of AP
131*> was the k-th column of A.
132*> \endverbatim
133*>
134*> \param[in] RCOND
135*> \verbatim
136*> RCOND is REAL
137*> RCOND is used to determine the effective rank of A, which
138*> is defined as the order of the largest leading triangular
139*> submatrix R11 in the QR factorization with pivoting of A,
140*> whose estimated condition number < 1/RCOND.
141*> \endverbatim
142*>
143*> \param[out] RANK
144*> \verbatim
145*> RANK is INTEGER
146*> The effective rank of A, i.e., the order of the submatrix
147*> R11. This is the same as the order of the submatrix T11
148*> in the complete orthogonal factorization of A.
149*> If NRHS = 0, RANK = 0 on output.
150*> \endverbatim
151*>
152*> \param[out] WORK
153*> \verbatim
154*> WORK is REAL array, dimension (MAX(1,LWORK))
155*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
156*> \endverbatim
157*>
158*> \param[in] LWORK
159*> \verbatim
160*> LWORK is INTEGER
161*> The dimension of the array WORK.
162*> The unblocked strategy requires that:
163*> LWORK >= MAX( MN+3*N+1, 2*MN+NRHS ),
164*> where MN = min( M, N ).
165*> The block algorithm requires that:
166*> LWORK >= MAX( MN+2*N+NB*(N+1), 2*MN+NB*NRHS ),
167*> where NB is an upper bound on the blocksize returned
168*> by ILAENV for the routines SGEQP3, STZRZF, STZRQF, SORMQR,
169*> and SORMRZ.
170*>
171*> If LWORK = -1, then a workspace query is assumed; the routine
172*> only calculates the optimal size of the WORK array, returns
173*> this value as the first entry of the WORK array, and no error
174*> message related to LWORK is issued by XERBLA.
175*> \endverbatim
176*>
177*> \param[out] INFO
178*> \verbatim
179*> INFO is INTEGER
180*> = 0: successful exit
181*> < 0: If INFO = -i, the i-th argument had an illegal value.
182*> \endverbatim
183*
184* Authors:
185* ========
186*
187*> \author Univ. of Tennessee
188*> \author Univ. of California Berkeley
189*> \author Univ. of Colorado Denver
190*> \author NAG Ltd.
191*
192*> \ingroup gelsy
193*
194*> \par Contributors:
195* ==================
196*>
197*> A. Petitet, Computer Science Dept., Univ. of Tenn., Knoxville, USA \n
198*> E. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain \n
199*> G. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain \n
200*>
201* =====================================================================
202 SUBROUTINE sgelsy( M, N, NRHS, A, LDA, B, LDB, JPVT, RCOND,
203 $ RANK,
204 $ WORK, LWORK, INFO )
205*
206* -- LAPACK driver routine --
207* -- LAPACK is a software package provided by Univ. of Tennessee, --
208* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
209*
210* .. Scalar Arguments ..
211 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
212 REAL RCOND
213* ..
214* .. Array Arguments ..
215 INTEGER JPVT( * )
216 REAL A( LDA, * ), B( LDB, * ), WORK( * )
217* ..
218*
219* =====================================================================
220*
221* .. Parameters ..
222 INTEGER IMAX, IMIN
223 PARAMETER ( IMAX = 1, imin = 2 )
224 REAL ZERO, ONE
225 parameter( zero = 0.0e+0, one = 1.0e+0 )
226* ..
227* .. Local Scalars ..
228 LOGICAL LQUERY
229 INTEGER I, IASCL, IBSCL, ISMAX, ISMIN, J, LWKMIN,
230 $ lwkopt, mn, nb, nb1, nb2, nb3, nb4
231 REAL ANRM, BIGNUM, BNRM, C1, C2, S1, S2, SMAX,
232 $ SMAXPR, SMIN, SMINPR, SMLNUM, WSIZE
233* ..
234* .. External Functions ..
235 INTEGER ILAENV
236 REAL SLAMCH, SLANGE, SROUNDUP_LWORK
237 EXTERNAL ilaenv, slamch, slange,
238 $ sroundup_lwork
239* ..
240* .. External Subroutines ..
241 EXTERNAL scopy, sgeqp3, slaic1, slascl,
242 $ slaset,
244* ..
245* .. Intrinsic Functions ..
246 INTRINSIC abs, max, min
247* ..
248* .. Executable Statements ..
249*
250 mn = min( m, n )
251 ismin = mn + 1
252 ismax = 2*mn + 1
253*
254* Test the input arguments.
255*
256 info = 0
257 lquery = ( lwork.EQ.-1 )
258 IF( m.LT.0 ) THEN
259 info = -1
260 ELSE IF( n.LT.0 ) THEN
261 info = -2
262 ELSE IF( nrhs.LT.0 ) THEN
263 info = -3
264 ELSE IF( lda.LT.max( 1, m ) ) THEN
265 info = -5
266 ELSE IF( ldb.LT.max( 1, m, n ) ) THEN
267 info = -7
268 END IF
269*
270* Figure out optimal block size
271*
272 IF( info.EQ.0 ) THEN
273 IF( mn.EQ.0 .OR. nrhs.EQ.0 ) THEN
274 lwkmin = 1
275 lwkopt = 1
276 ELSE
277 nb1 = ilaenv( 1, 'SGEQRF', ' ', m, n, -1, -1 )
278 nb2 = ilaenv( 1, 'SGERQF', ' ', m, n, -1, -1 )
279 nb3 = ilaenv( 1, 'SORMQR', ' ', m, n, nrhs, -1 )
280 nb4 = ilaenv( 1, 'SORMRQ', ' ', m, n, nrhs, -1 )
281 nb = max( nb1, nb2, nb3, nb4 )
282 lwkmin = mn + max( 2*mn, n + 1, mn + nrhs )
283 lwkopt = max( lwkmin,
284 $ mn + 2*n + nb*( n + 1 ), 2*mn + nb*nrhs )
285 END IF
286 work( 1 ) = sroundup_lwork(lwkopt)
287*
288 IF( lwork.LT.lwkmin .AND. .NOT.lquery ) THEN
289 info = -12
290 END IF
291 END IF
292*
293 IF( info.NE.0 ) THEN
294 CALL xerbla( 'SGELSY', -info )
295 RETURN
296 ELSE IF( lquery ) THEN
297 RETURN
298 END IF
299*
300* Quick return if possible
301*
302 IF( mn.EQ.0 .OR. nrhs.EQ.0 ) THEN
303 rank = 0
304 RETURN
305 END IF
306*
307* Get machine parameters
308*
309 smlnum = slamch( 'S' ) / slamch( 'P' )
310 bignum = one / smlnum
311*
312* Scale A, B if max entries outside range [SMLNUM,BIGNUM]
313*
314 anrm = slange( 'M', m, n, a, lda, work )
315 iascl = 0
316 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
317*
318* Scale matrix norm up to SMLNUM
319*
320 CALL slascl( 'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
321 iascl = 1
322 ELSE IF( anrm.GT.bignum ) THEN
323*
324* Scale matrix norm down to BIGNUM
325*
326 CALL slascl( 'G', 0, 0, anrm, bignum, m, n, a, lda, info )
327 iascl = 2
328 ELSE IF( anrm.EQ.zero ) THEN
329*
330* Matrix all zero. Return zero solution.
331*
332 CALL slaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb )
333 rank = 0
334 GO TO 70
335 END IF
336*
337 bnrm = slange( 'M', m, nrhs, b, ldb, work )
338 ibscl = 0
339 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
340*
341* Scale matrix norm up to SMLNUM
342*
343 CALL slascl( 'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
344 $ info )
345 ibscl = 1
346 ELSE IF( bnrm.GT.bignum ) THEN
347*
348* Scale matrix norm down to BIGNUM
349*
350 CALL slascl( 'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
351 $ info )
352 ibscl = 2
353 END IF
354*
355* Compute QR factorization with column pivoting of A:
356* A * P = Q * R
357*
358 CALL sgeqp3( m, n, a, lda, jpvt, work( 1 ), work( mn+1 ),
359 $ lwork-mn, info )
360 wsize = real( mn ) + work( mn+1 )
361*
362* workspace: MN+2*N+NB*(N+1).
363* Details of Householder rotations stored in WORK(1:MN).
364*
365* Determine RANK using incremental condition estimation
366*
367 work( ismin ) = one
368 work( ismax ) = one
369 smax = abs( a( 1, 1 ) )
370 smin = smax
371 IF( abs( a( 1, 1 ) ).EQ.zero ) THEN
372 rank = 0
373 CALL slaset( 'F', max( m, n ), nrhs, zero, zero, b, ldb )
374 GO TO 70
375 ELSE
376 rank = 1
377 END IF
378*
379 10 CONTINUE
380 IF( rank.LT.mn ) THEN
381 i = rank + 1
382 CALL slaic1( imin, rank, work( ismin ), smin, a( 1, i ),
383 $ a( i, i ), sminpr, s1, c1 )
384 CALL slaic1( imax, rank, work( ismax ), smax, a( 1, i ),
385 $ a( i, i ), smaxpr, s2, c2 )
386*
387 IF( smaxpr*rcond.LE.sminpr ) THEN
388 DO 20 i = 1, rank
389 work( ismin+i-1 ) = s1*work( ismin+i-1 )
390 work( ismax+i-1 ) = s2*work( ismax+i-1 )
391 20 CONTINUE
392 work( ismin+rank ) = c1
393 work( ismax+rank ) = c2
394 smin = sminpr
395 smax = smaxpr
396 rank = rank + 1
397 GO TO 10
398 END IF
399 END IF
400*
401* workspace: 3*MN.
402*
403* Logically partition R = [ R11 R12 ]
404* [ 0 R22 ]
405* where R11 = R(1:RANK,1:RANK)
406*
407* [R11,R12] = [ T11, 0 ] * Y
408*
409 IF( rank.LT.n )
410 $ CALL stzrzf( rank, n, a, lda, work( mn+1 ), work( 2*mn+1 ),
411 $ lwork-2*mn, info )
412*
413* workspace: 2*MN.
414* Details of Householder rotations stored in WORK(MN+1:2*MN)
415*
416* B(1:M,1:NRHS) := Q**T * B(1:M,1:NRHS)
417*
418 CALL sormqr( 'Left', 'Transpose', m, nrhs, mn, a, lda,
419 $ work( 1 ),
420 $ b, ldb, work( 2*mn+1 ), lwork-2*mn, info )
421 wsize = max( wsize, real( 2*mn )+work( 2*mn+1 ) )
422*
423* workspace: 2*MN+NB*NRHS.
424*
425* B(1:RANK,1:NRHS) := inv(T11) * B(1:RANK,1:NRHS)
426*
427 CALL strsm( 'Left', 'Upper', 'No transpose', 'Non-unit', rank,
428 $ nrhs, one, a, lda, b, ldb )
429*
430 DO 40 j = 1, nrhs
431 DO 30 i = rank + 1, n
432 b( i, j ) = zero
433 30 CONTINUE
434 40 CONTINUE
435*
436* B(1:N,1:NRHS) := Y**T * B(1:N,1:NRHS)
437*
438 IF( rank.LT.n ) THEN
439 CALL sormrz( 'Left', 'Transpose', n, nrhs, rank, n-rank, a,
440 $ lda, work( mn+1 ), b, ldb, work( 2*mn+1 ),
441 $ lwork-2*mn, info )
442 END IF
443*
444* workspace: 2*MN+NRHS.
445*
446* B(1:N,1:NRHS) := P * B(1:N,1:NRHS)
447*
448 DO 60 j = 1, nrhs
449 DO 50 i = 1, n
450 work( jpvt( i ) ) = b( i, j )
451 50 CONTINUE
452 CALL scopy( n, work( 1 ), 1, b( 1, j ), 1 )
453 60 CONTINUE
454*
455* workspace: N.
456*
457* Undo scaling
458*
459 IF( iascl.EQ.1 ) THEN
460 CALL slascl( 'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
461 $ info )
462 CALL slascl( 'U', 0, 0, smlnum, anrm, rank, rank, a, lda,
463 $ info )
464 ELSE IF( iascl.EQ.2 ) THEN
465 CALL slascl( 'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
466 $ info )
467 CALL slascl( 'U', 0, 0, bignum, anrm, rank, rank, a, lda,
468 $ info )
469 END IF
470 IF( ibscl.EQ.1 ) THEN
471 CALL slascl( 'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
472 $ info )
473 ELSE IF( ibscl.EQ.2 ) THEN
474 CALL slascl( 'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
475 $ info )
476 END IF
477*
478 70 CONTINUE
479 work( 1 ) = sroundup_lwork(lwkopt)
480*
481 RETURN
482*
483* End of SGELSY
484*
485 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
Definition scopy.f:82
subroutine sgelsy(m, n, nrhs, a, lda, b, ldb, jpvt, rcond, rank, work, lwork, info)
SGELSY solves overdetermined or underdetermined systems for GE matrices
Definition sgelsy.f:205
subroutine sgeqp3(m, n, a, lda, jpvt, tau, work, lwork, info)
SGEQP3
Definition sgeqp3.f:149
subroutine slaic1(job, j, x, sest, w, gamma, sestpr, s, c)
SLAIC1 applies one step of incremental condition estimation.
Definition slaic1.f:132
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:142
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:108
subroutine strsm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
STRSM
Definition strsm.f:181
subroutine stzrzf(m, n, a, lda, tau, work, lwork, info)
STZRZF
Definition stzrzf.f:149
subroutine sormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMQR
Definition sormqr.f:166
subroutine sormrz(side, trans, m, n, k, l, a, lda, tau, c, ldc, work, lwork, info)
SORMRZ
Definition sormrz.f:186