2 #ifdef USE_FORTRAN_GAUNT_XU
3 void __vec_trans_MOD_gaunt_xu(const double *m
, const double *n
, const double *mu
, const double *nu
, const int *qmax
, double *v_aq
, int *err
);
5 void gaunt_xu(int m
, int n
, int mu
, int nu
, int qmax
, double *v_aq
, int *err
) {
6 double mf
= m
, nf
=n
, muf
=mu
,nuf
=nu
;
7 __vec_trans_MOD_gaunt_xu(&mf
,&nf
,&muf
,&nuf
,&qmax
,v_aq
,err
);
10 #else //!USE_FORTRAN_GAUNT_XU
14 #include "assert_cython_workaround.h"
16 #define ZERO_THRESHOLD 1.e-8
17 #define BF_PREC 1.e-10
18 // "Besides, the determined Real Programmer can write FORTRAN programs in any language."
19 // -- Ed Post, Real Programmers Don't Use Pascal, 1982.
21 // logarithm of factorial (from basicsubs.f90)
22 double lnf (double z
) {
23 // expansion parameters
24 static const double v_c0
[] = {
25 0.16427423239836267e5
, -0.48589401600331902e5
, 0.55557391003815523e5
, -0.30964901015912058e5
,
26 0.87287202992571788e4
, -0.11714474574532352e4
, 0.63103078123601037e2
, -0.93060589791758878e0
,
27 0.13919002438227877e-2,-0.45006835613027859e-8, 0.13069587914063262e-9
29 static const double cp
= 2.5066282746310005;
32 b
= (z
+ 0.5) * log(b
) - b
;
33 for (int i
= 0; i
< (sizeof(v_c0
) / sizeof(double)); i
++) {
41 // logarithm of Pochhammer function (from basicsubs.f90)
42 // FIXME replace with standard C99 lgamma functions
43 double lpoch(double x
, double n
) {
44 if(fabs(n
) < 1e-5) // ???
47 return lnf(sum
-1.) - lnf(x
-1.);
50 // pochhammer function: substitute for fortran DPOCH
51 // gamma(a+x) / gamma(a)
52 double poch(double a
, double x
) { // FIXME replace with standard C99 lgamma functions
53 return exp(lpoch(a
,x
));
56 double f_a0 (int m
, int n
, int mu
, int nu
) {
57 double logw
= lnf(n
+nu
-m
-mu
) - lnf(n
-m
) - lnf(nu
-mu
);
58 double logp
= lpoch(n
+1, n
) + lpoch(nu
+1, nu
) - lpoch(n
+nu
+1, n
+nu
);
59 return exp(logw
+logp
);
62 // coefficient Ap(m,n,mu,nu,p) (from vec_trans.f90)
63 int f_Ap(int m
, int n
, int mu
, int nu
, int p
) {
64 return p
*(p
-1)*(m
-mu
)-(m
+mu
)*(n
-nu
)*(n
+nu
+1);
67 // coefficient a(m,n,mu,nu,1) normalized by the backward recursion (from vec_trans.f90)
69 double f_a1norm(int m
, int n
, int mu
, int nu
) {
70 int n4
= n
+ nu
- m
- mu
;
71 return ((2.*n
+ 2.*nu
- 3.) / 2.) * (1. - ((2.*n
+ 2.*nu
- 1.) / (n4
* (n4
-1.)))
72 * ((m
- n
) * (m
- n
+ 1.) / (2.*n
- 1.) + (mu
-nu
) * (mu
-nu
+1.)/(2.*nu
-1.)));
75 // coefficient a(m,n,mu,nu,2) normalized by the backward recursion (From vec_trans.f90)
77 double f_a2norm(int m
, int n
, int mu
, int nu
) {
78 double n4
= n
+ nu
- m
- mu
;
79 double n2nu
= 2*n
+ 2*nu
;
81 double munu
= mu
- nu
;
83 return ((n2nu
-1.)*(n2nu
-7.)/4.) * \
84 ( ((n2nu
-3.)/(n4
*(n4
-1.))) * \
85 ( ((n2nu
-5.)/(2.*(n4
-2.)*(n4
-3.))) * \
86 ( mn
*(mn
+1.)*(mn
+2.)*(mn
+3.)/((2.*n
-1.)*(2.*n
-3.)) + \
87 2.*mn
*(mn
+1.)*munu
*(munu
+1.)/((2.*n
-1.)*(2.*nu
-1.)) + \
88 munu
*(munu
+1.)*(munu
+2.)*(munu
+3.)/((2.*nu
-1.)*(2.*nu
-3.)) \
89 ) - mn
*(mn
+1.)/(2.*n
-1.) - munu
*(munu
+1.)/(2.*nu
-1.) ) +0.5);
92 // just for convenience – square of ints
93 static inline int isq(int x
) {return x
* x
;}
94 static inline double fsq(float x
) {return x
* x
;}
96 double f_alpha(int n
, int nu
, int p
) {
97 return (isq(p
) - isq(n
-nu
))*(isq(p
)-isq(n
+nu
+1)) / (double)(4*isq(p
)-1);
100 static inline int min1pow(int pow
) { return (pow
% 2) ? -1 : 1; }
102 // starting value of coefficient a(m,n,mu,nu,qmax) for the forward recursion
103 double f_aqmax(int m
, int n
, int mu
, int nu
, int qmax
) {
104 int pmin
= n
+ nu
- 2*qmax
;
105 // TODO? zde měl int a double varianty téhož – má to nějaký smysl???
107 double logw
= lnf(n
+m
) + lnf(2*pmin
+1) - lnf(nu
-mu
) - lnf(n
-nu
) - lnf(pmin
+m
+mu
);
108 double logp
= lpoch(nu
+1, nu
) - lpoch(n
+1, n
+1);
109 return min1pow(mu
)*exp(logw
+logp
);
110 } else if (pmin
== nu
-n
) {
111 double logw
= lnf(nu
+mu
) + lnf(2*pmin
+1) - lnf(n
-m
) - lnf(nu
-n
) - lnf(pmin
+m
+mu
);
112 double logp
= lpoch(n
+1, n
) - lpoch(nu
+1, nu
+1); // ??? nešel by druhý lpoch nahradit něčím rozumnějším?
113 return min1pow(m
)*exp(logw
+logp
);
114 } else if (pmin
== m
+mu
) {
115 double logw
= lpoch(qmax
+1,qmax
)+lnf(n
+nu
-qmax
)+lnf(n
+m
)+lnf(nu
+mu
) \
116 -lnf(n
-qmax
)-lnf(nu
-qmax
)-lnf(n
-m
)-lnf(nu
-mu
)-lnf(n
+nu
+pmin
+1);
117 return min1pow(n
+m
-qmax
)*(2*pmin
+1)*exp(logw
);
118 } else if (pmin
== -m
-mu
) {
119 double logw
= lpoch(qmax
+1,qmax
)+lnf(n
+nu
-qmax
)+lnf(pmin
-m
-mu
) \
120 -lnf(n
-qmax
)-lnf(nu
-qmax
)-lnf(n
+nu
+pmin
+1);
121 return min1pow(nu
+mu
-qmax
)*(2*pmin
+1)*exp(logw
);
122 } else if (pmin
==m
+mu
+1) {
123 int Apmin
= f_Ap(m
,n
,mu
,nu
,pmin
);
124 double logw
= lpoch(qmax
+1,qmax
)+lnf(n
+nu
-qmax
)+lnf(n
+m
)+lnf(nu
+mu
) \
125 -lnf(n
+nu
+pmin
+1)-lnf(n
-qmax
)-lnf(nu
-qmax
)-lnf(n
-m
)-lnf(nu
-mu
);
126 return min1pow(n
+m
-qmax
)*Apmin
*(2*pmin
+1)*exp(logw
)/(double)(pmin
-1);
127 } else if (pmin
==-m
-mu
+1) {
128 int Apmin
=f_Ap(m
,n
,mu
,nu
,pmin
);
129 double logw
=lpoch(qmax
+1,qmax
)+lnf(n
+nu
-qmax
)+lnf(pmin
-m
-mu
) \
130 -lnf(n
+nu
+pmin
+1)-lnf(n
-qmax
)-lnf(nu
-qmax
);
131 return min1pow(nu
+mu
-qmax
)*Apmin
*(2*pmin
+1)*exp(logw
) / (double)(pmin
-1);
136 // starting value of coefficient a(m,n,mu,nu,qmax-1) for the forward recursion
137 double f_aqmax_1(int m
, int n
, int mu
, int nu
, int qmax
) {
138 int pmin
=n
+nu
-2*qmax
;
139 //pmin_i=INT(pmin,lo)
140 //qmaxr=REAL(qmax,dbl)
141 int Apmin2
=f_Ap(m
,n
,mu
,nu
,pmin
+2);
143 if (pmin
==(m
+mu
+1)) { // pmin_if
144 double logw
=lpoch(qmax
+1,qmax
)+lnf(n
+nu
-qmax
)+lnf(n
+m
)+lnf(nu
+mu
)
145 -lnf(n
+nu
+pmin
)-lnf(n
-qmax
+1)-lnf(nu
-qmax
+1)-lnf(n
-m
)-lnf(nu
-mu
);
146 double f1
=min1pow(m
+n
-qmax
)*Apmin2
*(2.*pmin
+3.)*(2.*pmin
+5.) /(pmin
*(n
+nu
+pmin
+3.));
147 double f2
=(n
-qmax
)*(nu
-qmax
)*(2.*qmax
+1.)/((pmin
+m
+mu
+1.)*(pmin
+m
+mu
+2.)*(2*qmax
-1.));
148 return f1
*f2
*exp(logw
);
149 } else if (pmin
==(-m
-mu
+1)) {
150 double logw
=lpoch(qmax
+1.,qmax
+1.)+lnf(n
+nu
-qmax
)+lnf(pmin
-m
-mu
)
151 -lnf(n
+nu
+pmin
)-lnf(n
-qmax
+1.)-lnf(nu
-qmax
+1.);
152 double f1
=min1pow(nu
+mu
-qmax
)*Apmin2
*(2.*pmin
+3.)*(2.*pmin
+5.)
153 /(6.*pmin
*(n
+nu
+pmin
+3.));
154 double f2
=(n
-qmax
)*(nu
-qmax
)/(2.*qmax
-1.);
155 return f1
*f2
*exp(logw
);
158 }//END FUNCTION f_aqmax_1
161 // coeff a(m,n,mu,nu,2) normalizzato per la backward recursion calcolato questa volta per ricorsione
162 // (from vec_trans.f90)
163 double f_a2normr(int m
, int n
, int mu
, int nu
, double a1norm
) {
167 int Ap4
= f_Ap(m
,n
,mu
,nu
,p
+4);
168 int Ap6
= f_Ap(m
,n
,mu
,nu
,p
+6);
170 double alphap1
=f_alpha(n
,nu
,p
+1);
171 double alphap2
=f_alpha(n
,nu
,p
+2);
176 double c0
=(p
+2.)*(p1
+1.)*alphap1
;
177 double c1
=(p
+1.)*(p2
+2.)*alphap2
;
179 return (c1
/c0
)*a1norm
;
180 } else /* Ap6 != 0 */ {
181 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
182 double Ap3
=f_Ap(m
,n
,mu
,nu
,p
+3);
183 double Ap5
=f_Ap(m
,n
,mu
,nu
,p
+5);
184 double alphap5
=f_alpha(n
,nu
,p
+5);
186 double c0
=(p
+2.)*(p
+3.)*(p
+5.)*(p1
+1.)*(p1
+2.)*(p1
+4.)*Ap6
*alphap1
;
187 double c1
=(p
+5.)*(p1
+4.)*Ap6
*(Ap2
*Ap3
+(p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*alphap2
);
188 double c2
=(p
+2.)*(p2
+3.)*Ap2
*(Ap5
*Ap6
+(p
+4.)*(p
+6.)*(p1
+5.)*(p2
+5.)*alphap5
);
190 return (c1
/c0
)*a1norm
+(c2
/c0
);
192 } else /* Ap4 != 0 */ {
193 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
194 double Ap3
=f_Ap(m
,n
,mu
,nu
,p
+3);
195 double alphap3
=f_alpha(n
,nu
,p
+3);
196 double alphap4
=f_alpha(n
,nu
,p
+4);
198 double c0
=(p
+2.)*(p
+3.)*(p1
+1.)*(p1
+2.)*Ap4
*alphap1
;
199 double c1
=Ap2
*Ap3
*Ap4
+(p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*Ap4
*alphap2 \
200 + (p
+2.)*(p
+4.)*(p1
+3.)*(p2
+3.)*Ap2
*alphap3
;
201 double c2
=-(p
+2.)*(p
+3.)*(p2
+3.)*(p2
+4.)*Ap2
*alphap4
;
203 return (c1
/c0
)*a1norm
+(c2
/c0
);
207 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
209 int j3minimum(int j1
, int j2
, int m1
, int m2
) {
210 return MAX(abs(j1
-j2
), abs(m1
+m2
));
213 int nw(int j1
, int j2
, int m1
, int m2
) {
214 return j1
+j2
+1-MAX(abs(j1
-j2
),abs(m1
+m2
));
217 // per calcolare il primo termine della backward recursion; vec_trans.f90
218 double wdown0(int j1
, int j2
, int m1
, int m2
) {
219 double logw
=.5*(lnf(2.*j1
)+lnf(2.*j2
)+lnf(j1
+j2
-m1
-m2
)+lnf(j1
+j2
+m1
+m2
) - \
220 lnf(2.*j1
+2.*j2
+1.)-lnf(j1
-m1
)-lnf(j1
+m1
)-lnf(j2
-m2
)-lnf(j2
+m2
));
221 return min1pow(j1
+j2
+m1
+m2
)*exp(logw
);
224 // per calcolar il primo termine della upward recursion; vec_trans.f90
225 double wup0(int j1
, int j2
, int m1
, int m2
) {
227 if ( ((j1
-j2
)>=0) && ( abs(j1
-j2
)>=abs(m1
+m2
)) ) {
229 logw
=0.5 * ( lnf(j1
-m1
)+lnf(j1
+m1
)+lnf(2.*j1
-2.*j2
)+lnf(2.*j2
) - \
230 lnf(j2
-m2
)-lnf(j2
+m2
)-lnf(j1
-j2
-m1
-m2
)-lnf(j1
-j2
+m1
+m2
)-lnf(2.*j1
+1.) );
232 return min1pow(j1
+m1
)*exp(logw
);
233 } else if ( ((j1
-j2
)<0) && ( abs(j1
-j2
)>=abs(m1
+m2
)) ) {
235 logw
=0.5 * ( lnf(j2
-m2
)+lnf(j2
+m2
)+lnf(2.*j2
-2.*j1
)+lnf(2.*j1
) - \
236 lnf(j1
-m1
)-lnf(j1
+m1
)-lnf(j2
-j1
-m1
-m2
)-lnf(j2
-j1
+m1
+m2
)-lnf(2.*j2
+1.) );
238 return min1pow(j2
+m2
)*exp(logw
);
239 } else if ( ((m1
+m2
)>0) && (abs(j1
-j2
)<abs(m1
+m2
)) ) {
241 logw
=0.5 * ( lnf(j1
+m1
)+lnf(j2
+m2
)+lnf(j1
+j2
-m1
-m2
)+lnf(2.*m1
+2.*m2
) - \
242 lnf(j1
-m1
)-lnf(j2
-m2
)-lnf(j1
-j2
+m1
+m2
)-lnf(j2
-j1
+m1
+m2
)-lnf(j1
+j2
+m1
+m2
+1.) );
244 return min1pow(j2
+m2
)*exp(logw
);
245 } else if ( ((m1
+m2
)<0) && (abs(j1
-j2
)<abs(m1
+m2
)) ) {
247 logw
=0.5 * ( lnf(j1
-m1
)+lnf(j2
-m2
)+lnf(j1
+j2
+m1
+m2
)+lnf(-2.*m1
-2.*m2
) - \
248 lnf(j1
+m1
)-lnf(j2
+m2
)-lnf(j1
-j2
-m1
-m2
)-lnf(j2
-j1
-m1
-m2
)-lnf(j1
+j2
-m1
-m2
+1.) );
250 return min1pow(j1
+m1
)*exp(logw
);
255 // coefficiente per il calcolo ricorsivo
256 double cr(double j1
, double j2
, double j3
, double m1
, double m2
, double m3
) {
257 return (fsq(j3
)-fsq(j1
-j2
))*( fsq(j1
+j2
+1)-fsq(j3
) )*( fsq(j3
)-fsq(m3
) );
261 // coefficiente per il calcolo ricorsivo
262 // (nebo raději všude doubly)?
263 double dr(double j1
, double j2
, double j3
, double m1
, double m2
, double m3
) {
264 return -(2*j3
+1)*( j1
*(j1
+1)*m3
-j2
*(j2
+1)*m3
-j3
*(j3
+1)*(m2
-m1
) );
268 //******************************************************************************
269 //7) subroutine Wigner3jm: calcolo il vettore di simboli 3jm
270 //******************************************************************************
272 void wigner3jm(int j1
, int j2
, int m1
, int m2
, int j3min
, int j3max
, double *v_w3jm
){
273 // in the original code, the dimension of v_w3jm is (j3min:j3max).
274 // In C, this means it has length j3max-j3min+1, and we must
275 // always deduct j3min from the indices
277 // Inizializzo gli indici per la downward recursion
278 int j3
= j3max
; // we don't use separate j3int as gevero does.
280 // In questo if separo i casi in cui ho un vettore di lunghezza uno da quelli che
281 // necessitano dell'uso della ricorsione
282 if (j3min
==j3max
) // big_if
283 v_w3jm
[j3max
-j3min
]=wdown0(j1
,j2
,m1
,m2
); // Unico termine da calcolare
285 // Si inizializza la ricorsione
286 v_w3jm
[j3max
-j3min
]=wdown0(j1
,j2
,m1
,m2
);
287 v_w3jm
[j3max
-1-j3min
]=-(dr(j1
,j2
,j1
+j2
,m1
,m2
,-m1
-m2
)/( (j1
+j2
+1)*cr(j1
,j2
,j1
+j2
,m1
,m2
,-m1
-m2
) ))*v_w3jm
[j3max
-j3min
];
290 // Ciclo per il calcolo ricorsivo
291 while(j3
-2>=j3min
){ // down_do
293 //Primo coeff della ricorsione
294 double cd1
=dr(j1
,j2
,j3
-1,m1
,m2
,-m1
-m2
)/(j3
*cr(j1
,j2
,j3
-1,m1
,m2
,-m1
-m2
));
295 double cd2
=((j3
-1)*cr(j1
,j2
,j3
,m1
,m2
,-m1
-m2
))/(j3
*cr(j1
,j2
,j3
-1,m1
,m2
,-m1
-m2
));
297 v_w3jm
[j3
-2-j3min
]=-cd1
*v_w3jm
[j3
-1-j3min
]-cd2
*v_w3jm
[j3
-j3min
];
299 //Aggiorno gli indici
303 // Inizializzo gli indici per la upward recursion
306 // Calcolo del primo termine di wigner dal basso
307 v_w3jm
[j3
-j3min
]=wup0(j1
,j2
,m1
,m2
);
309 // Calcolo del secondo termine di wigner dal basso
310 // Pongo anche la condizione sul coefficienti nel caso ci sia signolarita'
311 double cu3
= (j3min
==0) ? 0 : (dr(j1
,j2
,j3
,m1
,m2
,-m1
-m2
)/(j3
*cr(j1
,j2
,j3
+1,m1
,m2
,-m1
-m2
)));
313 double w3jm_temp
=-cu3
*v_w3jm
[j3
-j3min
];
315 // If legato alla monotonia della successione
316 if (fabs(w3jm_temp
)>fabs(v_w3jm
[j3min
-j3min
])) { //up_if
318 // Aggiorno gli indici e metto nell'array il secondo valore
319 // in questo modo sono pronto per iniziale la upward recursion
322 v_w3jm
[j3
-j3min
]=w3jm_temp
;
323 while(1) { // up_do: DO
324 //Aggiorno gli indici
327 if (j3
-1==j3max
) break;
329 // IF ((INT(-m1)==-1).AND.(INT(j1)==1).AND.(INT(m2)==1).AND.(INT(j2)==2)) THEN
330 // WRITE(*,*) "j3-1,cr1,cr2",j3-1,cr(j1,j2,j3,m1,m2,-m1-m2),cr(j1,j2,j3,m1,m2,-m1-m2)
333 //Primo e secondo coeff della ricorsione
334 double cu1
=dr(j1
,j2
,j3
-1,m1
,m2
,-m1
-m2
)/((j3
-1)*cr(j1
,j2
,j3
,m1
,m2
,-m1
-m2
));
335 double cu2
=(j3
*cr(j1
,j2
,j3
-1,m1
,m2
,-m1
-m2
))/((j3
-1)*cr(j1
,j2
,j3
,m1
,m2
,-m1
-m2
));
337 //Assegnazione temporanea della ricorsione
338 double w3jm_temp
=-cu1
*v_w3jm
[j3
-1-j3min
]-cu2
*v_w3jm
[j3
-2-j3min
];
340 if ((fabs(w3jm_temp
)<fabs(v_w3jm
[j3
-1-j3min
])) || ((j3
-1)==j3max
) ) break; // Cond. di uscita
342 v_w3jm
[j3
-j3min
]=w3jm_temp
; //Assegno perche' e' ok
346 } // END SUBROUTINE wigner3jm
348 // calcolo una serie di coefficienti di Gaunt per una data quadrupletta di indici; vec_trans.f90
349 void gaunt_cz(int m
, int n
, int mu
, int nu
, int qmaxa
, double *v_aq
, int *error
) {
350 // TODO zrušit error a dát místo něj
351 if (error
) *error
= 0;
352 if (abs(m
) > n
|| abs(mu
) > nu
) { // error_if
358 // calcolo i bounds dei vettori di wigner
359 int pmin
= j3minimum(n
,nu
,m
,mu
);
361 int pmin0
= j3minimum(n
,nu
,0,0);
362 // Alloco i vettori di wigner e li calcolo
363 double *v_w3jm
= calloc(pmax
-pmin
+1, sizeof(double));
364 double *v_w3jm0
= calloc(pmax
-pmin
+1, sizeof(double));
367 //ALLOCATE(v_w3jm(pmin:pmax),v_w3jm0(pmin0:pmax),STAT=stat_a)
368 wigner3jm(n
,nu
,m
,mu
,pmin
,pmax
,v_w3jm
); // FIXME error handling, non-void return values
369 wigner3jm(n
,nu
,0,0,pmin0
,pmax
,v_w3jm0
);
371 // Entro nel ciclo per il calcolo dei coefficienti di gaunt
372 for (int q
= 0; q
<= qmaxa
; ++q
) { //gaunt_do: DO q=0,qmaxa
374 // Calcolo dell'indice p, sia reale che intero
376 //pr=REAL(p,dbl) // use only integer p
378 //Calcolo del fattoriale
379 double logw
= .5 * (lnf(n
+m
)+lnf(nu
+mu
)+lnf(p
-m
-mu
) - \
380 lnf(n
-m
)-lnf(nu
-mu
)-lnf(p
+m
+mu
));
381 double fac
= exp(logw
);
383 // Calcolo del coefficiente di gaunt
384 v_aq
[q
]=min1pow(m
+mu
)*(2*p
+1)*fac
*v_w3jm
[p
]*v_w3jm0
[p
];
388 // Disalloco i vettori di wigner a lavoro finito
391 } // END SUBROUTINE gaunt_cz
394 // gaunt_xu from vec_trans.f90
395 // FIXME set some sensible return value
396 void gaunt_xu(int m
, int n
, int mu
, int nu
, int qmax
, double *v_aq
, int *error
) {
401 for (int i
= 0; i
< qmax
; i
++) v_zero
[i
] = 1;
402 double v_aq_cz
[qmax
];
403 for (int i
= 0; i
< qmax
; i
++) v_aq_cz
[i
] = 0.;
406 if(abs(m
)>n
|| abs(mu
)>nu
) {
408 fprintf(stderr
, "invalid values for m, n, mu or nu\n");
409 return; // FIXME vyřešit chyby
412 switch(qmax
) { //qmax_case
414 v_aq
[0] = f_a0(m
,n
,mu
,nu
);
417 v_aq
[0] = f_a0(m
,n
,mu
,nu
);
418 v_aq
[1] = v_aq
[0] * f_a1norm(m
,n
,mu
,nu
);
419 // controllo gli zeri
420 if (fabs(v_aq
[1]/v_aq
[0]) < ZERO_THRESHOLD
) {
426 v_aq
[0] = f_a0(m
,n
,mu
,nu
);
428 v_aq
[1] = v_aq
[0] * f_a1norm(m
,n
,mu
,nu
);
429 // controllo gli zeri
430 if (fabs(v_aq
[1]/v_aq
[0]) < ZERO_THRESHOLD
) {
435 v_aq
[2] = v_aq
[0] * f_a2normr(m
,n
,mu
,nu
,v_aq
[1]/v_aq
[0]);
436 // controllo gli zeri
437 if (fabs(v_aq
[2]/v_aq
[0]) < ZERO_THRESHOLD
) {
443 if (m
== 0 && mu
== 0) { // big_if
444 v_aq
[0] = f_a0(m
,n
,mu
,nu
);
446 // backward recursion
447 for (int q
= 1; q
<= qmax
; ++q
) { // uno_b_do
448 int p
= n
+ nu
- 2*q
;
449 double c0
= f_alpha(n
,nu
,p
+1);
450 double c1
= f_alpha(n
,nu
,p
+2);
451 v_aq
[q
] = (c1
/c0
) * v_aq
[q
-1];
453 // Vedo se il q-esimo valore e' zero
454 if (v_zero
[q
-1] == 1) {// v_zero_if_1
455 if(fabs(v_aq
[q
]/v_aq
[q
-1]) < ZERO_THRESHOLD
) { // zg_if_1
459 } else if (v_zero
[q
-1]==0 && v_zero
[q
-2]) {
460 if(fabs(v_aq
[q
]/v_aq
[q
-2]) < ZERO_THRESHOLD
) {// zg_if1_1
466 } else if (mu
== m
&& nu
== n
) {
467 v_aq
[0] = f_a0(m
,n
,mu
,nu
);
469 // backward recursion
470 for (int q
= 1; q
<= qmax
; ++q
) { // due_b_do
471 // calculate pre-coefficients
472 int p
= n
+ nu
- 2*q
;
476 // calculate recursion coefficients
477 double c0
= (p
+2) * (p1
+1) * f_alpha(n
,nu
,p
+1);
478 double c1
= (p
+1) * (p2
+2) * f_alpha(n
,nu
,p
+2);
481 v_aq
[q
] = (c1
/c0
) * v_aq
[q
-1];
483 // Vedo se il q-esimo valore e' zero
484 if (v_zero
[q
-1] == 1) {// v_zero_if_2
485 if(fabs(v_aq
[q
]/v_aq
[q
-1]) < ZERO_THRESHOLD
) { // zg_if_2
489 } else if (v_zero
[q
-1]==0 && v_zero
[q
-2]) {
490 if(fabs(v_aq
[q
]/v_aq
[q
-2]) < ZERO_THRESHOLD
) {// zg_if1_2
496 } else if (mu
== -m
) {
497 // Primo valore per la backward recursion
498 v_aq
[0] = f_a0(m
,n
,mu
,nu
);
499 v_aq
[1] = f_a1norm(m
,n
,mu
,nu
)*v_aq
[0];
501 // Controllo gli zeri
502 if (fabs(v_aq
[1]/v_aq
[0]) < ZERO_THRESHOLD
) { //zg_if_3_0
507 // backward recursion
508 for (int q
= 2; q
<= qmax
; ++q
) { // tre_b_do
509 // calculate pre-coefficient
510 int p
= n
+ nu
- 2*q
;
512 // calculate recursion coefficients
513 double c0
= f_alpha(n
, nu
, p
+1);
514 double c1
= 4*isq(m
) + f_alpha(n
,nu
,p
+2) + f_alpha(n
,nu
,p
+3);
515 double c2
= - f_alpha(n
, nu
, p
+4);
518 v_aq
[q
] = (c1
/c0
)*v_aq
[q
-1] + (c2
/c0
)*v_aq
[q
-2];
520 // Vedo se il q-esimo valore e' zero
521 if (v_zero
[q
-1] == 1) {// v_zero_if_3
522 if(fabs(v_aq
[q
]/v_aq
[q
-1]) < ZERO_THRESHOLD
) { // zg_if_3
526 } else if (v_zero
[q
-1]==0 && v_zero
[q
-2]) {
527 if(fabs(v_aq
[q
]/v_aq
[q
-2]) < ZERO_THRESHOLD
) {// zg_if1_3
535 // Primo valore per la forward recursion,errore relativo e suo swap
536 double aq_fwd
=f_aqmax(m
,n
,mu
,nu
,qmax
);
537 double res
=fabs(aq_fwd
-v_aq
[qmax
])/fabs(aq_fwd
);
539 //Se non ho precisione, sostituisco i valori
540 if (res
>BF_PREC
) { //tre_f_if
543 int zeroswitch
= 0; // black magic (gevero's "switch")
544 //Entro nel ciclo della sostituzione valori
545 for( int q
=qmax
-1;q
>=0;--q
) { // tre_f_do
546 switch(qmax
-q
) {// tre_q_case // FIXME switch -> if/else
547 case 1: {// q==qmax-1
548 //Calcolo v_aq[qmax-1]
550 double c1
=4*isq(m
)+f_alpha(n
,nu
,p
+2)+f_alpha(n
,nu
,p
+3);
551 double c2
=-f_alpha(n
,nu
,p
+4);
552 double aq_fwd
=-(c1
/c2
)*v_aq
[qmax
];
554 switch(v_zero
[q
]) { // z_3_1_case
559 res
=fabs(aq_fwd
-v_aq
[q
])/fabs(aq_fwd
);
566 default: { //Per tutti gli altri q
567 //Calcolo v_aq[qmax-1]
569 double c0
=f_alpha(n
,nu
,p
+1);
570 double c1
=4*isq(m
)+f_alpha(n
,nu
,p
+2)+f_alpha(n
,nu
,p
+3);
571 double c2
=-f_alpha(n
,nu
,p
+4);
572 aq_fwd
=-(c1
/c2
)*v_aq
[q
+1]+(c0
/c2
)*v_aq
[q
+2];
574 switch(v_zero
[q
]){ // z_3_2_case//FIXME switch -> if/else
578 case 1: //Il valore precedente e' zero
579 res
=fabs(aq_fwd
-v_aq
[q
])/fabs(aq_fwd
);
586 //Adesso se la precisione e' raggiunta esco dal ciclo,
587 //se no sostituisco e rimango
588 if (res
<BF_PREC
|| q
==0 || fabs(aq_fwd
) < fabs(v_aq
[q
+1]))
590 //Sono nel ciclo, allora sostituisco eaggiorno indice e residuo
593 assert(q
); // assert níže přesunut sem
595 // Check sul ciclo di sostituzione
598 error_if1: IF (q==0) THEN
600 WRITE(*,*) "Si e' verificato un errore nella subroutine gaunt_xu:"
601 WRITE(*,*) "la precisione richiesta per i coefficienti di Gaunt nella backward"
602 WRITE(*,*) "e forward recursion non e' stata raggiunta"
609 } else { // caso generale (4)
611 // Calcolo direttamente i primi tre valori della ricorsione
612 v_aq
[0]=f_a0(m
,n
,mu
,nu
);
613 v_aq
[1]=v_aq
[0]*f_a1norm(m
,n
,mu
,nu
);
615 // vedo se il secondo valore e' zero
616 if (fabs(v_aq
[1]/v_aq
[0]) < ZERO_THRESHOLD
) { // zg1_if
621 //...........................................................
622 //Calcolo il terzo valore della ricorsione in funzione di Ap4
623 //...........................................................
624 //Inizializzo i valori comuni per i coefficienti
628 alphap1
=f_alpha(n
,nu
,p
+1);
629 double alphap2
=f_alpha(n
,nu
,p
+2);
630 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
631 double Ap3
=f_Ap(m
,n
,mu
,nu
,p
+3);
632 double Ap4
=f_Ap(m
,n
,mu
,nu
,p
+4);
634 //Con questo if decido se mi serve la ricorsione a 3 o 4 termini
635 if (Ap4
==0) { //Ap4_2_if
636 //Calcolo i restanti valori preliminari
637 double Ap5
=f_Ap(m
,n
,mu
,nu
,p
+5);
638 double Ap6
=f_Ap(m
,n
,mu
,nu
,p
+6);
639 double alphap5
=f_alpha(n
,nu
,p
+5);
640 double alphap6
=f_alpha(n
,nu
,p
+6);
642 //Calcolo i coefficienti per la ricorsione ma non c3 perche' qui e solo qui non mi serve
643 double c0
=(p
+2.)*(p
+3.)*(p
+5.)*(p1
+1.)*(p1
+2.)*(p1
+4.)*Ap6
*alphap1
;
644 double c1
=(p
+5.)*(p1
+4.)*Ap6
*(Ap2
*Ap3
+ (p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*alphap2
);
645 double c2
=(p
+2.)*(p2
+3.)*Ap2
*(Ap5
*Ap6
+ (p
+4.)*(p
+6.)*(p1
+5.)*(p2
+5.)*alphap5
);
647 //Calcolo il mio coefficiente
648 v_aq
[2]=(c1
/c0
)*v_aq
[1]+(c2
/c0
)*v_aq
[0];
650 //Assegno l'indice segnaposto per Ap4=0
653 //Calcolo i restanti valori preliminari
654 double alphap3
=f_alpha(n
,nu
,p
+3);
655 double alphap4
=f_alpha(n
,nu
,p
+4);
657 //Calcolo coefficienti ricorsione
658 double c0
=(p
+2.)*(p
+3.)*(p1
+1.)*(p1
+2.)*Ap4
*alphap1
;
659 double c1
=Ap2
*Ap3
*Ap4
+(p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*Ap4
*alphap2
+ \
660 (p
+2.)*(p
+4.)*(p1
+3.)*(p2
+3.)*Ap2
*alphap3
;
661 double c2
=-(p
+2.)*(p
+3.)*(p2
+3.)*(p2
+4.)*Ap2
*alphap4
;
663 //Calcolo il mio coefficiente
664 v_aq
[2]=(c1
/c0
)*v_aq
[1]+(c2
/c0
)*v_aq
[0];
667 //Vedo se il terzo valore e' zero
668 if (v_zero
[1]==1) { // v_zero_if1
669 if (fabs(v_aq
[2]/v_aq
[1])< ZERO_THRESHOLD
) { //zg2_if
673 } else if (v_zero
[1]==0) {
674 if (fabs(v_aq
[2]/v_aq
[0])<ZERO_THRESHOLD
) { //zg2_if1:
681 //...........................................................
682 //Calcolo i restanti valori nel loop
683 //...........................................................
684 for (int q
= 3; q
<= qmax
; q
++ ) { //gen_bwd_do: DO q=3,qmax
686 //Inizializzo i valori comuni per i coefficienti
690 alphap1
=f_alpha(n
,nu
,p
+1);
691 double alphap2
=f_alpha(n
,nu
,p
+2);
692 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
693 double Ap3
=f_Ap(m
,n
,mu
,nu
,p
+3);
694 double Ap4
=f_Ap(m
,n
,mu
,nu
,p
+4);
696 //Con questo if decido se mi serve la ricorsione a 3 o 4 termini
697 if (Ap4
==0) { // Ap4_bwd_if: IF (Ap4==0) THEN
699 //Calcolo i restanti valori preliminari
700 double Ap5
=f_Ap(m
,n
,mu
,nu
,p
+5);
701 double Ap6
=f_Ap(m
,n
,mu
,nu
,p
+6);
702 double alphap5
=f_alpha(n
,nu
,p
+5);
703 double alphap6
=f_alpha(n
,nu
,p
+6);
705 //Calcolo i coefficienti per la ricorsione ma non c3 perche' qui e solo qui non mi serve
706 double c0
=(p
+2.)*(p
+3.)*(p
+5.)*(p1
+1.)*(p1
+2.)*(p1
+4.)*Ap6
*alphap1
;
707 double c1
=(p
+5.)*(p1
+4.)*Ap6
*(Ap2
*Ap3
+ (p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*alphap2
);
708 double c2
=(p
+2.)*(p2
+3.)*Ap2
*(Ap5
*Ap6
+ (p
+4.)*(p
+6.)*(p1
+5.)*(p2
+5.)*alphap5
);
709 double c3
=-(p
+2.)*(p
+4.)*(p
+5.)*(p2
+3.)*(p2
+5.)*(p2
+6.)*Ap2
*alphap6
;
711 //Calcolo il mio coefficiente
712 v_aq
[q
]=(c1
/c0
)*v_aq
[q
-1]+(c2
/c0
)*v_aq
[q
-2]+(c3
/c0
)*v_aq
[q
-3];
714 //Assegno l'indice segnaposto per Ap4=0
715 //q4=q // FIXME nepoužitá proměnná
717 //Calcolo i restanti valori preliminari
718 double alphap3
=f_alpha(n
,nu
,p
+3);
719 double alphap4
=f_alpha(n
,nu
,p
+4);
721 //Calcolo coefficienti ricorsione
722 double c0
=(p
+2.)*(p
+3.)*(p1
+1.)*(p1
+2.)*Ap4
*alphap1
;
723 double c1
=Ap2
*Ap3
*Ap4
+(p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*Ap4
*alphap2
+ \
724 (p
+2.)*(p
+4.)*(p1
+3.)*(p2
+3.)*Ap2
*alphap3
;
725 double c2
=-(p
+2.)*(p
+3.)*(p2
+3.)*(p2
+4.)*Ap2
*alphap4
;
727 //Calcolo il mio coefficiente
728 v_aq
[q
]=(c1
/c0
)*v_aq
[q
-1]+(c2
/c0
)*v_aq
[q
-2];
729 } // END IF Ap4_bwd_if
731 //Vedo se il q-esimo valore e' zero
732 if(v_zero
[q
-1]==1) { //v_zero_ifq: IF (v_zero[q-1]==1) THEN
733 if(fabs(v_aq
[q
]/v_aq
[q
-1])<ZERO_THRESHOLD
) {//zgq_if
737 } else if ((v_zero
[q
-1]==0) && (v_zero
[q
-2] !=0)) {
738 if (fabs(v_aq
[q
]/v_aq
[q
-2])<ZERO_THRESHOLD
) {//zgq_if1:
746 //---------------------------------------------------------------------------------
748 //---------------------------------------------------------------------------------
750 //Calcolo pmin,Apmin e la mia variabile logica
751 int pmin
=n
+nu
-2*(qmax
);
752 int Apmin
=f_Ap(m
,n
,mu
,nu
,pmin
);
753 int test
=(((Apmin
)==0) &&
754 (((pmin
)==(m
+mu
+1)) || ((pmin
)==(-m
-mu
+1))));
756 //........................................................
757 //Se la mia variabile logica e' vera, Faccio il mio conto
758 //........................................................
759 if(test
) { //Apmin_if: if (test) THEN
761 //Il valore per qmax allora e' zero
764 //Calcolo il secondo valore, e se la precisione e' raggiunta esco
765 double aq_fwd
=f_aqmax_1(m
,n
,mu
,nu
,qmax
);
766 double res
=fabs(aq_fwd
-v_aq
[qmax
-1])/fabs(aq_fwd
);
770 //Assegno il secondo valore e faccio il ciclo
772 qi
=1; //FIXME nepoužitá proměnná
774 for (int q
= qmax
; q
>= 2; --q
) { //Apmin_do: DO q=qmax,2,-1
776 //Calcolo pre-coefficienti
780 alphap1
=f_alpha(n
,nu
,p
+1);
781 double alphap2
=f_alpha(n
,nu
,p
+2);
782 double alphap3
=f_alpha(n
,nu
,p
+3);
783 double alphap4
=f_alpha(n
,nu
,p
+4);
784 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
785 double Ap3
=f_Ap(m
,n
,mu
,nu
,p
+3);
786 double Ap4
=f_Ap(m
,n
,mu
,nu
,p
+4);
788 //Calcolo coefficienti ricorsione
789 double c0
=(p
+2.)*(p
+3.)*(p1
+1.)*(p1
+2.)*Ap4
*alphap1
;
790 double c1
=Ap2
*Ap3
*Ap4
+(p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*Ap4
*alphap2
+
791 (p
+2.)*(p
+4.)*(p1
+3.)*(p2
+3.)*Ap2
*alphap3
;
792 double c2
=-(p
+2.)*(p
+3.)*(p2
+3.)*(p2
+4.)*Ap2
*alphap4
;
794 //Ricorsione e residuo
795 aq_fwd
=-(c1
/c2
)*v_aq
[q
-1]+(c0
/c2
)*v_aq
[q
];
796 res
=fabs(aq_fwd
-v_aq
[q
-2])/fabs(aq_fwd
);
798 if (res
<BF_PREC
) return;
805 // Check sul ciclo di sostituzione
806 assert (qi
); // Apmin_error_if1
809 WRITE(*,*) "Si e' verificato un errore nella subroutine gaunt_xu, caso generale, Apmin=0:"
810 WRITE(*,*) "la precisione richiesta per i coefficienti di Gaunt nella backward"
811 WRITE(*,*) "e forward recursion non e' stata raggiunta"
815 }*/ // Apmin_error_if1
817 //Esco dalla subroutine gaunt_xu
822 //..........................................................................
823 //CASO GENERALE PER LA FORWARD RECURRENCE
824 //..........................................................................
826 //Primo valore per la forward recursion,errore relativo e suo swap
827 double aq_fwd
=f_aqmax(m
,n
,mu
,nu
,qmax
);
828 double res
=fabs(aq_fwd
-v_aq
[qmax
])/fabs(aq_fwd
);
831 if (res
>BF_PREC
) { //gen_f_if
832 //Se non ho precisione, sostituisco i valori
838 //Entro nel ciclo della sostituzione valori
839 while(1) { // gen_f_do: DO
841 switch(qmax
-qi
) {//gen_q_case:SELECT CASE (qmax-qi)
846 //Calcolo Ap4 per qi+2 per vedere quale schema usare
848 double Ap4
=f_Ap(m
,n
,mu
,nu
,p
+4);
850 //Scelgo la ricorrenza a seconda del valore di Ap4
851 if (Ap4
==0) { // Ap4_q1_if
853 //Calcolo aq secondo la ricorrenza a 4 termini: uso qi+3 perche' il termine piu' alto e'
854 //maggiore di 3 unita' rispetto a qi, pur essendo nullo e non comparendo nella ricorsione
858 double alphap5
=f_alpha(n
,nu
,p
+5);
859 double alphap6
=f_alpha(n
,nu
,p
+6);
860 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
861 double Ap5
=f_Ap(m
,n
,mu
,nu
,p
+5);
862 double Ap6
=f_Ap(m
,n
,mu
,nu
,p
+6);
863 double c2
=(p
+2.)*(p2
+3.)*Ap2
*(Ap5
*Ap6
+ (p
+4.)*(p
+6.)*(p1
+5.)*(p2
+5.)*alphap5
);
864 double c3
=-(p
+2.)*(p
+4.)*(p
+5.)*(p2
+3.)*(p2
+5.)*(p2
+6.)*Ap2
*alphap6
;
865 aq_fwd
=-(c2
/c3
)*v_aq
[qi
+1];
867 //A seconda che il mio valore sia 0 o meno confronto i valori
868 switch(v_zero
[qi
]){ //zAp41_case:SELECT CASE (v_zero[qi])
873 res
=fabs(aq_fwd
-v_aq
[qi
])/fabs(aq_fwd
);
876 //měli bychom breaknout smyčku, ale za
877 //ní už nic „smysluplného“ není
884 } // END SELECT zAp41_case
886 //Qui calcolo il valore successivo dopo aver aggiornato qi:
887 //Se v_aq[qi]=0 allora non chiamo cruzan, se no lo chamo e
888 //tengo un solo valore
891 switch(v_zero
[qi
]) {//zcz1_case:SELECT CASE (v_zero[qi])
895 continue; //CYCLE gen_f_do
898 gaunt_cz(m
,n
,mu
,nu
,qmax
,&(v_aq_cz
[qi
]),error
); // FIXME implementace gaunt_cz
899 aq_fwd
=(v_aq_cz
[qi
]);
900 res
=fabs(aq_fwd
-v_aq
[qi
])/fabs(aq_fwd
);
907 } else { //Qui Ap4/=0
913 double alphap2
=f_alpha(n
,nu
,p
+2);
914 double alphap3
=f_alpha(n
,nu
,p
+3);
915 double alphap4
=f_alpha(n
,nu
,p
+4);
916 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
917 double Ap3
=f_Ap(m
,n
,mu
,nu
,p
+3);
918 double Ap4
=f_Ap(m
,n
,mu
,nu
,p
+4);
919 double c1
=Ap2
*Ap3
*Ap4
+(p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*Ap4
*alphap2
+
920 (p
+2.)*(p
+4.)*(p1
+3.)*(p2
+3.)*Ap2
*alphap3
;
921 double c2
=-(p
+2.)*(p
+3.)*(p2
+3.)*(p2
+4.)*Ap2
*alphap4
;
922 aq_fwd
=-(c1
/c2
)*v_aq
[qi
+1]; //E' qui che lo calcolo
924 //A seconda che il mio valore sia 0 o meno confronto i valori
925 switch(v_zero
[qi
]) { // zAp4d1_case:SELECT CASE (v_zero[qi])
929 continue; // gen_f_do
932 res
=fabs(aq_fwd
-v_aq
[qi
])/fabs(aq_fwd
);
942 case 2: {//CASE(2) gen_q_case //q=qmax-2
950 //Calcolo Ap4 per qi+2 per vedere quale schema usare
952 double Ap4
=f_Ap(m
,n
,mu
,nu
,p
+4);
954 //Scelgo la ricorrenza a seconda del valore di Ap4
955 if (Ap4
==0) { // Ap4_q2_if
956 //Calcolo aq secondo la ricorrenza a 4 termini: uso qi+3 perche' il termine piu' alto e'
957 //maggiore di 3 unita' rispetto a qi, pur essendo nullo e non comparendo nella ricorsione
961 double alphap2
=f_alpha(n
,nu
,p
+2);
962 double alphap5
=f_alpha(n
,nu
,p
+5);
963 double alphap6
=f_alpha(n
,nu
,p
+6);
964 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
965 double Ap3
=f_Ap(m
,n
,mu
,nu
,p
+3);
966 double Ap5
=f_Ap(m
,n
,mu
,nu
,p
+5);
967 double Ap6
=f_Ap(m
,n
,mu
,nu
,p
+6);
968 double c1
=(p
+5.)*(p1
+4.)*Ap6
*(Ap2
*Ap3
+ (p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*alphap2
);
969 double c2
=(p
+2.)*(p2
+3.)*Ap2
*(Ap5
*Ap6
+ (p
+4.)*(p
+6.)*(p1
+5.)*(p2
+5.)*alphap5
);
970 double c3
=-(p
+2.)*(p
+4.)*(p
+5.)*(p2
+3.)*(p2
+5.)*(p2
+6.)*Ap2
*alphap6
;
971 aq_fwd
=-(c1
/c3
)*v_aq
[qi
+2] -(c2
/c3
)*v_aq
[qi
+1];
973 //A seconda che il mio valore sia 0 o meno confronto i valori
974 switch(v_zero
[qi
]) { // zAp42_case
979 res
=fabs(aq_fwd
-v_aq
[qi
])/fabs(aq_fwd
);
980 if (res
<BF_PREC
) { // EXIT gen_f_do
989 //Qui calcolo il valore successivo dopo aver aggiornato qi:
990 //Se v_aq[qi]=0 allora non chiamo cruzan, se no lo chamo e
991 //tengo un solo valore
994 switch (v_zero
[qi
]) {//zcz2_case:SELECT CASE (v_zero[qi])
998 continue; // gen_f_do
1001 //FIXME gaunt_cz !!!!!!!!!!!!!!!!!!
1002 gaunt_cz(m
,n
,mu
,nu
,qmax
,&(v_aq_cz
[qi
]),error
);
1004 res
=fabs(aq_fwd
-v_aq
[qi
])/fabs(aq_fwd
);
1009 } else { //Qui Ap4!=0
1011 int p
=n
+nu
-2*(qi
+2);
1014 double alphap2
=f_alpha(n
,nu
,p
+2);
1015 double alphap3
=f_alpha(n
,nu
,p
+3);
1016 double alphap4
=f_alpha(n
,nu
,p
+4);
1017 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
1018 double Ap3
=f_Ap(m
,n
,mu
,nu
,p
+3);
1019 double Ap4
=f_Ap(m
,n
,mu
,nu
,p
+4);
1020 double c0
=(p
+2.)*(p
+3.)*(p1
+1.)*(p1
+2.)*Ap4
*alphap1
;
1021 double c1
=Ap2
*Ap3
*Ap4
+(p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*Ap4
*alphap2
+
1022 (p
+2.)*(p
+4.)*(p1
+3.)*(p2
+3.)*Ap2
*alphap3
;
1023 double c2
=-(p
+2.)*(p
+3.)*(p2
+3.)*(p2
+4.)*Ap2
*alphap4
;
1024 aq_fwd
=(c0
/c2
)*v_aq
[qi
+2]-(c1
/c2
)*v_aq
[qi
+1]; //E' qui che lo calcolo
1026 //A seconda che il mio valore sia 0 o meno confronto i valori
1027 switch(v_zero
[qi
]) { //zAp4d2_case:SELECT CASE (v_zero[qi])
1031 continue; // gen_f_do
1034 res
=fabs(aq_fwd
-v_aq
[qi
])/fabs(aq_fwd
);
1044 //$$$$$$$$$$$$$$$$$$$$$$
1045 default: { //CASE DEFAULT gen_q_case //Per tutti gli altri q
1046 //$$$$$$$$$$$$$$$$$$$$$$
1048 //Calcolo Ap4 per qi+2 per vedere quale schema usare
1049 int p
=n
+nu
-2*(qi
+2);
1050 double Ap4
=f_Ap(m
,n
,mu
,nu
,p
+4);
1052 //Scelgo la ricorrenza a seconda del valore di Ap4
1053 if (Ap4
==0) { // Ap4_qq_if
1055 //Calcolo aq secondo la ricorrenza a 4 termini: uso qi+3 perche' il termine piu' alto e'
1056 //maggiore di 3 unita' rispetto a qi, pur essendo nullo e non comparendo nella ricorsione
1057 int p
=n
+nu
-2*(qi
+3);
1060 double alphap2
=f_alpha(n
,nu
,p
+2);
1061 double alphap5
=f_alpha(n
,nu
,p
+5);
1062 double alphap6
=f_alpha(n
,nu
,p
+6);
1063 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
1064 double Ap3
=f_Ap(m
,n
,mu
,nu
,p
+3);
1065 double Ap5
=f_Ap(m
,n
,mu
,nu
,p
+5);
1066 double Ap6
=f_Ap(m
,n
,mu
,nu
,p
+6);
1067 double c0
=(p
+2.)*(p
+3.)*(p
+5.)*(p1
+1.)*(p1
+2.)*(p1
+4.)*Ap6
*alphap1
;
1068 double c1
=(p
+5.)*(p1
+4.)*Ap6
*(Ap2
*Ap3
+ (p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*alphap2
);
1069 double c2
=(p
+2.)*(p2
+3.)*Ap2
*(Ap5
*Ap6
+ (p
+4.)*(p
+6.)*(p1
+5.)*(p2
+5.)*alphap5
);
1070 double c3
=-(p
+2.)*(p
+4.)*(p
+5.)*(p2
+3.)*(p2
+5.)*(p2
+6.)*Ap2
*alphap6
;
1071 aq_fwd
=(c0
/c3
)*v_aq
[qi
+3]-(c1
/c3
)*v_aq
[qi
+2] -(c2
/c3
)*v_aq
[qi
+1];
1073 //A seconda che il mio valore sia 0 o meno confronto i valori
1074 switch(v_zero
[qi
]) {//zAp4q_case:SELECT CASE (v_zero[qi])
1079 res
=fabs(aq_fwd
-v_aq
[qi
])/fabs(aq_fwd
);
1080 if (res
<BF_PREC
) {// EXIT gen_f_do
1089 //Qui calcolo il valore successivo dopo aver aggiornato qi:
1090 //Se v_aq[qi]=0 allora non chiamo cruzan, se no lo chiamo e
1091 //tengo un solo valore.L'if c'e' per non far sballare qi
1093 if (qi
>0) { // qi_if
1097 switch(v_zero
[qi
]) { //zczq_case:SELECT CASE (v_zero[qi])
1101 continue; // CYCLE gen_f_do
1104 gaunt_cz(m
,n
,mu
,nu
,qmax
,&(v_aq_cz
[qi
]),error
); // FIXME je potřeba mít v_aq_cz jako pole?
1106 res
=fabs(aq_fwd
-v_aq
[qi
])/fabs(aq_fwd
);
1115 } else { //Qui Ap4/=0
1119 int p
=n
+nu
-2*(qi
+2);
1122 double alphap2
=f_alpha(n
,nu
,p
+2);
1123 double alphap3
=f_alpha(n
,nu
,p
+3);
1124 double alphap4
=f_alpha(n
,nu
,p
+4);
1125 double Ap2
=f_Ap(m
,n
,mu
,nu
,p
+2);
1126 double Ap3
=f_Ap(m
,n
,mu
,nu
,p
+3);
1127 double Ap4
=f_Ap(m
,n
,mu
,nu
,p
+4);
1128 double c0
=(p
+2.)*(p
+3.)*(p1
+1.)*(p1
+2.)*Ap4
*alphap1
;
1129 double c1
=Ap2
*Ap3
*Ap4
+(p
+1.)*(p
+3.)*(p1
+2.)*(p2
+2.)*Ap4
*alphap2
+
1130 (p
+2.)*(p
+4.)*(p1
+3.)*(p2
+3.)*Ap2
*alphap3
;
1131 double c2
=-(p
+2.)*(p
+3.)*(p2
+3.)*(p2
+4.)*Ap2
*alphap4
;
1132 aq_fwd
=(c0
/c2
)*v_aq
[qi
+2]-(c1
/c2
)*v_aq
[qi
+1]; //E' qui che lo calcolo
1134 //A seconda che il mio valore sia 0 o meno confronto i valori
1135 switch(v_zero
[qi
]) { //zAp4dq_case:SELECT CASE (v_zero[qi])
1139 continue; // gen_f_do
1142 res
=fabs(aq_fwd
-v_aq
[qi
])/fabs(aq_fwd
);
1151 } // END SELECT gen_q_case
1153 //Adesso se la precisione e' raggiunta esco dal ciclo, se no sostituisco e rimango
1154 if ((res
<BF_PREC
) || (qi
==0) || (fabs(aq_fwd
)<fabs(v_aq
[qi
+1]))) // EXIT
1157 //Sono nel ciclo, allora sostituisco eaggiorno indice e residuo
1161 } // END DO gen_f_do
1163 // Check sul ciclo di sostituzione
1164 assert(qi
); /* gen_error_if1: if (qi==0) {
1166 WRITE(*,*) "Si e' verificato un errore nella subroutine gaunt_xu,caso generale:"
1167 WRITE(*,*) "la precisione richiesta per i coefficienti di Gaunt nella backward"
1168 WRITE(*,*) "e forward recursion non e' stata raggiunta"
1172 } */ // gen_error_if1
1182 #define MIN(x,y) (((x) > (y)) ? (y) : (x))
1183 static inline int q_max(int m
, int n
, int mu
, int nu
) {
1184 return MIN(n
, MIN(nu
,(n
+nu
-abs(m
+mu
))/2));
1187 /* THIS THING IS TOTALLY WRONG
1188 int gaunt(int m, int n, int mu, int nu, double *v) {
1190 int qmax = q_max(m,n,mu,nu);
1191 if (!v) v = calloc(qmax+1, sizeof(double));
1193 gaunt_xu(m, n, mu, nu, qmax, v, &err);
1200 void __vec_trans_MOD_gaunt_xu(const double *m
, const double *n
, const double *mu
, const double *nu
, const int *qmax
, double *v_aq
, int *err
);
1203 int NMAX
=20, REPEAT
=10;
1206 for (int r
= 0; r
< REPEAT
; ++r
) for (n
= 1; n
< NMAX
; ++n
) for (nu
= 1 ; nu
< NMAX
; ++nu
)
1207 for (mu
= -nu
; mu
<=nu
; ++mu
) for (m
= -n
; m
<= n
; ++m
) {
1208 //while(EOF != (scanned = scanf("%d %d %d %d", &m, &n, &mu, &nu))) {
1209 // if (scanned != 4) continue;
1210 // printf("%d %d %d %d\n", m, n, mu, nu);
1211 double mf
= m
, nf
= n
, muf
= mu
, nuf
= nu
;
1212 int qmax
= q_max(m
,n
,mu
,nu
);
1213 double v_aq_c
[qmax
+1], v_aq_f
[qmax
+1];
1215 __vec_trans_MOD_gaunt_xu(&mf
, &nf
, &muf
, &nuf
, &qmax
, v_aq_f
, &errf
);
1216 gaunt_xu(m
,n
,mu
,nu
,qmax
,v_aq_c
, &errc
);
1217 // for(int i = 0; i <= qmax; ++i) printf("%f ", v_aq_c[i]);
1219 // for(int i = 0; i <= qmax; ++i) printf("%f ", v_aq_f[i]);
1221 // for(int i = 0; i <= qmax; ++i) printf("%e ", v_aq_f[i] - v_aq_c[i]);
1229 #endif //USE_FORTRAN_GAUNT_XU