[gnumeric] SUMPRODUCT: improve accuracy



commit 0492a6e9dbae404e055e9ace3066497f97a8af6d
Author: Morten Welinder <terra gnome org>
Date:   Fri Nov 25 13:50:50 2011 -0500

    SUMPRODUCT: improve accuracy

 configure.in                |    2 +-
 plugins/fn-math/ChangeLog   |    4 ++++
 plugins/fn-math/functions.c |   21 +++++++++++++++------
 src/numbers.h               |   24 ++++++++++++++++++++++++
 4 files changed, 44 insertions(+), 7 deletions(-)
---
diff --git a/configure.in b/configure.in
index bd05d56..3b6daef 100644
--- a/configure.in
+++ b/configure.in
@@ -145,7 +145,7 @@ PKG_PROG_PKG_CONFIG(0.18)
 
 dnl *****************************
 libspreadsheet_reqs="
-	libgoffice-${GOFFICE_API_VER}	>= 0.9.0
+	libgoffice-${GOFFICE_API_VER}	>= 0.9.1
 	libgsf-1		>= 1.14.18
 	libxml-2.0		>= 2.4.12
 "
diff --git a/plugins/fn-math/ChangeLog b/plugins/fn-math/ChangeLog
index 1883e9e..85152a4 100644
--- a/plugins/fn-math/ChangeLog
+++ b/plugins/fn-math/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-25  Morten Welinder  <terra gnome org>
+
+	* functions.c (gnumeric_sumproduct_common): Improve accuracy.
+
 2011-11-24  Morten Welinder <terra gnome org>
 
 	* Release 1.11.0
diff --git a/plugins/fn-math/functions.c b/plugins/fn-math/functions.c
index 108541a..931c6f9 100644
--- a/plugins/fn-math/functions.c
+++ b/plugins/fn-math/functions.c
@@ -3056,17 +3056,26 @@ gnumeric_sumproduct_common (gboolean ignore_bools, GnmFuncEvalInfo *ei,
 		 */
 		result = value_new_error_VALUE (ei->pos);
 	} else {
-		gnm_float sum = 0;
+
+		void *state = gnm_accumulator_start ();
+		GnmAccumulator *acc = gnm_accumulator_new ();
 		int j;
 
 		for (j = 0; j < sizex * sizey; j++) {
-			gnm_float product = data[0][j];
-			for (i = 1; i < argc; i++)
-				product *= data[i][j];
-			sum += product;
+			int i;
+			GnmQuad product;
+			gnm_quad_init (&product, data[0][j]);
+			for (i = 1; i < argc; i++) {
+				GnmQuad q;
+				gnm_quad_init (&q, data[i][j]);
+				gnm_quad_mul (&product, &product, &q);
+			}
+			gnm_accumulator_add_quad (acc, &product);
 		}
 
-		result = value_new_float (sum);
+		result = value_new_float (gnm_accumulator_value (acc));
+		gnm_accumulator_free (acc);
+		gnm_accumulator_end (state);
 	}
 
 done:
diff --git a/src/numbers.h b/src/numbers.h
index 2c8ee4e..112f339 100644
--- a/src/numbers.h
+++ b/src/numbers.h
@@ -120,6 +120,18 @@ gnm_float gnm_yn (int n, gnm_float x);
 #define GNM_EPSILON	LDBL_EPSILON
 #define GNM_const(_c)	_c ## L
 
+#define GnmQuad GOQuadl
+#define gnm_quad_init go_quad_initl
+#define gnm_quad_mul go_quad_mull
+#define GnmAccumulator GOAccumulatorl
+#define gnm_accumulator_start go_accumulator_startl
+#define gnm_accumulator_end go_accumulator_endl
+#define gnm_accumulator_new go_accumulator_newl
+#define gnm_accumulator_free go_accumulator_freel
+#define gnm_accumulator_add go_accumulator_addl
+#define gnm_accumulator_add_quad go_accumulator_add_quadl
+#define gnm_accumulator_value go_accumulator_valuel
+
 #else /* !GNM_WITH_LONG_DOUBLE */
 
 typedef double gnm_float;
@@ -190,6 +202,18 @@ typedef double gnm_float;
 #define GNM_EPSILON	DBL_EPSILON
 #define GNM_const(_c)	_c
 
+#define GnmQuad GOQuad
+#define gnm_quad_init go_quad_init
+#define gnm_quad_mul go_quad_mul
+#define GnmAccumulator GOAccumulator
+#define gnm_accumulator_start go_accumulator_start
+#define gnm_accumulator_end go_accumulator_end
+#define gnm_accumulator_new go_accumulator_new
+#define gnm_accumulator_free go_accumulator_free
+#define gnm_accumulator_add go_accumulator_add
+#define gnm_accumulator_add_quad go_accumulator_add_quad
+#define gnm_accumulator_value go_accumulator_value
+
 #endif
 
 G_END_DECLS



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