1 | #include <math.h>
|
---|
2 | #include "lambuilder.h"
|
---|
3 | #include <iostream.h>
|
---|
4 | //++
|
---|
5 | // Class Lambda2Builder
|
---|
6 | //
|
---|
7 | // (see separate documentation)
|
---|
8 | //--
|
---|
9 |
|
---|
10 | double Lambda2Builder::bignorm = 1.e268; // = 1e-20*1.d288
|
---|
11 |
|
---|
12 | Lambda2Builder::Lambda2Builder(){}
|
---|
13 |
|
---|
14 | Lambda2Builder::Lambda2Builder(double theta, int lmax, int mmax):
|
---|
15 | LambdaBuilder(theta, lmax, mmax){
|
---|
16 | fact_=0;
|
---|
17 | w_=0;
|
---|
18 | ix_=0;
|
---|
19 | }
|
---|
20 |
|
---|
21 | Lambda2Builder::Lambda2Builder(const Lambda2Builder& lb):
|
---|
22 | LambdaBuilder(lb){
|
---|
23 | fact_=lb.fact_;
|
---|
24 | w_=lb.w_;
|
---|
25 | ix_=lb.ix_;
|
---|
26 | }
|
---|
27 |
|
---|
28 | void Lambda2Builder::reset(){
|
---|
29 | LambdaBuilder::reset();
|
---|
30 | fact_=0;
|
---|
31 | w_=0;
|
---|
32 | ix_=0;
|
---|
33 | }
|
---|
34 |
|
---|
35 | double Lambda2Builder::lam2lmp(int flip){
|
---|
36 | if (flip < 0){
|
---|
37 | return -fact_*par_lm_*(w_+ix_);
|
---|
38 | } else{
|
---|
39 | return lam2lmp();
|
---|
40 | }
|
---|
41 | }
|
---|
42 |
|
---|
43 | double Lambda2Builder::lam2lmp(int l, int m){
|
---|
44 | if ((l <= lmax_ && l==l_+1 && m==m_) ||
|
---|
45 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){
|
---|
46 | step();
|
---|
47 | return lam2lmp();
|
---|
48 | } else if (l==l_ && m==m_){
|
---|
49 | return lam2lmp();
|
---|
50 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){
|
---|
51 | reset();
|
---|
52 | while (l != l_ || m != m_){
|
---|
53 | step();
|
---|
54 | }
|
---|
55 | return lam2lmp();
|
---|
56 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){
|
---|
57 | while (l != l_ || m != m_){
|
---|
58 | step();
|
---|
59 | }
|
---|
60 | return lam2lmp();
|
---|
61 | } else{
|
---|
62 | return -1;
|
---|
63 | }
|
---|
64 | }
|
---|
65 |
|
---|
66 | double Lambda2Builder::lam2lmp(int l, int m, int flip){
|
---|
67 |
|
---|
68 | if ((l <= lmax_ && l==l_+1 && m==m_) ||
|
---|
69 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){
|
---|
70 | step();
|
---|
71 | return lam2lmp(flip);
|
---|
72 | } else if (l==l_ && m==m_){
|
---|
73 | return lam2lmp(flip);
|
---|
74 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){
|
---|
75 | reset();
|
---|
76 | while (l != l_ || m != m_){
|
---|
77 | step();
|
---|
78 | }
|
---|
79 | return lam2lmp(flip);
|
---|
80 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){
|
---|
81 | while (l != l_ || m != m_){
|
---|
82 | step();
|
---|
83 | }
|
---|
84 | return lam2lmp(flip);
|
---|
85 | } else{
|
---|
86 | return -1;
|
---|
87 | }
|
---|
88 | }
|
---|
89 |
|
---|
90 | double Lambda2Builder::lam2lmm(int flip){
|
---|
91 | if (flip < 0){
|
---|
92 | return -fact_*par_lm_*(w_-ix_);
|
---|
93 | } else{
|
---|
94 | return lam2lmp();
|
---|
95 | }
|
---|
96 | }
|
---|
97 |
|
---|
98 | double Lambda2Builder::lam2lmm(int l, int m){
|
---|
99 | if ((l <= lmax_ && l==l_+1 && m==m_) ||
|
---|
100 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){
|
---|
101 | step();
|
---|
102 | return lam2lmm();
|
---|
103 | } else if (l==l_ && m==m_){
|
---|
104 | return lam2lmm();
|
---|
105 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){
|
---|
106 | reset();
|
---|
107 | while (l != l_ || m != m_){
|
---|
108 | step();
|
---|
109 | }
|
---|
110 | return lam2lmm();
|
---|
111 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){
|
---|
112 | while (l != l_ || m != m_){
|
---|
113 | step();
|
---|
114 | }
|
---|
115 | return lam2lmm();
|
---|
116 | } else{
|
---|
117 | return -1;
|
---|
118 | }
|
---|
119 | }
|
---|
120 |
|
---|
121 | double Lambda2Builder::lam2lmm(int l, int m, int flip){
|
---|
122 | if ((l <= lmax_ && l==l_+1 && m==m_) ||
|
---|
123 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){
|
---|
124 | step();
|
---|
125 | return lam2lmm(flip);
|
---|
126 | } else if (l==l_ && m==m_){
|
---|
127 | return lam2lmm(flip);
|
---|
128 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){
|
---|
129 | reset();
|
---|
130 | while (l != l_ || m != m_){
|
---|
131 | step();
|
---|
132 | }
|
---|
133 | return lam2lmm(flip);
|
---|
134 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){
|
---|
135 | while (l != l_ || m != m_){
|
---|
136 | step();
|
---|
137 | }
|
---|
138 | return lam2lmm(flip);
|
---|
139 | } else{
|
---|
140 | return -1;
|
---|
141 | }
|
---|
142 | }
|
---|
143 |
|
---|
144 | void Lambda2Builder::step(){
|
---|
145 | if (l_>=lmax_ && m_>=mmax_){return;}
|
---|
146 | if (l_==lmax_){//move on to the next m and calculate l=m
|
---|
147 | LambdaBuilder::step();
|
---|
148 | if (l_>=2){
|
---|
149 | w_=-2.*(m_*(2.*m_+1.)-m_*(m_-1.)/sth_/sth_)*lamlm_;
|
---|
150 | ix_=-2.*m_*(m_-1.)*cth_/sth_/sth_*lamlm_;
|
---|
151 | fact_=sqrt(1./(m_-1.)/m_/(m_+1.)/(m_+2.));
|
---|
152 | } else{
|
---|
153 | w_=0;
|
---|
154 | ix_=0;
|
---|
155 | fact_=0;
|
---|
156 | }
|
---|
157 | } else{
|
---|
158 | double lastlamlm=lamlm_;
|
---|
159 | LambdaBuilder::step();
|
---|
160 | if (l_>=2){
|
---|
161 | w_=-2.*(-((l_-m_*m_)/sth_/sth_+.5*l_*(l_-1.))*lamlm_+
|
---|
162 | (l_+m_)*cth_/sth_/sth_*sqrt((2.*l_+1.)/(2.*l_-1.)*(l_-m_)/(l_+m_))*
|
---|
163 | lastlamlm);
|
---|
164 | ix_=-2.*m_/sth_/sth_*((l_-1.)*cth_*lamlm_-(l_+m_)*
|
---|
165 | sqrt((2.*l_+1.)/(2.*l_-1.)*(l_-m_)/(l_+m_))*
|
---|
166 | lastlamlm);
|
---|
167 | fact_=sqrt(1./(l_-1.)/l_/(l_+1.)/(l_+2.));
|
---|
168 | } else{
|
---|
169 | w_=0;
|
---|
170 | ix_=0;
|
---|
171 | fact_=0;
|
---|
172 | }
|
---|
173 | }
|
---|
174 | }
|
---|
175 |
|
---|
176 | LambdaBuilder::LambdaBuilder(){}
|
---|
177 |
|
---|
178 | LambdaBuilder::LambdaBuilder(double theta, int lmax, int mmax){
|
---|
179 | lmax_=lmax;
|
---|
180 | mmax_=mmax;
|
---|
181 | l_=0;
|
---|
182 | m_=0;
|
---|
183 | lamlm_=1. / sqrt(4.*M_PI);
|
---|
184 | cth_=cos(theta);
|
---|
185 | sth_=sin(theta);
|
---|
186 | lammm_=1. / sqrt(4.*M_PI) *bignorm;
|
---|
187 | par_lm_=1.;
|
---|
188 | lam_0_=0.;
|
---|
189 | lam_1_=1./bignorm;
|
---|
190 | a_rec_=sqrt(3.);
|
---|
191 | b_rec_=0;
|
---|
192 | fm2_=0;
|
---|
193 | }
|
---|
194 |
|
---|
195 | LambdaBuilder::LambdaBuilder(const LambdaBuilder& lb){
|
---|
196 | lmax_=lb.lmax_;
|
---|
197 | mmax_=lb.mmax_;
|
---|
198 | l_=lb.l_;
|
---|
199 | m_=lb.m_;
|
---|
200 | lamlm_=lb.lamlm_;
|
---|
201 | cth_=lb.cth_;
|
---|
202 | sth_=lb.sth_;
|
---|
203 | lammm_=lb.lammm_;
|
---|
204 | par_lm_=lb.par_lm_;
|
---|
205 | lam_0_=lb.lam_0_;
|
---|
206 | lam_1_=lb.lam_1_;
|
---|
207 | a_rec_=lb.a_rec_;
|
---|
208 | b_rec_=lb.b_rec_;
|
---|
209 | fm2_=lb.fm2_;
|
---|
210 | }
|
---|
211 |
|
---|
212 | void LambdaBuilder::reset(){
|
---|
213 | l_=0;
|
---|
214 | m_=0;
|
---|
215 | lamlm_=1. / sqrt(4.*M_PI);
|
---|
216 | lammm_=1. / sqrt(4.*M_PI) *bignorm;
|
---|
217 | par_lm_=1.;
|
---|
218 | lam_0_=0.;
|
---|
219 | lam_1_=1./bignorm;
|
---|
220 | a_rec_=sqrt(3.);
|
---|
221 | b_rec_=0;
|
---|
222 | fm2_=0;
|
---|
223 | }
|
---|
224 |
|
---|
225 | double LambdaBuilder::lamlm(int flip){
|
---|
226 | if (flip < 0){
|
---|
227 | return par_lm_*lamlm();
|
---|
228 | } else{
|
---|
229 | return lamlm();
|
---|
230 | }
|
---|
231 | }
|
---|
232 |
|
---|
233 | double LambdaBuilder::lamlm(int l, int m){
|
---|
234 | if ((l <= lmax_ && l==l_+1 && m==m_) ||
|
---|
235 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){
|
---|
236 | step();
|
---|
237 | return lamlm();
|
---|
238 | } else if (l==l_ && m==m_){
|
---|
239 | return lamlm_;
|
---|
240 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){
|
---|
241 | reset();
|
---|
242 | while (l != l_ || m != m_){
|
---|
243 | step();
|
---|
244 | }
|
---|
245 | return lamlm();
|
---|
246 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){
|
---|
247 | while (l != l_ || m != m_){
|
---|
248 | step();
|
---|
249 | }
|
---|
250 | return lamlm();
|
---|
251 | } else{
|
---|
252 | return -1;
|
---|
253 | }
|
---|
254 | }
|
---|
255 |
|
---|
256 | double LambdaBuilder::lamlm(int l, int m, int flip){
|
---|
257 | if ((l <= lmax_ && l==l_+1 && m==m_) ||
|
---|
258 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){
|
---|
259 | step();
|
---|
260 | return lamlm(flip);
|
---|
261 | } else if (l==l_ && m==m_){
|
---|
262 | return lamlm(flip);
|
---|
263 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){
|
---|
264 | reset();
|
---|
265 | while (l != l_ || m != m_){
|
---|
266 | step();
|
---|
267 | }
|
---|
268 | return lamlm(flip);
|
---|
269 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){
|
---|
270 | while (l != l_ || m != m_){
|
---|
271 | step();
|
---|
272 | }
|
---|
273 | return lamlm(flip);
|
---|
274 | } else{
|
---|
275 | return -1;
|
---|
276 | }
|
---|
277 | }
|
---|
278 |
|
---|
279 | void LambdaBuilder::step(){
|
---|
280 | /*-----------------------------------------------------------------------
|
---|
281 | computes lambda_lm(theta) in an optimal fashion
|
---|
282 | looping over m
|
---|
283 | For example, if nlmax =3 and nmmax=3 the order is
|
---|
284 | (l,m)=(0,0),(1,0),(2,0),(3,0),(1,1),(2,1),(3,1),(2,2),(3,2),(3,3)
|
---|
285 | -----------------------------------------------------------------------*/
|
---|
286 | if (l_>=lmax_ && m_>=mmax_){return;}
|
---|
287 | if (l_==lmax_){//move on to the next m and calculate l=m
|
---|
288 | m_=m_+1;
|
---|
289 | l_=m_;
|
---|
290 | double f2m = 2. * m_;
|
---|
291 | fm2_ = ((double) m_)*m_;
|
---|
292 | par_lm_ = 1.; // = (-1)^(l+m)
|
---|
293 | if (m_ >= 1) { /* lambda_0_0 for m>0*/
|
---|
294 | lammm_ = - lammm_ * sth_ * sqrt( (f2m+1.)/ f2m );
|
---|
295 | }
|
---|
296 | lamlm_ = lammm_ / bignorm;
|
---|
297 | lam_0_ = 0.;
|
---|
298 | lam_1_ = 1. / bignorm; /*small number --> to avoid overflow*/
|
---|
299 | a_rec_ = sqrt( f2m + 3.);
|
---|
300 | b_rec_ = 0.;
|
---|
301 | } else{
|
---|
302 | l_=l_+1;
|
---|
303 | par_lm_ = - par_lm_; /* = (-1)^(l+m)*/
|
---|
304 | double lam_2 = (cth_ * lam_1_ - b_rec_ * lam_0_) * a_rec_;
|
---|
305 | // cout<<lam_2<<" "<<cth_<<" "<<lam_1_<<" "<<b_rec_<<" "<<lam_0_<<" "<<a_rec_<<endl;
|
---|
306 | //actual lambda_lm (small and big numbers cancel out)
|
---|
307 | lamlm_ = lam_2 * lammm_;
|
---|
308 |
|
---|
309 | b_rec_ = 1. / a_rec_;
|
---|
310 | double fl2 = (l_+1.)*(l_+1.);
|
---|
311 | a_rec_ = sqrt( (4. * fl2 - 1.) / (fl2-fm2_) );
|
---|
312 | // cout <<fl2<<" "<<fm2<<endl;
|
---|
313 | lam_0_ = lam_1_;
|
---|
314 | lam_1_ = lam_2;
|
---|
315 | }
|
---|
316 | }
|
---|