int gsl_sf_lambert_Wm1_e(double x, gsl_sf_result * result) { if(x > 0.0) { return gsl_sf_lambert_W0_e(x, result); } else if(x == 0.0) { result->val = 0.0; result->err = 0.0; return GSL_SUCCESS; } else { static const unsigned int MAX_ITERS = 32; const double one_over_E = 1.0/M_E; const double q = x + one_over_E; double w; if (q < 0.0) { /* As in the W0 branch above, return some reasonable answer anyway. */ result->val = -1.0; result->err = sqrt(-q); return GSL_EDOM; } if(x < -1.0e-6) { /* Obtain initial approximation from series about q = 0, * as long as we're not very close to x = 0. * Use full series and try to bail out if q is too small, * since the Halley iteration has bad convergence properties * in finite arithmetic for q very small, because the * increment alternates and p is near zero. */ const double r = -sqrt(q); w = series_eval(r); if(q < 3.0e-3) { /* this approximation is good enough */ result->val = w; result->err = 5.0 * GSL_DBL_EPSILON * fabs(w); return GSL_SUCCESS; } } else { /* Obtain initial approximation from asymptotic near zero. */ const double L_1 = log(-x); const double L_2 = log(-L_1); w = L_1 - L_2 + L_2/L_1; } return halley_iteration(x, w, MAX_ITERS, result); } }
double gsl_sf_lambert_W0(double x) { EVAL_RESULT(gsl_sf_lambert_W0_e(x, &result)); }
double optimizeLambda(unsigned int x, unsigned int y) { #ifdef NEW_WAY double A = getComputedExpectation(x, y) * exp(-lambda_(x, y)); double B = 2 * beta2_; double C = empirical_pair_(x, y) - beta1_; #else double A = getComputedExpectation(x, y); double B = 2 * beta2_; double C = empirical_pair_(x, y) - beta1_ - 2 * beta2_ * lambda_(x, y); #endif // #define DEBUGGING_NOISE #ifdef DEBUGGING_NOISE if (empirical_pair_(x, y) > 0 && rand() < RAND_MAX / 1000) { double overcount_x = lambda_(x,y) * singleton_expectation_[y]; double overcount_y = lambda_(x,y) * singleton_expectation_[x]; double p10 = q_lambda_[x] + kappa_[x] - overcount_x; double p01 = q_lambda_[y] + kappa_[y] - overcount_y; double p11 = estimates_(x,y) - overcount_x - overcount_y; std::cout << getComputedExpectation(x, y) << " " << empirical_pair_(x, y) << " " << kappa_[x] << " " << kappa_[y] << " " << lambda_(x,y) << " " << x << " " << y << " " << q_lambda_[x] << " " << q_lambda_[y] << " " << estimates_(x,y) << " " << overcount_x << " " << overcount_y << " " << p10 << " " << p01 << " " << p11 << " " << std::endl; } #endif double delta1 = 0; double delta2 = 0; if (beta2_ == 0) { delta1 = log(C / A); } else { gsl_sf_result result; gsl_sf_lambert_W0_e(A / B * exp(C / B), &result); delta1 = C/B - result.val; } C += 2 * beta1_; if (beta2_ == 0) { delta2 = log(C / A); } else { gsl_sf_result result; gsl_sf_lambert_W0_e(A / B * exp(C / B), &result); delta2 = C/B - result.val; } double new_lambda = lambda_(x,y); if (new_lambda + delta1 >= 0) { new_lambda += delta1; } else if (new_lambda + delta2 <= 0) { new_lambda += delta2; } else { new_lambda = 0; } double delta = fabs(new_lambda - lambda_(x,y)); if (delta - delta != 0) { delta = 0.0; } lambda_(x,y) = new_lambda; lambda_(y,x) = new_lambda; return delta; }
static VALUE Lambert_W0_e(VALUE self, VALUE x) { int ret; gsl_sf_result r; ret = gsl_sf_lambert_W0_e(NUM2DBL(x), &r); return RESULT(&r); }