Mercurial > octave
comparison libcruft/lapack/sormbr.f @ 7789:82be108cc558
First attempt at single precision tyeps
* * *
corrections to qrupdate single precision routines
* * *
prefer demotion to single over promotion to double
* * *
Add single precision support to log2 function
* * *
Trivial PROJECT file update
* * *
Cache optimized hermitian/transpose methods
* * *
Add tests for tranpose/hermitian and ChangeLog entry for new transpose code
author | David Bateman <dbateman@free.fr> |
---|---|
date | Sun, 27 Apr 2008 22:34:17 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
7788:45f5faba05a2 | 7789:82be108cc558 |
---|---|
1 SUBROUTINE SORMBR( VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, | |
2 $ LDC, WORK, LWORK, INFO ) | |
3 * | |
4 * -- LAPACK routine (version 3.1) -- | |
5 * Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. | |
6 * November 2006 | |
7 * | |
8 * .. Scalar Arguments .. | |
9 CHARACTER SIDE, TRANS, VECT | |
10 INTEGER INFO, K, LDA, LDC, LWORK, M, N | |
11 * .. | |
12 * .. Array Arguments .. | |
13 REAL A( LDA, * ), C( LDC, * ), TAU( * ), | |
14 $ WORK( * ) | |
15 * .. | |
16 * | |
17 * Purpose | |
18 * ======= | |
19 * | |
20 * If VECT = 'Q', SORMBR overwrites the general real M-by-N matrix C | |
21 * with | |
22 * SIDE = 'L' SIDE = 'R' | |
23 * TRANS = 'N': Q * C C * Q | |
24 * TRANS = 'T': Q**T * C C * Q**T | |
25 * | |
26 * If VECT = 'P', SORMBR overwrites the general real M-by-N matrix C | |
27 * with | |
28 * SIDE = 'L' SIDE = 'R' | |
29 * TRANS = 'N': P * C C * P | |
30 * TRANS = 'T': P**T * C C * P**T | |
31 * | |
32 * Here Q and P**T are the orthogonal matrices determined by SGEBRD when | |
33 * reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and | |
34 * P**T are defined as products of elementary reflectors H(i) and G(i) | |
35 * respectively. | |
36 * | |
37 * Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the | |
38 * order of the orthogonal matrix Q or P**T that is applied. | |
39 * | |
40 * If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: | |
41 * if nq >= k, Q = H(1) H(2) . . . H(k); | |
42 * if nq < k, Q = H(1) H(2) . . . H(nq-1). | |
43 * | |
44 * If VECT = 'P', A is assumed to have been a K-by-NQ matrix: | |
45 * if k < nq, P = G(1) G(2) . . . G(k); | |
46 * if k >= nq, P = G(1) G(2) . . . G(nq-1). | |
47 * | |
48 * Arguments | |
49 * ========= | |
50 * | |
51 * VECT (input) CHARACTER*1 | |
52 * = 'Q': apply Q or Q**T; | |
53 * = 'P': apply P or P**T. | |
54 * | |
55 * SIDE (input) CHARACTER*1 | |
56 * = 'L': apply Q, Q**T, P or P**T from the Left; | |
57 * = 'R': apply Q, Q**T, P or P**T from the Right. | |
58 * | |
59 * TRANS (input) CHARACTER*1 | |
60 * = 'N': No transpose, apply Q or P; | |
61 * = 'T': Transpose, apply Q**T or P**T. | |
62 * | |
63 * M (input) INTEGER | |
64 * The number of rows of the matrix C. M >= 0. | |
65 * | |
66 * N (input) INTEGER | |
67 * The number of columns of the matrix C. N >= 0. | |
68 * | |
69 * K (input) INTEGER | |
70 * If VECT = 'Q', the number of columns in the original | |
71 * matrix reduced by SGEBRD. | |
72 * If VECT = 'P', the number of rows in the original | |
73 * matrix reduced by SGEBRD. | |
74 * K >= 0. | |
75 * | |
76 * A (input) REAL array, dimension | |
77 * (LDA,min(nq,K)) if VECT = 'Q' | |
78 * (LDA,nq) if VECT = 'P' | |
79 * The vectors which define the elementary reflectors H(i) and | |
80 * G(i), whose products determine the matrices Q and P, as | |
81 * returned by SGEBRD. | |
82 * | |
83 * LDA (input) INTEGER | |
84 * The leading dimension of the array A. | |
85 * If VECT = 'Q', LDA >= max(1,nq); | |
86 * if VECT = 'P', LDA >= max(1,min(nq,K)). | |
87 * | |
88 * TAU (input) REAL array, dimension (min(nq,K)) | |
89 * TAU(i) must contain the scalar factor of the elementary | |
90 * reflector H(i) or G(i) which determines Q or P, as returned | |
91 * by SGEBRD in the array argument TAUQ or TAUP. | |
92 * | |
93 * C (input/output) REAL array, dimension (LDC,N) | |
94 * On entry, the M-by-N matrix C. | |
95 * On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q | |
96 * or P*C or P**T*C or C*P or C*P**T. | |
97 * | |
98 * LDC (input) INTEGER | |
99 * The leading dimension of the array C. LDC >= max(1,M). | |
100 * | |
101 * WORK (workspace/output) REAL array, dimension (MAX(1,LWORK)) | |
102 * On exit, if INFO = 0, WORK(1) returns the optimal LWORK. | |
103 * | |
104 * LWORK (input) INTEGER | |
105 * The dimension of the array WORK. | |
106 * If SIDE = 'L', LWORK >= max(1,N); | |
107 * if SIDE = 'R', LWORK >= max(1,M). | |
108 * For optimum performance LWORK >= N*NB if SIDE = 'L', and | |
109 * LWORK >= M*NB if SIDE = 'R', where NB is the optimal | |
110 * blocksize. | |
111 * | |
112 * If LWORK = -1, then a workspace query is assumed; the routine | |
113 * only calculates the optimal size of the WORK array, returns | |
114 * this value as the first entry of the WORK array, and no error | |
115 * message related to LWORK is issued by XERBLA. | |
116 * | |
117 * INFO (output) INTEGER | |
118 * = 0: successful exit | |
119 * < 0: if INFO = -i, the i-th argument had an illegal value | |
120 * | |
121 * ===================================================================== | |
122 * | |
123 * .. Local Scalars .. | |
124 LOGICAL APPLYQ, LEFT, LQUERY, NOTRAN | |
125 CHARACTER TRANST | |
126 INTEGER I1, I2, IINFO, LWKOPT, MI, NB, NI, NQ, NW | |
127 * .. | |
128 * .. External Functions .. | |
129 LOGICAL LSAME | |
130 INTEGER ILAENV | |
131 EXTERNAL ILAENV, LSAME | |
132 * .. | |
133 * .. External Subroutines .. | |
134 EXTERNAL SORMLQ, SORMQR, XERBLA | |
135 * .. | |
136 * .. Intrinsic Functions .. | |
137 INTRINSIC MAX, MIN | |
138 * .. | |
139 * .. Executable Statements .. | |
140 * | |
141 * Test the input arguments | |
142 * | |
143 INFO = 0 | |
144 APPLYQ = LSAME( VECT, 'Q' ) | |
145 LEFT = LSAME( SIDE, 'L' ) | |
146 NOTRAN = LSAME( TRANS, 'N' ) | |
147 LQUERY = ( LWORK.EQ.-1 ) | |
148 * | |
149 * NQ is the order of Q or P and NW is the minimum dimension of WORK | |
150 * | |
151 IF( LEFT ) THEN | |
152 NQ = M | |
153 NW = N | |
154 ELSE | |
155 NQ = N | |
156 NW = M | |
157 END IF | |
158 IF( .NOT.APPLYQ .AND. .NOT.LSAME( VECT, 'P' ) ) THEN | |
159 INFO = -1 | |
160 ELSE IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN | |
161 INFO = -2 | |
162 ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN | |
163 INFO = -3 | |
164 ELSE IF( M.LT.0 ) THEN | |
165 INFO = -4 | |
166 ELSE IF( N.LT.0 ) THEN | |
167 INFO = -5 | |
168 ELSE IF( K.LT.0 ) THEN | |
169 INFO = -6 | |
170 ELSE IF( ( APPLYQ .AND. LDA.LT.MAX( 1, NQ ) ) .OR. | |
171 $ ( .NOT.APPLYQ .AND. LDA.LT.MAX( 1, MIN( NQ, K ) ) ) ) | |
172 $ THEN | |
173 INFO = -8 | |
174 ELSE IF( LDC.LT.MAX( 1, M ) ) THEN | |
175 INFO = -11 | |
176 ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THEN | |
177 INFO = -13 | |
178 END IF | |
179 * | |
180 IF( INFO.EQ.0 ) THEN | |
181 IF( APPLYQ ) THEN | |
182 IF( LEFT ) THEN | |
183 NB = ILAENV( 1, 'SORMQR', SIDE // TRANS, M-1, N, M-1, | |
184 $ -1 ) | |
185 ELSE | |
186 NB = ILAENV( 1, 'SORMQR', SIDE // TRANS, M, N-1, N-1, | |
187 $ -1 ) | |
188 END IF | |
189 ELSE | |
190 IF( LEFT ) THEN | |
191 NB = ILAENV( 1, 'SORMLQ', SIDE // TRANS, M-1, N, M-1, | |
192 $ -1 ) | |
193 ELSE | |
194 NB = ILAENV( 1, 'SORMLQ', SIDE // TRANS, M, N-1, N-1, | |
195 $ -1 ) | |
196 END IF | |
197 END IF | |
198 LWKOPT = MAX( 1, NW )*NB | |
199 WORK( 1 ) = LWKOPT | |
200 END IF | |
201 * | |
202 IF( INFO.NE.0 ) THEN | |
203 CALL XERBLA( 'SORMBR', -INFO ) | |
204 RETURN | |
205 ELSE IF( LQUERY ) THEN | |
206 RETURN | |
207 END IF | |
208 * | |
209 * Quick return if possible | |
210 * | |
211 WORK( 1 ) = 1 | |
212 IF( M.EQ.0 .OR. N.EQ.0 ) | |
213 $ RETURN | |
214 * | |
215 IF( APPLYQ ) THEN | |
216 * | |
217 * Apply Q | |
218 * | |
219 IF( NQ.GE.K ) THEN | |
220 * | |
221 * Q was determined by a call to SGEBRD with nq >= k | |
222 * | |
223 CALL SORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, | |
224 $ WORK, LWORK, IINFO ) | |
225 ELSE IF( NQ.GT.1 ) THEN | |
226 * | |
227 * Q was determined by a call to SGEBRD with nq < k | |
228 * | |
229 IF( LEFT ) THEN | |
230 MI = M - 1 | |
231 NI = N | |
232 I1 = 2 | |
233 I2 = 1 | |
234 ELSE | |
235 MI = M | |
236 NI = N - 1 | |
237 I1 = 1 | |
238 I2 = 2 | |
239 END IF | |
240 CALL SORMQR( SIDE, TRANS, MI, NI, NQ-1, A( 2, 1 ), LDA, TAU, | |
241 $ C( I1, I2 ), LDC, WORK, LWORK, IINFO ) | |
242 END IF | |
243 ELSE | |
244 * | |
245 * Apply P | |
246 * | |
247 IF( NOTRAN ) THEN | |
248 TRANST = 'T' | |
249 ELSE | |
250 TRANST = 'N' | |
251 END IF | |
252 IF( NQ.GT.K ) THEN | |
253 * | |
254 * P was determined by a call to SGEBRD with nq > k | |
255 * | |
256 CALL SORMLQ( SIDE, TRANST, M, N, K, A, LDA, TAU, C, LDC, | |
257 $ WORK, LWORK, IINFO ) | |
258 ELSE IF( NQ.GT.1 ) THEN | |
259 * | |
260 * P was determined by a call to SGEBRD with nq <= k | |
261 * | |
262 IF( LEFT ) THEN | |
263 MI = M - 1 | |
264 NI = N | |
265 I1 = 2 | |
266 I2 = 1 | |
267 ELSE | |
268 MI = M | |
269 NI = N - 1 | |
270 I1 = 1 | |
271 I2 = 2 | |
272 END IF | |
273 CALL SORMLQ( SIDE, TRANST, MI, NI, NQ-1, A( 1, 2 ), LDA, | |
274 $ TAU, C( I1, I2 ), LDC, WORK, LWORK, IINFO ) | |
275 END IF | |
276 END IF | |
277 WORK( 1 ) = LWKOPT | |
278 RETURN | |
279 * | |
280 * End of SORMBR | |
281 * | |
282 END |