Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/mathlibs/src/lapack/cgels.f
5196 views
1
SUBROUTINE CGELS( TRANS, M, N, NRHS, A, LDA, B, LDB, WORK, LWORK,
2
$ INFO )
3
*
4
* -- LAPACK driver routine (version 3.0) --
5
* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
6
* Courant Institute, Argonne National Lab, and Rice University
7
* June 30, 1999
8
*
9
* .. Scalar Arguments ..
10
CHARACTER TRANS
11
INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS
12
* ..
13
* .. Array Arguments ..
14
COMPLEX A( LDA, * ), B( LDB, * ), WORK( * )
15
* ..
16
*
17
* Purpose
18
* =======
19
*
20
* CGELS solves overdetermined or underdetermined complex linear systems
21
* involving an M-by-N matrix A, or its conjugate-transpose, using a QR
22
* or LQ factorization of A. It is assumed that A has full rank.
23
*
24
* The following options are provided:
25
*
26
* 1. If TRANS = 'N' and m >= n: find the least squares solution of
27
* an overdetermined system, i.e., solve the least squares problem
28
* minimize || B - A*X ||.
29
*
30
* 2. If TRANS = 'N' and m < n: find the minimum norm solution of
31
* an underdetermined system A * X = B.
32
*
33
* 3. If TRANS = 'C' and m >= n: find the minimum norm solution of
34
* an undetermined system A**H * X = B.
35
*
36
* 4. If TRANS = 'C' and m < n: find the least squares solution of
37
* an overdetermined system, i.e., solve the least squares problem
38
* minimize || B - A**H * X ||.
39
*
40
* Several right hand side vectors b and solution vectors x can be
41
* handled in a single call; they are stored as the columns of the
42
* M-by-NRHS right hand side matrix B and the N-by-NRHS solution
43
* matrix X.
44
*
45
* Arguments
46
* =========
47
*
48
* TRANS (input) CHARACTER
49
* = 'N': the linear system involves A;
50
* = 'C': the linear system involves A**H.
51
*
52
* M (input) INTEGER
53
* The number of rows of the matrix A. M >= 0.
54
*
55
* N (input) INTEGER
56
* The number of columns of the matrix A. N >= 0.
57
*
58
* NRHS (input) INTEGER
59
* The number of right hand sides, i.e., the number of
60
* columns of the matrices B and X. NRHS >= 0.
61
*
62
* A (input/output) COMPLEX array, dimension (LDA,N)
63
* On entry, the M-by-N matrix A.
64
* if M >= N, A is overwritten by details of its QR
65
* factorization as returned by CGEQRF;
66
* if M < N, A is overwritten by details of its LQ
67
* factorization as returned by CGELQF.
68
*
69
* LDA (input) INTEGER
70
* The leading dimension of the array A. LDA >= max(1,M).
71
*
72
* B (input/output) COMPLEX array, dimension (LDB,NRHS)
73
* On entry, the matrix B of right hand side vectors, stored
74
* columnwise; B is M-by-NRHS if TRANS = 'N', or N-by-NRHS
75
* if TRANS = 'C'.
76
* On exit, B is overwritten by the solution vectors, stored
77
* columnwise:
78
* if TRANS = 'N' and m >= n, rows 1 to n of B contain the least
79
* squares solution vectors; the residual sum of squares for the
80
* solution in each column is given by the sum of squares of
81
* elements N+1 to M in that column;
82
* if TRANS = 'N' and m < n, rows 1 to N of B contain the
83
* minimum norm solution vectors;
84
* if TRANS = 'C' and m >= n, rows 1 to M of B contain the
85
* minimum norm solution vectors;
86
* if TRANS = 'C' and m < n, rows 1 to M of B contain the
87
* least squares solution vectors; the residual sum of squares
88
* for the solution in each column is given by the sum of
89
* squares of elements M+1 to N in that column.
90
*
91
* LDB (input) INTEGER
92
* The leading dimension of the array B. LDB >= MAX(1,M,N).
93
*
94
* WORK (workspace/output) COMPLEX array, dimension (LWORK)
95
* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
96
*
97
* LWORK (input) INTEGER
98
* The dimension of the array WORK.
99
* LWORK >= max( 1, MN + max( MN, NRHS ) ).
100
* For optimal performance,
101
* LWORK >= max( 1, MN + max( MN, NRHS )*NB ).
102
* where MN = min(M,N) and NB is the optimum block size.
103
*
104
* If LWORK = -1, then a workspace query is assumed; the routine
105
* only calculates the optimal size of the WORK array, returns
106
* this value as the first entry of the WORK array, and no error
107
* message related to LWORK is issued by XERBLA.
108
*
109
* INFO (output) INTEGER
110
* = 0: successful exit
111
* < 0: if INFO = -i, the i-th argument had an illegal value
112
*
113
* =====================================================================
114
*
115
* .. Parameters ..
116
REAL ZERO, ONE
117
PARAMETER ( ZERO = 0.0E+0, ONE = 1.0E+0 )
118
COMPLEX CZERO, CONE
119
PARAMETER ( CZERO = ( 0.0E+0, 0.0E+0 ),
120
$ CONE = ( 1.0E+0, 0.0E+0 ) )
121
* ..
122
* .. Local Scalars ..
123
LOGICAL LQUERY, TPSD
124
INTEGER BROW, I, IASCL, IBSCL, J, MN, NB, SCLLEN, WSIZE
125
REAL ANRM, BIGNUM, BNRM, SMLNUM
126
* ..
127
* .. Local Arrays ..
128
REAL RWORK( 1 )
129
* ..
130
* .. External Functions ..
131
LOGICAL LSAME
132
INTEGER ILAENV
133
REAL CLANGE, SLAMCH
134
EXTERNAL LSAME, ILAENV, CLANGE, SLAMCH
135
* ..
136
* .. External Subroutines ..
137
EXTERNAL CGELQF, CGEQRF, CLASCL, CLASET, CTRSM, CUNMLQ,
138
$ CUNMQR, SLABAD, XERBLA
139
* ..
140
* .. Intrinsic Functions ..
141
INTRINSIC MAX, MIN, REAL
142
* ..
143
* .. Executable Statements ..
144
*
145
* Test the input arguments.
146
*
147
INFO = 0
148
MN = MIN( M, N )
149
LQUERY = ( LWORK.EQ.-1 )
150
IF( .NOT.( LSAME( TRANS, 'N' ) .OR. LSAME( TRANS, 'C' ) ) ) THEN
151
INFO = -1
152
ELSE IF( M.LT.0 ) THEN
153
INFO = -2
154
ELSE IF( N.LT.0 ) THEN
155
INFO = -3
156
ELSE IF( NRHS.LT.0 ) THEN
157
INFO = -4
158
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
159
INFO = -6
160
ELSE IF( LDB.LT.MAX( 1, M, N ) ) THEN
161
INFO = -8
162
ELSE IF( LWORK.LT.MAX( 1, MN+MAX( MN, NRHS ) ) .AND.
163
$ .NOT.LQUERY ) THEN
164
INFO = -10
165
END IF
166
*
167
* Figure out optimal block size
168
*
169
IF( INFO.EQ.0 .OR. INFO.EQ.-10 ) THEN
170
*
171
TPSD = .TRUE.
172
IF( LSAME( TRANS, 'N' ) )
173
$ TPSD = .FALSE.
174
*
175
IF( M.GE.N ) THEN
176
NB = ILAENV( 1, 'CGEQRF', ' ', M, N, -1, -1 )
177
IF( TPSD ) THEN
178
NB = MAX( NB, ILAENV( 1, 'CUNMQR', 'LN', M, NRHS, N,
179
$ -1 ) )
180
ELSE
181
NB = MAX( NB, ILAENV( 1, 'CUNMQR', 'LC', M, NRHS, N,
182
$ -1 ) )
183
END IF
184
ELSE
185
NB = ILAENV( 1, 'CGELQF', ' ', M, N, -1, -1 )
186
IF( TPSD ) THEN
187
NB = MAX( NB, ILAENV( 1, 'CUNMLQ', 'LC', N, NRHS, M,
188
$ -1 ) )
189
ELSE
190
NB = MAX( NB, ILAENV( 1, 'CUNMLQ', 'LN', N, NRHS, M,
191
$ -1 ) )
192
END IF
193
END IF
194
*
195
WSIZE = MAX( 1, MN + MAX( MN, NRHS )*NB )
196
WORK( 1 ) = REAL( WSIZE )
197
*
198
END IF
199
*
200
IF( INFO.NE.0 ) THEN
201
CALL XERBLA( 'CGELS ', -INFO )
202
RETURN
203
ELSE IF( LQUERY ) THEN
204
RETURN
205
END IF
206
*
207
* Quick return if possible
208
*
209
IF( MIN( M, N, NRHS ).EQ.0 ) THEN
210
CALL CLASET( 'Full', MAX( M, N ), NRHS, CZERO, CZERO, B, LDB )
211
RETURN
212
END IF
213
*
214
* Get machine parameters
215
*
216
SMLNUM = SLAMCH( 'S' ) / SLAMCH( 'P' )
217
BIGNUM = ONE / SMLNUM
218
CALL SLABAD( SMLNUM, BIGNUM )
219
*
220
* Scale A, B if max element outside range [SMLNUM,BIGNUM]
221
*
222
ANRM = CLANGE( 'M', M, N, A, LDA, RWORK )
223
IASCL = 0
224
IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
225
*
226
* Scale matrix norm up to SMLNUM
227
*
228
CALL CLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
229
IASCL = 1
230
ELSE IF( ANRM.GT.BIGNUM ) THEN
231
*
232
* Scale matrix norm down to BIGNUM
233
*
234
CALL CLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
235
IASCL = 2
236
ELSE IF( ANRM.EQ.ZERO ) THEN
237
*
238
* Matrix all zero. Return zero solution.
239
*
240
CALL CLASET( 'F', MAX( M, N ), NRHS, CZERO, CZERO, B, LDB )
241
GO TO 50
242
END IF
243
*
244
BROW = M
245
IF( TPSD )
246
$ BROW = N
247
BNRM = CLANGE( 'M', BROW, NRHS, B, LDB, RWORK )
248
IBSCL = 0
249
IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
250
*
251
* Scale matrix norm up to SMLNUM
252
*
253
CALL CLASCL( 'G', 0, 0, BNRM, SMLNUM, BROW, NRHS, B, LDB,
254
$ INFO )
255
IBSCL = 1
256
ELSE IF( BNRM.GT.BIGNUM ) THEN
257
*
258
* Scale matrix norm down to BIGNUM
259
*
260
CALL CLASCL( 'G', 0, 0, BNRM, BIGNUM, BROW, NRHS, B, LDB,
261
$ INFO )
262
IBSCL = 2
263
END IF
264
*
265
IF( M.GE.N ) THEN
266
*
267
* compute QR factorization of A
268
*
269
CALL CGEQRF( M, N, A, LDA, WORK( 1 ), WORK( MN+1 ), LWORK-MN,
270
$ INFO )
271
*
272
* workspace at least N, optimally N*NB
273
*
274
IF( .NOT.TPSD ) THEN
275
*
276
* Least-Squares Problem min || A * X - B ||
277
*
278
* B(1:M,1:NRHS) := Q' * B(1:M,1:NRHS)
279
*
280
CALL CUNMQR( 'Left', 'Conjugate transpose', M, NRHS, N, A,
281
$ LDA, WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,
282
$ INFO )
283
*
284
* workspace at least NRHS, optimally NRHS*NB
285
*
286
* B(1:N,1:NRHS) := inv(R) * B(1:N,1:NRHS)
287
*
288
CALL CTRSM( 'Left', 'Upper', 'No transpose', 'Non-unit', N,
289
$ NRHS, CONE, A, LDA, B, LDB )
290
*
291
SCLLEN = N
292
*
293
ELSE
294
*
295
* Overdetermined system of equations A' * X = B
296
*
297
* B(1:N,1:NRHS) := inv(R') * B(1:N,1:NRHS)
298
*
299
CALL CTRSM( 'Left', 'Upper', 'Conjugate transpose',
300
$ 'Non-unit', N, NRHS, CONE, A, LDA, B, LDB )
301
*
302
* B(N+1:M,1:NRHS) = ZERO
303
*
304
DO 20 J = 1, NRHS
305
DO 10 I = N + 1, M
306
B( I, J ) = CZERO
307
10 CONTINUE
308
20 CONTINUE
309
*
310
* B(1:M,1:NRHS) := Q(1:N,:) * B(1:N,1:NRHS)
311
*
312
CALL CUNMQR( 'Left', 'No transpose', M, NRHS, N, A, LDA,
313
$ WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,
314
$ INFO )
315
*
316
* workspace at least NRHS, optimally NRHS*NB
317
*
318
SCLLEN = M
319
*
320
END IF
321
*
322
ELSE
323
*
324
* Compute LQ factorization of A
325
*
326
CALL CGELQF( M, N, A, LDA, WORK( 1 ), WORK( MN+1 ), LWORK-MN,
327
$ INFO )
328
*
329
* workspace at least M, optimally M*NB.
330
*
331
IF( .NOT.TPSD ) THEN
332
*
333
* underdetermined system of equations A * X = B
334
*
335
* B(1:M,1:NRHS) := inv(L) * B(1:M,1:NRHS)
336
*
337
CALL CTRSM( 'Left', 'Lower', 'No transpose', 'Non-unit', M,
338
$ NRHS, CONE, A, LDA, B, LDB )
339
*
340
* B(M+1:N,1:NRHS) = 0
341
*
342
DO 40 J = 1, NRHS
343
DO 30 I = M + 1, N
344
B( I, J ) = CZERO
345
30 CONTINUE
346
40 CONTINUE
347
*
348
* B(1:N,1:NRHS) := Q(1:N,:)' * B(1:M,1:NRHS)
349
*
350
CALL CUNMLQ( 'Left', 'Conjugate transpose', N, NRHS, M, A,
351
$ LDA, WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,
352
$ INFO )
353
*
354
* workspace at least NRHS, optimally NRHS*NB
355
*
356
SCLLEN = N
357
*
358
ELSE
359
*
360
* overdetermined system min || A' * X - B ||
361
*
362
* B(1:N,1:NRHS) := Q * B(1:N,1:NRHS)
363
*
364
CALL CUNMLQ( 'Left', 'No transpose', N, NRHS, M, A, LDA,
365
$ WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,
366
$ INFO )
367
*
368
* workspace at least NRHS, optimally NRHS*NB
369
*
370
* B(1:M,1:NRHS) := inv(L') * B(1:M,1:NRHS)
371
*
372
CALL CTRSM( 'Left', 'Lower', 'Conjugate transpose',
373
$ 'Non-unit', M, NRHS, CONE, A, LDA, B, LDB )
374
*
375
SCLLEN = M
376
*
377
END IF
378
*
379
END IF
380
*
381
* Undo scaling
382
*
383
IF( IASCL.EQ.1 ) THEN
384
CALL CLASCL( 'G', 0, 0, ANRM, SMLNUM, SCLLEN, NRHS, B, LDB,
385
$ INFO )
386
ELSE IF( IASCL.EQ.2 ) THEN
387
CALL CLASCL( 'G', 0, 0, ANRM, BIGNUM, SCLLEN, NRHS, B, LDB,
388
$ INFO )
389
END IF
390
IF( IBSCL.EQ.1 ) THEN
391
CALL CLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB,
392
$ INFO )
393
ELSE IF( IBSCL.EQ.2 ) THEN
394
CALL CLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB,
395
$ INFO )
396
END IF
397
*
398
50 CONTINUE
399
WORK( 1 ) = REAL( WSIZE )
400
*
401
RETURN
402
*
403
* End of CGELS
404
*
405
END
406
407