/* zlaesy.f -- translated by f2c (version 20061008). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; 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 */ #include "f2c.h" #include "blaswrap.h" /* Table of constant values */ static doublecomplex c_b1 = {1.,0.}; static integer c__2 = 2; /* Subroutine */ int zlaesy_(doublecomplex *a, doublecomplex *b, doublecomplex *c__, doublecomplex *rt1, doublecomplex *rt2, doublecomplex *evscal, doublecomplex *cs1, doublecomplex *sn1) { /* System generated locals */ doublereal d__1, d__2; doublecomplex z__1, z__2, z__3, z__4, z__5, z__6, z__7; /* Builtin functions */ double z_abs(doublecomplex *); void pow_zi(doublecomplex *, doublecomplex *, integer *), z_sqrt( doublecomplex *, doublecomplex *), z_div(doublecomplex *, doublecomplex *, doublecomplex *); /* Local variables */ doublecomplex s, t; doublereal z__; doublecomplex tmp; doublereal babs, tabs, evnorm; /* -- LAPACK auxiliary routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZLAESY computes the eigendecomposition of a 2-by-2 symmetric matrix */ /* ( ( A, B );( B, C ) ) */ /* provided the norm of the matrix of eigenvectors is larger than */ /* some threshold value. */ /* RT1 is the eigenvalue of larger absolute value, and RT2 of */ /* smaller absolute value. If the eigenvectors are computed, then */ /* on return ( CS1, SN1 ) is the unit eigenvector for RT1, hence */ /* [ CS1 SN1 ] . [ A B ] . [ CS1 -SN1 ] = [ RT1 0 ] */ /* [ -SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ] */ /* Arguments */ /* ========= */ /* A (input) COMPLEX*16 */ /* The ( 1, 1 ) element of input matrix. */ /* B (input) COMPLEX*16 */ /* The ( 1, 2 ) element of input matrix. The ( 2, 1 ) element */ /* is also given by B, since the 2-by-2 matrix is symmetric. */ /* C (input) COMPLEX*16 */ /* The ( 2, 2 ) element of input matrix. */ /* RT1 (output) COMPLEX*16 */ /* The eigenvalue of larger modulus. */ /* RT2 (output) COMPLEX*16 */ /* The eigenvalue of smaller modulus. */ /* EVSCAL (output) COMPLEX*16 */ /* The complex value by which the eigenvector matrix was scaled */ /* to make it orthonormal. If EVSCAL is zero, the eigenvectors */ /* were not computed. This means one of two things: the 2-by-2 */ /* matrix could not be diagonalized, or the norm of the matrix */ /* of eigenvectors before scaling was larger than the threshold */ /* value THRESH (set below). */ /* CS1 (output) COMPLEX*16 */ /* SN1 (output) COMPLEX*16 */ /* If EVSCAL .NE. 0, ( CS1, SN1 ) is the unit right eigenvector */ /* for RT1. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Special case: The matrix is actually diagonal. */ /* To avoid divide by zero later, we treat this case separately. */ if (z_abs(b) == 0.) { rt1->r = a->r, rt1->i = a->i; rt2->r = c__->r, rt2->i = c__->i; if (z_abs(rt1) < z_abs(rt2)) { tmp.r = rt1->r, tmp.i = rt1->i; rt1->r = rt2->r, rt1->i = rt2->i; rt2->r = tmp.r, rt2->i = tmp.i; cs1->r = 0., cs1->i = 0.; sn1->r = 1., sn1->i = 0.; } else { cs1->r = 1., cs1->i = 0.; sn1->r = 0., sn1->i = 0.; } } else { /* Compute the eigenvalues and eigenvectors. */ /* The characteristic equation is */ /* lambda **2 - (A+C) lambda + (A*C - B*B) */ /* and we solve it using the quadratic formula. */ z__2.r = a->r + c__->r, z__2.i = a->i + c__->i; z__1.r = z__2.r * .5, z__1.i = z__2.i * .5; s.r = z__1.r, s.i = z__1.i; z__2.r = a->r - c__->r, z__2.i = a->i - c__->i; z__1.r = z__2.r * .5, z__1.i = z__2.i * .5; t.r = z__1.r, t.i = z__1.i; /* Take the square root carefully to avoid over/under flow. */ babs = z_abs(b); tabs = z_abs(&t); z__ = max(babs,tabs); if (z__ > 0.) { z__5.r = t.r / z__, z__5.i = t.i / z__; pow_zi(&z__4, &z__5, &c__2); z__7.r = b->r / z__, z__7.i = b->i / z__; pow_zi(&z__6, &z__7, &c__2); z__3.r = z__4.r + z__6.r, z__3.i = z__4.i + z__6.i; z_sqrt(&z__2, &z__3); z__1.r = z__ * z__2.r, z__1.i = z__ * z__2.i; t.r = z__1.r, t.i = z__1.i; } /* Compute the two eigenvalues. RT1 and RT2 are exchanged */ /* if necessary so that RT1 will have the greater magnitude. */ z__1.r = s.r + t.r, z__1.i = s.i + t.i; rt1->r = z__1.r, rt1->i = z__1.i; z__1.r = s.r - t.r, z__1.i = s.i - t.i; rt2->r = z__1.r, rt2->i = z__1.i; if (z_abs(rt1) < z_abs(rt2)) { tmp.r = rt1->r, tmp.i = rt1->i; rt1->r = rt2->r, rt1->i = rt2->i; rt2->r = tmp.r, rt2->i = tmp.i; } /* Choose CS1 = 1 and SN1 to satisfy the first equation, then */ /* scale the components of this eigenvector so that the matrix */ /* of eigenvectors X satisfies X * X' = I . (No scaling is */ /* done if the norm of the eigenvalue matrix is less than THRESH.) */ z__2.r = rt1->r - a->r, z__2.i = rt1->i - a->i; z_div(&z__1, &z__2, b); sn1->r = z__1.r, sn1->i = z__1.i; tabs = z_abs(sn1); if (tabs > 1.) { /* Computing 2nd power */ d__2 = 1. / tabs; d__1 = d__2 * d__2; z__5.r = sn1->r / tabs, z__5.i = sn1->i / tabs; pow_zi(&z__4, &z__5, &c__2); z__3.r = d__1 + z__4.r, z__3.i = z__4.i; z_sqrt(&z__2, &z__3); z__1.r = tabs * z__2.r, z__1.i = tabs * z__2.i; t.r = z__1.r, t.i = z__1.i; } else { z__3.r = sn1->r * sn1->r - sn1->i * sn1->i, z__3.i = sn1->r * sn1->i + sn1->i * sn1->r; z__2.r = z__3.r + 1., z__2.i = z__3.i + 0.; z_sqrt(&z__1, &z__2); t.r = z__1.r, t.i = z__1.i; } evnorm = z_abs(&t); if (evnorm >= .1) { z_div(&z__1, &c_b1, &t); evscal->r = z__1.r, evscal->i = z__1.i; cs1->r = evscal->r, cs1->i = evscal->i; z__1.r = sn1->r * evscal->r - sn1->i * evscal->i, z__1.i = sn1->r * evscal->i + sn1->i * evscal->r; sn1->r = z__1.r, sn1->i = z__1.i; } else { evscal->r = 0., evscal->i = 0.; } } return 0; /* End of ZLAESY */ } /* zlaesy_ */