1       SUBROUTINE ZLARGV( N, X, INCX, Y, INCY, C, INCC )
  2 *
  3 *  -- LAPACK auxiliary routine (version 3.2) --
  4 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  5 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  6 *     November 2006
  7 *
  8 *     .. Scalar Arguments ..
  9       INTEGER            INCC, INCX, INCY, N
 10 *     ..
 11 *     .. Array Arguments ..
 12       DOUBLE PRECISION   C( * )
 13       COMPLEX*16         X( * ), Y( * )
 14 *     ..
 15 *
 16 *  Purpose
 17 *  =======
 18 *
 19 *  ZLARGV generates a vector of complex plane rotations with real
 20 *  cosines, determined by elements of the complex vectors x and y.
 21 *  For i = 1,2,...,n
 22 *
 23 *     (        c(i)   s(i) ) ( x(i) ) = ( r(i) )
 24 *     ( -conjg(s(i))  c(i) ) ( y(i) ) = (   0  )
 25 *
 26 *     where c(i)**2 + ABS(s(i))**2 = 1
 27 *
 28 *  The following conventions are used (these are the same as in ZLARTG,
 29 *  but differ from the BLAS1 routine ZROTG):
 30 *     If y(i)=0, then c(i)=1 and s(i)=0.
 31 *     If x(i)=0, then c(i)=0 and s(i) is chosen so that r(i) is real.
 32 *
 33 *  Arguments
 34 *  =========
 35 *
 36 *  N       (input) INTEGER
 37 *          The number of plane rotations to be generated.
 38 *
 39 *  X       (input/output) COMPLEX*16 array, dimension (1+(N-1)*INCX)
 40 *          On entry, the vector x.
 41 *          On exit, x(i) is overwritten by r(i), for i = 1,...,n.
 42 *
 43 *  INCX    (input) INTEGER
 44 *          The increment between elements of X. INCX > 0.
 45 *
 46 *  Y       (input/output) COMPLEX*16 array, dimension (1+(N-1)*INCY)
 47 *          On entry, the vector y.
 48 *          On exit, the sines of the plane rotations.
 49 *
 50 *  INCY    (input) INTEGER
 51 *          The increment between elements of Y. INCY > 0.
 52 *
 53 *  C       (output) DOUBLE PRECISION array, dimension (1+(N-1)*INCC)
 54 *          The cosines of the plane rotations.
 55 *
 56 *  INCC    (input) INTEGER
 57 *          The increment between elements of C. INCC > 0.
 58 *
 59 *  Further Details
 60 *  ======= =======
 61 *
 62 *  6-6-96 - Modified with a new algorithm by W. Kahan and J. Demmel
 63 *
 64 *  This version has a few statements commented out for thread safety
 65 *  (machine parameters are computed on each entry). 10 feb 03, SJH.
 66 *
 67 *  =====================================================================
 68 *
 69 *     .. Parameters ..
 70       DOUBLE PRECISION   TWO, ONE, ZERO
 71       PARAMETER          ( TWO = 2.0D+0, ONE = 1.0D+0, ZERO = 0.0D+0 )
 72       COMPLEX*16         CZERO
 73       PARAMETER          ( CZERO = ( 0.0D+00.0D+0 ) )
 74 *     ..
 75 *     .. Local Scalars ..
 76 *     LOGICAL            FIRST
 77 
 78       INTEGER            COUNT, I, IC, IX, IY, J
 79       DOUBLE PRECISION   CS, D, DI, DR, EPS, F2, F2S, G2, G2S, SAFMIN,
 80      $                   SAFMN2, SAFMX2, SCALE
 81       COMPLEX*16         F, FF, FS, G, GS, R, SN
 82 *     ..
 83 *     .. External Functions ..
 84       DOUBLE PRECISION   DLAMCH, DLAPY2
 85       EXTERNAL           DLAMCH, DLAPY2
 86 *     ..
 87 *     .. Intrinsic Functions ..
 88       INTRINSIC          ABSDBLEDCMPLXDCONJGDIMAGINTLOG,
 89      $                   MAXSQRT
 90 *     ..
 91 *     .. Statement Functions ..
 92       DOUBLE PRECISION   ABS1, ABSSQ
 93 *     ..
 94 *     .. Save statement ..
 95 *     SAVE               FIRST, SAFMX2, SAFMIN, SAFMN2
 96 *     ..
 97 *     .. Data statements ..
 98 *     DATA               FIRST / .TRUE. /
 99 *     ..
