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