36 #ifndef VIGRA_CLEBSCH_GORDAN_HXX
37 #define VIGRA_CLEBSCH_GORDAN_HXX
40 #include "numerictraits.hxx"
42 #include "mathutil.hxx"
43 #include "array_vector.hxx"
49 void ThreeJSymbolM(
double l1,
double l2,
double l3,
double m1,
50 double &m2min,
double &m2max,
double *thrcof,
int ndim,
53 ContractViolation err;
54 const double zero = 0.0, eps = 0.01, one = 1.0, two = 2.0;
56 int nfin, nlim, i, n, index, lstep, nfinp1, nfinp2, nfinp3, nstep2;
57 double oldfac, dv, newfac, sumbac = 0.0, thresh, a1s, sumfor, sumuni,
58 sum1, sum2, x, y, m2, m3, x1, x2, x3, y1, y2, y3, cnorm,
59 ratio, a1, c1, c2, c1old = 0.0, sign1, sign2;
68 double hugedouble =
std::sqrt(NumericTraits<double>::max() / 20.0),
70 tiny = one / hugedouble,
71 srtiny = one / srhuge;
76 if (l1 -
abs(m1) + eps < zero
77 || std::fmod(l1 +
abs(m1) + eps, one) >= eps + eps)
80 err <<
"ThreeJSymbolM: l1-abs(m1) less than zero or l1+abs(m1) not integer.\n";
83 else if (l1+l2-l3 < -eps || l1-l2+l3 < -eps || -(l1) + l2+l3 < -eps)
86 err <<
" ThreeJSymbolM: l1, l2, l3 do not satisfy triangular condition:"
87 << l1 <<
" " << l2 <<
" " << l3 <<
"\n";
90 else if (std::fmod(l1 + l2 + l3 + eps, one) >= eps + eps)
93 err <<
" ThreeJSymbolM: l1+l2+l3 not integer.\n";
98 m2min = std::max(-l2,-l3-m1);
99 m2max = std::min(l2,l3-m1);
102 if (std::fmod(m2max - m2min + eps, one) >= eps + eps) {
104 err <<
" ThreeJSymbolM: m2max-m2min not integer.\n";
107 if (m2min < m2max - eps)
109 if (m2min < m2max + eps)
114 err <<
" ThreeJSymbolM: m2min greater than m2max.\n";
120 thrcof[1] = (
odd(
int(
abs(l2-l3-m1)+eps))
128 nfin = int(m2max - m2min + one + eps);
129 if (ndim - nfin >= 0)
135 err <<
" ThreeJSymbolM: Dimension of result array for 3j coefficients too small.\n";
154 a1 = (l2 - m2 + one) * (l2 + m2) * (l3 + m3 + one) * (l3 - m3);
157 dv = (l1+l2+l3+one) * (l2+l3-l1) - (l2-m2+one) * (l3+m3+one)
158 - (l2+m2-one) * (l3-m3-one);
174 sum1 += tiny * c1 * c1;
180 c2 = -oldfac / newfac;
183 x = c1 * thrcof[lstep-1] + c2 * thrcof[lstep-2];
199 for (i = 1; i <= lstep; ++i)
201 if (
abs(thrcof[i]) < srtiny)
206 sumfor /= hugedouble;
215 if (c1old -
abs(c1) > 0.0)
223 nstep2 = nfin - lstep + 3;
225 x2 = thrcof[lstep-1];
226 x3 = thrcof[lstep-2];
235 thrcof[nfin] = srtiny;
245 a1s = (l2-m2+two) * (l2+m2-one) * (l3+m3+two) * (l3-m3-one);
247 dv = (l1+l2+l3+one) * (l2+l3-l1) - (l2-m2+one) * (l3+m3+one)
248 - (l2+m2-one) * (l3-m3-one);
256 thrcof[nfin - 1] = y;
264 c2 = -oldfac / newfac;
268 y = c1 * thrcof[nfinp2 - lstep] + c2 * thrcof[nfinp3 - lstep];
273 thrcof[nfinp1 - lstep] = y;
287 for (i = 1; i <= lstep; ++i)
289 index = nfin - i + 1;
290 if (
abs(thrcof[index]) < srtiny)
291 thrcof[index] = zero;
292 thrcof[index] /= srhuge;
295 sumbac /= hugedouble;
304 y2 = thrcof[nfinp2-lstep];
305 y1 = thrcof[nfinp3-lstep];
310 ratio = (x1*y1 + x2*y2 + x3*y3) / (x1*x1 + x2*x2 + x3*x3);
311 nlim = nfin - nstep2 + 1;
313 if (
abs(ratio) < one)
315 for (n = 1; n <= nlim; ++n)
316 thrcof[n] = ratio * thrcof[n];
317 sumuni = ratio * ratio * sumfor + sumbac;
323 for (n = nlim; n <= nfin; ++n)
324 thrcof[n] = ratio * thrcof[n];
325 sumuni = sumfor + ratio * ratio * sumbac;
333 cnorm = one /
std::sqrt((l1+l1+one) * sumuni);
337 sign1 =
sign(thrcof[nfin]);
338 sign2 =
odd(
int(
abs(l2-l3-m1)+eps))
341 if (sign1 * sign2 <= 0.0)
350 if (
abs(cnorm) < one)
353 for (n = 1; n <= nfin; ++n)
354 thrcof[n] = cnorm * thrcof[n];
358 thresh = tiny /
abs(cnorm);
359 for (n = 1; n <= nfin; ++n)
361 if (
abs(thrcof[n]) < thresh)
363 thrcof[n] = cnorm * thrcof[n];
370 double clebschGordan (
double l1,
double m1,
double l2,
double m2,
double l3,
double m3)
372 const double err = 0.01;
373 double CG = 0.0, m2min, m2max, *cofp;
375 const int ncof = 100;
379 ContractViolation Err;
383 if (
abs(m1 + m2 - m3) > err)
386 Err <<
" clebschGordan: m1 + m2 - m3 is not zero.\n";
391 int njm =
roundi(std::min(l2,l3-m1) - std::max(-l2,-l3-m1) + 1);
394 ArrayVector<double> cofa;
406 ThreeJSymbolM (l1,l2,l3,m1, m2min,m2max, cofp,njm, errflag);
414 Err <<
" clebschGordan: 3jM-sym error.\n";
422 #endif // VIGRA_CLEBSCH_GORDAN_HXX
Int32 roundi(FixedPoint16< IntBits, OverflowHandling > v)
rounding to the nearest integer.
Definition: fixedpoint.hxx:1775
bool odd(int t)
Check if an integer is odd.
FFTWComplex< R >::NormType abs(const FFTWComplex< R > &a)
absolute value (= magnitude)
Definition: fftw3.hxx:1002
T sign(T t)
The sign function.
Definition: mathutil.hxx:591
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root.
Definition: fixedpoint.hxx:616