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