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