Esempio n. 1
0
File: gamma.go Progetto: swook/gogsl
func Lngamma_sgn_sing(N int, eps float64, lng *Result, sgn *float64) error {
	if eps == 0.0 {
		lng.val = 0.0
		lng.err = 0.0
		*sgn = 0.0
		return err.EDOM
	} else if N == 1 {
		/* calculate series for
		* g = eps gamma(-1+eps) + 1 + eps/2 (1+3eps)/(1-eps^2)
		* double-precision for |eps| < 0.02
		 */
		c0 := 0.07721566490153286061
		c1 := 0.08815966957356030521
		c2 := -0.00436125434555340577
		c3 := 0.01391065882004640689
		c4 := -0.00409427227680839100
		c5 := 0.00275661310191541584
		c6 := -0.00124162645565305019
		c7 := 0.00065267976121802783
		c8 := -0.00032205261682710437
		c9 := 0.00016229131039545456
		g5 := c5 + eps*(c6+eps*(c7+eps*(c8+eps*c9)))
		g := eps * (c0 + eps*(c1+eps*(c2+eps*(c3+eps*(c4+eps*g5)))))

		/* calculate eps gamma(-1+eps), a negative quantity */
		gam_e := g - 1.0 - 0.5*eps*(1.0+3.0*eps)/(1.0-eps*eps)

		lng.val = math.Log(math.Abs(gam_e) / math.Abs(eps))
		lng.err = 2.0 * gsl.DBL_EPSILON * math.Abs(lng.val)
		if eps > 0.0 {
			*sgn = -1.0
		} else {
			*sgn = 1.0
		}
		return err.SUCCESS
	}

	var g float64

	/* series for sin(Pi(N+1-eps))/(Pi eps) modulo the sign
	* double-precision for |eps| < 0.02
	 */
	cs1 := -1.6449340668482264365
	cs2 := 0.8117424252833536436
	cs3 := -0.1907518241220842137
	cs4 := 0.0261478478176548005
	cs5 := -0.0023460810354558236
	e2 := eps * eps
	sin_ser := 1.0 + e2*(cs1+e2*(cs2+e2*(cs3+e2*(cs4+e2*cs5))))

	/* calculate series for ln(gamma(1+N-eps))
	* double-precision for |eps| < 0.02
	 */
	aeps := math.Abs(eps)
	var c1, c2, c3, c4, c5, c6, c7, lng_ser float64
	var c0, psi_0, psi_1, psi_2, psi_3, psi_4, psi_5, psi_6 *Result
	psi_2.val = 0.0
	psi_3.val = 0.0
	psi_4.val = 0.0
	psi_5.val = 0.0
	psi_6.val = 0.0
	Lnfact_e(N, c0)
	Psi_int_e(N+1, psi_0)
	Psi_1_int_e(N+1, psi_1)
	switch {
	case aeps > 0.00001:
		Psi_n_e(2, float64(N)+1.0, psi_2)
	case aeps > 0.0002:
		Psi_n_e(3, float64(N)+1.0, psi_3)
	case aeps > 0.001:
		Psi_n_e(4, float64(N)+1.0, psi_4)
	case aeps > 0.005:
		Psi_n_e(5, float64(N)+1.0, psi_5)
	case aeps > 0.01:
		Psi_n_e(6, float64(N)+1.0, psi_6)
	}
	c1 = psi_0.val
	c2 = psi_1.val / 2.0
	c3 = psi_2.val / 6.0
	c4 = psi_3.val / 24.0
	c5 = psi_4.val / 120.0
	c6 = psi_5.val / 720.0
	c7 = psi_6.val / 5040.0
	lng_ser = c0.val - eps*(c1-eps*(c2-eps*(c3-eps*(c4-eps*(c5-eps*(c6-eps*c7))))))

	/* calculate
	* g = ln(|eps gamma(-N+eps)|)
	*   = -ln(gamma(1+N-eps)) + ln(|eps Pi/sin(Pi(N+1+eps))|)
	 */
	g = -lng_ser - math.Log(sin_ser)

	lng.val = g - math.Log(math.Abs(eps))
	lng.err = c0.err + 2.0*gsl.DBL_EPSILON*(math.Abs(g)+math.Abs(lng.val))

	if eps > 0.0 {
		*sgn = 1.0
	} else {
		*sgn = -1.0
	}
	if gsl.IsOdd(N) {
		*sgn *= -1.0
	} else {
		*sgn *= 1.0
	}

	return err.SUCCESS
}
Esempio n. 2
0
File: exp.go Progetto: swook/gogsl
func Exprel_n_CF(N int, x float64, result *Result) error {
	RECUR_BIG := gsl.SQRT_DBL_MAX
	maxiter := 5000
	n := 1
	Anm2 := 1.0
	Bnm2 := 0.0
	Anm1 := 0.0
	Bnm1 := 1.0
	a1 := 1.0
	b1 := 1.0
	a2 := -x
	b2 := float64(N) + 1.0
	var an, bn, old_fn, del float64

	An := b1*Anm1 + a1*Anm2 /* A1 */
	Bn := b1*Bnm1 + a1*Bnm2 /* B1 */

	/* One explicit step, before we get to the main pattern. */
	n++
	Anm2 = Anm1
	Bnm2 = Bnm1
	Anm1 = An
	Bnm1 = Bn
	An = b2*Anm1 + a2*Anm2 /* A2 */
	Bn = b2*Bnm1 + a2*Bnm2 /* B2 */

	fn := An / Bn

	for n < maxiter {
		n++
		Anm2 = Anm1
		Bnm2 = Bnm1
		Anm1 = An
		Bnm1 = Bn
		if gsl.IsOdd(n) {
			an = (float64(n-1) / 2.0) * x
		} else {
			an = -(float64(N) + (float64(n) / 2) - 1.0) * x
		}
		bn = float64(N + n - 1)
		An = bn*Anm1 + an*Anm2
		Bn = bn*Bnm1 + an*Bnm2

		if math.Abs(An) > RECUR_BIG || math.Abs(Bn) > RECUR_BIG {
			An /= RECUR_BIG
			Bn /= RECUR_BIG
			Anm1 /= RECUR_BIG
			Bnm1 /= RECUR_BIG
			Anm2 /= RECUR_BIG
			Bnm2 /= RECUR_BIG
		}

		old_fn = fn
		fn = An / Bn
		del = old_fn / fn

		if math.Abs(del-1.0) < 2.0*gsl.DBL_EPSILON {
			break
		}
	}

	result.val = fn
	result.err = 2.0 * (float64(n) + 1.0) * gsl.DBL_EPSILON * math.Abs(fn)

	if n == maxiter {
		return err.EMAXITER
	}
	return err.SUCCESS
}