43 subroutine imtqlx(mat_size, diag, off_diag, sol_vec)
47 integer,
intent(in) :: mat_size
48 real(dp),
intent(inout) :: diag(mat_size)
49 real(dp),
intent(inout) :: off_diag(mat_size - 1)
50 real(dp),
intent(inout) :: sol_vec(mat_size)
53 real(dp) :: precision, pivot_val, g_val, rot_val, scale_val, f_val, b_val, cos_val
54 integer :: lower_bound, upper_bound, inner_i, i, iter_count
55 integer,
parameter :: max_iter = 30
58 precision = epsilon(precision)
61 off_diag(mat_size - 1) = 0.0_dp
64 do lower_bound = 1, mat_size
68 do while (iter_count < max_iter)
70 do upper_bound = lower_bound, mat_size
71 if (upper_bound == mat_size)
exit
72 if (abs(off_diag(upper_bound)) <= precision * (abs(diag(upper_bound)) + abs(diag(upper_bound + 1))))
exit
76 pivot_val = diag(lower_bound)
77 if (upper_bound == lower_bound)
exit
80 if (iter_count > max_iter)
then
82 print*,
"IMTQLX - Fatal error."
83 print*,
"Iteration limit exceeded."
84 stop
"Terminating due to iteration limit exceeded."
87 iter_count = iter_count + 1
90 g_val = (diag(lower_bound + 1) - pivot_val) / (2.0_dp * off_diag(lower_bound))
91 rot_val = sqrt(g_val * g_val + 1.0_dp)
92 g_val = diag(upper_bound) - pivot_val + off_diag(lower_bound) / (g_val + sign(rot_val, g_val))
100 do inner_i = 1, upper_bound - lower_bound
101 i = upper_bound - inner_i
102 f_val = scale_val * off_diag(i)
103 b_val = cos_val * off_diag(i)
106 if (abs(g_val) <= abs(f_val))
then
107 cos_val = g_val / f_val
108 rot_val = sqrt(cos_val * cos_val + 1.0_dp)
109 off_diag(i + 1) = f_val * rot_val
110 scale_val = 1.0_dp / rot_val
111 cos_val = cos_val * scale_val
113 scale_val = f_val / g_val
114 rot_val = sqrt(scale_val * scale_val + 1.0_dp)
115 off_diag(i + 1) = g_val * rot_val
116 cos_val = 1.0_dp / rot_val
117 scale_val = scale_val * cos_val
121 g_val = diag(i + 1) - pivot_val
122 rot_val = (diag(i) - g_val) * scale_val + 2.0_dp * cos_val * b_val
123 pivot_val = scale_val * rot_val
124 diag(i + 1) = g_val + pivot_val
125 g_val = cos_val * rot_val - b_val
128 f_val = sol_vec(i + 1)
129 sol_vec(i + 1) = scale_val * sol_vec(i) + cos_val * f_val
130 sol_vec(i) = cos_val * sol_vec(i) - scale_val * f_val
134 diag(lower_bound) = diag(lower_bound) - pivot_val
135 off_diag(lower_bound) = g_val
136 off_diag(upper_bound) = 0.0_dp
141 call dsort2a(mat_size, diag, sol_vec)
146 integer,
intent(in) :: n
147 real(dp),
intent(inout) :: x(n), y(n)
148 integer :: i, j, min_idx
154 if (x(j) < x(min_idx)) min_idx = j
156 if (min_idx /= i)
then
subroutine dsort2a(n, x, y)
subroutine imtqlx(mat_size, diag, off_diag, sol_vec)
Implicitly-shifted Modified QL factorization algorithm for symmetric tridiagonal matrices.
Module for defining types and precision levels for Gauss-Jacobi Polynomial (GJP) calculations.
integer, parameter, public dp
Define various kinds for real numbers.