void check_3j_family_j_gsl (const int two_j1, const int two_j2, const int two_m1, const int two_m2) { double *a; int two_jmin, two_jmax, imax, i; int two_m3 = -(two_m1 + two_m2); wigner3j_family_j (two_j1, two_j2, two_m1, two_m2, &a, &two_jmin, &two_jmax); imax = (two_jmax-two_jmin)/2; printf ("two_j1: %d two_j2: %d two_m1: %d two_m2: %d\n", two_j1, two_j2, two_m1, two_m2); for(i=0; i<=imax; i++) { int two_j3=two_jmin+i*2; double gsl=gsl_sf_coupling_3j(two_j1, two_j2, two_j3, two_m1, two_m2, two_m3); printf ("\ttwo_j3: %d\t\twigner: %g\tgsl: %g\tdiff: %g\n", two_j3, a[i], gsl, a[i]-gsl); } free (a); }
void hammer_3j_j (const int two_jmax) { double *a; int two_j2, two_j3, two_m2, two_m3, tjmax, tjmin; for (two_j2 = 0; two_j2 <= two_jmax; two_j2++) for (two_m2 = -two_j2; two_m2 <=two_j2; two_m2 += 2) for (two_j3 = 0; two_j3 <= two_jmax; two_j3++) for (two_m3 = -two_j3; two_m3 <=two_j3; two_m3+=2) { printf ("%d %d %d %d\n", two_j2, two_j3, two_m2, two_m3); wigner3j_family_j (two_j2, two_j3, two_m2, two_m3, &a, &tjmax, &tjmin); free (a); } }
double wigner3j (const int two_j1, const int two_j2, const int two_j3, const int two_m1, const int two_m2, const int two_m3) /* Returns a single Wigner 3J symbol. Computation is done by calculating the family of 3J symbols by J recursion with two_j2 and two_j3 fixed, and returning the symbol corresponding to the specified value of two_j1. In most cases this will require less computation than using M recursion. */ { int a = abs (two_j2 - two_j3); int b = abs (two_m2 + two_m3); int two_jmin = __MAX(a, b); int two_jmax = two_j2 + two_j3; int dim = 1 + (two_jmax - two_jmin) / 2; double buff[__MAX (dim, 1)]; /* Don't want 0 or negative size here. */ /* Check that |m| <= j */ if ((abs (two_m1) > two_j1) || (abs (two_m2) > two_j2) || (abs (two_m3) > two_j3)) return NAN; /* Check (j,m) pairs are both integer or both half integer */ if (__ODD (two_m2 + two_j2) || __ODD (two_m2 + two_j2) || __ODD (two_m3 + two_j3)) return NAN; /* Check for positive j */ if (two_j1 < 0 || two_j2 < 0 || two_j3 < 0) return NAN; /* Check sum of Ms is 0 */ if (two_m1 + two_m2 + two_m3 != 0) return 0.0; /* And, finally check triangle condition is met */ if (!is_triangle (two_j1, two_j2, two_j3)) return 0.0; wigner3j_family_j (two_j2, two_j3, two_m2, two_m3, buff, &two_jmin, &two_jmax); return buff[(two_j1 - two_jmin) / 2]; }
void check_3j_family_j (const int two_j1, const int two_j2, const int two_m1, const int two_m2) { double *a; int two_jmin, two_jmax, imax, i; wigner3j_family_j (two_j1, two_j2, two_m1, two_m2, &a, &two_jmin, &two_jmax); imax = (two_jmax-two_jmin)/2; printf ("two_j1: %d two_j2: %d two_m1: %d two_m2: %d\n", two_j1, two_j2, two_m1, two_m2); for(i=0; i<=imax; i++) { int j=two_jmin+i; printf ("\ttwo_j3: %d\t %g\n", j, a[i]); } free (a); }
void check_3j_family_j_exact_2 (const int two_jmax) { int two_j; printf("two_j\trecursive\tgsl\texact\trec-ex\tgsl-ex\n"); for (two_j = 0; two_j <=two_jmax; two_j = (two_j + 1)*100) { double exact = 1.0 / sqrt (two_j + 1.0); double gsl = gsl_sf_coupling_3j(two_j, two_j, 0, 0, 0, 0); double *a; int tjmax, tjmin; wigner3j_family_j (two_j, two_j, 0, 0, &a, &tjmax, &tjmin); printf("%d\t%g\t%g\t%g\t%g\t%g\n", two_j, a[0],gsl, exact, a[0]-exact, gsl-exact); free (a); } }
void check_3j_family_j_exact_1 (const int two_jmax) { int two_j; for (two_j = 0; two_j <=two_jmax; two_j = (two_j + 1)*100-1) { double exact = 1.0 / sqrt (two_j + 1.0); double gsl = gsl_sf_coupling_3j(two_j, two_j, 0, two_j, -two_j, 0); double *a; int tjmax, tjmin; wigner3j_family_j (two_j, two_j, two_j, -two_j, &a, &tjmax, &tjmin); printf ("two_j: %d\trecursive: % .18e\t exact: % .18e\tdiff: % .18e\n", two_j, a[0], exact, a[0]-exact); printf ("two_j: %d\t gsl: % .18e\t exact: % .18e\tdiff: % .18e\n", two_j, gsl, exact, gsl-exact); free (a); } }