100 *     .. Statement Function definitions ..
101       ABS1( FF ) = MAXABSDBLE( FF ) ), ABSDIMAG( FF ) ) )
102       ABSSQ( FF ) = DBLE( FF )**2 + DIMAG( FF )**2
103 *     ..
104 *     .. Executable Statements ..
105 *
106 *     IF( FIRST ) THEN
107 *        FIRST = .FALSE.
108          SAFMIN = DLAMCH( 'S' )
109          EPS = DLAMCH( 'E' )
110          SAFMN2 = DLAMCH( 'B' )**INTLOG( SAFMIN / EPS ) /
111      $            LOG( DLAMCH( 'B' ) ) / TWO )
112          SAFMX2 = ONE / SAFMN2
113 *     END IF
114       IX = 1
115       IY = 1
116       IC = 1
117       DO 60 I = 1, N
118          F = X( IX )
119          G = Y( IY )
120 *
121 *        Use identical algorithm as in ZLARTG
122 *
123          SCALE = MAX( ABS1( F ), ABS1( G ) )
124          FS = F
125          GS = G
126          COUNT = 0
127          IFSCALE.GE.SAFMX2 ) THEN
128    10       CONTINUE
129             COUNT = COUNT + 1
130             FS = FS*SAFMN2
131             GS = GS*SAFMN2
132             SCALE = SCALE*SAFMN2
133             IFSCALE.GE.SAFMX2 )
134      $         GO TO 10
135          ELSE IFSCALE.LE.SAFMN2 ) THEN
136             IF( G.EQ.CZERO ) THEN
137                CS = ONE
138                SN = CZERO
139                R = F
140                GO TO 50
141             END IF
142    20       CONTINUE
143             COUNT = COUNT - 1
144             FS = FS*SAFMX2
145             GS = GS*SAFMX2
146             SCALE = SCALE*SAFMX2
147             IFSCALE.LE.SAFMN2 )
148      $         GO TO 20
149          END IF
150          F2 = ABSSQ( FS )
151          G2 = ABSSQ( GS )
152          IF( F2.LE.MAX( G2, ONE )*SAFMIN ) THEN
153 *
154 *           This is a rare case: F is very small.
155 *
156             IF( F.EQ.CZERO ) THEN
157                CS = ZERO
158                R = DLAPY2( DBLE( G ), DIMAG( G ) )
159 *              Do complex/real division explicitly with two real
160 *              divisions
161                D = DLAPY2( DBLE( GS ), DIMAG( GS ) )
162                SN = DCMPLXDBLE( GS ) / D, -DIMAG( GS ) / D )
163                GO TO 50
164             END IF
165             F2S = DLAPY2( DBLE( FS ), DIMAG( FS ) )
166 *           G2 and G2S are accurate
167 *           G2 is at least SAFMIN, and G2S is at least SAFMN2
168             G2S = SQRT( G2 )
169 *           Error in CS from underflow in F2S is at most
170 *           UNFL / SAFMN2 .lt. sqrt(UNFL*EPS) .lt. EPS
171 *           If MAX(G2,ONE)=G2, then F2 .lt. G2*SAFMIN,
172 *           and so CS .lt. sqrt(SAFMIN)
173 *           If MAX(G2,ONE)=ONE, then F2 .lt. SAFMIN
174 *           and so CS .lt. sqrt(SAFMIN)/SAFMN2 = sqrt(EPS)
175 *           Therefore, CS = F2S/G2S / sqrt( 1 + (F2S/G2S)**2 ) = F2S/G2S
176             CS = F2S / G2S
177 *           Make sure abs(FF) = 1
178 *           Do complex/real division explicitly with 2 real divisions
179             IF( ABS1( F ).GT.ONE ) THEN
180                D = DLAPY2( DBLE( F ), DIMAG( F ) )
181                FF = DCMPLXDBLE( F ) / D, DIMAG( F ) / D )
182             ELSE
183                DR = SAFMX2*DBLE( F )
184                DI = SAFMX2*DIMAG( F )
185                D = DLAPY2( DR, DI )
186                FF = DCMPLX( DR / D, DI / D )
187             END IF
188             SN = FF*DCMPLXDBLE( GS ) / G2S, -DIMAG( GS ) / G2S )
189             R = CS*+ SN*G
190          ELSE
191 *
192 *           This is the most common case.
193 *           Neither F2 nor F2/G2 are less than SAFMIN
194 *           F2S cannot overflow, and it is accurate
195 *
196             F2S = SQRT( ONE+G2 / F2 )
197 *           Do the F2S(real)*FS(complex) multiply with two real
198 *           multiplies
199             R = DCMPLX( F2S*DBLE( FS ), F2S*DIMAG( FS ) )
200             CS = ONE / F2S
201             D = F2 + G2
202 *           Do complex/real division explicitly with two real divisions
203             SN = DCMPLXDBLE( R ) / D, DIMAG( R ) / D )
204             SN = SN*DCONJG( GS )
205             IFCOUNT.NE.0 ) THEN
206                IFCOUNT.GT.0 ) THEN
207                   DO 30 J = 1COUNT
208                      R = R*SAFMX2
209    30             CONTINUE
210                ELSE
211                   DO 40 J = 1-COUNT
212                      R = R*SAFMN2
213    40             CONTINUE
214                END IF
215             END IF
216          END IF
217    50    CONTINUE
218          C( IC ) = CS
219          Y( IY ) = SN
220          X( IX ) = R
221          IC = IC + INCC
222          IY = IY + INCY
223          IX = IX + INCX
224    60 CONTINUE
225       RETURN
226 *
227 *     End of ZLARGV
228 *
229       END