PLASMA  2.4.5
PLASMA - Parallel Linear Algebra for Scalable Multi-core Architectures
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
zlartg.f
Go to the documentation of this file.
1  SUBROUTINE zlartg( F, G, CS, SN, R )
2 *
3 * -- LAPACK auxiliary routine (version 3.2) --
4 * Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
5 * November 2006
6 *
7 * .. Scalar Arguments ..
8  DOUBLE PRECISION cs
9  COMPLEX*16 f, g, r, sn
10 * ..
11 *
12 * Purpose
13 * =======
14 *
15 * ZLARTG generates a plane rotation so that
16 *
17 * [ CS SN ] [ F ] [ R ]
18 * [ __ ] . [ ] = [ ] where CS**2 + |SN|**2 = 1.
19 * [ -SN CS ] [ G ] [ 0 ]
20 *
21 * This is a faster version of the BLAS1 routine ZROTG, except for
22 * the following differences:
23 * F and G are unchanged on return.
24 * If G=0, then CS=1 and SN=0.
25 * If F=0, then CS=0 and SN is chosen so that R is real.
26 *
27 * Arguments
28 * =========
29 *
30 * F (input) COMPLEX*16
31 * The first component of vector to be rotated.
32 *
33 * G (input) COMPLEX*16
34 * The second component of vector to be rotated.
35 *
36 * CS (output) DOUBLE PRECISION
37 * The cosine of the rotation.
38 *
39 * SN (output) COMPLEX*16
40 * The sine of the rotation.
41 *
42 * R (output) COMPLEX*16
43 * The nonzero component of the rotated vector.
44 *
45 * Further Details
46 * ======= =======
47 *
48 * 3-5-96 - Modified with a new algorithm by W. Kahan and J. Demmel
49 *
50 * This version has a few statements commented out for thread safety
51 * (machine parameters are computed on each entry). 10 feb 03, SJH.
52 *
53 * =====================================================================
54 *
55 * .. Parameters ..
56  DOUBLE PRECISION two, one, zero
57  parameter( two = 2.0d+0, one = 1.0d+0, zero = 0.0d+0 )
58  COMPLEX*16 czero
59  parameter( czero = ( 0.0d+0, 0.0d+0 ) )
60 * ..
61 * .. Local Scalars ..
62 * LOGICAL FIRST
63  INTEGER count, i
64  DOUBLE PRECISION d, di, dr, eps, f2, f2s, g2, g2s, safmin,
65  $ safmn2, safmx2, scale
66  COMPLEX*16 ff, fs, gs
67 * ..
68 * .. External Functions ..
69  DOUBLE PRECISION dlamch, dlapy2
70  EXTERNAL dlamch, dlapy2
71 * ..
72 * .. Intrinsic Functions ..
73  INTRINSIC abs, dble, dcmplx, dconjg, dimag, int, log,
74  $ max, sqrt
75 * ..
76 * .. Statement Functions ..
77  DOUBLE PRECISION abs1, abssq
78 * ..
79 * .. Save statement ..
80 * SAVE FIRST, SAFMX2, SAFMIN, SAFMN2
81 * ..
82 * .. Data statements ..
83 * DATA FIRST / .TRUE. /
84 * ..
85 * .. Statement Function definitions ..
86  abs1( ff ) = max( abs( dble( ff ) ), abs( dimag( ff ) ) )
87  abssq( ff ) = dble( ff )**2 + dimag( ff )**2
88 * ..
89 * .. Executable Statements ..
90 *
91 * IF( FIRST ) THEN
92  safmin = dlamch( 'S' )
93  eps = dlamch( 'E' )
94  safmn2 = dlamch( 'B' )**int( log( safmin / eps ) /
95  $ log( dlamch( 'B' ) ) / two )
96  safmx2 = one / safmn2
97 * FIRST = .FALSE.
98 * END IF
99  scale = max( abs1( f ), abs1( g ) )
100  fs = f
101  gs = g
102  count = 0
103  IF( scale.GE.safmx2 ) THEN
104  10 continue
105  count = count + 1
106  fs = fs*safmn2
107  gs = gs*safmn2
108  scale = scale*safmn2
109  IF( scale.GE.safmx2 )
110  $ go to 10
111  ELSE IF( scale.LE.safmn2 ) THEN
112  IF( g.EQ.czero ) THEN
113  cs = one
114  sn = czero
115  r = f
116  return
117  END IF
118  20 continue
119  count = count - 1
120  fs = fs*safmx2
121  gs = gs*safmx2
122  scale = scale*safmx2
123  IF( scale.LE.safmn2 )
124  $ go to 20
125  END IF
126  f2 = abssq( fs )
127  g2 = abssq( gs )
128  IF( f2.LE.max( g2, one )*safmin ) THEN
129 *
130 * This is a rare case: F is very small.
131 *
132  IF( f.EQ.czero ) THEN
133  cs = zero
134  r = dlapy2( dble( g ), dimag( g ) )
135 * Do complex/real division explicitly with two real divisions
136  d = dlapy2( dble( gs ), dimag( gs ) )
137  sn = dcmplx( dble( gs ) / d, -dimag( gs ) / d )
138  return
139  END IF
140  f2s = dlapy2( dble( fs ), dimag( fs ) )
141 * G2 and G2S are accurate
142 * G2 is at least SAFMIN, and G2S is at least SAFMN2
143  g2s = sqrt( g2 )
144 * Error in CS from underflow in F2S is at most
145 * UNFL / SAFMN2 .lt. sqrt(UNFL*EPS) .lt. EPS
146 * If MAX(G2,ONE)=G2, then F2 .lt. G2*SAFMIN,
147 * and so CS .lt. sqrt(SAFMIN)
148 * If MAX(G2,ONE)=ONE, then F2 .lt. SAFMIN
149 * and so CS .lt. sqrt(SAFMIN)/SAFMN2 = sqrt(EPS)
150 * Therefore, CS = F2S/G2S / sqrt( 1 + (F2S/G2S)**2 ) = F2S/G2S
151  cs = f2s / g2s
152 * Make sure abs(FF) = 1
153 * Do complex/real division explicitly with 2 real divisions
154  IF( abs1( f ).GT.one ) THEN
155  d = dlapy2( dble( f ), dimag( f ) )
156  ff = dcmplx( dble( f ) / d, dimag( f ) / d )
157  ELSE
158  dr = safmx2*dble( f )
159  di = safmx2*dimag( f )
160  d = dlapy2( dr, di )
161  ff = dcmplx( dr / d, di / d )
162  END IF
163  sn = ff*dcmplx( dble( gs ) / g2s, -dimag( gs ) / g2s )
164  r = cs*f + sn*g
165  ELSE
166 *
167 * This is the most common case.
168 * Neither F2 nor F2/G2 are less than SAFMIN
169 * F2S cannot overflow, and it is accurate
170 *
171  f2s = sqrt( one+g2 / f2 )
172 * Do the F2S(real)*FS(complex) multiply with two real multiplies
173  r = dcmplx( f2s*dble( fs ), f2s*dimag( fs ) )
174  cs = one / f2s
175  d = f2 + g2
176 * Do complex/real division explicitly with two real divisions
177  sn = dcmplx( dble( r ) / d, dimag( r ) / d )
178  sn = sn*dconjg( gs )
179  IF( count.NE.0 ) THEN
180  IF( count.GT.0 ) THEN
181  DO 30 i = 1, count
182  r = r*safmx2
183  30 continue
184  ELSE
185  DO 40 i = 1, -count
186  r = r*safmn2
187  40 continue
188  END IF
189  END IF
190  END IF
191  return
192 *
193 * End of ZLARTG
194 *
195  END