[gnumeric] GAMMA: minor improvements.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] GAMMA: minor improvements.
- Date: Wed, 4 Dec 2013 03:29:34 +0000 (UTC)
commit ec415e26f4600cfa5d85ea364a9fb2caa861e403
Author: Morten Welinder <terra gnome org>
Date: Tue Dec 3 22:29:12 2013 -0500
GAMMA: minor improvements.
ChangeLog | 8 ++++++++
NEWS | 1 +
src/complex.c | 15 ++++++++-------
src/sf-gamma.c | 4 ++--
4 files changed, 19 insertions(+), 9 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 43acdc1..4027159 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2013-12-03 welinder <terra gnome org>
+
+ * src/sf-gamma.c (qgammaf): Avoid losing the least significant bit
+ of the argument for [-1.5;-0.5].
+
+ * src/complex.c (complex_fact): Avoid infinite recursion for 0 <
+ Re z < 1/2. Avoid some overflow.
+
2013-12-02 Morten Welinder <terra gnome org>
* src/sf-bessel.c (bessel_y): Use the J series when possible.
diff --git a/NEWS b/NEWS
index 00ff9c8..921ac60 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,7 @@ Morten:
* Improve accuracy of BETA and BETALN.
* Improve accuracy of BESSELJ and BESSELY.
* New functions: IMGAMMA, IMFACT.
+ * Avoid some overflows in IMGAMMA.
--------------------------------------------------------------------------
Gnumeric 1.12.9
diff --git a/src/complex.c b/src/complex.c
index ee2c103..96d8791 100644
--- a/src/complex.c
+++ b/src/complex.c
@@ -199,7 +199,7 @@ complex_fact (complex_t *dst, complex_t const *src)
{
if (complex_real_p (src)) {
complex_init (dst, gnm_fact (src->re), 0);
- } else if (src->re < 0.5) {
+ } else if (src->re < 0) {
/* Fact(z) = -pi / (sin(pi*z) * Gamma(-z)) */
complex_t a, b, mz;
@@ -209,6 +209,7 @@ complex_fact (complex_t *dst, complex_t const *src)
complex_init (&b,
M_PIgnum * gnm_fmod (src->re, 2),
M_PIgnum * src->im);
+ /* Hmm... sin overflows when b.im is large. */
complex_sin (&b, &b);
complex_mul (&a, &a, &b);
@@ -237,11 +238,13 @@ complex_fact (complex_t *dst, complex_t const *src)
const gnm_float g = GNM_const(607.0) / 128;
const gnm_float sqrt2pi =
GNM_const (2.506628274631000502415765284811045253006986740609938316629923);
- complex_t zph, zpgh, s, f;
+ complex_t zph, zpghde, s, f;
int i;
complex_init (&zph, src->re + 0.5, src->im);
- complex_init (&zpgh, src->re + g + 0.5, src->im);
+ complex_init (&zpghde,
+ (src->re + g + 0.5) / M_Egnum,
+ src->im / M_Egnum);
complex_init (&s, 0, 0);
for (i = G_N_ELEMENTS(c) - 1; i >= 1; i--) {
@@ -253,11 +256,9 @@ complex_fact (complex_t *dst, complex_t const *src)
}
s.re += c[0];
- complex_init (&f, sqrt2pi, 0);
+ complex_init (&f, sqrt2pi * gnm_exp (-g), 0);
complex_mul (&s, &s, &f);
- complex_exp (&f, &zpgh);
- complex_div (&s, &s, &f);
- complex_pow (&f, &zpgh, &zph);
+ complex_pow (&f, &zpghde, &zph);
complex_mul (&s, &s, &f);
*dst = s;
diff --git a/src/sf-gamma.c b/src/sf-gamma.c
index c522247..a3068f6 100644
--- a/src/sf-gamma.c
+++ b/src/sf-gamma.c
@@ -991,7 +991,7 @@ qfactf (gnm_float x, GnmQuad *mant, int *exp2)
static int
qgammaf (gnm_float x, GnmQuad *mant, int *exp2)
{
- if (gnm_abs (x) > 0.5)
+ if (x < -1.5 || x > 0.5)
return qfactf (x - 1, mant, exp2);
else if (gnm_isnan (x) || x == 0)
return 2;
@@ -1005,7 +1005,7 @@ qgammaf (gnm_float x, GnmQuad *mant, int *exp2)
rescale_mant_exp (mant, exp2);
gnm_quad_end (state);
return 0;
- }
+ }
}
/* ------------------------------------------------------------------------- */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]