001:       SUBROUTINE DGSVJ1( JOBV, M, N, N1, A, LDA, D, SVA, MV, V, LDV,
002:      &            EPS, SFMIN, TOL, NSWEEP, WORK, LWORK, INFO )
003: *
004: *  -- LAPACK routine (version 3.2)                                    --
005: *
006: *  -- Contributed by Zlatko Drmac of the University of Zagreb and     --
007: *  -- Kresimir Veselic of the Fernuniversitaet Hagen                  --
008: *  -- November 2008                                                   --
009: *
010: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
011: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
012: *
013: * This routine is also part of SIGMA (version 1.23, October 23. 2008.)
014: * SIGMA is a library of algorithms for highly accurate algorithms for
015: * computation of SVD, PSVD, QSVD, (H,K)-SVD, and for solution of the
016: * eigenvalue problems Hx = lambda M x, H M x = lambda x with H, M > 0.
017: *
018: *     -#- Scalar Arguments -#-
019: *
020:       IMPLICIT    NONE
021:       DOUBLE PRECISION  EPS, SFMIN, TOL
022:       INTEGER     INFO, LDA, LDV, LWORK, M, MV, N, N1, NSWEEP
023:       CHARACTER*1 JOBV
024: *
025: *     -#- Array Arguments -#-
026: *
027:       DOUBLE PRECISION A( LDA, * ), D( N ), SVA( N ), V( LDV, * ),
028:      &                 WORK( LWORK )
029: *     ..
030: *
031: *  Purpose
032: *  ~~~~~~~
033: *  DGSVJ1 is called from SGESVJ as a pre-processor and that is its main
034: *  purpose. It applies Jacobi rotations in the same way as SGESVJ does, but
035: *  it targets only particular pivots and it does not check convergence
036: *  (stopping criterion). Few tunning parameters (marked by [TP]) are
037: *  available for the implementer.
038: *
039: *  Further details
040: *  ~~~~~~~~~~~~~~~
041: *  DGSVJ1 applies few sweeps of Jacobi rotations in the column space of
042: *  the input M-by-N matrix A. The pivot pairs are taken from the (1,2)
043: *  off-diagonal block in the corresponding N-by-N Gram matrix A^T * A. The
044: *  block-entries (tiles) of the (1,2) off-diagonal block are marked by the
045: *  [x]'s in the following scheme:
046: *
047: *     | *   *   * [x] [x] [x]|
048: *     | *   *   * [x] [x] [x]|    Row-cycling in the nblr-by-nblc [x] blocks.
049: *     | *   *   * [x] [x] [x]|    Row-cyclic pivoting inside each [x] block.
050: *     |[x] [x] [x] *   *   * |
051: *     |[x] [x] [x] *   *   * |
052: *     |[x] [x] [x] *   *   * |
053: *
054: *  In terms of the columns of A, the first N1 columns are rotated 'against'
055: *  the remaining N-N1 columns, trying to increase the angle between the
056: *  corresponding subspaces. The off-diagonal block is N1-by(N-N1) and it is
057: *  tiled using quadratic tiles of side KBL. Here, KBL is a tunning parmeter.
058: *  The number of sweeps is given in NSWEEP and the orthogonality threshold
059: *  is given in TOL.
060: *
061: *  Contributors
062: *  ~~~~~~~~~~~~
063: *  Zlatko Drmac (Zagreb, Croatia) and Kresimir Veselic (Hagen, Germany)
064: *
065: *  Arguments
066: *  ~~~~~~~~~
067: *
068: *  JOBV    (input) CHARACTER*1
069: *          Specifies whether the output from this procedure is used
070: *          to compute the matrix V:
071: *          = 'V': the product of the Jacobi rotations is accumulated
072: *                 by postmulyiplying the N-by-N array V.
073: *                (See the description of V.)
074: *          = 'A': the product of the Jacobi rotations is accumulated
075: *                 by postmulyiplying the MV-by-N array V.
076: *                (See the descriptions of MV and V.)
077: *          = 'N': the Jacobi rotations are not accumulated.
078: *
079: *  M       (input) INTEGER
080: *          The number of rows of the input matrix A.  M >= 0.
081: *
082: *  N       (input) INTEGER
083: *          The number of columns of the input matrix A.
084: *          M >= N >= 0.
085: *
086: *  N1      (input) INTEGER
087: *          N1 specifies the 2 x 2 block partition, the first N1 columns are
088: *          rotated 'against' the remaining N-N1 columns of A.
089: *
090: *  A       (input/output) REAL array, dimension (LDA,N)
091: *          On entry, M-by-N matrix A, such that A*diag(D) represents
092: *          the input matrix.
093: *          On exit,
094: *          A_onexit * D_onexit represents the input matrix A*diag(D)
095: *          post-multiplied by a sequence of Jacobi rotations, where the
096: *          rotation threshold and the total number of sweeps are given in
097: *          TOL and NSWEEP, respectively.
098: *          (See the descriptions of N1, D, TOL and NSWEEP.)
099: *
100: *  LDA     (input) INTEGER
101: *          The leading dimension of the array A.  LDA >= max(1,M).
102: *
103: *  D       (input/workspace/output) REAL 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) REAL 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) REAL 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) INTEGER
137: *          EPS = SLAMCH('Epsilon')
138: *
139: *  SFMIN   (input) INTEGER
140: *          SFMIN = SLAMCH('Safe Minimum')
141: *
142: *  TOL     (input) REAL
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) REAL 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: *     -#- Local Parameters -#-
161: *
162:       DOUBLE PRECISION   ZERO,  HALF,         ONE,         TWO
163:       PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0, TWO = 2.0D0 )
164: 
165: *     -#- Local Scalars -#-
166: *
167:       DOUBLE PRECISION AAPP, AAPP0, AAPQ, AAQQ, APOAQ, AQOAP, BIG,
168:      &          BIGTHETA,  CS, LARGE, MXAAPQ, MXSINJ, ROOTBIG, ROOTEPS,
169:      &          ROOTSFMIN, ROOTTOL, SMALL, SN, T, TEMP1, THETA, THSIGN
170:       INTEGER   BLSKIP, EMPTSW, i, ibr, igl, IERR, IJBLSK, ISWROT, jbc,
171:      &          jgl, KBL, MVL, NOTROT, nblc, nblr, p, PSKIPPED, q,
172:      &          ROWSKIP, SWBAND
173:       LOGICAL   APPLV, ROTOK, RSVEC
174: *
175: *     Local Arrays
176: *
177:       DOUBLE PRECISION FASTR(5)
178: *
179: *     Intrinsic Functions
180: *
181:       INTRINSIC DABS, DMAX1, DBLE, MIN0, DSIGN, DSQRT
182: *
183: *     External Functions
184: *
185:       DOUBLE PRECISION DDOT, DNRM2
186:       INTEGER          IDAMAX
187:       LOGICAL          LSAME
188:       EXTERNAL         IDAMAX, LSAME, DDOT, DNRM2
189: *
190: *     External Subroutines
191: *
192:       EXTERNAL  DAXPY, DCOPY, DLASCL, DLASSQ, DROTM, DSWAP
193: *
194: *
195:       APPLV = LSAME(JOBV,'A')
196:       RSVEC = LSAME(JOBV,'V')
197:       IF ( .NOT.( RSVEC .OR. APPLV .OR. LSAME(JOBV,'N'))) THEN
198:          INFO = -1
199:       ELSE IF ( M .LT. 0 ) THEN
200:          INFO = -2
201:       ELSE IF ( ( N .LT. 0 ) .OR. ( N .GT. M )) THEN
202:          INFO = -3
203:       ELSE IF ( N1 .LT. 0 ) THEN
204:          INFO = -4
205:       ELSE IF ( LDA .LT. M ) THEN
206:          INFO = -6
207:       ELSE IF ( MV .LT. 0 ) THEN
208:          INFO = -9
209:       ELSE IF ( LDV .LT. M ) THEN
210:          INFO = -11
211:       ELSE IF ( TOL .LE. EPS ) THEN
212:          INFO = -14
213:       ELSE IF ( NSWEEP .LT. 0 ) THEN
214:          INFO = -15
215:       ELSE IF ( LWORK .LT. M ) THEN
216:          INFO = -17
217:       ELSE
218:          INFO = 0
219:       END IF
220: *
221: *     #:(
222:       IF ( INFO .NE. 0 ) THEN
223:          CALL XERBLA( 'DGSVJ1', -INFO )
224:          RETURN
225:       END IF
226: *
227:       IF ( RSVEC ) THEN
228:          MVL = N
229:       ELSE IF ( APPLV ) THEN
230:          MVL = MV
231:       END IF
232:       RSVEC = RSVEC .OR. APPLV
233: 
234:          ROOTEPS     = DSQRT(EPS)
235:          ROOTSFMIN   = DSQRT(SFMIN)
236:          SMALL       = SFMIN  / EPS
237:          BIG         = ONE   / SFMIN
238:          ROOTBIG     = ONE  / ROOTSFMIN
239:          LARGE       = BIG / DSQRT(DBLE(M*N))
240:          BIGTHETA    = ONE  / ROOTEPS
241:          ROOTTOL = DSQRT(TOL)
242: *
243: *     -#- Initialize the right singular vector matrix -#-
244: *
245: *     RSVEC = LSAME( JOBV, 'Y' )
246: *
247:       EMPTSW = N1 * ( N - N1 )
248:       NOTROT     = 0
249:       FASTR(1)   = ZERO
250: *
251: *     -#- Row-cyclic pivot strategy with de Rijk's pivoting -#-
252: *
253:       KBL = MIN0(8,N)
254:       NBLR = N1 / KBL
255:       IF ( ( NBLR * KBL ) .NE. N1 ) NBLR = NBLR + 1
256: 
257: *     .. the tiling is nblr-by-nblc [tiles]
258: 
259:       NBLC = ( N - N1 ) / KBL
260:       IF ( ( NBLC * KBL ) .NE. ( N - N1 ) ) NBLC = NBLC + 1
261:       BLSKIP = ( KBL**2 ) + 1
262: *[TP] BLKSKIP is a tuning parameter that depends on SWBAND and KBL.
263: 
264:       ROWSKIP = MIN0( 5, KBL )
265: *[TP] ROWSKIP is a tuning parameter.
266:       SWBAND = 0
267: *[TP] SWBAND is a tuning parameter. It is meaningful and effective
268: *     if SGESVJ is used as a computational routine in the preconditioned
269: *     Jacobi SVD algorithm SGESVJ.
270: *
271: *
272: *     | *   *   * [x] [x] [x]|
273: *     | *   *   * [x] [x] [x]|    Row-cycling in the nblr-by-nblc [x] blocks.
274: *     | *   *   * [x] [x] [x]|    Row-cyclic pivoting inside each [x] block.
275: *     |[x] [x] [x] *   *   * |
276: *     |[x] [x] [x] *   *   * |
277: *     |[x] [x] [x] *   *   * |
278: *
279: *
280:       DO 1993 i = 1, NSWEEP
281: *     .. go go go ...
282: *
283:       MXAAPQ = ZERO
284:       MXSINJ = ZERO
285:       ISWROT = 0
286: *
287:       NOTROT = 0
288:       PSKIPPED = 0
289: *
290:       DO 2000 ibr = 1, NBLR
291: 
292:       igl = ( ibr - 1 ) * KBL + 1
293: *
294: *
295: *........................................................
296: * ... go to the off diagonal blocks
297: 
298:       igl = ( ibr - 1 ) * KBL + 1
299: 
300:       DO 2010 jbc = 1, NBLC
301: 
302:          jgl = N1 + ( jbc - 1 ) * KBL + 1
303: 
304: *        doing the block at ( ibr, jbc )
305: 
306:          IJBLSK = 0
307:          DO 2100 p = igl, MIN0( igl + KBL - 1, N1 )
308: 
309:          AAPP = SVA(p)
310: 
311:          IF ( AAPP .GT. ZERO ) THEN
312: 
313:          PSKIPPED = 0
314: 
315:          DO 2200 q = jgl, MIN0( jgl + KBL - 1, N )
316: *
317:          AAQQ = SVA(q)
318: 
319:          IF ( AAQQ .GT. ZERO ) THEN
320:             AAPP0 = AAPP
321: *
322: *     -#- M x 2 Jacobi SVD -#-
323: *
324: *        -#- Safe Gram matrix computation -#-
325: *
326:          IF ( AAQQ .GE. ONE ) THEN
327:             IF ( AAPP .GE. AAQQ ) THEN
328:                ROTOK = ( SMALL*AAPP ) .LE. AAQQ
329:             ELSE
330:                ROTOK = ( SMALL*AAQQ ) .LE. AAPP
331:             END IF
332:             IF ( AAPP .LT. ( BIG / AAQQ ) ) THEN
333:                AAPQ = ( DDOT(M, A(1,p), 1, A(1,q), 1 ) *
334:      &                  D(p) * D(q) / AAQQ ) / AAPP
335:             ELSE
336:                CALL DCOPY( M, A(1,p), 1, WORK, 1 )
337:                CALL DLASCL( 'G', 0, 0, AAPP, D(p), M,
338:      &              1, WORK, LDA, IERR )
339:                AAPQ = DDOT( M, WORK, 1, A(1,q), 1 ) *
340:      &                D(q) / AAQQ
341:             END IF
342:          ELSE
343:             IF ( AAPP .GE. AAQQ ) THEN
344:                ROTOK = AAPP .LE. ( AAQQ / SMALL )
345:             ELSE
346:                ROTOK = AAQQ .LE. ( AAPP / SMALL )
347:             END IF
348:             IF ( AAPP .GT.  ( SMALL / AAQQ ) ) THEN
349:                AAPQ = ( DDOT( M, A(1,p), 1, A(1,q), 1 ) *
350:      &               D(p) * D(q) / AAQQ ) / AAPP
351:             ELSE
352:                CALL DCOPY( M, A(1,q), 1, WORK, 1 )
353:                CALL DLASCL( 'G', 0, 0, AAQQ, D(q), M, 1,
354:      &              WORK, LDA, IERR )
355:                AAPQ = DDOT(M,WORK,1,A(1,p),1) * D(p) / AAPP
356:             END IF
357:          END IF
358: 
359:          MXAAPQ = DMAX1( MXAAPQ, DABS(AAPQ) )
360: 
361: *        TO rotate or NOT to rotate, THAT is the question ...
362: *
363:          IF ( DABS( AAPQ ) .GT. TOL ) THEN
364:             NOTROT   = 0
365: *           ROTATED  = ROTATED + 1
366:             PSKIPPED = 0
367:             ISWROT   = ISWROT  + 1
368: *
369:             IF ( ROTOK ) THEN
370: *
371:                AQOAP = AAQQ / AAPP
372:                APOAQ = AAPP / AAQQ
373:                THETA = - HALF * DABS( AQOAP - APOAQ ) / AAPQ
374:                IF ( AAQQ .GT. AAPP0 ) THETA = - THETA
375: 
376:                IF ( DABS( THETA ) .GT. BIGTHETA ) THEN
377:                   T = HALF / THETA
378:                   FASTR(3) =  T * D(p) / D(q)
379:                   FASTR(4) = -T * D(q) / D(p)
380:                   CALL DROTM( M,   A(1,p), 1, A(1,q), 1, FASTR )
381:                   IF ( RSVEC )
382:      &            CALL DROTM( MVL, V(1,p), 1, V(1,q), 1, FASTR )
383:                   SVA(q) = AAQQ*DSQRT( DMAX1(ZERO,ONE + T*APOAQ*AAPQ) )
384:                   AAPP   = AAPP*DSQRT( DMAX1(ZERO,ONE - T*AQOAP*AAPQ) )
385:                   MXSINJ = DMAX1( MXSINJ, DABS(T) )
386:                ELSE
387: *
388: *                 .. choose correct signum for THETA and rotate
389: *
390:                   THSIGN = - DSIGN(ONE,AAPQ)
391:                   IF ( AAQQ .GT. AAPP0 ) THSIGN = - THSIGN
392:                   T  = ONE / ( THETA + THSIGN*DSQRT(ONE+THETA*THETA) )
393:                   CS = DSQRT( ONE / ( ONE + T*T ) )
394:                   SN = T * CS
395:                   MXSINJ = DMAX1( MXSINJ, DABS(SN) )
396:                   SVA(q) = AAQQ*DSQRT( DMAX1(ZERO, ONE+T*APOAQ*AAPQ) )
397:                   AAPP   = AAPP*DSQRT( ONE - T*AQOAP*AAPQ)
398: 
399:                   APOAQ = D(p) / D(q)
400:                   AQOAP = D(q) / D(p)
401:                   IF ( D(p) .GE. ONE ) THEN
402: *
403:                      IF ( D(q) .GE.  ONE ) THEN
404:                         FASTR(3) =   T * APOAQ
405:                         FASTR(4) = - T * AQOAP
406:                         D(p)  = D(p) * CS
407:                         D(q)  = D(q) * CS
408:                         CALL DROTM( M,   A(1,p),1, A(1,q),1, FASTR )
409:                         IF ( RSVEC )
410:      &                  CALL DROTM( MVL, V(1,p),1, V(1,q),1, FASTR )
411:                      ELSE
412:                         CALL DAXPY( M,    -T*AQOAP, A(1,q),1, A(1,p),1 )
413:                         CALL DAXPY( M, CS*SN*APOAQ, A(1,p),1, A(1,q),1 )
414:                         IF ( RSVEC ) THEN
415:                         CALL DAXPY( MVL, -T*AQOAP,  V(1,q),1, V(1,p),1 )
416:                         CALL DAXPY( MVL,CS*SN*APOAQ,V(1,p),1, V(1,q),1 )
417:                         END IF
418:                         D(p) = D(p) * CS
419:                         D(q) = D(q) / CS
420:                      END IF
421:                   ELSE
422:                      IF ( D(q) .GE. ONE ) THEN
423:                         CALL DAXPY( M,     T*APOAQ, A(1,p),1, A(1,q),1 )
424:                         CALL DAXPY( M,-CS*SN*AQOAP, A(1,q),1, A(1,p),1 )
425:                         IF ( RSVEC ) THEN
426:                         CALL DAXPY(MVL,T*APOAQ,     V(1,p),1, V(1,q),1 )
427:                         CALL DAXPY(MVL,-CS*SN*AQOAP,V(1,q),1, V(1,p),1 )
428:                         END IF
429:                         D(p) = D(p) / CS
430:                         D(q) = D(q) * CS
431:                      ELSE
432:                         IF ( D(p) .GE. D(q) ) THEN
433:                            CALL DAXPY( M,-T*AQOAP,   A(1,q),1,A(1,p),1 )
434:                            CALL DAXPY( M,CS*SN*APOAQ,A(1,p),1,A(1,q),1 )
435:                            D(p) = D(p) * CS
436:                            D(q) = D(q) / CS
437:                            IF ( RSVEC ) THEN
438:                            CALL DAXPY( MVL, -T*AQOAP, V(1,q),1,V(1,p),1)
439:                            CALL DAXPY(MVL,CS*SN*APOAQ,V(1,p),1,V(1,q),1)
440:                            END IF
441:                         ELSE
442:                            CALL DAXPY(M, T*APOAQ,    A(1,p),1,A(1,q),1)
443:                            CALL DAXPY(M,-CS*SN*AQOAP,A(1,q),1,A(1,p),1)
444:                            D(p) = D(p) / CS
445:                            D(q) = D(q) * CS
446:                           IF ( RSVEC ) THEN
447:                           CALL DAXPY(MVL, T*APOAQ,    V(1,p),1,V(1,q),1)
448:                           CALL DAXPY(MVL,-CS*SN*AQOAP,V(1,q),1,V(1,p),1)
449:                           END IF
450:                         END IF
451:                      END IF
452:                   ENDIF
453:                END IF
454: 
455:             ELSE
456:                IF ( AAPP .GT. AAQQ ) THEN
457:                   CALL DCOPY( M, A(1,p), 1, WORK, 1 )
458:                   CALL DLASCL('G',0,0,AAPP,ONE,M,1,WORK,LDA,IERR)
459:                   CALL DLASCL('G',0,0,AAQQ,ONE,M,1,   A(1,q),LDA,IERR)
460:                   TEMP1 = -AAPQ * D(p) / D(q)
461:                   CALL DAXPY(M,TEMP1,WORK,1,A(1,q),1)
462:                   CALL DLASCL('G',0,0,ONE,AAQQ,M,1,A(1,q),LDA,IERR)
463:                   SVA(q) = AAQQ*DSQRT(DMAX1(ZERO, ONE - AAPQ*AAPQ))
464:                   MXSINJ = DMAX1( MXSINJ, SFMIN )
465:                ELSE
466:                   CALL DCOPY( M, A(1,q), 1, WORK, 1 )
467:                   CALL DLASCL('G',0,0,AAQQ,ONE,M,1,WORK,LDA,IERR)
468:                   CALL DLASCL('G',0,0,AAPP,ONE,M,1,   A(1,p),LDA,IERR)
469:                   TEMP1 = -AAPQ * D(q) / D(p)
470:                   CALL DAXPY(M,TEMP1,WORK,1,A(1,p),1)
471:                   CALL DLASCL('G',0,0,ONE,AAPP,M,1,A(1,p),LDA,IERR)
472:                   SVA(p) = AAPP*DSQRT(DMAX1(ZERO, ONE - AAPQ*AAPQ))
473:                   MXSINJ = DMAX1( MXSINJ, SFMIN )
474:                END IF
475:             END IF
476: *           END IF ROTOK THEN ... ELSE
477: *
478: *           In the case of cancellation in updating SVA(q)
479: *           .. recompute SVA(q)
480:             IF ( (SVA(q) / AAQQ )**2 .LE. ROOTEPS  ) THEN
481:                IF ((AAQQ .LT. ROOTBIG).AND.(AAQQ .GT. ROOTSFMIN)) THEN
482:                   SVA(q) = DNRM2( M, A(1,q), 1 ) * D(q)
483:                ELSE
484:                   T    = ZERO
485:                   AAQQ = ZERO
486:                   CALL DLASSQ( M, A(1,q), 1, T, AAQQ )
487:                   SVA(q) = T * DSQRT(AAQQ) * D(q)
488:                END IF
489:             END IF
490:             IF ( (AAPP / AAPP0 )**2 .LE. ROOTEPS  ) THEN
491:                IF ((AAPP .LT. ROOTBIG).AND.(AAPP .GT. ROOTSFMIN)) THEN
492:                   AAPP = DNRM2( M, A(1,p), 1 ) * D(p)
493:                ELSE
494:                   T    = ZERO
495:                   AAPP = ZERO
496:                   CALL DLASSQ( M, A(1,p), 1, T, AAPP )
497:                   AAPP = T * DSQRT(AAPP) * D(p)
498:                END IF
499:                SVA(p) = AAPP
500:             END IF
501: *              end of OK rotation
502:          ELSE
503:             NOTROT   = NOTROT   + 1
504: *           SKIPPED  = SKIPPED  + 1
505:             PSKIPPED = PSKIPPED + 1
506:             IJBLSK   = IJBLSK   + 1
507:          END IF
508:       ELSE
509:          NOTROT   = NOTROT   + 1
510:          PSKIPPED = PSKIPPED + 1
511:          IJBLSK   = IJBLSK   + 1
512:       END IF
513: 
514: *      IF ( NOTROT .GE. EMPTSW )  GO TO 2011
515:       IF ( ( i .LE. SWBAND ) .AND. ( IJBLSK .GE. BLSKIP ) ) THEN
516:          SVA(p) = AAPP
517:          NOTROT = 0
518:          GO TO 2011
519:       END IF
520:       IF ( ( i .LE. SWBAND ) .AND. ( PSKIPPED .GT. ROWSKIP ) ) THEN
521:          AAPP = -AAPP
522:          NOTROT = 0
523:          GO TO 2203
524:       END IF
525: 
526: *
527:  2200    CONTINUE
528: *        end of the q-loop
529:  2203    CONTINUE
530: 
531:          SVA(p) = AAPP
532: *
533:       ELSE
534:          IF ( AAPP .EQ. ZERO ) NOTROT=NOTROT+MIN0(jgl+KBL-1,N)-jgl+1
535:          IF ( AAPP .LT. ZERO ) NOTROT = 0
536: ***      IF ( NOTROT .GE. EMPTSW )  GO TO 2011
537:       END IF
538: 
539:  2100 CONTINUE
540: *     end of the p-loop
541:  2010 CONTINUE
542: *     end of the jbc-loop
543:  2011 CONTINUE
544: *2011 bailed out of the jbc-loop
545:       DO 2012 p = igl, MIN0( igl + KBL - 1, N )
546:          SVA(p) = DABS(SVA(p))
547:  2012 CONTINUE
548: ***   IF ( NOTROT .GE. EMPTSW ) GO TO 1994
549:  2000 CONTINUE
550: *2000 :: end of the ibr-loop
551: *
552: *     .. update SVA(N)
553:       IF ((SVA(N) .LT. ROOTBIG).AND.(SVA(N) .GT. ROOTSFMIN)) THEN
554:          SVA(N) = DNRM2( M, A(1,N), 1 ) * D(N)
555:       ELSE
556:          T    = ZERO
557:          AAPP = ZERO
558:          CALL DLASSQ( M, A(1,N), 1, T, AAPP )
559:          SVA(N) = T * DSQRT(AAPP) * D(N)
560:       END IF
561: *
562: *     Additional steering devices
563: *
564:       IF ( ( i.LT.SWBAND ) .AND. ( ( MXAAPQ.LE.ROOTTOL ) .OR.
565:      &     ( ISWROT .LE. N ) ) )
566:      &   SWBAND = i
567: 
568:       IF ((i.GT.SWBAND+1).AND. (MXAAPQ.LT.DBLE(N)*TOL).AND.
569:      &   (DBLE(N)*MXAAPQ*MXSINJ.LT.TOL))THEN
570:         GO TO 1994
571:       END IF
572: 
573: *
574:       IF ( NOTROT .GE. EMPTSW ) GO TO 1994
575: 
576:  1993 CONTINUE
577: *     end i=1:NSWEEP loop
578: * #:) Reaching this point means that the procedure has completed the given
579: *     number of sweeps.
580:       INFO = NSWEEP - 1
581:       GO TO 1995
582:  1994 CONTINUE
583: * #:) Reaching this point means that during the i-th sweep all pivots were
584: *     below the given threshold, causing early exit.
585: 
586:       INFO = 0
587: * #:) INFO = 0 confirms successful iterations.
588:  1995 CONTINUE
589: *
590: *     Sort the vector D
591: *
592:       DO 5991 p = 1, N - 1
593:          q = IDAMAX( N-p+1, SVA(p), 1 ) + p - 1
594:          IF ( p .NE. q ) THEN
595:             TEMP1  = SVA(p)
596:             SVA(p) = SVA(q)
597:             SVA(q) = TEMP1
598:             TEMP1   = D(p)
599:             D(p) = D(q)
600:             D(q) = TEMP1
601:             CALL DSWAP( M, A(1,p), 1, A(1,q), 1 )
602:             IF ( RSVEC ) CALL DSWAP( MVL, V(1,p), 1, V(1,q), 1 )
603:          END IF
604:  5991 CONTINUE
605: *
606:       RETURN
607: *     ..
608: *     .. END OF DGSVJ1
609: *     ..
610:       END
611: *
612: