[461] | 1 | #include <math.h>
|
---|
| 2 | #include "lambuilder.h"
|
---|
| 3 | #include <iostream.h>
|
---|
[682] | 4 | #ifdef __MWERKS__
|
---|
| 5 | #include "unixmac.h"
|
---|
| 6 | #endif
|
---|
| 7 |
|
---|
[568] | 8 | //++
|
---|
| 9 | // Class Lambda2Builder
|
---|
| 10 | //
|
---|
| 11 | // (see separate documentation)
|
---|
| 12 | //--
|
---|
[461] | 13 |
|
---|
[682] | 14 | const double LambdaBuilder::bignorm = 1.e268; // = 1e-20*1.d288
|
---|
[518] | 15 |
|
---|
[461] | 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 | }
|
---|