OscProb
zhetrd3.cxx
Go to the documentation of this file.
1// ----------------------------------------------------------------------------
2// Numerical diagonalization of 3x3 matrcies
3// Copyright (C) 2006 Joachim Kopp
4// ----------------------------------------------------------------------------
5// This library is free software; you can redistribute it and/or
6// modify it under the terms of the GNU Lesser General Public
7// License as published by the Free Software Foundation; either
8// version 2.1 of the License, or (at your option) any later version.
9//
10// This library is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13// Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public
16// License along with this library; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18// ----------------------------------------------------------------------------
19#include <stdio.h>
20#include <cmath>
21#include <complex>
22#include "zhetrd3.h"
23
24// Macros
25#define SQR(x) ((x)*(x)) // x^2
26#define SQR_ABS(x) (SQR(real(x)) + SQR(imag(x))) // |x|^2
27
28
29// ----------------------------------------------------------------------------
30void zhetrd3(std::complex<double> A[3][3], std::complex<double> Q[3][3],
31 double d[3], double e[2])
32// ----------------------------------------------------------------------------
33// Reduces a hermitian 3x3 matrix to real tridiagonal form by applying
34// (unitary) Householder transformations:
35// [ d[0] e[0] ]
36// A = Q . [ e[0] d[1] e[1] ] . Q^T
37// [ e[1] d[2] ]
38// The function accesses only the diagonal and upper triangular parts of
39// A. The access is read-only.
40// ---------------------------------------------------------------------------
41{
42 const int n = 3;
43 std::complex<double> u[n], q[n];
44 std::complex<double> omega, f;
45 double K, h, g;
46
47 // Initialize Q to the identitity matrix
48#ifndef EVALS_ONLY
49 for (int i=0; i < n; i++)
50 {
51 Q[i][i] = 1.0;
52 for (int j=0; j < i; j++)
53 Q[i][j] = Q[j][i] = 0.0;
54 }
55#endif
56
57 // Bring first row and column to the desired form
58 h = SQR_ABS(A[0][1]) + SQR_ABS(A[0][2]);
59 if (real(A[0][1]) > 0)
60 g = -sqrt(h);
61 else
62 g = sqrt(h);
63 e[0] = g;
64 f = g * A[0][1];
65 u[1] = conj(A[0][1]) - g;
66 u[2] = conj(A[0][2]);
67
68 omega = h - f;
69 if (real(omega) > 0.0)
70 {
71 omega = 0.5 * (1.0 + conj(omega)/omega) / real(omega);
72 K = 0.0;
73 for (int i=1; i < n; i++)
74 {
75 f = conj(A[1][i]) * u[1] + A[i][2] * u[2];
76 q[i] = omega * f; // p
77 K += real(conj(u[i]) * f); // u* A u
78 }
79 K *= 0.5 * SQR_ABS(omega);
80
81 for (int i=1; i < n; i++)
82 q[i] = q[i] - K * u[i];
83
84 d[0] = real(A[0][0]);
85 d[1] = real(A[1][1]) - 2.0*real(q[1]*conj(u[1]));
86 d[2] = real(A[2][2]) - 2.0*real(q[2]*conj(u[2]));
87
88 // Store inverse Householder transformation in Q
89#ifndef EVALS_ONLY
90 for (int j=1; j < n; j++)
91 {
92 f = omega * conj(u[j]);
93 for (int i=1; i < n; i++)
94 Q[i][j] = Q[i][j] - f*u[i];
95 }
96#endif
97
98 // Calculate updated A[1][2] and store it in f
99 f = A[1][2] - q[1]*conj(u[2]) - u[1]*conj(q[2]);
100 }
101 else
102 {
103 for (int i=0; i < n; i++)
104 d[i] = real(A[i][i]);
105 f = A[1][2];
106 }
107
108 // Make (23) element real
109 e[1] = abs(f);
110#ifndef EVALS_ONLY
111 if (e[1] != 0.0)
112 {
113 f = conj(f) / e[1];
114 for (int i=1; i < n; i++)
115 Q[i][n-1] = Q[i][n-1] * f;
116 }
117#endif
118}
119
#define SQR_ABS(x)
Definition: zhetrd3.cxx:26
void zhetrd3(std::complex< double > A[3][3], std::complex< double > Q[3][3], double d[3], double e[2])
Definition: zhetrd3.cxx:30