Commit 653e12e3 authored by Morten Welinder's avatar Morten Welinder Committed by Morten Welinder

Use float_range_function2d to handle pairing. Fixes #554732.

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.


svn path=/trunk/; revision=16853
parent d350bb30
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.
2008-10-03 Andreas J. Guelzow <aguelzow@pyrshep.ca>
Fix for #553342
......
......@@ -46,6 +46,7 @@ Morten:
* 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]
......
2008-10-03 Morten Welinder <terra@gnome.org>
* functions.c (gnumeric_xirr): Use float_range_function2d to
handle pairing. Fixes #554732.
2008-08-29 Jody Goldberg <jody@gnome.org>
* Release 1.9.2
......
......@@ -1935,66 +1935,47 @@ static GnmFuncHelp const help_xirr[] = {
};
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;
const gnumeric_xirr_t *p = user_data;
gnm_float sum = 0;
int i;
values = p->values;
dates = p->dates;
n = p->n;
sum = 0;
for (i = 0; i < n; i++) {
gnm_float d = dates[i] - dates[0];
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 @@ gnumeric_xirr (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
}
}
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);
}
/***************************************************************************/
......
......@@ -342,11 +342,12 @@ gnm_strip_missing (GArray *data, GSList *missing)
}
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 @@ float_range_function2 (GnmValue const *val0, GnmValue const *val1,
}
}
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 @@ float_range_function2 (GnmValue const *val0, GnmValue const *val1,
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);
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
......
......@@ -29,12 +29,9 @@ typedef enum {
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 @@ GnmValue *float_range_function2 (GnmValue const *val0, GnmValue const *val1,
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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment