gnumeric r16853 - in trunk: . plugins/fn-financial src



Author: mortenw
Date: Fri Oct  3 23:55:55 2008
New Revision: 16853
URL: http://svn.gnome.org/viewvc/gnumeric?rev=16853&view=rev

Log:
2008-10-03  Morten Welinder  <terra gnome org>

	* functions.c (gnumeric_xirr): Use float_range_function2d to
	handle pairing.  Fixes #554732.

2008-10-03  Morten Welinder  <terra gnome org>

	* src/collect.c (float_range_function2d): New function.
	(float_range_function2): Implement in terms on
	float_range_function2d.



Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/plugins/fn-financial/ChangeLog
   trunk/plugins/fn-financial/functions.c
   trunk/src/collect.c
   trunk/src/collect.h

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Fri Oct  3 23:55:55 2008
@@ -46,6 +46,7 @@
 	* Fix SUMIF crash.  [#552006]
 	* Fix NETWORKDAYS problem.  [#553047]
 	* Bring SUMX2MY2, SUMX2PY2, and SUMXMY2 into 21st century.  [#554040]
+	* Fix XIRR problem with missing data.  [#554732]
 
 Nakai:
 	* Enable Perl plugin again. [#553939]

Modified: trunk/plugins/fn-financial/functions.c
==============================================================================
--- trunk/plugins/fn-financial/functions.c	(original)
+++ trunk/plugins/fn-financial/functions.c	Fri Oct  3 23:55:55 2008
@@ -1935,66 +1935,47 @@
 };
 
 typedef struct {
-        int     n;
-        gnm_float *values;
-        gnm_float *dates;
+        int n;
+        const gnm_float *values;
+        const gnm_float *dates;
 } gnumeric_xirr_t;
 
 static GoalSeekStatus
 xirr_npv (gnm_float rate, gnm_float *y, void *user_data)
 {
-	gnumeric_xirr_t *p = user_data;
-	gnm_float *values, *dates, sum;
-        int i, n;
-
-	values = p->values;
-	dates = p->dates;
-	n = p->n;
-
-	sum = 0;
-	for (i = 0; i < n; i++) {
-		gnm_float d = dates[i] - dates[0];
+	const gnumeric_xirr_t *p = user_data;
+	gnm_float sum = 0;
+        int i;
+
+	for (i = 0; i < p->n; i++) {
+		gnm_float d = p->dates[i] - p->dates[0];
 
 		if (d < 0)
 			return GOAL_SEEK_ERROR;
-		sum += values[i] / pow1p (rate, d / 365.0);
+		sum += p->values[i] / pow1p (rate, d / 365.0);
 	}
 
 	*y = sum;
 	return GOAL_SEEK_OK;
 }
 
-static GnmValue *
-gnumeric_xirr (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
+static int
+gnm_range_xirr (gnm_float const *xs, const gnm_float *ys,
+		int n, gnm_float *res, gpointer user)
 {
-	GoalSeekData    data;
-	GoalSeekStatus  status;
-	GnmValue           *result = NULL;
 	gnumeric_xirr_t p;
-	gnm_float      rate0;
-	int             n, d_n;
+	gnm_float rate0 = *(gnm_float *)user;
+	GoalSeekData data;
+	GoalSeekStatus status;
+
+	p.dates = ys;
+	p.values = xs;
+	p.n = n;
 
 	goal_seek_initialize (&data);
 	data.xmin = -1;
 	data.xmax = MIN (1000, data.xmax);
 
-	rate0 = argv[2] ? value_get_as_float (argv[2]) : 0.1;
-
-	p.values = collect_floats_value (argv[0], ei->pos,
-					 COLLECT_COERCE_STRINGS,
-					 &n, &result);
-	p.dates = NULL;
-
-	if (result != NULL)
-		goto out;
-
-	p.dates = collect_floats_value (argv[1], ei->pos,
-					COLLECT_COERCE_STRINGS,
-					&d_n, &result);
-	if (result != NULL)
-		goto out;
-
-	p.n = n;
 	status = goal_seek_newton (&xirr_npv, NULL, &data, &p, rate0);
 	if (status != GOAL_SEEK_OK) {
 		int i;
@@ -2007,16 +1988,30 @@
 		}
 	}
 
-	if (status == GOAL_SEEK_OK)
-		result = value_new_float (data.root);
-	else
-		result = value_new_error_NUM (ei->pos);
+	if (status == GOAL_SEEK_OK) {
+		*res = data.root;
+		return 0;
+	}
 
- out:
-	g_free (p.values);
-	g_free (p.dates);
+	return 1;
+}
 
-	return result;
+
+static GnmValue *
+gnumeric_xirr (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
+{
+	gnm_float rate0 = argv[2] ? value_get_as_float (argv[2]) : 0.1;
+
+	/* Strings in a constant array need to be coerced -- finfuns.xls  */
+	/* FIXME: check strings in ranges and weep.  */
+	return float_range_function2d (argv[0], argv[1],
+				       ei,
+				       gnm_range_xirr,
+				       COLLECT_IGNORE_BLANKS |
+				       COLLECT_COERCE_STRINGS |
+				       COLLECT_IGNORE_BOOLS,
+				       GNM_ERROR_VALUE,
+				       &rate0);
 }
 
 /***************************************************************************/

Modified: trunk/src/collect.c
==============================================================================
--- trunk/src/collect.c	(original)
+++ trunk/src/collect.c	Fri Oct  3 23:55:55 2008
@@ -342,11 +342,12 @@
 }
 
 GnmValue *
-float_range_function2 (GnmValue const *val0, GnmValue const *val1,
-		       GnmFuncEvalInfo *ei,
-		       float_range_function2_t func,
-		       CollectFlags flags,
-		       GnmStdError func_error)
+float_range_function2d (GnmValue const *val0, GnmValue const *val1,
+			GnmFuncEvalInfo *ei,
+			float_range_function2d_t func,
+			CollectFlags flags,
+			GnmStdError func_error,
+			gpointer data)
 {
 	gnm_float *vals0, *vals1;
 	int n0, n1;
@@ -403,7 +404,7 @@
 			}
 		}
 
-		if (func (vals0, vals1, n0, &fres))
+		if (func (vals0, vals1, n0, &fres, data))
 			res = value_new_error_std (ei->pos, func_error);
 		else
 			res = value_new_float (fres);
@@ -414,6 +415,20 @@
 	return res;
 }
 
+GnmValue *
+float_range_function2 (GnmValue const *val0, GnmValue const *val1,
+		       GnmFuncEvalInfo *ei,
+		       float_range_function2_t func,
+		       CollectFlags flags,
+		       GnmStdError func_error)
+{
+	return float_range_function2d (val0, val1, ei,
+				       (float_range_function2d_t)func,
+				       flags,
+				       func_error,
+				       NULL);
+}
+
 /* ------------------------------------------------------------------------- */
 /* ------------------------------------------------------------------------- */
 

Modified: trunk/src/collect.h
==============================================================================
--- trunk/src/collect.h	(original)
+++ trunk/src/collect.h	Fri Oct  3 23:55:55 2008
@@ -29,12 +29,9 @@
 
 typedef int (*float_range_function_t) (gnm_float const *, int, gnm_float *);
 typedef int (*float_range_function2_t) (gnm_float const *, gnm_float const *, int, gnm_float *);
+typedef int (*float_range_function2d_t) (gnm_float const *, gnm_float const *, int, gnm_float *, gpointer);
 typedef int (*string_range_function_t) (GPtrArray *, char**);
 
-/*gnm_float *collect_floats (int argc, GnmExprConstPtr const *argv,
-				GnmEvalPos const *ep, CollectFlags flags,
-				int *n, GnmValue **error, GSList **info);*/
-
 gnm_float *collect_floats_value (GnmValue const *val,
 				 GnmEvalPos const *ep,
 				 CollectFlags flags,
@@ -56,6 +53,13 @@
 				 CollectFlags flags,
 				 GnmStdError func_error);
 
+GnmValue *float_range_function2d (GnmValue const *val0, GnmValue const *val1,
+				  GnmFuncEvalInfo *ei,
+				  float_range_function2d_t func,
+				  CollectFlags flags,
+				  GnmStdError func_error,
+				  gpointer data);
+
 GnmValue *string_range_function (int argc, GnmExprConstPtr const *argv,
 				 GnmFuncEvalInfo *ei,
 				 string_range_function_t func,



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