[goffice] Quad: fix overflow in mul12.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Quad: fix overflow in mul12.
- Date: Wed, 17 May 2017 13:45:38 +0000 (UTC)
commit b25fec70148ba52f9a2d886833733f75be67fa36
Author: Morten Welinder <terra gnome org>
Date: Wed May 17 09:45:02 2017 -0400
Quad: fix overflow in mul12.
Splitting very large numbers could overflow for no good reason.
ChangeLog | 5 +++++
NEWS | 3 +++
goffice/math/go-quad.c | 35 +++++++++++++++++++++++++++--------
3 files changed, 35 insertions(+), 8 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 2b0a5fa..2b02e21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2017-05-17 Morten Welinder <terra gnome org>
+
+ * goffice/math/go-quad.c (go_quad_mul12): Avoid unnecessary
+ overflow when splitting a number into two parts.
+
2017-03-20 Morten Welinder <terra gnome org>
* configure.ac: Post-release bump.
diff --git a/NEWS b/NEWS
index 08d4239..61741f6 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
goffice 0.10.35:
+Morten:
+ * Fix quad-precision overflow problem.
+
--------------------------------------------------------------------------
goffice 0.10.34:
diff --git a/goffice/math/go-quad.c b/goffice/math/go-quad.c
index b018958..9908a86 100644
--- a/goffice/math/go-quad.c
+++ b/goffice/math/go-quad.c
@@ -69,6 +69,7 @@ typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));
#define DOUBLE double
#define SUFFIX(_n) _n
#define DOUBLE_MANT_DIG DBL_MANT_DIG
+#define DOUBLE_EPSILON DBL_EPSILON
#ifdef GOFFICE_WITH_LONG_DOUBLE
#include "go-quad.c"
@@ -76,9 +77,11 @@ typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));
#undef DOUBLE
#undef SUFFIX
#undef DOUBLE_MANT_DIG
+#undef DOUBLE_EPSILON
#define DOUBLE long double
#define SUFFIX(_n) _n ## l
#define DOUBLE_MANT_DIG LDBL_MANT_DIG
+#define DOUBLE_EPSILON LDBL_EPSILON
#endif
#endif
@@ -392,6 +395,22 @@ SUFFIX(go_quad_sub) (QUAD *res, const QUAD *a, const QUAD *b)
res->l = r - res->h + s;
}
+
+#define SPLIT1(x,h,t) do { \
+ DOUBLE p = x * SUFFIX(CST); \
+ if (!SUFFIX(go_finite) (p) && SUFFIX(go_finite)(x)) { \
+ x *= DOUBLE_EPSILON; \
+ p = x * SUFFIX(CST); \
+ h = x - p + p; \
+ t = x - h; \
+ h *= (1 / DOUBLE_EPSILON); \
+ t *= (1 / DOUBLE_EPSILON); \
+ } else { \
+ h = x - p + p; \
+ t = x - h; \
+ } \
+} while (0)
+
/**
* go_quad_mul12:
* @res: (out): result location
@@ -413,20 +432,20 @@ SUFFIX(go_quad_sub) (QUAD *res, const QUAD *a, const QUAD *b)
void
SUFFIX(go_quad_mul12) (QUAD *res, DOUBLE x, DOUBLE y)
{
- DOUBLE p1 = x * SUFFIX(CST);
- DOUBLE hx = x - p1 + p1;
- DOUBLE tx = x - hx;
+ DOUBLE hx, tx, hy, ty, p, q;
- DOUBLE p2 = y * SUFFIX(CST);
- DOUBLE hy = y - p2 + p2;
- DOUBLE ty = y - hy;
+ SPLIT1 (x, hx, tx);
+ SPLIT1 (y, hy, ty);
- DOUBLE p = hx * hy;
- DOUBLE q = hx * ty + tx * hy;
+ p = hx * hy;
+ q = hx * ty + tx * hy;
res->h = p + q;
res->l = p - res->h + q + tx * ty;
}
+#undef SPLIT1
+
+
/**
* go_quad_mul:
* @res: (out): result location
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]