[658] | 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 | }
|
---|