Skip to content

Commit e11a90f

Browse files
committed
Switch Lagrange interpolation and Spouge approximation
1 parent fb294ee commit e11a90f

2 files changed

Lines changed: 16 additions & 9 deletions

File tree

lib/bigdecimal/math.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,8 @@ def gamma(x, prec)
737737
return pi.div(gamma(1 - x, prec2).mult(sin, prec2), prec)
738738
elsif x.frac.zero? && x < 1000 * prec
739739
return _gamma_positive_integer(x, prec2).mult(1, prec)
740+
elsif x < prec * 2
741+
return _gamma_lagrange(x, prec2).mult(1, prec)
740742
end
741743

742744
a, sum = _gamma_spouge_sum_part(x, prec2)
@@ -764,7 +766,7 @@ def gamma(x, prec)
764766
[prd, coef]
765767
end
766768

767-
def gamma_lagrange(x, prec)
769+
private_class_method def _gamma_lagrange(x, prec)
768770
# Calculate approximage gamma by Lagrange interpolation of b**x/x! at x=b-l, b-l+1, ..., b+l
769771

770772
x = BigDecimal(x) - 1
@@ -904,8 +906,13 @@ def lgamma(x, prec)
904906
end
905907

906908
prec2 += [-diff1_exponent, -diff2_exponent, 0].max
907-
a, sum = _gamma_spouge_sum_part(x, prec2)
908-
log_gamma = BigMath.log(sum, prec2).add((x - 0.5).mult(BigMath.log(x.add(a - 1, prec2), prec2), prec2) + 1 - x, prec)
909+
910+
if x < prec * 2
911+
log_gamma = BigMath.log(_gamma_lagrange(x, prec2), prec)
912+
else
913+
a, sum = _gamma_spouge_sum_part(x, prec2)
914+
log_gamma = BigMath.log(sum, prec2).add((x - 0.5).mult(BigMath.log(x.add(a - 1, prec2), prec2), prec2) + 1 - x, prec)
915+
end
909916
[log_gamma, 1]
910917
end
911918
end

test/bigdecimal/test_bigmath.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,11 @@ def test_gamma
567567
BigDecimal('0.28242294079603478742934215780245355184774949260912e456569'),
568568
BigMath.gamma(100000, 50)
569569
)
570-
precisions = [50, 100, 150]
571-
assert_converge_in_precision(precisions) {|n| gamma(BigDecimal("0.3"), n) }
572-
assert_converge_in_precision(precisions) {|n| gamma(BigDecimal("-1.9" + "9" * 30), n) }
573-
assert_converge_in_precision(precisions) {|n| gamma(BigDecimal("1234.56789"), n) }
574-
assert_converge_in_precision(precisions) {|n| gamma(BigDecimal("-987.654321"), n) }
570+
precisions = [100, 200, 300, 400]
571+
assert_converge_in_precision() {|n| gamma(BigDecimal("0.3"), n) }
572+
assert_converge_in_precision() {|n| gamma(BigDecimal("-1.9" + "9" * 30), n) }
573+
assert_converge_in_precision() {|n| gamma(BigDecimal("1234.56789"), n) }
574+
assert_converge_in_precision() {|n| gamma(BigDecimal("-987.654321"), n) }
575575
end
576576

577577
def test_lgamma
@@ -587,7 +587,7 @@ def test_lgamma
587587
assert_equal(sign, bigsign)
588588
end
589589
assert_equal([BigMath.log(PI(120).sqrt(120), 100), 1], lgamma(BigDecimal("0.5"), 100))
590-
precisions = [50, 100, 150]
590+
precisions = [50, 100, 150, 200]
591591
assert_converge_in_precision(precisions) {|n| lgamma(BigDecimal("0." + "9" * 80), n).first }
592592
assert_converge_in_precision(precisions) {|n| lgamma(BigDecimal("1." + "0" * 80 + "1"), n).first }
593593
assert_converge_in_precision(precisions) {|n| lgamma(BigDecimal("1." + "9" * 80), n).first }

0 commit comments

Comments
 (0)