static VALUE rb_gsl_sf_choose_e(VALUE obj, VALUE n, VALUE m) { gsl_sf_result *rslt = NULL; VALUE v; CHECK_FIXNUM(n); CHECK_FIXNUM(m); v = Data_Make_Struct(cgsl_sf_result, gsl_sf_result, 0, free, rslt); gsl_sf_choose_e(FIX2INT(n), FIX2INT(m), rslt); return v; }
/// Binomial coefficients. double choose(unsigned int n, unsigned int k) { if (k > n) return 0.0; // GSL barfs on this for no reason. gsl_sf_result result; int stat = gsl_sf_choose_e(n, k, &result); if (stat != GSL_SUCCESS) { std::ostringstream msg("Error in choose:"); msg << " n=" << n << " k=" << k; throw std::runtime_error(msg.str()); } else return result.val; }
int gsl_sf_coupling_3j_e (int two_ja, int two_jb, int two_jc, int two_ma, int two_mb, int two_mc, gsl_sf_result * result) { /* CHECK_POINTER(result) */ if(two_ja < 0 || two_jb < 0 || two_jc < 0) { DOMAIN_ERROR(result); } else if ( triangle_selection_fails(two_ja, two_jb, two_jc) || m_selection_fails(two_ja, two_jb, two_jc, two_ma, two_mb, two_mc) ) { result->val = 0.0; result->err = 0.0; return GSL_SUCCESS; } else { int jca = (-two_ja + two_jb + two_jc) / 2, jcb = ( two_ja - two_jb + two_jc) / 2, jcc = ( two_ja + two_jb - two_jc) / 2, jmma = ( two_ja - two_ma) / 2, jmmb = ( two_jb - two_mb) / 2, jmmc = ( two_jc - two_mc) / 2, jpma = ( two_ja + two_ma) / 2, jpmb = ( two_jb + two_mb) / 2, jpmc = ( two_jc + two_mc) / 2, jsum = ( two_ja + two_jb + two_jc) / 2, kmin = locMax3 (0, jpmb - jmmc, jmma - jpmc), kmax = locMin3 (jcc, jmma, jpmb), k, sign = GSL_IS_ODD (kmin - jpma + jmmb) ? -1 : 1, status = 0; double sum_pos = 0.0, sum_neg = 0.0, norm, term; gsl_sf_result bc1, bc2, bc3, bcn1, bcn2, bcd1, bcd2, bcd3, bcd4; status += gsl_sf_choose_e (two_ja, jcc , &bcn1); status += gsl_sf_choose_e (two_jb, jcc , &bcn2); status += gsl_sf_choose_e (jsum+1, jcc , &bcd1); status += gsl_sf_choose_e (two_ja, jmma, &bcd2); status += gsl_sf_choose_e (two_jb, jmmb, &bcd3); status += gsl_sf_choose_e (two_jc, jpmc, &bcd4); if (status != 0) { OVERFLOW_ERROR (result); } norm = sqrt (bcn1.val * bcn2.val) / sqrt (bcd1.val * bcd2.val * bcd3.val * bcd4.val * ((double) two_jc + 1.0)); for (k = kmin; k <= kmax; k++) { status += gsl_sf_choose_e (jcc, k, &bc1); status += gsl_sf_choose_e (jcb, jmma - k, &bc2); status += gsl_sf_choose_e (jca, jpmb - k, &bc3); if (status != 0) { OVERFLOW_ERROR (result); } term = bc1.val * bc2.val * bc3.val; if (sign < 0) { sum_neg += norm * term; } else { sum_pos += norm * term; } sign = -sign; } result->val = sum_pos - sum_neg; result->err = 2.0 * GSL_DBL_EPSILON * (sum_pos + sum_neg); result->err += 2.0 * GSL_DBL_EPSILON * (kmax - kmin) * fabs(result->val); return GSL_SUCCESS; } }