ScaLAPACK 2.1  2.1
ScaLAPACK: Scalable Linear Algebra PACKage
pdgels.f
Go to the documentation of this file.
1  SUBROUTINE pdgels( TRANS, M, N, NRHS, A, IA, JA, DESCA, B, IB, JB,
2  $ DESCB, WORK, LWORK, INFO )
3 *
4 * -- ScaLAPACK routine (version 1.7) --
5 * University of Tennessee, Knoxville, Oak Ridge National Laboratory,
6 * and University of California, Berkeley.
7 * May 1, 1997
8 *
9 * .. Scalar Arguments ..
10  CHARACTER TRANS
11  INTEGER IA, IB, INFO, JA, JB, LWORK, M, N, NRHS
12 * ..
13 * .. Array Arguments ..
14  INTEGER DESCA( * ), DESCB( * )
15  DOUBLE PRECISION A( * ), B( * ), WORK( * )
16 * ..
17 *
18 * Purpose
19 * =======
20 *
21 * PDGELS solves overdetermined or underdetermined real linear
22 * systems involving an M-by-N matrix sub( A ) = A(IA:IA+M-1,JA:JA+N-1),
23 * or its transpose, using a QR or LQ factorization of sub( A ). It is
24 * assumed that sub( A ) has full rank.
25 *
26 * The following options are provided:
27 *
28 * 1. If TRANS = 'N' and m >= n: find the least squares solution of
29 * an overdetermined system, i.e., solve the least squares problem
30 * minimize || sub( B ) - sub( A )*X ||.
31 *
32 * 2. If TRANS = 'N' and m < n: find the minimum norm solution of
33 * an underdetermined system sub( A ) * X = sub( B ).
34 *
35 * 3. If TRANS = 'T' and m >= n: find the minimum norm solution of
36 * an undetermined system sub( A )**T * X = sub( B ).
37 *
38 * 4. If TRANS = 'T' and m < n: find the least squares solution of
39 * an overdetermined system, i.e., solve the least squares problem
40 * minimize || sub( B ) - sub( A )**T * X ||.
41 *
42 * where sub( B ) denotes B( IB:IB+M-1, JB:JB+NRHS-1 ) when TRANS = 'N'
43 * and B( IB:IB+N-1, JB:JB+NRHS-1 ) otherwise. Several right hand side
44 * vectors b and solution vectors x can be handled in a single call;
45 * When TRANS = 'N', the solution vectors are stored as the columns of
46 * the N-by-NRHS right hand side matrix sub( B ) and the M-by-NRHS
47 * right hand side matrix sub( B ) otherwise.
48 *
49 * Notes
50 * =====
51 *
52 * Each global data object is described by an associated description
53 * vector. This vector stores the information required to establish
54 * the mapping between an object element and its corresponding process
55 * and memory location.
56 *
57 * Let A be a generic term for any 2D block cyclicly distributed array.
58 * Such a global array has an associated description vector DESCA.
59 * In the following comments, the character _ should be read as
60 * "of the global array".
61 *
62 * NOTATION STORED IN EXPLANATION
63 * --------------- -------------- --------------------------------------
64 * DTYPE_A(global) DESCA( DTYPE_ )The descriptor type. In this case,
65 * DTYPE_A = 1.
66 * CTXT_A (global) DESCA( CTXT_ ) The BLACS context handle, indicating
67 * the BLACS process grid A is distribu-
68 * ted over. The context itself is glo-
69 * bal, but the handle (the integer
70 * value) may vary.
71 * M_A (global) DESCA( M_ ) The number of rows in the global
72 * array A.
73 * N_A (global) DESCA( N_ ) The number of columns in the global
74 * array A.
75 * MB_A (global) DESCA( MB_ ) The blocking factor used to distribute
76 * the rows of the array.
77 * NB_A (global) DESCA( NB_ ) The blocking factor used to distribute
78 * the columns of the array.
79 * RSRC_A (global) DESCA( RSRC_ ) The process row over which the first
80 * row of the array A is distributed.
81 * CSRC_A (global) DESCA( CSRC_ ) The process column over which the
82 * first column of the array A is
83 * distributed.
84 * LLD_A (local) DESCA( LLD_ ) The leading dimension of the local
85 * array. LLD_A >= MAX(1,LOCr(M_A)).
86 *
87 * Let K be the number of rows or columns of a distributed matrix,
88 * and assume that its process grid has dimension p x q.
89 * LOCr( K ) denotes the number of elements of K that a process
90 * would receive if K were distributed over the p processes of its
91 * process column.
92 * Similarly, LOCc( K ) denotes the number of elements of K that a
93 * process would receive if K were distributed over the q processes of
94 * its process row.
95 * The values of LOCr() and LOCc() may be determined via a call to the
96 * ScaLAPACK tool function, NUMROC:
97 * LOCr( M ) = NUMROC( M, MB_A, MYROW, RSRC_A, NPROW ),
98 * LOCc( N ) = NUMROC( N, NB_A, MYCOL, CSRC_A, NPCOL ).
99 * An upper bound for these quantities may be computed by:
100 * LOCr( M ) <= ceil( ceil(M/MB_A)/NPROW )*MB_A
101 * LOCc( N ) <= ceil( ceil(N/NB_A)/NPCOL )*NB_A
102 *
103 * Arguments
104 * =========
105 *
106 * TRANS (global input) CHARACTER
107 * = 'N': the linear system involves sub( A );
108 * = 'T': the linear system involves sub( A )**T.
109 *
110 * M (global input) INTEGER
111 * The number of rows to be operated on, i.e. the number of
112 * rows of the distributed submatrix sub( A ). M >= 0.
113 *
114 * N (global input) INTEGER
115 * The number of columns to be operated on, i.e. the number of
116 * columns of the distributed submatrix sub( A ). N >= 0.
117 *
118 * NRHS (global input) INTEGER
119 * The number of right hand sides, i.e. the number of columns
120 * of the distributed submatrices sub( B ) and X. NRHS >= 0.
121 *
122 * A (local input/local output) DOUBLE PRECISION pointer into the
123 * local memory to an array of local dimension
124 * ( LLD_A, LOCc(JA+N-1) ). On entry, the M-by-N matrix A.
125 * if M >= N, sub( A ) is overwritten by details of its QR
126 * factorization as returned by PDGEQRF;
127 * if M < N, sub( A ) is overwritten by details of its LQ
128 * factorization as returned by PDGELQF.
129 *
130 * IA (global input) INTEGER
131 * The row index in the global array A indicating the first
132 * row of sub( A ).
133 *
134 * JA (global input) INTEGER
135 * The column index in the global array A indicating the
136 * first column of sub( A ).
137 *
138 * DESCA (global and local input) INTEGER array of dimension DLEN_.
139 * The array descriptor for the distributed matrix A.
140 *
141 * B (local input/local output) DOUBLE PRECISION pointer into the
142 * local memory to an array of local dimension
143 * (LLD_B, LOCc(JB+NRHS-1)). On entry, this array contains the
144 * local pieces of the distributed matrix B of right hand side
145 * vectors, stored columnwise;
146 * sub( B ) is M-by-NRHS if TRANS='N', and N-by-NRHS otherwise.
147 * On exit, sub( B ) is overwritten by the solution vectors,
148 * stored columnwise: if TRANS = 'N' and M >= N, rows 1 to N
149 * of sub( B ) contain the least squares solution vectors; the
150 * residual sum of squares for the solution in each column is
151 * given by the sum of squares of elements N+1 to M in that
152 * column; if TRANS = 'N' and M < N, rows 1 to N of sub( B )
153 * contain the minimum norm solution vectors; if TRANS = 'T'
154 * and M >= N, rows 1 to M of sub( B ) contain the minimum norm
155 * solution vectors; if TRANS = 'T' and M < N, rows 1 to M of
156 * sub( B ) contain the least squares solution vectors; the
157 * residual sum of squares for the solution in each column is
158 * given by the sum of squares of elements M+1 to N in that
159 * column.
160 *
161 * IB (global input) INTEGER
162 * The row index in the global array B indicating the first
163 * row of sub( B ).
164 *
165 * JB (global input) INTEGER
166 * The column index in the global array B indicating the
167 * first column of sub( B ).
168 *
169 * DESCB (global and local input) INTEGER array of dimension DLEN_.
170 * The array descriptor for the distributed matrix B.
171 *
172 * WORK (local workspace/local output) DOUBLE PRECISION array,
173 * dimension (LWORK)
174 * On exit, WORK(1) returns the minimal and optimal LWORK.
175 *
176 * LWORK (local or global input) INTEGER
177 * The dimension of the array WORK.
178 * LWORK is local input and must be at least
179 * LWORK >= LTAU + MAX( LWF, LWS ) where
180 * If M >= N, then
181 * LTAU = NUMROC( JA+MIN(M,N)-1, NB_A, MYCOL, CSRC_A, NPCOL ),
182 * LWF = NB_A * ( MpA0 + NqA0 + NB_A )
183 * LWS = MAX( (NB_A*(NB_A-1))/2, (NRHSqB0 + MpB0)*NB_A ) +
184 * NB_A * NB_A
185 * Else
186 * LTAU = NUMROC( IA+MIN(M,N)-1, MB_A, MYROW, RSRC_A, NPROW ),
187 * LWF = MB_A * ( MpA0 + NqA0 + MB_A )
188 * LWS = MAX( (MB_A*(MB_A-1))/2, ( NpB0 + MAX( NqA0 +
189 * NUMROC( NUMROC( N+IROFFB, MB_A, 0, 0, NPROW ),
190 * MB_A, 0, 0, LCMP ), NRHSqB0 ) )*MB_A ) +
191 * MB_A * MB_A
192 * End if
193 *
194 * where LCMP = LCM / NPROW with LCM = ILCM( NPROW, NPCOL ),
195 *
196 * IROFFA = MOD( IA-1, MB_A ), ICOFFA = MOD( JA-1, NB_A ),
197 * IAROW = INDXG2P( IA, MB_A, MYROW, RSRC_A, NPROW ),
198 * IACOL = INDXG2P( JA, NB_A, MYCOL, CSRC_A, NPCOL ),
199 * MpA0 = NUMROC( M+IROFFA, MB_A, MYROW, IAROW, NPROW ),
200 * NqA0 = NUMROC( N+ICOFFA, NB_A, MYCOL, IACOL, NPCOL ),
201 *
202 * IROFFB = MOD( IB-1, MB_B ), ICOFFB = MOD( JB-1, NB_B ),
203 * IBROW = INDXG2P( IB, MB_B, MYROW, RSRC_B, NPROW ),
204 * IBCOL = INDXG2P( JB, NB_B, MYCOL, CSRC_B, NPCOL ),
205 * MpB0 = NUMROC( M+IROFFB, MB_B, MYROW, IBROW, NPROW ),
206 * NpB0 = NUMROC( N+IROFFB, MB_B, MYROW, IBROW, NPROW ),
207 * NRHSqB0 = NUMROC( NRHS+ICOFFB, NB_B, MYCOL, IBCOL, NPCOL ),
208 *
209 * ILCM, INDXG2P and NUMROC are ScaLAPACK tool functions;
210 * MYROW, MYCOL, NPROW and NPCOL can be determined by calling
211 * the subroutine BLACS_GRIDINFO.
212 *
213 * If LWORK = -1, then LWORK is global input and a workspace
214 * query is assumed; the routine only calculates the minimum
215 * and optimal size for all work arrays. Each of these
216 * values is returned in the first entry of the corresponding
217 * work array, and no error message is issued by PXERBLA.
218 *
219 * INFO (global output) INTEGER
220 * = 0: successful exit
221 * < 0: If the i-th argument is an array and the j-entry had
222 * an illegal value, then INFO = -(i*100+j), if the i-th
223 * argument is a scalar and had an illegal value, then
224 * INFO = -i.
225 *
226 * =====================================================================
227 *
228 * .. Parameters ..
229  INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
230  $ lld_, mb_, m_, nb_, n_, rsrc_
231  parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
232  $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
233  $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
234  DOUBLE PRECISION ZERO, ONE
235  parameter( zero = 0.0d+0, one = 1.0d+0 )
236 * ..
237 * .. Local Scalars ..
238  LOGICAL LQUERY, TPSD
239  INTEGER BROW, IACOL, IAROW, IASCL, IBCOL, IBROW, IBSCL,
240  $ icoffa, icoffb, ictxt, ipw, iroffa, iroffb,
241  $ lcm, lcmp, ltau, lwf, lwmin, lws, mpa0, mpb0,
242  $ mycol, myrow, npb0, npcol, nprow, nqa0,
243  $ nrhsqb0, scllen
244  DOUBLE PRECISION ANRM, BIGNUM, BNRM, SMLNUM
245 * ..
246 * .. Local Arrays ..
247  INTEGER IDUM1( 2 ), IDUM2( 2 )
248  DOUBLE PRECISION RWORK( 1 )
249 * ..
250 * .. External Functions ..
251  LOGICAL LSAME
252  INTEGER ILCM
253  INTEGER INDXG2P, NUMROC
254  DOUBLE PRECISION PDLAMCH, PDLANGE
255  EXTERNAL ilcm, indxg2p, lsame, numroc, pdlamch,
256  $ pdlange
257 * ..
258 * .. External Subroutines ..
259  EXTERNAL blacs_gridinfo, chk1mat, pchk2mat, pdgelqf,
261  $ pdormlq, pdormqr, pdtrsm, pxerbla
262 * ..
263 * .. Intrinsic Functions ..
264  INTRINSIC dble, ichar, max, min, mod
265 * ..
266 * .. Executable Statements ..
267 *
268 * Get grid parameters
269 *
270  ictxt = desca( ctxt_ )
271  CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
272 *
273 * Test the input parameters
274 *
275  info = 0
276  IF( nprow.EQ.-1 ) THEN
277  info = -( 800 + ctxt_ )
278  ELSE
279  CALL chk1mat( m, 2, n, 3, ia, ja, desca, 8, info )
280  IF ( m .GE. n ) THEN
281  CALL chk1mat( m, 2, nrhs, 4, ib, jb, descb, 12, info )
282  ELSE
283  CALL chk1mat( n, 3, nrhs, 4, ib, jb, descb, 12, info )
284  ENDIF
285  IF( info.EQ.0 ) THEN
286  iroffa = mod( ia-1, desca( mb_ ) )
287  icoffa = mod( ja-1, desca( nb_ ) )
288  iroffb = mod( ib-1, descb( mb_ ) )
289  icoffb = mod( jb-1, descb( nb_ ) )
290  iarow = indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
291  $ nprow )
292  iacol = indxg2p( ia, desca( nb_ ), mycol, desca( csrc_ ),
293  $ npcol )
294  mpa0 = numroc( m+iroffa, desca( mb_ ), myrow, iarow, nprow )
295  nqa0 = numroc( n+icoffa, desca( nb_ ), mycol, iacol, npcol )
296 *
297  ibrow = indxg2p( ib, descb( mb_ ), myrow, descb( rsrc_ ),
298  $ nprow )
299  ibcol = indxg2p( ib, descb( nb_ ), mycol, descb( csrc_ ),
300  $ npcol )
301  nrhsqb0 = numroc( nrhs+icoffb, descb( nb_ ), mycol, ibcol,
302  $ npcol )
303  IF( m.GE.n ) THEN
304  mpb0 = numroc( m+iroffb, descb( mb_ ), myrow, ibrow,
305  $ nprow )
306  ltau = numroc( ja+min(m,n)-1, desca( nb_ ), mycol,
307  $ desca( csrc_ ), npcol )
308  lwf = desca( nb_ ) * ( mpa0 + nqa0 + desca( nb_ ) )
309  lws = max( ( desca( nb_ )*( desca( nb_ ) - 1 ) ) / 2,
310  $ ( mpb0 + nrhsqb0 ) * desca( nb_ ) ) +
311  $ desca( nb_ )*desca( nb_ )
312  ELSE
313  lcm = ilcm( nprow, npcol )
314  lcmp = lcm / nprow
315  npb0 = numroc( n+iroffb, descb( mb_ ), myrow, ibrow,
316  $ nprow )
317  ltau = numroc( ia+min(m,n)-1, desca( mb_ ), myrow,
318  $ desca( rsrc_ ), nprow )
319  lwf = desca( mb_ ) * ( mpa0 + nqa0 + desca( mb_ ) )
320  lws = max( ( desca( mb_ )*( desca( mb_ ) - 1 ) ) / 2,
321  $ ( npb0 + max( nqa0 + numroc( numroc( n+iroffb,
322  $ desca( mb_ ), 0, 0, nprow ), desca( mb_ ), 0, 0,
323  $ lcmp ), nrhsqb0 ) )*desca( mb_ ) ) +
324  $ desca( mb_ ) * desca( mb_ )
325  END IF
326  lwmin = ltau + max( lwf, lws )
327  work( 1 ) = dble( lwmin )
328  lquery = ( lwork.EQ.-1 )
329 *
330  tpsd = .true.
331  IF( lsame( trans, 'N' ) )
332  $ tpsd = .false.
333 *
334  IF( .NOT.( lsame( trans, 'N' ) .OR.
335  $ lsame( trans, 'T' ) ) ) THEN
336  info = -1
337  ELSE IF( m.LT.0 ) THEN
338  info = -2
339  ELSE IF( n.LT.0 ) THEN
340  info = -3
341  ELSE IF( nrhs.LT.0 ) THEN
342  info = -4
343  ELSE IF( m.GE.n .AND. iroffa.NE.iroffb ) THEN
344  info = -10
345  ELSE IF( m.GE.n .AND. iarow.NE.ibrow ) THEN
346  info = -10
347  ELSE IF( m.LT.n .AND. icoffa.NE.iroffb ) THEN
348  info = -10
349  ELSE IF( m.GE.n .AND. desca( mb_ ).NE.descb( mb_ ) ) THEN
350  info = -( 1200 + mb_ )
351  ELSE IF( m.LT.n .AND. desca( nb_ ).NE.descb( mb_ ) ) THEN
352  info = -( 1200 + mb_ )
353  ELSE IF( ictxt.NE.descb( ctxt_ ) ) THEN
354  info = -( 1200 + ctxt_ )
355  ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
356  info = -14
357  END IF
358  END IF
359 *
360  IF( .NOT.tpsd ) THEN
361  idum1( 1 ) = ichar( 'N' )
362  ELSE
363  idum1( 1 ) = ichar( 'T' )
364  END IF
365  idum2( 1 ) = 1
366  IF( lwork.EQ.-1 ) THEN
367  idum1( 2 ) = -1
368  ELSE
369  idum1( 2 ) = 1
370  END IF
371  idum2( 2 ) = 14
372  CALL pchk2mat( m, 2, n, 3, ia, ja, desca, 8, n, 3, nrhs, 4,
373  $ ib, jb, descb, 12, 2, idum1, idum2, info )
374  END IF
375 *
376  IF( info.NE.0 ) THEN
377  CALL pxerbla( ictxt, 'PDGELS', -info )
378  RETURN
379  ELSE IF( lquery ) THEN
380  RETURN
381  END IF
382 *
383 * Quick return if possible
384 *
385  IF( min( m, n, nrhs ).EQ.0 ) THEN
386  CALL pdlaset( 'Full', max( m, n ), nrhs, zero, zero, b,
387  $ ib, jb, descb )
388  RETURN
389  END IF
390 *
391 * Get machine parameters
392 *
393  smlnum = pdlamch( ictxt, 'S' )
394  smlnum = smlnum / pdlamch( ictxt, 'P' )
395  bignum = one / smlnum
396  CALL pdlabad( ictxt, smlnum, bignum )
397 *
398 * Scale A, B if max entry outside range [SMLNUM,BIGNUM]
399 *
400  anrm = pdlange( 'M', m, n, a, ia, ja, desca, rwork )
401  iascl = 0
402  IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
403 *
404 * Scale matrix norm up to SMLNUM
405 *
406  CALL pdlascl( 'G', anrm, smlnum, m, n, a, ia, ja, desca,
407  $ info )
408  iascl = 1
409  ELSE IF( anrm.GT.bignum ) THEN
410 *
411 * Scale matrix norm down to BIGNUM
412 *
413  CALL pdlascl( 'G', anrm, bignum, m, n, a, ia, ja, desca,
414  $ info )
415  iascl = 2
416  ELSE IF( anrm.EQ.zero ) THEN
417 *
418 * Matrix all zero. Return zero solution.
419 *
420  CALL pdlaset( 'F', max( m, n ), nrhs, zero, zero, b, ib, jb,
421  $ descb )
422  GO TO 10
423  END IF
424 *
425  brow = m
426  IF( tpsd )
427  $ brow = n
428 *
429  bnrm = pdlange( 'M', brow, nrhs, b, ib, jb, descb, rwork )
430 *
431  ibscl = 0
432  IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
433 *
434 * Scale matrix norm up to SMLNUM
435 *
436  CALL pdlascl( 'G', bnrm, smlnum, brow, nrhs, b, ib, jb,
437  $ descb, info )
438  ibscl = 1
439  ELSE IF( bnrm.GT.bignum ) THEN
440 *
441 * Scale matrix norm down to BIGNUM
442 *
443  CALL pdlascl( 'G', bnrm, bignum, brow, nrhs, b, ib, jb,
444  $ descb, info )
445  ibscl = 2
446  END IF
447 *
448  ipw = ltau + 1
449 *
450  IF( m.GE.n ) THEN
451 *
452 * compute QR factorization of A
453 *
454  CALL pdgeqrf( m, n, a, ia, ja, desca, work, work( ipw ),
455  $ lwork-ltau, info )
456 *
457 * workspace at least N, optimally N*NB
458 *
459  IF( .NOT.tpsd ) THEN
460 *
461 * Least-Squares Problem min || A * X - B ||
462 *
463 * B(IB:IB+M-1,JB:JB+NRHS-1) := Q' * B(IB:IB+M-1,JB:JB+NRHS-1)
464 *
465  CALL pdormqr( 'Left', 'Transpose', m, nrhs, n, a, ia, ja,
466  $ desca, work, b, ib, jb, descb, work( ipw ),
467  $ lwork-ltau, info )
468 *
469 * workspace at least NRHS, optimally NRHS*NB
470 *
471 * B(IB:IB+N-1,JB:JB+NRHS-1) := inv(R) *
472 * B(IB:IB+N-1,JB:JB+NRHS-1)
473 *
474  CALL pdtrsm( 'Left', 'Upper', 'No transpose', 'Non-unit', n,
475  $ nrhs, one, a, ia, ja, desca, b, ib, jb, descb )
476 *
477  scllen = n
478 *
479  ELSE
480 *
481 * Overdetermined system of equations sub( A )' * X = sub( B )
482 *
483 * sub( B ) := inv(R') * sub( B )
484 *
485  CALL pdtrsm( 'Left', 'Upper', 'Transpose', 'Non-unit', n,
486  $ nrhs, one, a, ia, ja, desca, b, ib, jb, descb )
487 *
488 * B(IB+N:IB+M-1,JB:JB+NRHS-1) = ZERO
489 *
490  CALL pdlaset( 'All', m-n, nrhs, zero, zero, b, ib+n, jb,
491  $ descb )
492 *
493 * B(IB:IB+M-1,JB:JB+NRHS-1) := Q(1:N,:) *
494 * B(IB:IB+N-1,JB:JB+NRHS-1)
495 *
496  CALL pdormqr( 'Left', 'No transpose', m, nrhs, n, a, ia, ja,
497  $ desca, work, b, ib, jb, descb, work( ipw ),
498  $ lwork-ltau, info )
499 *
500 * workspace at least NRHS, optimally NRHS*NB
501 *
502  scllen = m
503 *
504  END IF
505 *
506  ELSE
507 *
508 * Compute LQ factorization of sub( A )
509 *
510  CALL pdgelqf( m, n, a, ia, ja, desca, work, work( ipw ),
511  $ lwork-ltau, info )
512 *
513 * workspace at least M, optimally M*NB.
514 *
515  IF( .NOT.tpsd ) THEN
516 *
517 * underdetermined system of equations sub( A ) * X = sub( B )
518 *
519 * B(IB:IB+M-1,JB:JB+NRHS-1) := inv(L) *
520 * B(IB:IB+M-1,JB:JB+NRHS-1)
521 *
522  CALL pdtrsm( 'Left', 'Lower', 'No transpose', 'Non-unit', m,
523  $ nrhs, one, a, ia, ja, desca, b, ib, jb, descb )
524 *
525 * B(IB+M:IB+N-1,JB:JB+NRHS-1) = 0
526 *
527  CALL pdlaset( 'All', n-m, nrhs, zero, zero, b, ib+m, jb,
528  $ descb )
529 *
530 * B(IB:IB+N-1,JB:JB+NRHS-1) := Q(1:N,:)' *
531 * B(IB:IB+M-1,JB:JB+NRHS-1)
532 *
533  CALL pdormlq( 'Left', 'Transpose', n, nrhs, m, a, ia, ja,
534  $ desca, work, b, ib, jb, descb, work( ipw ),
535  $ lwork-ltau, info )
536 *
537 * workspace at least NRHS, optimally NRHS*NB
538 *
539  scllen = n
540 *
541  ELSE
542 *
543 * overdetermined system min || A' * X - B ||
544 *
545 * B(IB:IB+N-1,JB:JB+NRHS-1) := Q * B(IB:IB+N-1,JB:JB+NRHS-1)
546 *
547  CALL pdormlq( 'Left', 'No transpose', n, nrhs, m, a, ia, ja,
548  $ desca, work, b, ib, jb, descb, work( ipw ),
549  $ lwork-ltau, info )
550 *
551 * workspace at least NRHS, optimally NRHS*NB
552 *
553 * B(IB:IB+M-1,JB:JB+NRHS-1) := inv(L') *
554 * B(IB:IB+M-1,JB:JB+NRHS-1)
555 *
556  CALL pdtrsm( 'Left', 'Lower', 'Transpose', 'Non-unit', m,
557  $ nrhs, one, a, ia, ja, desca, b, ib, jb, descb )
558 *
559  scllen = m
560 *
561  END IF
562 *
563  END IF
564 *
565 * Undo scaling
566 *
567  IF( iascl.EQ.1 ) THEN
568  CALL pdlascl( 'G', anrm, smlnum, scllen, nrhs, b, ib, jb,
569  $ descb, info )
570  ELSE IF( iascl.EQ.2 ) THEN
571  CALL pdlascl( 'G', anrm, bignum, scllen, nrhs, b, ib, jb,
572  $ descb, info )
573  END IF
574  IF( ibscl.EQ.1 ) THEN
575  CALL pdlascl( 'G', smlnum, bnrm, scllen, nrhs, b, ib, jb,
576  $ descb, info )
577  ELSE IF( ibscl.EQ.2 ) THEN
578  CALL pdlascl( 'G', bignum, bnrm, scllen, nrhs, b, ib, jb,
579  $ descb, info )
580  END IF
581 *
582  10 CONTINUE
583 *
584  work( 1 ) = dble( lwmin )
585 *
586  RETURN
587 *
588 * End of PDGELS
589 *
590  END
max
#define max(A, B)
Definition: pcgemr.c:180
pdlabad
subroutine pdlabad(ICTXT, SMALL, LARGE)
Definition: pdlabad.f:2
pdormqr
subroutine pdormqr(SIDE, TRANS, M, N, K, A, IA, JA, DESCA, TAU, C, IC, JC, DESCC, WORK, LWORK, INFO)
Definition: pdormqr.f:3
pchk2mat
subroutine pchk2mat(MA, MAPOS0, NA, NAPOS0, IA, JA, DESCA, DESCAPOS0, MB, MBPOS0, NB, NBPOS0, IB, JB, DESCB, DESCBPOS0, NEXTRA, EX, EXPOS, INFO)
Definition: pchkxmat.f:175
pdlascl
subroutine pdlascl(TYPE, CFROM, CTO, M, N, A, IA, JA, DESCA, INFO)
Definition: pdlascl.f:3
pdlaset
subroutine pdlaset(UPLO, M, N, ALPHA, BETA, A, IA, JA, DESCA)
Definition: pdblastst.f:6862
pdgeqrf
subroutine pdgeqrf(M, N, A, IA, JA, DESCA, TAU, WORK, LWORK, INFO)
Definition: pdgeqrf.f:3
chk1mat
subroutine chk1mat(MA, MAPOS0, NA, NAPOS0, IA, JA, DESCA, DESCAPOS0, INFO)
Definition: chk1mat.f:3
pdgels
subroutine pdgels(TRANS, M, N, NRHS, A, IA, JA, DESCA, B, IB, JB, DESCB, WORK, LWORK, INFO)
Definition: pdgels.f:3
pxerbla
subroutine pxerbla(ICTXT, SRNAME, INFO)
Definition: pxerbla.f:2
pdgelqf
subroutine pdgelqf(M, N, A, IA, JA, DESCA, TAU, WORK, LWORK, INFO)
Definition: pdgelqf.f:3
pdormlq
subroutine pdormlq(SIDE, TRANS, M, N, K, A, IA, JA, DESCA, TAU, C, IC, JC, DESCC, WORK, LWORK, INFO)
Definition: pdormlq.f:3
min
#define min(A, B)
Definition: pcgemr.c:181