1 /* ../netlib/zlaesy.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib;
2 on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */
3 #include "FLA_f2c.h" /* Table of constant values */
4 static doublecomplex c_b1 =
5 {
6 1.,0.
7 }
8 ;
9 static integer c__2 = 2;
10 /* > \brief \b ZLAESY computes the eigenvalues and eigenvectors of a 2-by-2 complex symmetric matrix. */
11 /* =========== DOCUMENTATION =========== */
12 /* Online html documentation available at */
13 /* http://www.netlib.org/lapack/explore-html/ */
14 /* > \htmlonly */
15 /* > Download ZLAESY + dependencies */
16 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zlaesy. f"> */
17 /* > [TGZ]</a> */
18 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zlaesy. f"> */
19 /* > [ZIP]</a> */
20 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlaesy. f"> */
21 /* > [TXT]</a> */
22 /* > \endhtmlonly */
23 /* Definition: */
24 /* =========== */
25 /* SUBROUTINE ZLAESY( A, B, C, RT1, RT2, EVSCAL, CS1, SN1 ) */
26 /* .. Scalar Arguments .. */
27 /* COMPLEX*16 A, B, C, CS1, EVSCAL, RT1, RT2, SN1 */
28 /* .. */
29 /* > \par Purpose: */
30 /* ============= */
31 /* > */
32 /* > \verbatim */
33 /* > */
34 /* > ZLAESY computes the eigendecomposition of a 2-by-2 symmetric matrix */
35 /* > ( ( A, B );
36 ( B, C ) ) */
37 /* > provided the norm of the matrix of eigenvectors is larger than */
38 /* > some threshold value. */
39 /* > */
40 /* > RT1 is the eigenvalue of larger absolute value, and RT2 of */
41 /* > smaller absolute value. If the eigenvectors are computed, then */
42 /* > on return ( CS1, SN1 ) is the unit eigenvector for RT1, hence */
43 /* > */
44 /* > [ CS1 SN1 ] . [ A B ] . [ CS1 -SN1 ] = [ RT1 0 ] */
45 /* > [ -SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ] */
46 /* > \endverbatim */
47 /* Arguments: */
48 /* ========== */
49 /* > \param[in] A */
50 /* > \verbatim */
51 /* > A is COMPLEX*16 */
52 /* > The ( 1, 1 ) element of input matrix. */
53 /* > \endverbatim */
54 /* > */
55 /* > \param[in] B */
56 /* > \verbatim */
57 /* > B is COMPLEX*16 */
58 /* > The ( 1, 2 ) element of input matrix. The ( 2, 1 ) element */
59 /* > is also given by B, since the 2-by-2 matrix is symmetric. */
60 /* > \endverbatim */
61 /* > */
62 /* > \param[in] C */
63 /* > \verbatim */
64 /* > C is COMPLEX*16 */
65 /* > The ( 2, 2 ) element of input matrix. */
66 /* > \endverbatim */
67 /* > */
68 /* > \param[out] RT1 */
69 /* > \verbatim */
70 /* > RT1 is COMPLEX*16 */
71 /* > The eigenvalue of larger modulus. */
72 /* > \endverbatim */
73 /* > */
74 /* > \param[out] RT2 */
75 /* > \verbatim */
76 /* > RT2 is COMPLEX*16 */
77 /* > The eigenvalue of smaller modulus. */
78 /* > \endverbatim */
79 /* > */
80 /* > \param[out] EVSCAL */
81 /* > \verbatim */
82 /* > EVSCAL is COMPLEX*16 */
83 /* > The complex value by which the eigenvector matrix was scaled */
84 /* > to make it orthonormal. If EVSCAL is zero, the eigenvectors */
85 /* > were not computed. This means one of two things: the 2-by-2 */
86 /* > matrix could not be diagonalized, or the norm of the matrix */
87 /* > of eigenvectors before scaling was larger than the threshold */
88 /* > value THRESH (set below). */
89 /* > \endverbatim */
90 /* > */
91 /* > \param[out] CS1 */
92 /* > \verbatim */
93 /* > CS1 is COMPLEX*16 */
94 /* > \endverbatim */
95 /* > */
96 /* > \param[out] SN1 */
97 /* > \verbatim */
98 /* > SN1 is COMPLEX*16 */
99 /* > If EVSCAL .NE. 0, ( CS1, SN1 ) is the unit right eigenvector */
100 /* > for RT1. */
101 /* > \endverbatim */
102 /* Authors: */
103 /* ======== */
104 /* > \author Univ. of Tennessee */
105 /* > \author Univ. of California Berkeley */
106 /* > \author Univ. of Colorado Denver */
107 /* > \author NAG Ltd. */
108 /* > \date September 2012 */
109 /* > \ingroup complex16SYauxiliary */
110 /* ===================================================================== */
111 /* Subroutine */
zlaesy_(doublecomplex * a,doublecomplex * b,doublecomplex * c__,doublecomplex * rt1,doublecomplex * rt2,doublecomplex * evscal,doublecomplex * cs1,doublecomplex * sn1)112 int zlaesy_(doublecomplex *a, doublecomplex *b, doublecomplex *c__, doublecomplex *rt1, doublecomplex *rt2, doublecomplex *evscal, doublecomplex *cs1, doublecomplex *sn1)
113 {
114 /* System generated locals */
115 doublereal d__1, d__2;
116 doublecomplex z__1, z__2, z__3, z__4, z__5, z__6, z__7;
117 /* Builtin functions */
118 double z_abs(doublecomplex *);
119 void pow_zi(doublecomplex *, doublecomplex *, integer *), z_sqrt( doublecomplex *, doublecomplex *), z_div(doublecomplex *, doublecomplex *, doublecomplex *);
120 /* Local variables */
121 doublecomplex s, t;
122 doublereal z__;
123 doublecomplex tmp;
124 doublereal babs, tabs, evnorm;
125 /* -- LAPACK auxiliary routine (version 3.4.2) -- */
126 /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */
127 /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */
128 /* September 2012 */
129 /* .. Scalar Arguments .. */
130 /* .. */
131 /* ===================================================================== */
132 /* .. Parameters .. */
133 /* .. */
134 /* .. Local Scalars .. */
135 /* .. */
136 /* .. Intrinsic Functions .. */
137 /* .. */
138 /* .. Executable Statements .. */
139 /* Special case: The matrix is actually diagonal. */
140 /* To avoid divide by zero later, we treat this case separately. */
141 if (z_abs(b) == 0.)
142 {
143 rt1->r = a->r, rt1->i = a->i;
144 rt2->r = c__->r, rt2->i = c__->i;
145 if (z_abs(rt1) < z_abs(rt2))
146 {
147 tmp.r = rt1->r;
148 tmp.i = rt1->i; // , expr subst
149 rt1->r = rt2->r, rt1->i = rt2->i;
150 rt2->r = tmp.r, rt2->i = tmp.i;
151 cs1->r = 0., cs1->i = 0.;
152 sn1->r = 1., sn1->i = 0.;
153 }
154 else
155 {
156 cs1->r = 1., cs1->i = 0.;
157 sn1->r = 0., sn1->i = 0.;
158 }
159 }
160 else
161 {
162 /* Compute the eigenvalues and eigenvectors. */
163 /* The characteristic equation is */
164 /* lambda **2 - (A+C) lambda + (A*C - B*B) */
165 /* and we solve it using the quadratic formula. */
166 z__2.r = a->r + c__->r;
167 z__2.i = a->i + c__->i; // , expr subst
168 z__1.r = z__2.r * .5;
169 z__1.i = z__2.i * .5; // , expr subst
170 s.r = z__1.r;
171 s.i = z__1.i; // , expr subst
172 z__2.r = a->r - c__->r;
173 z__2.i = a->i - c__->i; // , expr subst
174 z__1.r = z__2.r * .5;
175 z__1.i = z__2.i * .5; // , expr subst
176 t.r = z__1.r;
177 t.i = z__1.i; // , expr subst
178 /* Take the square root carefully to avoid over/under flow. */
179 babs = z_abs(b);
180 tabs = z_abs(&t);
181 z__ = max(babs,tabs);
182 if (z__ > 0.)
183 {
184 z__5.r = t.r / z__;
185 z__5.i = t.i / z__; // , expr subst
186 pow_zi(&z__4, &z__5, &c__2);
187 z__7.r = b->r / z__;
188 z__7.i = b->i / z__; // , expr subst
189 pow_zi(&z__6, &z__7, &c__2);
190 z__3.r = z__4.r + z__6.r;
191 z__3.i = z__4.i + z__6.i; // , expr subst
192 z_sqrt(&z__2, &z__3);
193 z__1.r = z__ * z__2.r;
194 z__1.i = z__ * z__2.i; // , expr subst
195 t.r = z__1.r;
196 t.i = z__1.i; // , expr subst
197 }
198 /* Compute the two eigenvalues. RT1 and RT2 are exchanged */
199 /* if necessary so that RT1 will have the greater magnitude. */
200 z__1.r = s.r + t.r;
201 z__1.i = s.i + t.i; // , expr subst
202 rt1->r = z__1.r, rt1->i = z__1.i;
203 z__1.r = s.r - t.r;
204 z__1.i = s.i - t.i; // , expr subst
205 rt2->r = z__1.r, rt2->i = z__1.i;
206 if (z_abs(rt1) < z_abs(rt2))
207 {
208 tmp.r = rt1->r;
209 tmp.i = rt1->i; // , expr subst
210 rt1->r = rt2->r, rt1->i = rt2->i;
211 rt2->r = tmp.r, rt2->i = tmp.i;
212 }
213 /* Choose CS1 = 1 and SN1 to satisfy the first equation, then */
214 /* scale the components of this eigenvector so that the matrix */
215 /* of eigenvectors X satisfies X * X**T = I . (No scaling is */
216 /* done if the norm of the eigenvalue matrix is less than THRESH.) */
217 z__2.r = rt1->r - a->r;
218 z__2.i = rt1->i - a->i; // , expr subst
219 z_div(&z__1, &z__2, b);
220 sn1->r = z__1.r, sn1->i = z__1.i;
221 tabs = z_abs(sn1);
222 if (tabs > 1.)
223 {
224 /* Computing 2nd power */
225 d__2 = 1. / tabs;
226 d__1 = d__2 * d__2;
227 z__5.r = sn1->r / tabs;
228 z__5.i = sn1->i / tabs; // , expr subst
229 pow_zi(&z__4, &z__5, &c__2);
230 z__3.r = d__1 + z__4.r;
231 z__3.i = z__4.i; // , expr subst
232 z_sqrt(&z__2, &z__3);
233 z__1.r = tabs * z__2.r;
234 z__1.i = tabs * z__2.i; // , expr subst
235 t.r = z__1.r;
236 t.i = z__1.i; // , expr subst
237 }
238 else
239 {
240 z__3.r = sn1->r * sn1->r - sn1->i * sn1->i;
241 z__3.i = sn1->r * sn1->i + sn1->i * sn1->r; // , expr subst
242 z__2.r = z__3.r + 1.;
243 z__2.i = z__3.i + 0.; // , expr subst
244 z_sqrt(&z__1, &z__2);
245 t.r = z__1.r;
246 t.i = z__1.i; // , expr subst
247 }
248 evnorm = z_abs(&t);
249 if (evnorm >= .1)
250 {
251 z_div(&z__1, &c_b1, &t);
252 evscal->r = z__1.r, evscal->i = z__1.i;
253 cs1->r = evscal->r, cs1->i = evscal->i;
254 z__1.r = sn1->r * evscal->r - sn1->i * evscal->i;
255 z__1.i = sn1->r * evscal->i + sn1->i * evscal->r; // , expr subst
256 sn1->r = z__1.r, sn1->i = z__1.i;
257 }
258 else
259 {
260 evscal->r = 0., evscal->i = 0.;
261 }
262 }
263 return 0;
264 /* End of ZLAESY */
265 }
266 /* zlaesy_ */
267