Annotation of rpl/lapack/lapack/dgsvj1.f, revision 1.2
1.1 bertrand 1: SUBROUTINE DGSVJ1( JOBV, M, N, N1, A, LDA, D, SVA, MV, V, LDV,
2: + EPS, SFMIN, TOL, NSWEEP, WORK, LWORK, INFO )
3: *
4: * -- LAPACK routine (version 3.2.2) --
5: *
6: * -- Contributed by Zlatko Drmac of the University of Zagreb and --
7: * -- Kresimir Veselic of the Fernuniversitaet Hagen --
8: * -- June 2010 --
9: *
10: * -- LAPACK is a software package provided by Univ. of Tennessee, --
11: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
12: *
13: * This routine is also part of SIGMA (version 1.23, October 23. 2008.)
14: * SIGMA is a library of algorithms for highly accurate algorithms for
15: * computation of SVD, PSVD, QSVD, (H,K)-SVD, and for solution of the
16: * eigenvalue problems Hx = lambda M x, H M x = lambda x with H, M > 0.
17: *
18: IMPLICIT NONE
19: * ..
20: * .. Scalar Arguments ..
21: DOUBLE PRECISION EPS, SFMIN, TOL
22: INTEGER INFO, LDA, LDV, LWORK, M, MV, N, N1, NSWEEP
23: CHARACTER*1 JOBV
24: * ..
25: * .. Array Arguments ..
26: DOUBLE PRECISION A( LDA, * ), D( N ), SVA( N ), V( LDV, * ),
27: + WORK( LWORK )
28: * ..
29: *
30: * Purpose
31: * =======
32: *
33: * DGSVJ1 is called from SGESVJ as a pre-processor and that is its main
34: * purpose. It applies Jacobi rotations in the same way as SGESVJ does, but
35: * it targets only particular pivots and it does not check convergence
36: * (stopping criterion). Few tunning parameters (marked by [TP]) are
37: * available for the implementer.
38: *
39: * Further Details
40: * ~~~~~~~~~~~~~~~
41: * DGSVJ1 applies few sweeps of Jacobi rotations in the column space of
42: * the input M-by-N matrix A. The pivot pairs are taken from the (1,2)
43: * off-diagonal block in the corresponding N-by-N Gram matrix A^T * A. The
44: * block-entries (tiles) of the (1,2) off-diagonal block are marked by the
45: * [x]'s in the following scheme:
46: *
47: * | * * * [x] [x] [x]|
48: * | * * * [x] [x] [x]| Row-cycling in the nblr-by-nblc [x] blocks.
49: * | * * * [x] [x] [x]| Row-cyclic pivoting inside each [x] block.
50: * |[x] [x] [x] * * * |
51: * |[x] [x] [x] * * * |
52: * |[x] [x] [x] * * * |
53: *
54: * In terms of the columns of A, the first N1 columns are rotated 'against'
55: * the remaining N-N1 columns, trying to increase the angle between the
56: * corresponding subspaces. The off-diagonal block is N1-by(N-N1) and it is
57: * tiled using quadratic tiles of side KBL. Here, KBL is a tunning parmeter.
58: * The number of sweeps is given in NSWEEP and the orthogonality threshold
59: * is given in TOL.
60: *
61: * Contributors
62: * ~~~~~~~~~~~~
63: * Zlatko Drmac (Zagreb, Croatia) and Kresimir Veselic (Hagen, Germany)
64: *
65: * Arguments
66: * =========
67: *
68: * JOBV (input) CHARACTER*1
69: * Specifies whether the output from this procedure is used
70: * to compute the matrix V:
71: * = 'V': the product of the Jacobi rotations is accumulated
72: * by postmulyiplying the N-by-N array V.
73: * (See the description of V.)
74: * = 'A': the product of the Jacobi rotations is accumulated
75: * by postmulyiplying the MV-by-N array V.
76: * (See the descriptions of MV and V.)
77: * = 'N': the Jacobi rotations are not accumulated.
78: *
79: * M (input) INTEGER
80: * The number of rows of the input matrix A. M >= 0.
81: *
82: * N (input) INTEGER
83: * The number of columns of the input matrix A.
84: * M >= N >= 0.
85: *
86: * N1 (input) INTEGER
87: * N1 specifies the 2 x 2 block partition, the first N1 columns are
88: * rotated 'against' the remaining N-N1 columns of A.
89: *
90: * A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
91: * On entry, M-by-N matrix A, such that A*diag(D) represents
92: * the input matrix.
93: * On exit,
94: * A_onexit * D_onexit represents the input matrix A*diag(D)
95: * post-multiplied by a sequence of Jacobi rotations, where the
96: * rotation threshold and the total number of sweeps are given in
97: * TOL and NSWEEP, respectively.
98: * (See the descriptions of N1, D, TOL and NSWEEP.)
99: *
100: * LDA (input) INTEGER
101: * The leading dimension of the array A. LDA >= max(1,M).
102: *
103: * D (input/workspace/output) DOUBLE PRECISION array, dimension (N)
104: * The array D accumulates the scaling factors from the fast scaled
105: * Jacobi rotations.
106: * On entry, A*diag(D) represents the input matrix.
107: * On exit, A_onexit*diag(D_onexit) represents the input matrix
108: * post-multiplied by a sequence of Jacobi rotations, where the
109: * rotation threshold and the total number of sweeps are given in
110: * TOL and NSWEEP, respectively.
111: * (See the descriptions of N1, A, TOL and NSWEEP.)
112: *
113: * SVA (input/workspace/output) DOUBLE PRECISION array, dimension (N)
114: * On entry, SVA contains the Euclidean norms of the columns of
115: * the matrix A*diag(D).
116: * On exit, SVA contains the Euclidean norms of the columns of
117: * the matrix onexit*diag(D_onexit).
118: *
119: * MV (input) INTEGER
120: * If JOBV .EQ. 'A', then MV rows of V are post-multipled by a
121: * sequence of Jacobi rotations.
122: * If JOBV = 'N', then MV is not referenced.
123: *
124: * V (input/output) DOUBLE PRECISION array, dimension (LDV,N)
125: * If JOBV .EQ. 'V' then N rows of V are post-multipled by a
126: * sequence of Jacobi rotations.
127: * If JOBV .EQ. 'A' then MV rows of V are post-multipled by a
128: * sequence of Jacobi rotations.
129: * If JOBV = 'N', then V is not referenced.
130: *
131: * LDV (input) INTEGER
132: * The leading dimension of the array V, LDV >= 1.
133: * If JOBV = 'V', LDV .GE. N.
134: * If JOBV = 'A', LDV .GE. MV.
135: *
136: * EPS (input) DOUBLE PRECISION
137: * EPS = DLAMCH('Epsilon')
138: *
139: * SFMIN (input) DOUBLE PRECISION
140: * SFMIN = DLAMCH('Safe Minimum')
141: *
142: * TOL (input) DOUBLE PRECISION
143: * TOL is the threshold for Jacobi rotations. For a pair
144: * A(:,p), A(:,q) of pivot columns, the Jacobi rotation is
145: * applied only if DABS(COS(angle(A(:,p),A(:,q)))) .GT. TOL.
146: *
147: * NSWEEP (input) INTEGER
148: * NSWEEP is the number of sweeps of Jacobi rotations to be
149: * performed.
150: *
151: * WORK (workspace) DOUBLE PRECISION array, dimension (LWORK)
152: *
153: * LWORK (input) INTEGER
154: * LWORK is the dimension of WORK. LWORK .GE. M.
155: *
156: * INFO (output) INTEGER
157: * = 0 : successful exit.
158: * < 0 : if INFO = -i, then the i-th argument had an illegal value
159: *
160: * =====================================================================
161: *
162: * .. Local Parameters ..
163: DOUBLE PRECISION ZERO, HALF, ONE, TWO
164: PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0,
165: + TWO = 2.0D0 )
166: * ..
167: * .. Local Scalars ..
168: DOUBLE PRECISION AAPP, AAPP0, AAPQ, AAQQ, APOAQ, AQOAP, BIG,
169: + BIGTHETA, CS, LARGE, MXAAPQ, MXSINJ, ROOTBIG,
170: + ROOTEPS, ROOTSFMIN, ROOTTOL, SMALL, SN, T,
171: + TEMP1, THETA, THSIGN
172: INTEGER BLSKIP, EMPTSW, i, ibr, igl, IERR, IJBLSK,
173: + ISWROT, jbc, jgl, KBL, MVL, NOTROT, nblc, nblr,
174: + p, PSKIPPED, q, ROWSKIP, SWBAND
175: LOGICAL APPLV, ROTOK, RSVEC
176: * ..
177: * .. Local Arrays ..
178: DOUBLE PRECISION FASTR( 5 )
179: * ..
180: * .. Intrinsic Functions ..
181: INTRINSIC DABS, DMAX1, DBLE, MIN0, DSIGN, DSQRT
182: * ..
183: * .. External Functions ..
184: DOUBLE PRECISION DDOT, DNRM2
185: INTEGER IDAMAX
186: LOGICAL LSAME
187: EXTERNAL IDAMAX, LSAME, DDOT, DNRM2
188: * ..
189: * .. External Subroutines ..
190: EXTERNAL DAXPY, DCOPY, DLASCL, DLASSQ, DROTM, DSWAP
191: * ..
192: * .. Executable Statements ..
193: *
194: * Test the input parameters.
195: *
196: APPLV = LSAME( JOBV, 'A' )
197: RSVEC = LSAME( JOBV, 'V' )
198: IF( .NOT.( RSVEC .OR. APPLV .OR. LSAME( JOBV, 'N' ) ) ) THEN
199: INFO = -1
200: ELSE IF( M.LT.0 ) THEN
201: INFO = -2
202: ELSE IF( ( N.LT.0 ) .OR. ( N.GT.M ) ) THEN
203: INFO = -3
204: ELSE IF( N1.LT.0 ) THEN
205: INFO = -4
206: ELSE IF( LDA.LT.M ) THEN
207: INFO = -6
208: ELSE IF( MV.LT.0 ) THEN
209: INFO = -9
210: ELSE IF( LDV.LT.M ) THEN
211: INFO = -11
212: ELSE IF( TOL.LE.EPS ) THEN
213: INFO = -14
214: ELSE IF( NSWEEP.LT.0 ) THEN
215: INFO = -15
216: ELSE IF( LWORK.LT.M ) THEN
217: INFO = -17
218: ELSE
219: INFO = 0
220: END IF
221: *
222: * #:(
223: IF( INFO.NE.0 ) THEN
224: CALL XERBLA( 'DGSVJ1', -INFO )
225: RETURN
226: END IF
227: *
228: IF( RSVEC ) THEN
229: MVL = N
230: ELSE IF( APPLV ) THEN
231: MVL = MV
232: END IF
233: RSVEC = RSVEC .OR. APPLV
234:
235: ROOTEPS = DSQRT( EPS )
236: ROOTSFMIN = DSQRT( SFMIN )
237: SMALL = SFMIN / EPS
238: BIG = ONE / SFMIN
239: ROOTBIG = ONE / ROOTSFMIN
240: LARGE = BIG / DSQRT( DBLE( M*N ) )
241: BIGTHETA = ONE / ROOTEPS
242: ROOTTOL = DSQRT( TOL )
243: *
244: * .. Initialize the right singular vector matrix ..
245: *
246: * RSVEC = LSAME( JOBV, 'Y' )
247: *
248: EMPTSW = N1*( N-N1 )
249: NOTROT = 0
250: FASTR( 1 ) = ZERO
251: *
252: * .. Row-cyclic pivot strategy with de Rijk's pivoting ..
253: *
254: KBL = MIN0( 8, N )
255: NBLR = N1 / KBL
256: IF( ( NBLR*KBL ).NE.N1 )NBLR = NBLR + 1
257:
258: * .. the tiling is nblr-by-nblc [tiles]
259:
260: NBLC = ( N-N1 ) / KBL
261: IF( ( NBLC*KBL ).NE.( N-N1 ) )NBLC = NBLC + 1
262: BLSKIP = ( KBL**2 ) + 1
263: *[TP] BLKSKIP is a tuning parameter that depends on SWBAND and KBL.
264:
265: ROWSKIP = MIN0( 5, KBL )
266: *[TP] ROWSKIP is a tuning parameter.
267: SWBAND = 0
268: *[TP] SWBAND is a tuning parameter. It is meaningful and effective
269: * if SGESVJ is used as a computational routine in the preconditioned
270: * Jacobi SVD algorithm SGESVJ.
271: *
272: *
273: * | * * * [x] [x] [x]|
274: * | * * * [x] [x] [x]| Row-cycling in the nblr-by-nblc [x] blocks.
275: * | * * * [x] [x] [x]| Row-cyclic pivoting inside each [x] block.
276: * |[x] [x] [x] * * * |
277: * |[x] [x] [x] * * * |
278: * |[x] [x] [x] * * * |
279: *
280: *
281: DO 1993 i = 1, NSWEEP
282: * .. go go go ...
283: *
284: MXAAPQ = ZERO
285: MXSINJ = ZERO
286: ISWROT = 0
287: *
288: NOTROT = 0
289: PSKIPPED = 0
290: *
291: DO 2000 ibr = 1, NBLR
292:
293: igl = ( ibr-1 )*KBL + 1
294: *
295: *
296: *........................................................
297: * ... go to the off diagonal blocks
298:
299: igl = ( ibr-1 )*KBL + 1
300:
301: DO 2010 jbc = 1, NBLC
302:
303: jgl = N1 + ( jbc-1 )*KBL + 1
304:
305: * doing the block at ( ibr, jbc )
306:
307: IJBLSK = 0
308: DO 2100 p = igl, MIN0( igl+KBL-1, N1 )
309:
310: AAPP = SVA( p )
311:
312: IF( AAPP.GT.ZERO ) THEN
313:
314: PSKIPPED = 0
315:
316: DO 2200 q = jgl, MIN0( jgl+KBL-1, N )
317: *
318: AAQQ = SVA( q )
319:
320: IF( AAQQ.GT.ZERO ) THEN
321: AAPP0 = AAPP
322: *
323: * .. M x 2 Jacobi SVD ..
324: *
325: * .. Safe Gram matrix computation ..
326: *
327: IF( AAQQ.GE.ONE ) THEN
328: IF( AAPP.GE.AAQQ ) THEN
329: ROTOK = ( SMALL*AAPP ).LE.AAQQ
330: ELSE
331: ROTOK = ( SMALL*AAQQ ).LE.AAPP
332: END IF
333: IF( AAPP.LT.( BIG / AAQQ ) ) THEN
334: AAPQ = ( DDOT( M, A( 1, p ), 1, A( 1,
335: + q ), 1 )*D( p )*D( q ) / AAQQ )
336: + / AAPP
337: ELSE
338: CALL DCOPY( M, A( 1, p ), 1, WORK, 1 )
339: CALL DLASCL( 'G', 0, 0, AAPP, D( p ),
340: + M, 1, WORK, LDA, IERR )
341: AAPQ = DDOT( M, WORK, 1, A( 1, q ),
342: + 1 )*D( q ) / AAQQ
343: END IF
344: ELSE
345: IF( AAPP.GE.AAQQ ) THEN
346: ROTOK = AAPP.LE.( AAQQ / SMALL )
347: ELSE
348: ROTOK = AAQQ.LE.( AAPP / SMALL )
349: END IF
350: IF( AAPP.GT.( SMALL / AAQQ ) ) THEN
351: AAPQ = ( DDOT( M, A( 1, p ), 1, A( 1,
352: + q ), 1 )*D( p )*D( q ) / AAQQ )
353: + / AAPP
354: ELSE
355: CALL DCOPY( M, A( 1, q ), 1, WORK, 1 )
356: CALL DLASCL( 'G', 0, 0, AAQQ, D( q ),
357: + M, 1, WORK, LDA, IERR )
358: AAPQ = DDOT( M, WORK, 1, A( 1, p ),
359: + 1 )*D( p ) / AAPP
360: END IF
361: END IF
362:
363: MXAAPQ = DMAX1( MXAAPQ, DABS( AAPQ ) )
364:
365: * TO rotate or NOT to rotate, THAT is the question ...
366: *
367: IF( DABS( AAPQ ).GT.TOL ) THEN
368: NOTROT = 0
369: * ROTATED = ROTATED + 1
370: PSKIPPED = 0
371: ISWROT = ISWROT + 1
372: *
373: IF( ROTOK ) THEN
374: *
375: AQOAP = AAQQ / AAPP
376: APOAQ = AAPP / AAQQ
377: THETA = -HALF*DABS( AQOAP-APOAQ ) /
378: + AAPQ
379: IF( AAQQ.GT.AAPP0 )THETA = -THETA
380:
381: IF( DABS( THETA ).GT.BIGTHETA ) THEN
382: T = HALF / THETA
383: FASTR( 3 ) = T*D( p ) / D( q )
384: FASTR( 4 ) = -T*D( q ) / D( p )
385: CALL DROTM( M, A( 1, p ), 1,
386: + A( 1, q ), 1, FASTR )
387: IF( RSVEC )CALL DROTM( MVL,
388: + V( 1, p ), 1,
389: + V( 1, q ), 1,
390: + FASTR )
391: SVA( q ) = AAQQ*DSQRT( DMAX1( ZERO,
392: + ONE+T*APOAQ*AAPQ ) )
393: AAPP = AAPP*DSQRT( DMAX1( ZERO,
394: + ONE-T*AQOAP*AAPQ ) )
395: MXSINJ = DMAX1( MXSINJ, DABS( T ) )
396: ELSE
397: *
398: * .. choose correct signum for THETA and rotate
399: *
400: THSIGN = -DSIGN( ONE, AAPQ )
401: IF( AAQQ.GT.AAPP0 )THSIGN = -THSIGN
402: T = ONE / ( THETA+THSIGN*
403: + DSQRT( ONE+THETA*THETA ) )
404: CS = DSQRT( ONE / ( ONE+T*T ) )
405: SN = T*CS
406: MXSINJ = DMAX1( MXSINJ, DABS( SN ) )
407: SVA( q ) = AAQQ*DSQRT( DMAX1( ZERO,
408: + ONE+T*APOAQ*AAPQ ) )
409: AAPP = AAPP*DSQRT( ONE-T*AQOAP*
410: + AAPQ )
411:
412: APOAQ = D( p ) / D( q )
413: AQOAP = D( q ) / D( p )
414: IF( D( p ).GE.ONE ) THEN
415: *
416: IF( D( q ).GE.ONE ) THEN
417: FASTR( 3 ) = T*APOAQ
418: FASTR( 4 ) = -T*AQOAP
419: D( p ) = D( p )*CS
420: D( q ) = D( q )*CS
421: CALL DROTM( M, A( 1, p ), 1,
422: + A( 1, q ), 1,
423: + FASTR )
424: IF( RSVEC )CALL DROTM( MVL,
425: + V( 1, p ), 1, V( 1, q ),
426: + 1, FASTR )
427: ELSE
428: CALL DAXPY( M, -T*AQOAP,
429: + A( 1, q ), 1,
430: + A( 1, p ), 1 )
431: CALL DAXPY( M, CS*SN*APOAQ,
432: + A( 1, p ), 1,
433: + A( 1, q ), 1 )
434: IF( RSVEC ) THEN
435: CALL DAXPY( MVL, -T*AQOAP,
436: + V( 1, q ), 1,
437: + V( 1, p ), 1 )
438: CALL DAXPY( MVL,
439: + CS*SN*APOAQ,
440: + V( 1, p ), 1,
441: + V( 1, q ), 1 )
442: END IF
443: D( p ) = D( p )*CS
444: D( q ) = D( q ) / CS
445: END IF
446: ELSE
447: IF( D( q ).GE.ONE ) THEN
448: CALL DAXPY( M, T*APOAQ,
449: + A( 1, p ), 1,
450: + A( 1, q ), 1 )
451: CALL DAXPY( M, -CS*SN*AQOAP,
452: + A( 1, q ), 1,
453: + A( 1, p ), 1 )
454: IF( RSVEC ) THEN
455: CALL DAXPY( MVL, T*APOAQ,
456: + V( 1, p ), 1,
457: + V( 1, q ), 1 )
458: CALL DAXPY( MVL,
459: + -CS*SN*AQOAP,
460: + V( 1, q ), 1,
461: + V( 1, p ), 1 )
462: END IF
463: D( p ) = D( p ) / CS
464: D( q ) = D( q )*CS
465: ELSE
466: IF( D( p ).GE.D( q ) ) THEN
467: CALL DAXPY( M, -T*AQOAP,
468: + A( 1, q ), 1,
469: + A( 1, p ), 1 )
470: CALL DAXPY( M, CS*SN*APOAQ,
471: + A( 1, p ), 1,
472: + A( 1, q ), 1 )
473: D( p ) = D( p )*CS
474: D( q ) = D( q ) / CS
475: IF( RSVEC ) THEN
476: CALL DAXPY( MVL,
477: + -T*AQOAP,
478: + V( 1, q ), 1,
479: + V( 1, p ), 1 )
480: CALL DAXPY( MVL,
481: + CS*SN*APOAQ,
482: + V( 1, p ), 1,
483: + V( 1, q ), 1 )
484: END IF
485: ELSE
486: CALL DAXPY( M, T*APOAQ,
487: + A( 1, p ), 1,
488: + A( 1, q ), 1 )
489: CALL DAXPY( M,
490: + -CS*SN*AQOAP,
491: + A( 1, q ), 1,
492: + A( 1, p ), 1 )
493: D( p ) = D( p ) / CS
494: D( q ) = D( q )*CS
495: IF( RSVEC ) THEN
496: CALL DAXPY( MVL,
497: + T*APOAQ, V( 1, p ),
498: + 1, V( 1, q ), 1 )
499: CALL DAXPY( MVL,
500: + -CS*SN*AQOAP,
501: + V( 1, q ), 1,
502: + V( 1, p ), 1 )
503: END IF
504: END IF
505: END IF
506: END IF
507: END IF
508:
509: ELSE
510: IF( AAPP.GT.AAQQ ) THEN
511: CALL DCOPY( M, A( 1, p ), 1, WORK,
512: + 1 )
513: CALL DLASCL( 'G', 0, 0, AAPP, ONE,
514: + M, 1, WORK, LDA, IERR )
515: CALL DLASCL( 'G', 0, 0, AAQQ, ONE,
516: + M, 1, A( 1, q ), LDA,
517: + IERR )
518: TEMP1 = -AAPQ*D( p ) / D( q )
519: CALL DAXPY( M, TEMP1, WORK, 1,
520: + A( 1, q ), 1 )
521: CALL DLASCL( 'G', 0, 0, ONE, AAQQ,
522: + M, 1, A( 1, q ), LDA,
523: + IERR )
524: SVA( q ) = AAQQ*DSQRT( DMAX1( ZERO,
525: + ONE-AAPQ*AAPQ ) )
526: MXSINJ = DMAX1( MXSINJ, SFMIN )
527: ELSE
528: CALL DCOPY( M, A( 1, q ), 1, WORK,
529: + 1 )
530: CALL DLASCL( 'G', 0, 0, AAQQ, ONE,
531: + M, 1, WORK, LDA, IERR )
532: CALL DLASCL( 'G', 0, 0, AAPP, ONE,
533: + M, 1, A( 1, p ), LDA,
534: + IERR )
535: TEMP1 = -AAPQ*D( q ) / D( p )
536: CALL DAXPY( M, TEMP1, WORK, 1,
537: + A( 1, p ), 1 )
538: CALL DLASCL( 'G', 0, 0, ONE, AAPP,
539: + M, 1, A( 1, p ), LDA,
540: + IERR )
541: SVA( p ) = AAPP*DSQRT( DMAX1( ZERO,
542: + ONE-AAPQ*AAPQ ) )
543: MXSINJ = DMAX1( MXSINJ, SFMIN )
544: END IF
545: END IF
546: * END IF ROTOK THEN ... ELSE
547: *
548: * In the case of cancellation in updating SVA(q)
549: * .. recompute SVA(q)
550: IF( ( SVA( q ) / AAQQ )**2.LE.ROOTEPS )
551: + THEN
552: IF( ( AAQQ.LT.ROOTBIG ) .AND.
553: + ( AAQQ.GT.ROOTSFMIN ) ) THEN
554: SVA( q ) = DNRM2( M, A( 1, q ), 1 )*
555: + D( q )
556: ELSE
557: T = ZERO
558: AAQQ = ZERO
559: CALL DLASSQ( M, A( 1, q ), 1, T,
560: + AAQQ )
561: SVA( q ) = T*DSQRT( AAQQ )*D( q )
562: END IF
563: END IF
564: IF( ( AAPP / AAPP0 )**2.LE.ROOTEPS ) THEN
565: IF( ( AAPP.LT.ROOTBIG ) .AND.
566: + ( AAPP.GT.ROOTSFMIN ) ) THEN
567: AAPP = DNRM2( M, A( 1, p ), 1 )*
568: + D( p )
569: ELSE
570: T = ZERO
571: AAPP = ZERO
572: CALL DLASSQ( M, A( 1, p ), 1, T,
573: + AAPP )
574: AAPP = T*DSQRT( AAPP )*D( p )
575: END IF
576: SVA( p ) = AAPP
577: END IF
578: * end of OK rotation
579: ELSE
580: NOTROT = NOTROT + 1
581: * SKIPPED = SKIPPED + 1
582: PSKIPPED = PSKIPPED + 1
583: IJBLSK = IJBLSK + 1
584: END IF
585: ELSE
586: NOTROT = NOTROT + 1
587: PSKIPPED = PSKIPPED + 1
588: IJBLSK = IJBLSK + 1
589: END IF
590:
591: * IF ( NOTROT .GE. EMPTSW ) GO TO 2011
592: IF( ( i.LE.SWBAND ) .AND. ( IJBLSK.GE.BLSKIP ) )
593: + THEN
594: SVA( p ) = AAPP
595: NOTROT = 0
596: GO TO 2011
597: END IF
598: IF( ( i.LE.SWBAND ) .AND.
599: + ( PSKIPPED.GT.ROWSKIP ) ) THEN
600: AAPP = -AAPP
601: NOTROT = 0
602: GO TO 2203
603: END IF
604:
605: *
606: 2200 CONTINUE
607: * end of the q-loop
608: 2203 CONTINUE
609:
610: SVA( p ) = AAPP
611: *
612: ELSE
613: IF( AAPP.EQ.ZERO )NOTROT = NOTROT +
614: + MIN0( jgl+KBL-1, N ) - jgl + 1
615: IF( AAPP.LT.ZERO )NOTROT = 0
616: *** IF ( NOTROT .GE. EMPTSW ) GO TO 2011
617: END IF
618:
619: 2100 CONTINUE
620: * end of the p-loop
621: 2010 CONTINUE
622: * end of the jbc-loop
623: 2011 CONTINUE
624: *2011 bailed out of the jbc-loop
625: DO 2012 p = igl, MIN0( igl+KBL-1, N )
626: SVA( p ) = DABS( SVA( p ) )
627: 2012 CONTINUE
628: *** IF ( NOTROT .GE. EMPTSW ) GO TO 1994
629: 2000 CONTINUE
630: *2000 :: end of the ibr-loop
631: *
632: * .. update SVA(N)
633: IF( ( SVA( N ).LT.ROOTBIG ) .AND. ( SVA( N ).GT.ROOTSFMIN ) )
634: + THEN
635: SVA( N ) = DNRM2( M, A( 1, N ), 1 )*D( N )
636: ELSE
637: T = ZERO
638: AAPP = ZERO
639: CALL DLASSQ( M, A( 1, N ), 1, T, AAPP )
640: SVA( N ) = T*DSQRT( AAPP )*D( N )
641: END IF
642: *
643: * Additional steering devices
644: *
645: IF( ( i.LT.SWBAND ) .AND. ( ( MXAAPQ.LE.ROOTTOL ) .OR.
646: + ( ISWROT.LE.N ) ) )SWBAND = i
647:
648: IF( ( i.GT.SWBAND+1 ) .AND. ( MXAAPQ.LT.DBLE( N )*TOL ) .AND.
649: + ( DBLE( N )*MXAAPQ*MXSINJ.LT.TOL ) ) THEN
650: GO TO 1994
651: END IF
652:
653: *
654: IF( NOTROT.GE.EMPTSW )GO TO 1994
655:
656: 1993 CONTINUE
657: * end i=1:NSWEEP loop
658: * #:) Reaching this point means that the procedure has completed the given
659: * number of sweeps.
660: INFO = NSWEEP - 1
661: GO TO 1995
662: 1994 CONTINUE
663: * #:) Reaching this point means that during the i-th sweep all pivots were
664: * below the given threshold, causing early exit.
665:
666: INFO = 0
667: * #:) INFO = 0 confirms successful iterations.
668: 1995 CONTINUE
669: *
670: * Sort the vector D
671: *
672: DO 5991 p = 1, N - 1
673: q = IDAMAX( N-p+1, SVA( p ), 1 ) + p - 1
674: IF( p.NE.q ) THEN
675: TEMP1 = SVA( p )
676: SVA( p ) = SVA( q )
677: SVA( q ) = TEMP1
678: TEMP1 = D( p )
679: D( p ) = D( q )
680: D( q ) = TEMP1
681: CALL DSWAP( M, A( 1, p ), 1, A( 1, q ), 1 )
682: IF( RSVEC )CALL DSWAP( MVL, V( 1, p ), 1, V( 1, q ), 1 )
683: END IF
684: 5991 CONTINUE
685: *
686: RETURN
687: * ..
688: * .. END OF DGSVJ1
689: * ..
690: END
CVSweb interface <joel.bertrand@systella.fr>