[goffice] fake-rounding: fix for very large numbers.



commit a384adbfd2c3cf72535d6f2474b90bfe48c26425
Author: Morten Welinder <terra gnome org>
Date:   Tue Jun 15 12:02:45 2010 -0400

    fake-rounding: fix for very large numbers.

 ChangeLog              |    7 +++++++
 NEWS                   |    1 +
 goffice/math/go-math.c |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 0 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index c99d058..6c91456 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2010-06-15  Morten Welinder  <terra gnome org>
+
+	* goffice/math/go-math.c (go_fake_floor, go_fake_ceil,
+	go_fake_trunc, go_fake_floorl, go_fake_ceill, go_fake_truncl):
+	Handle very large numbers right.  Handle ix86 excess precision for
+	"double" versions.
+
 2010-06-11  Morten Welinder  <terra gnome org>
 
 	* goffice/gtk/go-format-sel.c (funny_currency_order): Fix order.
diff --git a/NEWS b/NEWS
index 2dd34a0..d726557 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ Morten:
 	* Ensure format menu has yyyy-mm-dd.
 	* Improve docs.
 	* Fix currency ordering.  [#621336]
+	* Fix rounding problems for very large numbers.
 
 --------------------------------------------------------------------------
 goffice 0.8.5:
diff --git a/goffice/math/go-math.c b/goffice/math/go-math.c
index 879b108..291c0f7 100644
--- a/goffice/math/go-math.c
+++ b/goffice/math/go-math.c
@@ -220,9 +220,22 @@ go_sub_epsilon (double x)
 	}
 }
 
+static double
+go_d2d (double x)
+{
+	/* Kill excess precision by forcing a memory read.  */
+	const volatile double *px = &x;
+	return *px;
+}
+
 double
 go_fake_floor (double x)
 {
+	x = go_d2d (x);
+
+	if (x == floor (x))
+		return x;
+
 	return (x >= 0)
 		? floor (go_add_epsilon (x))
 		: floor (go_sub_epsilon (x));
@@ -231,6 +244,11 @@ go_fake_floor (double x)
 double
 go_fake_ceil (double x)
 {
+	x = go_d2d (x);
+
+	if (x == floor (x))
+		return x;
+
 	return (x >= 0)
 		? ceil (go_sub_epsilon (x))
 		: ceil (go_add_epsilon (x));
@@ -246,6 +264,11 @@ go_fake_round (double x)
 double
 go_fake_trunc (double x)
 {
+	x = go_d2d (x);
+
+	if (x == floor (x))
+		return x;
+
 	return (x >= 0)
 		? floor (go_add_epsilon (x))
 		: -floor (go_add_epsilon (-x));
@@ -636,6 +659,9 @@ go_sub_epsilonl (long double x)
 long double
 go_fake_floorl (long double x)
 {
+	if (x == floorl (x))
+		return x;
+
 	return (x >= 0)
 		? floorl (go_add_epsilonl (x))
 		: floorl (go_sub_epsilonl (x));
@@ -644,6 +670,9 @@ go_fake_floorl (long double x)
 long double
 go_fake_ceill (long double x)
 {
+	if (x == floorl (x))
+		return x;
+
 	return (x >= 0)
 		? ceill (go_sub_epsilonl (x))
 		: ceill (go_add_epsilonl (x));
@@ -659,6 +688,9 @@ go_fake_roundl (long double x)
 long double
 go_fake_truncl (long double x)
 {
+	if (x == floorl (x))
+		return x;
+
 	return (x >= 0)
 		? floorl (go_add_epsilonl (x))
 		: -floorl (go_add_epsilonl (-x));



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