37 void wigner_d_halfpi_risbo_scalar::do_line0 (
double *l1,
int j)
40 for (
int i=n; i>=1; --i)
41 l1[i] = xj*sqt[j]*(sqt[j-i]*l1[i] - sqt[i]*l1[i-1]);
44 void wigner_d_halfpi_risbo_scalar::do_line (
const double *l1,
double *l2,
48 double t1 = xj*sqt[j-k];
49 double t2 = xj*sqt[k];
50 for (
int i=n; i>=1; --i)
51 l2[i] = t1 * (sqt[j-i]*l2[i] - sqt[i]*l2[i-1])
52 +t2 * (sqt[j-i]*l1[i] + sqt[i]*l1[i-1]);
53 l2[0] = sqt[j] * (t2*l1[0]+t1*l2[0]);
56 wigner_d_halfpi_risbo_scalar::wigner_d_halfpi_risbo_scalar(
int lmax)
57 : pq(.5*sqrt(2.)), sqt(2*lmax+1), d(lmax+2,lmax+2), n(-1)
58 {
for (
tsize m=0; m<sqt.size(); ++m) sqt[m] = sqrt(
double(m)); }
60 const arr2<double> &wigner_d_halfpi_risbo_scalar::recurse ()
67 d[0][0] = .5; d[0][1] =-pq;
68 d[1][0] = pq; d[1][1] = 0.;
74 for (
int i=0; i<n; ++i)
76 d[i][n]=flip*d[i][n-2];
77 d[n][i]=flip*d[n-2][i];
80 d[n][n]=flip*d[n-2][n];
82 do_line (d[n-1],d[n],2*n-1,n);
83 for (
int k=n; k>=2; --k)
85 do_line (d[k-2],d[k-1],2*n-1,k-1);
86 do_line (d[k-1],d[k],2*n,k);
88 do_line0 (d[0],2*n-1);
89 do_line (d[0],d[1],2*n,1);
95 void wigner_d_risbo_scalar::do_line0 (
double *l1,
int j)
99 for (
int i=j-1; i>=1; --i)
100 l1[i] = xj*sqt[j]*(q*sqt[j-i]*l1[i] - p*sqt[i]*l1[i-1]);
103 void wigner_d_risbo_scalar::do_line (
const double *l1,
double *l2,
int j,
int k)
106 double t1 = xj*sqt[j-k]*q, t2 = xj*sqt[j-k]*p;
107 double t3 = xj*sqt[k]*p, t4 = xj*sqt[k]*q;
108 l2[j] = sqt[j] * (t4*l1[j-1]-t2*l2[j-1]);
109 for (
int i=j-1; i>=1; --i)
110 l2[i] = t1*sqt[j-i]*l2[i] - t2*sqt[i]*l2[i-1]
111 +t3*sqt[j-i]*l1[i] + t4*sqt[i]*l1[i-1];
112 l2[0] = sqt[j] * (t3*l1[0]+t1*l2[0]);
115 wigner_d_risbo_scalar::wigner_d_risbo_scalar(
int lmax,
double ang)
116 : p(sin(ang/2)), q(cos(ang/2)), sqt(2*lmax+1),
117 d(lmax+1,2*lmax+1), n(-1)
118 {
for (
tsize m=0; m<sqt.size(); ++m) sqt[m] = sqrt(
double(m)); }
127 d[0][0] = q*q; d[0][1] = -p*q*sqt[2]; d[0][2] = p*p;
128 d[1][0] = -d[0][1]; d[1][1] = q*q-p*p; d[1][2] = d[0][1];
133 int sign = (n&1)? -1 : 1;
134 for (
int i=0; i<=2*n-2; ++i)
136 d[n][i] =
sign*d[n-2][2*n-2-i];
139 do_line (d[n-1],d[n],2*n-1,n);
140 for (
int k=n; k>=2; --k)
142 do_line (d[k-2],d[k-1],2*n-1,k-1);
143 do_line (d[k-1],d[k],2*n,k);
145 do_line0 (d[0],2*n-1);
146 do_line (d[0],d[1],2*n,1);
152 wigner_d_halfpi_risbo_openmp::wigner_d_halfpi_risbo_openmp(
int lmax)
153 : pq(.5*sqrt(2.)), sqt(2*lmax+1), d(lmax+2,lmax+2),
154 dd(lmax+2,lmax+2), n(-1)
155 {
for (
tsize m=0; m<sqt.size(); ++m) sqt[m] = sqrt(
double(m)); }
157 const arr2<double> &wigner_d_halfpi_risbo_openmp::recurse ()
165 d[0][0] = .5; d[0][1] =-pq;
166 d[1][0] = pq; d[1][1] = 0.;
172 for (
int i=0; i<n; ++i)
174 d[i][n]=flip*d[i][n-2];
175 d[n][i]=flip*d[n-2][i];
178 d[n][n]=flip*d[n-2][n];
180 for (
int j=2*n-1; j<=2*n; ++j)
184 dd[0][0] = pq*d[0][0];
185 for (
int i=1;i<=n; ++i)
186 dd[0][i] = tmpx1*sqt[j]*(sqt[j-i]*d[0][i] - sqt[i]*d[0][i-1]);
190 #pragma omp for schedule(static) 193 double stmp1=sqt[j-k]*tmpx1;
194 double stmp2=sqt[k]*tmpx1;
195 double save1 = stmp1*d[k][0], save2 = stmp2*d[k-1][0];
196 dd[k][0] = sqt[j]*(save1+save2);
197 for (
int i=1; i<=n; ++i)
199 dd[k][i] = sqt[i]*(save2-save1);
200 save1 = stmp1*d[k][i];
201 save2 = stmp2*d[k-1][i];
202 dd[k][i] += sqt[j-i]*(save1+save2);
212 wigner_d_risbo_openmp::wigner_d_risbo_openmp(
int lmax,
double ang)
213 : p(sin(ang/2)), q(cos(ang/2)), sqt(2*lmax+1),
214 d(lmax+1,2*lmax+1), dd(lmax+1,2*lmax+1), n(-1)
215 {
for (
tsize m=0; m<sqt.size(); ++m) sqt[m] = sqrt(
double(m)); }
224 d[0][0] = q*q; d[0][1] = -p*q*sqt[2]; d[0][2] = p*p;
225 d[1][0] = -d[0][1]; d[1][1] = q*q-p*p; d[1][2] = d[0][1];
230 int sign = (n&1)? -1 : 1;
231 for (
int i=0; i<=2*n-2; ++i)
233 d[n][i] =
sign*d[n-2][2*n-2-i];
236 for (
int j=2*n-1; j<=2*n; ++j)
239 dd[0][0] = q*d[0][0];
240 for (
int i=1;i<j; ++i)
241 dd[0][i] = xj*sqt[j]*(q*sqt[j-i]*d[0][i] - p*sqt[i]*d[0][i-1]);
242 dd[0][j] = -p*d[0][j-1];
246 #pragma omp for schedule(static) 249 double t1 = xj*sqt[j-k]*q, t2 = xj*sqt[j-k]*p;
250 double t3 = xj*sqt[k ]*p, t4 = xj*sqt[k ]*q;
251 dd[k][0] = xj*sqt[j]*(q*sqt[j-k]*d[k][0] + p*sqt[k]*d[k-1][0]);
252 for (
int i=1; i<j; ++i)
253 dd[k][i] = t1*sqt[j-i]*d[k ][i] - t2*sqt[i]*d[k ][i-1]
254 + t3*sqt[j-i]*d[k-1][i] + t4*sqt[i]*d[k-1][i-1];
255 dd[k][j] = -t2*sqt[j]*d[k][j-1] + t4*sqt[j]*d[k-1][j-1];
267 : eps(epsilon), lmax(lmax_),
268 logsum(2*lmax+1), lc05(thetas.size()), ls05(thetas.size()),
269 flm1(2*lmax+1), flm2(2*lmax+1),
270 cf(maxscale+1-minscale), costh(thetas.size()), xl(lmax+1),
271 thetaflip(thetas.size()),
272 m1(-1234567890), m2(-1234567890), am1(-1234567890), am2(-1234567890),
273 mlo(-1234567890), mhi(-1234567890),
274 fx(lmax+2), result(lmax+1)
279 logsum[m] = logsum[m-1]+log(static_cast<long double>(m));
282 flm1[lm] = sqrt(1./(lm+1.));
283 flm2[lm] = sqrt(lm/(lm+1.));
286 cf[i] = ldexp(1.,(
int(i)+minscale)*large_exponent2);
288 fsmall = ldexp(1.,-large_exponent2);
289 fbig = ldexp(1.,large_exponent2);
293 double theta=
fmodulo(thetas[i],twopi);
294 if (theta>pi) theta-=twopi;
295 thetaflip[i]=(theta<0);
298 if (theta==0.) theta=1e-16;
299 if (
abs_approx(theta,pi,1e-15)) theta=pi-1e-15;
301 lc05[i]=log(cos(0.5L*theta));
302 ls05[i]=log(sin(0.5L*theta));
305 for (
tsize l=1; l<xl.
size(); ++l) xl[l]=1./l;
308 fx[l][0]=fx[l][1]=fx[l][2]=0.;
313 if ((m1_==m1) && (m2_==m2))
return;
315 int mlo_=abs(m1_), mhi_=abs(m2_);
316 if (mhi_<mlo_) swap(mhi_,mlo_);
317 bool ms_similar = ((mhi==mhi_) && (mlo==mlo_));
318 bool flip_m_sign = ms_similar && ((m1*m2)!=(m1_*m2_));
321 mlo=am1=abs(m1); mhi=am2=abs(m2);
322 if (mhi<mlo) swap(mhi,mlo);
327 for (
int l=mhi; l<lmax; ++l)
328 fx[l+1][1]=-fx[l+1][1];
332 for (
int l=mhi; l<lmax; ++l)
334 double t = flm1[l+m1]*flm1[l-m1]*flm1[l+m2]*flm1[l-m2];
338 fx[l+1][1]=m1*m2*xl[l]*xl[l+1];
339 t = flm2[l+m1]*flm2[l-m1]*flm2[l+m2]*flm2[l-m2];
340 fx[l+1][2]=t*l1*xl[l];
344 prefactor = 0.5L*(logsum[2*mhi]-logsum[mhi+mlo]-logsum[mhi-mlo]);
349 cosPow = mhi-m2; sinPow = mhi+m2;
351 { swap(cosPow, sinPow); preMinus=((mhi-m2)&1); }
355 cosPow = mhi+m1; sinPow = mhi-m1;
357 { swap(cosPow, sinPow); preMinus=((mhi+m1)&1); }
363 calc(nth, firstl, result);
370 const dbl3 *fy = &fx[0];
371 const double cth = costh[nth];
372 double *res = &resx[0];
373 long double logval = prefactor + lc05[nth]*cosPow + ls05[nth]*sinPow;
375 int scale = int (logval/large_exponent2)-minscale;
377 double rec2 = double(exp(ln2*(logval-(scale+minscale)*large_exponent2)));
378 if (preMinus ^ (thetaflip[nth] && ((am1+am2)&1))) rec2 = -rec2;
383 rec1 = (cth - fy[l][1])*fy[l][0]*rec2 - fy[l][2]*rec1;
385 rec2 = (cth - fy[l][1])*fy[l][0]*rec1 - fy[l][2]*rec2;
387 while (abs(rec2)>fbig)
395 if (scale<0) { firstl=lmax+1;
return; }
401 if (abs(rec2)>eps)
break;
402 rec1 = (cth - fy[l+1][1])*fy[l+1][0]*rec2 - fy[l+1][2]*rec1;
403 if (abs(rec1)>eps) { swap(rec1,rec2); ++l;
break; }
404 rec2 = (cth - fy[l+2][1])*fy[l+2][0]*rec1 - fy[l+2][2]*rec2;
406 if ((abs(rec2)<=eps) && (++l<=lmax))
408 rec1 = (cth - fy[l][1])*fy[l][0]*rec2 - fy[l][2]*rec1;
412 if ((l==lmax)&&(abs(rec2)<=eps)) { firstl=lmax+1;
return; }
420 res[l+1] = rec1 = (cth - fy[l+1][1])*fy[l+1][0]*rec2 - fy[l+1][2]*rec1;
421 res[l+2] = rec2 = (cth - fy[l+2][1])*fy[l+2][0]*rec1 - fy[l+2][2]*rec2;
426 res[l] = rec1 = (cth - fy[l][1])*fy[l][0]*rec2 - fy[l][2]*rec1;
428 res[l] = rec2 = (cth - fy[l][1])*fy[l][0]*rec1 - fy[l][2]*rec2;
434 #define RENORMALIZE \ 437 double rec1a, rec1b, rec2a, rec2b, cfa, cfb; \ 438 rec1.writeTo(rec1a,rec1b); rec2.writeTo(rec2a,rec2b); \ 439 corfac.writeTo(cfa,cfb); \ 440 while (abs(rec2a)>fbig) \ 442 rec1a*=fsmall; rec2a*=fsmall; ++scale1; \ 443 cfa = (scale1<0) ? 0. : cf[scale1]; \ 445 while (abs(rec2b)>fbig) \ 447 rec1b*=fsmall; rec2b*=fsmall; ++scale2; \ 448 cfb = (scale2<0) ? 0. : cf[scale2]; \ 450 rec1.readFrom(rec1a,rec1b); rec2.readFrom(rec2a,rec2b); \ 451 corfac.readFrom(cfa,cfb); \ 455 #define GETPRE(prea,preb,lv) \ 456 prea=(cth-fy[lv][1])*fy[lv][0]; \ 459 #define NEXTSTEP(prea,preb,prec,pred,reca,recb,lv) \ 464 V2df t0 (fy[lv][0]); \ 473 calc(nth1, nth2, firstl, result2);
481 const dbl3 *fy = &fx[0];
482 const V2df cth(costh[nth1],costh[nth2]);
483 V2df *res = &resx[0];
484 long double logval1 = prefactor + lc05[nth1]*cosPow + ls05[nth1]*sinPow,
485 logval2 = prefactor + lc05[nth2]*cosPow + ls05[nth2]*sinPow;
488 int scale1 = int (logval1/large_exponent2)-minscale,
489 scale2 = int (logval2/large_exponent2)-minscale;
491 double tr1 = double(exp(ln2*(logval1-(scale1+minscale)*large_exponent2))),
492 tr2 = double(exp(ln2*(logval2-(scale2+minscale)*large_exponent2)));
493 if (preMinus ^ (thetaflip[nth1] && ((am1+am2)&1))) tr1 = -tr1;
494 if (preMinus ^ (thetaflip[nth2] && ((am1+am2)&1))) tr2 = -tr2;
496 V2df corfac ((scale1<0) ? 0. : cf[scale1], (scale2<0) ? 0. : cf[scale2]);
501 V2df pre0,pre1,pre2,pre3;
503 GETPRE(pre0,pre1,l+1)
504 if ((scale1<0) && (scale2<0))
509 NEXTSTEP(pre0,pre1,pre2,pre3,rec1,rec2,l+1)
511 NEXTSTEP(pre2,pre3,pre0,pre1,rec2,rec1,l+1)
512 if (any(abs(rec2).gt(fbig2)))
515 if ((scale1>=0) || (scale2>=0))
break;
522 GETPRE(pre0,pre1,l+1)
526 res[l]=t1=rec2*corfac;
527 if (any(abs(t1).gt(eps2)))
531 NEXTSTEP(pre0,pre1,pre2,pre3,rec1,rec2,l+1)
533 res[l]=t1=rec1*corfac;
534 if (any(abs(t1).gt(eps2)))
535 { swap(rec1,rec2);
break; }
538 NEXTSTEP(pre2,pre3,pre0,pre1,rec2,rec1,l+1)
540 if (any(abs(rec2).gt(fbig2)))
544 if ((l==lmax)&&(!any(abs(rec2).gt(eps2)))) { firstl=lmax+1;
return; }
548 GETPRE(pre0,pre1,l+1)
552 res[l]=t1=rec2*corfac;
553 if (all(abs(t1).ge(eps2)))
557 NEXTSTEP(pre0,pre1,pre2,pre3,rec1,rec2,l+1)
559 res[l]=t1=rec1*corfac;
560 if (all(abs(t1).ge(eps2)))
561 { swap(rec1,rec2);
break; }
564 NEXTSTEP(pre2,pre3,pre0,pre1,rec2,rec1,l+1)
566 if (any(abs(rec2).gt(fbig2)))
574 GETPRE(pre0,pre1,l+1)
578 NEXTSTEP(pre0,pre1,pre2,pre3,rec1,rec2,l+2)
580 NEXTSTEP(pre2,pre3,pre0,pre1,rec2,rec1,l+3)
586 NEXTSTEP(pre0,pre1,pre2,pre3,rec1,rec2,l+1)
593 wigner_estimator::wigner_estimator (
int lmax_,
double epsPow_)
594 : lmax(lmax_), xlmax(1./lmax_), epsPow(epsPow_) {}
596 void wigner_estimator::prepare_m (
int m1_,
int m2_)
598 m1=abs(m1_); m2=abs(m2_);
600 double cos1=m1*xlmax, cos2=m2*xlmax;
601 double s1s2=sqrt((1.-cos1*cos1)*(1.-cos2*cos2));
602 cosm1m2=cos1*cos2+s1s2;
605 bool wigner_estimator::canSkip (
double theta)
const 607 if (mbig==lmax)
return false;
608 double delta = m1*m1 + m2*m2 - abs(2.*m1*m2*cos(theta));
609 double sth = sin(theta);
610 if (
abs_approx(sth,0.,1e-7))
return (delta>1.);
611 return (((sqrt(delta)-epsPow)*cosm1m2/abs(sth)) > lmax);
void prepare(int m1_, int m2_)
wignergen_scalar(int lmax_, const arr< double > &thetas, double epsilon)
const arr< double > & calc(int nth, int &firstl)
#define planck_assert(testval, msg)
double fmodulo(double v1, double v2)
void fast_alloc(tsize sz1, tsize sz2)
bool abs_approx(F a, F b, F epsilon=1e-5)
T sign(const T &signvalue)