mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
levinsonRecursion.hpp
1
2//***********************************************************************//
3// Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
4//
5// This file is part of mxlib.
6//
7// mxlib is free software: you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation, either version 3 of the License, or
10// (at your option) any later version.
11//
12// mxlib is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with mxlib. If not, see <http://www.gnu.org/licenses/>.
19//***********************************************************************//
20
21#ifndef levinsonRecursion_hpp
22#define levinsonRecursion_hpp
23
24/*Solves the Toeplitz system PN
25j=1 R(N+i−j)xj = yi (i = 0,...,N-1). The Toeplitz matrix need
26not be symmetric. y[0..n-1] and r[0..2*n-2] are input arrays; x[0..n-1] is the output array.*/
27
28template <typename floatT>
29void levinsonRecursion( floatT *_r, floatT *_x, floatT *_y, int n )
30{
31
32 int j, k, m, m1, m2;
33 floatT pp, pt1, pt2, qq, qt1, qt2, sd, sgd, sgn, shn, sxn;
34
35 /*Have to adjust for the stupid NR convention of 1-counting*/
36 floatT *r = _r - 1;
37 floatT *x = _x - 1;
38 floatT *y = _y - 1;
39
40 floatT *g, *h, *_g, *_h;
41
42 if( r[n] == 0.0 )
43 {
44 std::cerr << "toeplz-1 singular principal minor" << "\n";
45 return;
46 }
47
48 /*Have to adjust for the stupid NR convention of 1-counting*/
49 _g = new floatT[n];
50 g = _g - 1;
51 _h = new floatT[n];
52 h = _h - 1;
53
54 x[1] = y[1] / r[n]; // Initialize for the recursion.
55
56 if( n == 1 )
57 {
58 delete[] _g;
59 delete[] _h;
60 return;
61 }
62
63 g[1] = r[n - 1] / r[n];
64
65 h[1] = r[n + 1] / r[n];
66
67 for( m = 1; m <= n; ++m )
68 { // Main loop over the recursion.
69
70 m1 = m + 1;
71 sxn = -y[m1]; // Compute numerator and denominator for x,
72 sd = -r[n];
73
74 for( j = 1; j <= m; ++j )
75 {
76 sxn += r[n + m1 - j] * x[j];
77 sd += r[n + m1 - j] * g[m - j + 1];
78 }
79
80 if( sd == 0.0 )
81 {
82 std::cerr << "toeplz-2 singular principal minor" << "\n";
83
84 delete[] _g;
85 delete[] _h;
86 return;
87 }
88
89 x[m1] = sxn / sd; // whence x.
90
91 for( j = 1; j <= m; ++j )
92 x[j] -= x[m1] * g[m - j + 1];
93
94 if( m1 == n )
95 {
96 delete[] _g;
97 delete[] _h;
98 return;
99 }
100
101 sgn = -r[n - m1]; // Compute numerator and denominator for G and H,
102
103 shn = -r[n + m1];
104
105 sgd = -r[n];
106
107 for( j = 1; j <= m; ++j )
108 {
109 sgn += r[n + j - m1] * g[j];
110 shn += r[n + m1 - j] * h[j];
111 sgd += r[n + j - m1] * h[m - j + 1];
112 }
113
114 if( sd == 0.0 || sgd == 0.0 )
115 {
116 std::cerr << "toeplz-3 singular principal minor" << "\n";
117
118 delete[] _g;
119 delete[] _h;
120 return;
121 }
122
123 g[m1] = sgn / sgd; // whence G and H.
124 h[m1] = shn / sd;
125
126 k = m;
127 m2 = ( m + 1 ) >> 1;
128 pp = g[m1];
129 qq = h[m1];
130 for( j = 1; j <= m2; ++j )
131 {
132 pt1 = g[j];
133 pt2 = g[k];
134 qt1 = h[j];
135 qt2 = h[k];
136 g[j] = pt1 - pp * qt2;
137 g[k] = pt2 - pp * qt1;
138 h[j] = qt1 - qq * pt2;
139 h[k--] = qt2 - qq * pt1;
140 }
141 } // Back for another recurrence.
142
143 std::cerr << "toeplz - should not arrive here!" << "\n";
144
145 delete[] _g;
146 delete[] _h;
147 return;
148}
149
150#endif // levinsonRecursion_hpp
constexpr units::realT h()
Planck Constant.
Definition constants.hpp:91
constexpr units::realT k()
Boltzmann Constant.
Definition constants.hpp:69