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