[gnumeric] R.DBINOM: Avoid overflow and assert for extreme values.



commit bc07921d2d08266cdd22c94f651187de4f4dd55d
Author: Morten Welinder <terra gnome org>
Date:   Wed Jan 6 19:33:49 2016 -0500

    R.DBINOM: Avoid overflow and assert for extreme values.

 ChangeLog      |    4 ++++
 NEWS           |    1 +
 src/mathfunc.c |   10 ++++++----
 3 files changed, 11 insertions(+), 4 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index d09fd91..714dd47 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2016-01-06  Morten Welinder  <terra gnome org>
+
+       * src/mathfunc.c (ebd0): Fix problem with overflow.  [#760230]
+
 2016-01-04  Morten Welinder  <terra gnome org>
 
        * src/sheet-style.c (sheet_style_apply_range)
diff --git a/NEWS b/NEWS
index fd7e335..6538bbd 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ Morten:
        * Improve test suite.
        * Fuzzed file fixes.  [#760046] [#760085] [#760087] [#760089]
          [#760043] [#760103] [#760102] [#760101] [#760105] [#760106]
+       * Fix R.DBINOM extreme-value case.  [#760230]
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.26
diff --git a/src/mathfunc.c b/src/mathfunc.c
index d2d7b6c..efd2de9 100644
--- a/src/mathfunc.c
+++ b/src/mathfunc.c
@@ -240,8 +240,8 @@ static const float bd0_scale[128 + 1][4] = {
 static void
 ebd0(gnm_float x, gnm_float M, gnm_float *yh, gnm_float *yl)
 {
-       gnm_float r, f, fg, M1;
-       int e;
+       gnm_float r, r1, r2, f, fg, M1;
+       int e, e1, e2;
        int i, j;
        const int Sb = 10;
        const double S = 1u << Sb;
@@ -257,8 +257,10 @@ ebd0(gnm_float x, gnm_float M, gnm_float *yh, gnm_float *yl)
        g_printerr ("x=%.20g  M=%.20g\n", x, M);
 #endif
 
-       /* FIXME: handle overflow/underflow in division below */
-       r = gnm_frexp (M / x, &e);
+       r1 = gnm_frexp (M, &e1);
+       r2 = gnm_frexp (x, &e2);
+       r = gnm_frexp (r1 / r2, &e);
+       e += (e1 - e2);
        i = gnm_floor ((r - 0.5) * (2 * N) + 0.5);
        g_assert (i >= 0 && i <= N);
        f = gnm_floor (S / (0.5 + i / (2.0 * N)) + 0.5);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]