| 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 | } | 
|---|