Commit 6fb55943 authored by Morten Welinder's avatar Morten Welinder
Browse files

Fixup IRR same as RATE.

parent a9807ec1
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* src/functions/fn-financial.c (gnumeric_rate): Respect the sign * src/functions/fn-financial.c (gnumeric_rate): Respect the sign
of the guess. Work much harder at getting an answer. of the guess. Work much harder at getting an answer.
(gnumeric_irr): Mirror the RATE improvements.
* src/goal-seek.c (goal_seek_point): New function. * src/goal-seek.c (goal_seek_point): New function.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* src/functions/fn-financial.c (gnumeric_rate): Respect the sign * src/functions/fn-financial.c (gnumeric_rate): Respect the sign
of the guess. Work much harder at getting an answer. of the guess. Work much harder at getting an answer.
(gnumeric_irr): Mirror the RATE improvements.
* src/goal-seek.c (goal_seek_point): New function. * src/goal-seek.c (goal_seek_point): New function.
......
...@@ -46,7 +46,7 @@ Morten: ...@@ -46,7 +46,7 @@ Morten:
* Fixed many bogusities in xbase plugin. * Fixed many bogusities in xbase plugin.
* Cleanup limits in numtheory. Added BITXOR. * Cleanup limits in numtheory. Added BITXOR.
* Fixed RATE, SLD, and SYD. * Fixed RATE, SLD, and SYD.
* Improved RATE's root searching. * Improved RATE's and IRR's root searching.
Pablo De Napoli: Pablo De Napoli:
* New NT_MU function in numtheory. * New NT_MU function in numtheory.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* src/functions/fn-financial.c (gnumeric_rate): Respect the sign * src/functions/fn-financial.c (gnumeric_rate): Respect the sign
of the guess. Work much harder at getting an answer. of the guess. Work much harder at getting an answer.
(gnumeric_irr): Mirror the RATE improvements.
* src/goal-seek.c (goal_seek_point): New function. * src/goal-seek.c (goal_seek_point): New function.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* src/functions/fn-financial.c (gnumeric_rate): Respect the sign * src/functions/fn-financial.c (gnumeric_rate): Respect the sign
of the guess. Work much harder at getting an answer. of the guess. Work much harder at getting an answer.
(gnumeric_irr): Mirror the RATE improvements.
* src/goal-seek.c (goal_seek_point): New function. * src/goal-seek.c (goal_seek_point): New function.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* src/functions/fn-financial.c (gnumeric_rate): Respect the sign * src/functions/fn-financial.c (gnumeric_rate): Respect the sign
of the guess. Work much harder at getting an answer. of the guess. Work much harder at getting an answer.
(gnumeric_irr): Mirror the RATE improvements.
* src/goal-seek.c (goal_seek_point): New function. * src/goal-seek.c (goal_seek_point): New function.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* src/functions/fn-financial.c (gnumeric_rate): Respect the sign * src/functions/fn-financial.c (gnumeric_rate): Respect the sign
of the guess. Work much harder at getting an answer. of the guess. Work much harder at getting an answer.
(gnumeric_irr): Mirror the RATE improvements.
* src/goal-seek.c (goal_seek_point): New function. * src/goal-seek.c (goal_seek_point): New function.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* src/functions/fn-financial.c (gnumeric_rate): Respect the sign * src/functions/fn-financial.c (gnumeric_rate): Respect the sign
of the guess. Work much harder at getting an answer. of the guess. Work much harder at getting an answer.
(gnumeric_irr): Mirror the RATE improvements.
* src/goal-seek.c (goal_seek_point): New function. * src/goal-seek.c (goal_seek_point): New function.
......
...@@ -1739,22 +1739,44 @@ gnumeric_irr (FunctionEvalInfo *ei, Value **argv) ...@@ -1739,22 +1739,44 @@ gnumeric_irr (FunctionEvalInfo *ei, Value **argv)
Value *result = NULL; Value *result = NULL;
gnumeric_irr_t p; gnumeric_irr_t p;
float_t rate0; float_t rate0;
int n;
goal_seek_initialise (&data);
rate0 = argv[1] ? value_get_as_float (argv[1]) : 0.1; rate0 = argv[1] ? value_get_as_float (argv[1]) : 0.1;
p.values = collect_floats_value (argv[0], ei->pos, p.values = collect_floats_value (argv[0], ei->pos,
COLLECT_IGNORE_STRINGS | COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BLANKS, COLLECT_IGNORE_BLANKS,
&n, &result); &p.n, &result);
if (result != NULL) { if (result != NULL) {
g_free (p.values); g_free (p.values);
return result; return result;
} }
p.n = n; goal_seek_initialise (&data);
/* Respect the sign of the guess. */
if (rate0 >= 0) {
data.xmin = 0;
data.xmax = MIN (data.xmax,
pow (DBL_MAX / 1e10, 1.0 / (p.n + 1)) - 1);
} else {
data.xmin = MAX (data.xmin,
-pow (DBL_MAX / 1e10, 1.0 / (p.n + 1)) + 1);
data.xmax = 0;
}
status = goal_seek_newton (&irr_npv, &irr_npv_df, &data, &p, rate0); status = goal_seek_newton (&irr_npv, &irr_npv_df, &data, &p, rate0);
if (status != GOAL_SEEK_OK) {
int factor;
/* Lay a net of test points around the guess. */
for (factor = 2; factor < 100; factor *= 2) {
goal_seek_point (&irr_npv, &data, &p, rate0 * factor);
goal_seek_point (&irr_npv, &data, &p, rate0 / factor);
}
/* Pray we got both sides of the root. */
status = goal_seek_bisection (&irr_npv, &data, &p);
}
g_free (p.values); g_free (p.values);
if (status == GOAL_SEEK_OK) if (status == GOAL_SEEK_OK)
......
...@@ -1739,22 +1739,44 @@ gnumeric_irr (FunctionEvalInfo *ei, Value **argv) ...@@ -1739,22 +1739,44 @@ gnumeric_irr (FunctionEvalInfo *ei, Value **argv)
Value *result = NULL; Value *result = NULL;
gnumeric_irr_t p; gnumeric_irr_t p;
float_t rate0; float_t rate0;
int n;
goal_seek_initialise (&data);
rate0 = argv[1] ? value_get_as_float (argv[1]) : 0.1; rate0 = argv[1] ? value_get_as_float (argv[1]) : 0.1;
p.values = collect_floats_value (argv[0], ei->pos, p.values = collect_floats_value (argv[0], ei->pos,
COLLECT_IGNORE_STRINGS | COLLECT_IGNORE_STRINGS |
COLLECT_IGNORE_BLANKS, COLLECT_IGNORE_BLANKS,
&n, &result); &p.n, &result);
if (result != NULL) { if (result != NULL) {
g_free (p.values); g_free (p.values);
return result; return result;
} }
p.n = n; goal_seek_initialise (&data);
/* Respect the sign of the guess. */
if (rate0 >= 0) {
data.xmin = 0;
data.xmax = MIN (data.xmax,
pow (DBL_MAX / 1e10, 1.0 / (p.n + 1)) - 1);
} else {
data.xmin = MAX (data.xmin,
-pow (DBL_MAX / 1e10, 1.0 / (p.n + 1)) + 1);
data.xmax = 0;
}
status = goal_seek_newton (&irr_npv, &irr_npv_df, &data, &p, rate0); status = goal_seek_newton (&irr_npv, &irr_npv_df, &data, &p, rate0);
if (status != GOAL_SEEK_OK) {
int factor;
/* Lay a net of test points around the guess. */
for (factor = 2; factor < 100; factor *= 2) {
goal_seek_point (&irr_npv, &data, &p, rate0 * factor);
goal_seek_point (&irr_npv, &data, &p, rate0 / factor);
}
/* Pray we got both sides of the root. */
status = goal_seek_bisection (&irr_npv, &data, &p);
}
g_free (p.values); g_free (p.values);
if (status == GOAL_SEEK_OK) if (status == GOAL_SEEK_OK)
......
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