LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
sormbr.f
Go to the documentation of this file.
1*> \brief \b SORMBR
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download SORMBR + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sormbr.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sormbr.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sormbr.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE SORMBR( VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C,
20* LDC, WORK, LWORK, INFO )
21*
22* .. Scalar Arguments ..
23* CHARACTER SIDE, TRANS, VECT
24* INTEGER INFO, K, LDA, LDC, LWORK, M, N
25* ..
26* .. Array Arguments ..
27* REAL A( LDA, * ), C( LDC, * ), TAU( * ),
28* $ WORK( * )
29* ..
30*
31*
32*> \par Purpose:
33* =============
34*>
35*> \verbatim
36*>
37*> If VECT = 'Q', SORMBR overwrites the general real M-by-N matrix C
38*> with
39*> SIDE = 'L' SIDE = 'R'
40*> TRANS = 'N': Q * C C * Q
41*> TRANS = 'T': Q**T * C C * Q**T
42*>
43*> If VECT = 'P', SORMBR overwrites the general real M-by-N matrix C
44*> with
45*> SIDE = 'L' SIDE = 'R'
46*> TRANS = 'N': P * C C * P
47*> TRANS = 'T': P**T * C C * P**T
48*>
49*> Here Q and P**T are the orthogonal matrices determined by SGEBRD when
50*> reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and
51*> P**T are defined as products of elementary reflectors H(i) and G(i)
52*> respectively.
53*>
54*> Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the
55*> order of the orthogonal matrix Q or P**T that is applied.
56*>
57*> If VECT = 'Q', A is assumed to have been an NQ-by-K matrix:
58*> if nq >= k, Q = H(1) H(2) . . . H(k);
59*> if nq < k, Q = H(1) H(2) . . . H(nq-1).
60*>
61*> If VECT = 'P', A is assumed to have been a K-by-NQ matrix:
62*> if k < nq, P = G(1) G(2) . . . G(k);
63*> if k >= nq, P = G(1) G(2) . . . G(nq-1).
64*> \endverbatim
65*
66* Arguments:
67* ==========
68*
69*> \param[in] VECT
70*> \verbatim
71*> VECT is CHARACTER*1
72*> = 'Q': apply Q or Q**T;
73*> = 'P': apply P or P**T.
74*> \endverbatim
75*>
76*> \param[in] SIDE
77*> \verbatim
78*> SIDE is CHARACTER*1
79*> = 'L': apply Q, Q**T, P or P**T from the Left;
80*> = 'R': apply Q, Q**T, P or P**T from the Right.
81*> \endverbatim
82*>
83*> \param[in] TRANS
84*> \verbatim
85*> TRANS is CHARACTER*1
86*> = 'N': No transpose, apply Q or P;
87*> = 'T': Transpose, apply Q**T or P**T.
88*> \endverbatim
89*>
90*> \param[in] M
91*> \verbatim
92*> M is INTEGER
93*> The number of rows of the matrix C. M >= 0.
94*> \endverbatim
95*>
96*> \param[in] N
97*> \verbatim
98*> N is INTEGER
99*> The number of columns of the matrix C. N >= 0.
100*> \endverbatim
101*>
102*> \param[in] K
103*> \verbatim
104*> K is INTEGER
105*> If VECT = 'Q', the number of columns in the original
106*> matrix reduced by SGEBRD.
107*> If VECT = 'P', the number of rows in the original
108*> matrix reduced by SGEBRD.
109*> K >= 0.
110*> \endverbatim
111*>
112*> \param[in] A
113*> \verbatim
114*> A is REAL array, dimension
115*> (LDA,min(nq,K)) if VECT = 'Q'
116*> (LDA,nq) if VECT = 'P'
117*> The vectors which define the elementary reflectors H(i) and
118*> G(i), whose products determine the matrices Q and P, as
119*> returned by SGEBRD.
120*> \endverbatim
121*>
122*> \param[in] LDA
123*> \verbatim
124*> LDA is INTEGER
125*> The leading dimension of the array A.
126*> If VECT = 'Q', LDA >= max(1,nq);
127*> if VECT = 'P', LDA >= max(1,min(nq,K)).
128*> \endverbatim
129*>
130*> \param[in] TAU
131*> \verbatim
132*> TAU is REAL array, dimension (min(nq,K))
133*> TAU(i) must contain the scalar factor of the elementary
134*> reflector H(i) or G(i) which determines Q or P, as returned
135*> by SGEBRD in the array argument TAUQ or TAUP.
136*> \endverbatim
137*>
138*> \param[in,out] C
139*> \verbatim
140*> C is REAL array, dimension (LDC,N)
141*> On entry, the M-by-N matrix C.
142*> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q
143*> or P*C or P**T*C or C*P or C*P**T.
144*> \endverbatim
145*>
146*> \param[in] LDC
147*> \verbatim
148*> LDC is INTEGER
149*> The leading dimension of the array C. LDC >= max(1,M).
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*> If SIDE = 'L', LWORK >= max(1,N);
163*> if SIDE = 'R', LWORK >= max(1,M).
164*> For optimum performance LWORK >= N*NB if SIDE = 'L', and
165*> LWORK >= M*NB if SIDE = 'R', where NB is the optimal
166*> blocksize.
167*>
168*> If LWORK = -1, then a workspace query is assumed; the routine
169*> only calculates the optimal size of the WORK array, returns
170*> this value as the first entry of the WORK array, and no error
171*> message related to LWORK is issued by XERBLA.
172*> \endverbatim
173*>
174*> \param[out] INFO
175*> \verbatim
176*> INFO is INTEGER
177*> = 0: successful exit
178*> < 0: if INFO = -i, the i-th argument had an illegal value
179*> \endverbatim
180*
181* Authors:
182* ========
183*
184*> \author Univ. of Tennessee
185*> \author Univ. of California Berkeley
186*> \author Univ. of Colorado Denver
187*> \author NAG Ltd.
188*
189*> \ingroup unmbr
190*
191* =====================================================================
192 SUBROUTINE sormbr( VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C,
193 $ LDC, WORK, LWORK, INFO )
194*
195* -- LAPACK computational routine --
196* -- LAPACK is a software package provided by Univ. of Tennessee, --
197* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
198*
199* .. Scalar Arguments ..
200 CHARACTER SIDE, TRANS, VECT
201 INTEGER INFO, K, LDA, LDC, LWORK, M, N
202* ..
203* .. Array Arguments ..
204 REAL A( LDA, * ), C( LDC, * ), TAU( * ),
205 $ work( * )
206* ..
207*
208* =====================================================================
209*
210* .. Local Scalars ..
211 LOGICAL APPLYQ, LEFT, LQUERY, NOTRAN
212 CHARACTER TRANST
213 INTEGER I1, I2, IINFO, LWKOPT, MI, NB, NI, NQ, NW
214* ..
215* .. External Functions ..
216 LOGICAL LSAME
217 INTEGER ILAENV
218 REAL SROUNDUP_LWORK
219 EXTERNAL ilaenv, lsame, sroundup_lwork
220* ..
221* .. External Subroutines ..
222 EXTERNAL sormlq, sormqr, xerbla
223* ..
224* .. Intrinsic Functions ..
225 INTRINSIC max, min
226* ..
227* .. Executable Statements ..
228*
229* Test the input arguments
230*
231 info = 0
232 applyq = lsame( vect, 'Q' )
233 left = lsame( side, 'L' )
234 notran = lsame( trans, 'N' )
235 lquery = ( lwork.EQ.-1 )
236*
237* NQ is the order of Q or P and NW is the minimum dimension of WORK
238*
239 IF( left ) THEN
240 nq = m
241 nw = max( 1, n )
242 ELSE
243 nq = n
244 nw = max( 1, m )
245 END IF
246 IF( .NOT.applyq .AND. .NOT.lsame( vect, 'P' ) ) THEN
247 info = -1
248 ELSE IF( .NOT.left .AND. .NOT.lsame( side, 'R' ) ) THEN
249 info = -2
250 ELSE IF( .NOT.notran .AND. .NOT.lsame( trans, 'T' ) ) THEN
251 info = -3
252 ELSE IF( m.LT.0 ) THEN
253 info = -4
254 ELSE IF( n.LT.0 ) THEN
255 info = -5
256 ELSE IF( k.LT.0 ) THEN
257 info = -6
258 ELSE IF( ( applyq .AND. lda.LT.max( 1, nq ) ) .OR.
259 $ ( .NOT.applyq .AND. lda.LT.max( 1, min( nq, k ) ) ) )
260 $ THEN
261 info = -8
262 ELSE IF( ldc.LT.max( 1, m ) ) THEN
263 info = -11
264 ELSE IF( lwork.LT.nw .AND. .NOT.lquery ) THEN
265 info = -13
266 END IF
267*
268 IF( info.EQ.0 ) THEN
269 IF( applyq ) THEN
270 IF( left ) THEN
271 nb = ilaenv( 1, 'SORMQR', side // trans, m-1, n, m-1,
272 $ -1 )
273 ELSE
274 nb = ilaenv( 1, 'SORMQR', side // trans, m, n-1, n-1,
275 $ -1 )
276 END IF
277 ELSE
278 IF( left ) THEN
279 nb = ilaenv( 1, 'SORMLQ', side // trans, m-1, n, m-1,
280 $ -1 )
281 ELSE
282 nb = ilaenv( 1, 'SORMLQ', side // trans, m, n-1, n-1,
283 $ -1 )
284 END IF
285 END IF
286 lwkopt = nw*nb
287 work( 1 ) = sroundup_lwork(lwkopt)
288 END IF
289*
290 IF( info.NE.0 ) THEN
291 CALL xerbla( 'SORMBR', -info )
292 RETURN
293 ELSE IF( lquery ) THEN
294 RETURN
295 END IF
296*
297* Quick return if possible
298*
299 work( 1 ) = 1
300 IF( m.EQ.0 .OR. n.EQ.0 )
301 $ RETURN
302*
303 IF( applyq ) THEN
304*
305* Apply Q
306*
307 IF( nq.GE.k ) THEN
308*
309* Q was determined by a call to SGEBRD with nq >= k
310*
311 CALL sormqr( side, trans, m, n, k, a, lda, tau, c, ldc,
312 $ work, lwork, iinfo )
313 ELSE IF( nq.GT.1 ) THEN
314*
315* Q was determined by a call to SGEBRD with nq < k
316*
317 IF( left ) THEN
318 mi = m - 1
319 ni = n
320 i1 = 2
321 i2 = 1
322 ELSE
323 mi = m
324 ni = n - 1
325 i1 = 1
326 i2 = 2
327 END IF
328 CALL sormqr( side, trans, mi, ni, nq-1, a( 2, 1 ), lda,
329 $ tau,
330 $ c( i1, i2 ), ldc, work, lwork, iinfo )
331 END IF
332 ELSE
333*
334* Apply P
335*
336 IF( notran ) THEN
337 transt = 'T'
338 ELSE
339 transt = 'N'
340 END IF
341 IF( nq.GT.k ) THEN
342*
343* P was determined by a call to SGEBRD with nq > k
344*
345 CALL sormlq( side, transt, m, n, k, a, lda, tau, c, ldc,
346 $ work, lwork, iinfo )
347 ELSE IF( nq.GT.1 ) THEN
348*
349* P was determined by a call to SGEBRD with nq <= k
350*
351 IF( left ) THEN
352 mi = m - 1
353 ni = n
354 i1 = 2
355 i2 = 1
356 ELSE
357 mi = m
358 ni = n - 1
359 i1 = 1
360 i2 = 2
361 END IF
362 CALL sormlq( side, transt, mi, ni, nq-1, a( 1, 2 ), lda,
363 $ tau, c( i1, i2 ), ldc, work, lwork, iinfo )
364 END IF
365 END IF
366 work( 1 ) = sroundup_lwork(lwkopt)
367 RETURN
368*
369* End of SORMBR
370*
371 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine sormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMBR
Definition sormbr.f:194
subroutine sormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMLQ
Definition sormlq.f:166
subroutine sormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMQR
Definition sormqr.f:166