Annotation of rpl/lapack/lapack/dlals0.f, revision 1.8
1.8 ! bertrand 1: *> \brief \b DLALS0
! 2: *
! 3: * =========== DOCUMENTATION ===========
! 4: *
! 5: * Online html documentation available at
! 6: * http://www.netlib.org/lapack/explore-html/
! 7: *
! 8: *> \htmlonly
! 9: *> Download DLALS0 + dependencies
! 10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlals0.f">
! 11: *> [TGZ]</a>
! 12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlals0.f">
! 13: *> [ZIP]</a>
! 14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlals0.f">
! 15: *> [TXT]</a>
! 16: *> \endhtmlonly
! 17: *
! 18: * Definition:
! 19: * ===========
! 20: *
! 21: * SUBROUTINE DLALS0( ICOMPQ, NL, NR, SQRE, NRHS, B, LDB, BX, LDBX,
! 22: * PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM, LDGNUM,
! 23: * POLES, DIFL, DIFR, Z, K, C, S, WORK, INFO )
! 24: *
! 25: * .. Scalar Arguments ..
! 26: * INTEGER GIVPTR, ICOMPQ, INFO, K, LDB, LDBX, LDGCOL,
! 27: * $ LDGNUM, NL, NR, NRHS, SQRE
! 28: * DOUBLE PRECISION C, S
! 29: * ..
! 30: * .. Array Arguments ..
! 31: * INTEGER GIVCOL( LDGCOL, * ), PERM( * )
! 32: * DOUBLE PRECISION B( LDB, * ), BX( LDBX, * ), DIFL( * ),
! 33: * $ DIFR( LDGNUM, * ), GIVNUM( LDGNUM, * ),
! 34: * $ POLES( LDGNUM, * ), WORK( * ), Z( * )
! 35: * ..
! 36: *
! 37: *
! 38: *> \par Purpose:
! 39: * =============
! 40: *>
! 41: *> \verbatim
! 42: *>
! 43: *> DLALS0 applies back the multiplying factors of either the left or the
! 44: *> right singular vector matrix of a diagonal matrix appended by a row
! 45: *> to the right hand side matrix B in solving the least squares problem
! 46: *> using the divide-and-conquer SVD approach.
! 47: *>
! 48: *> For the left singular vector matrix, three types of orthogonal
! 49: *> matrices are involved:
! 50: *>
! 51: *> (1L) Givens rotations: the number of such rotations is GIVPTR; the
! 52: *> pairs of columns/rows they were applied to are stored in GIVCOL;
! 53: *> and the C- and S-values of these rotations are stored in GIVNUM.
! 54: *>
! 55: *> (2L) Permutation. The (NL+1)-st row of B is to be moved to the first
! 56: *> row, and for J=2:N, PERM(J)-th row of B is to be moved to the
! 57: *> J-th row.
! 58: *>
! 59: *> (3L) The left singular vector matrix of the remaining matrix.
! 60: *>
! 61: *> For the right singular vector matrix, four types of orthogonal
! 62: *> matrices are involved:
! 63: *>
! 64: *> (1R) The right singular vector matrix of the remaining matrix.
! 65: *>
! 66: *> (2R) If SQRE = 1, one extra Givens rotation to generate the right
! 67: *> null space.
! 68: *>
! 69: *> (3R) The inverse transformation of (2L).
! 70: *>
! 71: *> (4R) The inverse transformation of (1L).
! 72: *> \endverbatim
! 73: *
! 74: * Arguments:
! 75: * ==========
! 76: *
! 77: *> \param[in] ICOMPQ
! 78: *> \verbatim
! 79: *> ICOMPQ is INTEGER
! 80: *> Specifies whether singular vectors are to be computed in
! 81: *> factored form:
! 82: *> = 0: Left singular vector matrix.
! 83: *> = 1: Right singular vector matrix.
! 84: *> \endverbatim
! 85: *>
! 86: *> \param[in] NL
! 87: *> \verbatim
! 88: *> NL is INTEGER
! 89: *> The row dimension of the upper block. NL >= 1.
! 90: *> \endverbatim
! 91: *>
! 92: *> \param[in] NR
! 93: *> \verbatim
! 94: *> NR is INTEGER
! 95: *> The row dimension of the lower block. NR >= 1.
! 96: *> \endverbatim
! 97: *>
! 98: *> \param[in] SQRE
! 99: *> \verbatim
! 100: *> SQRE is INTEGER
! 101: *> = 0: the lower block is an NR-by-NR square matrix.
! 102: *> = 1: the lower block is an NR-by-(NR+1) rectangular matrix.
! 103: *>
! 104: *> The bidiagonal matrix has row dimension N = NL + NR + 1,
! 105: *> and column dimension M = N + SQRE.
! 106: *> \endverbatim
! 107: *>
! 108: *> \param[in] NRHS
! 109: *> \verbatim
! 110: *> NRHS is INTEGER
! 111: *> The number of columns of B and BX. NRHS must be at least 1.
! 112: *> \endverbatim
! 113: *>
! 114: *> \param[in,out] B
! 115: *> \verbatim
! 116: *> B is DOUBLE PRECISION array, dimension ( LDB, NRHS )
! 117: *> On input, B contains the right hand sides of the least
! 118: *> squares problem in rows 1 through M. On output, B contains
! 119: *> the solution X in rows 1 through N.
! 120: *> \endverbatim
! 121: *>
! 122: *> \param[in] LDB
! 123: *> \verbatim
! 124: *> LDB is INTEGER
! 125: *> The leading dimension of B. LDB must be at least
! 126: *> max(1,MAX( M, N ) ).
! 127: *> \endverbatim
! 128: *>
! 129: *> \param[out] BX
! 130: *> \verbatim
! 131: *> BX is DOUBLE PRECISION array, dimension ( LDBX, NRHS )
! 132: *> \endverbatim
! 133: *>
! 134: *> \param[in] LDBX
! 135: *> \verbatim
! 136: *> LDBX is INTEGER
! 137: *> The leading dimension of BX.
! 138: *> \endverbatim
! 139: *>
! 140: *> \param[in] PERM
! 141: *> \verbatim
! 142: *> PERM is INTEGER array, dimension ( N )
! 143: *> The permutations (from deflation and sorting) applied
! 144: *> to the two blocks.
! 145: *> \endverbatim
! 146: *>
! 147: *> \param[in] GIVPTR
! 148: *> \verbatim
! 149: *> GIVPTR is INTEGER
! 150: *> The number of Givens rotations which took place in this
! 151: *> subproblem.
! 152: *> \endverbatim
! 153: *>
! 154: *> \param[in] GIVCOL
! 155: *> \verbatim
! 156: *> GIVCOL is INTEGER array, dimension ( LDGCOL, 2 )
! 157: *> Each pair of numbers indicates a pair of rows/columns
! 158: *> involved in a Givens rotation.
! 159: *> \endverbatim
! 160: *>
! 161: *> \param[in] LDGCOL
! 162: *> \verbatim
! 163: *> LDGCOL is INTEGER
! 164: *> The leading dimension of GIVCOL, must be at least N.
! 165: *> \endverbatim
! 166: *>
! 167: *> \param[in] GIVNUM
! 168: *> \verbatim
! 169: *> GIVNUM is DOUBLE PRECISION array, dimension ( LDGNUM, 2 )
! 170: *> Each number indicates the C or S value used in the
! 171: *> corresponding Givens rotation.
! 172: *> \endverbatim
! 173: *>
! 174: *> \param[in] LDGNUM
! 175: *> \verbatim
! 176: *> LDGNUM is INTEGER
! 177: *> The leading dimension of arrays DIFR, POLES and
! 178: *> GIVNUM, must be at least K.
! 179: *> \endverbatim
! 180: *>
! 181: *> \param[in] POLES
! 182: *> \verbatim
! 183: *> POLES is DOUBLE PRECISION array, dimension ( LDGNUM, 2 )
! 184: *> On entry, POLES(1:K, 1) contains the new singular
! 185: *> values obtained from solving the secular equation, and
! 186: *> POLES(1:K, 2) is an array containing the poles in the secular
! 187: *> equation.
! 188: *> \endverbatim
! 189: *>
! 190: *> \param[in] DIFL
! 191: *> \verbatim
! 192: *> DIFL is DOUBLE PRECISION array, dimension ( K ).
! 193: *> On entry, DIFL(I) is the distance between I-th updated
! 194: *> (undeflated) singular value and the I-th (undeflated) old
! 195: *> singular value.
! 196: *> \endverbatim
! 197: *>
! 198: *> \param[in] DIFR
! 199: *> \verbatim
! 200: *> DIFR is DOUBLE PRECISION array, dimension ( LDGNUM, 2 ).
! 201: *> On entry, DIFR(I, 1) contains the distances between I-th
! 202: *> updated (undeflated) singular value and the I+1-th
! 203: *> (undeflated) old singular value. And DIFR(I, 2) is the
! 204: *> normalizing factor for the I-th right singular vector.
! 205: *> \endverbatim
! 206: *>
! 207: *> \param[in] Z
! 208: *> \verbatim
! 209: *> Z is DOUBLE PRECISION array, dimension ( K )
! 210: *> Contain the components of the deflation-adjusted updating row
! 211: *> vector.
! 212: *> \endverbatim
! 213: *>
! 214: *> \param[in] K
! 215: *> \verbatim
! 216: *> K is INTEGER
! 217: *> Contains the dimension of the non-deflated matrix,
! 218: *> This is the order of the related secular equation. 1 <= K <=N.
! 219: *> \endverbatim
! 220: *>
! 221: *> \param[in] C
! 222: *> \verbatim
! 223: *> C is DOUBLE PRECISION
! 224: *> C contains garbage if SQRE =0 and the C-value of a Givens
! 225: *> rotation related to the right null space if SQRE = 1.
! 226: *> \endverbatim
! 227: *>
! 228: *> \param[in] S
! 229: *> \verbatim
! 230: *> S is DOUBLE PRECISION
! 231: *> S contains garbage if SQRE =0 and the S-value of a Givens
! 232: *> rotation related to the right null space if SQRE = 1.
! 233: *> \endverbatim
! 234: *>
! 235: *> \param[out] WORK
! 236: *> \verbatim
! 237: *> WORK is DOUBLE PRECISION array, dimension ( K )
! 238: *> \endverbatim
! 239: *>
! 240: *> \param[out] INFO
! 241: *> \verbatim
! 242: *> INFO is INTEGER
! 243: *> = 0: successful exit.
! 244: *> < 0: if INFO = -i, the i-th argument had an illegal value.
! 245: *> \endverbatim
! 246: *
! 247: * Authors:
! 248: * ========
! 249: *
! 250: *> \author Univ. of Tennessee
! 251: *> \author Univ. of California Berkeley
! 252: *> \author Univ. of Colorado Denver
! 253: *> \author NAG Ltd.
! 254: *
! 255: *> \date November 2011
! 256: *
! 257: *> \ingroup doubleOTHERcomputational
! 258: *
! 259: *> \par Contributors:
! 260: * ==================
! 261: *>
! 262: *> Ming Gu and Ren-Cang Li, Computer Science Division, University of
! 263: *> California at Berkeley, USA \n
! 264: *> Osni Marques, LBNL/NERSC, USA \n
! 265: *
! 266: * =====================================================================
1.1 bertrand 267: SUBROUTINE DLALS0( ICOMPQ, NL, NR, SQRE, NRHS, B, LDB, BX, LDBX,
268: $ PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM, LDGNUM,
269: $ POLES, DIFL, DIFR, Z, K, C, S, WORK, INFO )
270: *
1.8 ! bertrand 271: * -- LAPACK computational routine (version 3.4.0) --
1.1 bertrand 272: * -- LAPACK is a software package provided by Univ. of Tennessee, --
273: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
1.8 ! bertrand 274: * November 2011
1.1 bertrand 275: *
276: * .. Scalar Arguments ..
277: INTEGER GIVPTR, ICOMPQ, INFO, K, LDB, LDBX, LDGCOL,
278: $ LDGNUM, NL, NR, NRHS, SQRE
279: DOUBLE PRECISION C, S
280: * ..
281: * .. Array Arguments ..
282: INTEGER GIVCOL( LDGCOL, * ), PERM( * )
283: DOUBLE PRECISION B( LDB, * ), BX( LDBX, * ), DIFL( * ),
284: $ DIFR( LDGNUM, * ), GIVNUM( LDGNUM, * ),
285: $ POLES( LDGNUM, * ), WORK( * ), Z( * )
286: * ..
287: *
288: * =====================================================================
289: *
290: * .. Parameters ..
291: DOUBLE PRECISION ONE, ZERO, NEGONE
292: PARAMETER ( ONE = 1.0D0, ZERO = 0.0D0, NEGONE = -1.0D0 )
293: * ..
294: * .. Local Scalars ..
295: INTEGER I, J, M, N, NLP1
296: DOUBLE PRECISION DIFLJ, DIFRJ, DJ, DSIGJ, DSIGJP, TEMP
297: * ..
298: * .. External Subroutines ..
299: EXTERNAL DCOPY, DGEMV, DLACPY, DLASCL, DROT, DSCAL,
300: $ XERBLA
301: * ..
302: * .. External Functions ..
303: DOUBLE PRECISION DLAMC3, DNRM2
304: EXTERNAL DLAMC3, DNRM2
305: * ..
306: * .. Intrinsic Functions ..
307: INTRINSIC MAX
308: * ..
309: * .. Executable Statements ..
310: *
311: * Test the input parameters.
312: *
313: INFO = 0
314: *
315: IF( ( ICOMPQ.LT.0 ) .OR. ( ICOMPQ.GT.1 ) ) THEN
316: INFO = -1
317: ELSE IF( NL.LT.1 ) THEN
318: INFO = -2
319: ELSE IF( NR.LT.1 ) THEN
320: INFO = -3
321: ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THEN
322: INFO = -4
323: END IF
324: *
325: N = NL + NR + 1
326: *
327: IF( NRHS.LT.1 ) THEN
328: INFO = -5
329: ELSE IF( LDB.LT.N ) THEN
330: INFO = -7
331: ELSE IF( LDBX.LT.N ) THEN
332: INFO = -9
333: ELSE IF( GIVPTR.LT.0 ) THEN
334: INFO = -11
335: ELSE IF( LDGCOL.LT.N ) THEN
336: INFO = -13
337: ELSE IF( LDGNUM.LT.N ) THEN
338: INFO = -15
339: ELSE IF( K.LT.1 ) THEN
340: INFO = -20
341: END IF
342: IF( INFO.NE.0 ) THEN
343: CALL XERBLA( 'DLALS0', -INFO )
344: RETURN
345: END IF
346: *
347: M = N + SQRE
348: NLP1 = NL + 1
349: *
350: IF( ICOMPQ.EQ.0 ) THEN
351: *
352: * Apply back orthogonal transformations from the left.
353: *
354: * Step (1L): apply back the Givens rotations performed.
355: *
356: DO 10 I = 1, GIVPTR
357: CALL DROT( NRHS, B( GIVCOL( I, 2 ), 1 ), LDB,
358: $ B( GIVCOL( I, 1 ), 1 ), LDB, GIVNUM( I, 2 ),
359: $ GIVNUM( I, 1 ) )
360: 10 CONTINUE
361: *
362: * Step (2L): permute rows of B.
363: *
364: CALL DCOPY( NRHS, B( NLP1, 1 ), LDB, BX( 1, 1 ), LDBX )
365: DO 20 I = 2, N
366: CALL DCOPY( NRHS, B( PERM( I ), 1 ), LDB, BX( I, 1 ), LDBX )
367: 20 CONTINUE
368: *
369: * Step (3L): apply the inverse of the left singular vector
370: * matrix to BX.
371: *
372: IF( K.EQ.1 ) THEN
373: CALL DCOPY( NRHS, BX, LDBX, B, LDB )
374: IF( Z( 1 ).LT.ZERO ) THEN
375: CALL DSCAL( NRHS, NEGONE, B, LDB )
376: END IF
377: ELSE
378: DO 50 J = 1, K
379: DIFLJ = DIFL( J )
380: DJ = POLES( J, 1 )
381: DSIGJ = -POLES( J, 2 )
382: IF( J.LT.K ) THEN
383: DIFRJ = -DIFR( J, 1 )
384: DSIGJP = -POLES( J+1, 2 )
385: END IF
386: IF( ( Z( J ).EQ.ZERO ) .OR. ( POLES( J, 2 ).EQ.ZERO ) )
387: $ THEN
388: WORK( J ) = ZERO
389: ELSE
390: WORK( J ) = -POLES( J, 2 )*Z( J ) / DIFLJ /
391: $ ( POLES( J, 2 )+DJ )
392: END IF
393: DO 30 I = 1, J - 1
394: IF( ( Z( I ).EQ.ZERO ) .OR.
395: $ ( POLES( I, 2 ).EQ.ZERO ) ) THEN
396: WORK( I ) = ZERO
397: ELSE
398: WORK( I ) = POLES( I, 2 )*Z( I ) /
399: $ ( DLAMC3( POLES( I, 2 ), DSIGJ )-
400: $ DIFLJ ) / ( POLES( I, 2 )+DJ )
401: END IF
402: 30 CONTINUE
403: DO 40 I = J + 1, K
404: IF( ( Z( I ).EQ.ZERO ) .OR.
405: $ ( POLES( I, 2 ).EQ.ZERO ) ) THEN
406: WORK( I ) = ZERO
407: ELSE
408: WORK( I ) = POLES( I, 2 )*Z( I ) /
409: $ ( DLAMC3( POLES( I, 2 ), DSIGJP )+
410: $ DIFRJ ) / ( POLES( I, 2 )+DJ )
411: END IF
412: 40 CONTINUE
413: WORK( 1 ) = NEGONE
414: TEMP = DNRM2( K, WORK, 1 )
415: CALL DGEMV( 'T', K, NRHS, ONE, BX, LDBX, WORK, 1, ZERO,
416: $ B( J, 1 ), LDB )
417: CALL DLASCL( 'G', 0, 0, TEMP, ONE, 1, NRHS, B( J, 1 ),
418: $ LDB, INFO )
419: 50 CONTINUE
420: END IF
421: *
422: * Move the deflated rows of BX to B also.
423: *
424: IF( K.LT.MAX( M, N ) )
425: $ CALL DLACPY( 'A', N-K, NRHS, BX( K+1, 1 ), LDBX,
426: $ B( K+1, 1 ), LDB )
427: ELSE
428: *
429: * Apply back the right orthogonal transformations.
430: *
431: * Step (1R): apply back the new right singular vector matrix
432: * to B.
433: *
434: IF( K.EQ.1 ) THEN
435: CALL DCOPY( NRHS, B, LDB, BX, LDBX )
436: ELSE
437: DO 80 J = 1, K
438: DSIGJ = POLES( J, 2 )
439: IF( Z( J ).EQ.ZERO ) THEN
440: WORK( J ) = ZERO
441: ELSE
442: WORK( J ) = -Z( J ) / DIFL( J ) /
443: $ ( DSIGJ+POLES( J, 1 ) ) / DIFR( J, 2 )
444: END IF
445: DO 60 I = 1, J - 1
446: IF( Z( J ).EQ.ZERO ) THEN
447: WORK( I ) = ZERO
448: ELSE
449: WORK( I ) = Z( J ) / ( DLAMC3( DSIGJ, -POLES( I+1,
450: $ 2 ) )-DIFR( I, 1 ) ) /
451: $ ( DSIGJ+POLES( I, 1 ) ) / DIFR( I, 2 )
452: END IF
453: 60 CONTINUE
454: DO 70 I = J + 1, K
455: IF( Z( J ).EQ.ZERO ) THEN
456: WORK( I ) = ZERO
457: ELSE
458: WORK( I ) = Z( J ) / ( DLAMC3( DSIGJ, -POLES( I,
459: $ 2 ) )-DIFL( I ) ) /
460: $ ( DSIGJ+POLES( I, 1 ) ) / DIFR( I, 2 )
461: END IF
462: 70 CONTINUE
463: CALL DGEMV( 'T', K, NRHS, ONE, B, LDB, WORK, 1, ZERO,
464: $ BX( J, 1 ), LDBX )
465: 80 CONTINUE
466: END IF
467: *
468: * Step (2R): if SQRE = 1, apply back the rotation that is
469: * related to the right null space of the subproblem.
470: *
471: IF( SQRE.EQ.1 ) THEN
472: CALL DCOPY( NRHS, B( M, 1 ), LDB, BX( M, 1 ), LDBX )
473: CALL DROT( NRHS, BX( 1, 1 ), LDBX, BX( M, 1 ), LDBX, C, S )
474: END IF
475: IF( K.LT.MAX( M, N ) )
476: $ CALL DLACPY( 'A', N-K, NRHS, B( K+1, 1 ), LDB, BX( K+1, 1 ),
477: $ LDBX )
478: *
479: * Step (3R): permute rows of B.
480: *
481: CALL DCOPY( NRHS, BX( 1, 1 ), LDBX, B( NLP1, 1 ), LDB )
482: IF( SQRE.EQ.1 ) THEN
483: CALL DCOPY( NRHS, BX( M, 1 ), LDBX, B( M, 1 ), LDB )
484: END IF
485: DO 90 I = 2, N
486: CALL DCOPY( NRHS, BX( I, 1 ), LDBX, B( PERM( I ), 1 ), LDB )
487: 90 CONTINUE
488: *
489: * Step (4R): apply back the Givens rotations performed.
490: *
491: DO 100 I = GIVPTR, 1, -1
492: CALL DROT( NRHS, B( GIVCOL( I, 2 ), 1 ), LDB,
493: $ B( GIVCOL( I, 1 ), 1 ), LDB, GIVNUM( I, 2 ),
494: $ -GIVNUM( I, 1 ) )
495: 100 CONTINUE
496: END IF
497: *
498: RETURN
499: *
500: * End of DLALS0
501: *
502: END
CVSweb interface <joel.bertrand@systella.fr>