[gnumeric] VDB: Fix interpretation of partial periods.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] VDB: Fix interpretation of partial periods.
- Date: Wed, 15 Nov 2017 00:37:30 +0000 (UTC)
commit c4a954cfaadbe49c32a862696f8b33a6ed3ed6c7
Author: Morten Welinder <terra gnome org>
Date: Tue Nov 14 19:36:38 2017 -0500
VDB: Fix interpretation of partial periods.
Inspired by AOO and LO bug reports.
NEWS | 1 +
plugins/fn-financial/ChangeLog | 5 +++
plugins/fn-financial/sc-fin.c | 58 ++++++++++++++++++++++++++--------------
3 files changed, 44 insertions(+), 20 deletions(-)
---
diff --git a/NEWS b/NEWS
index 77a51c6..7c9fc6f 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,7 @@ Morten:
* Fix xlsx export of trend line equation.
* Fix xlsx import and export of trend line affine flag.
* Avoid critical on exporting unnamed xlsx trend line.
+ * Fix VDB for partial periods. [#790299]
--------------------------------------------------------------------------
Gnumeric 1.12.35
diff --git a/plugins/fn-financial/ChangeLog b/plugins/fn-financial/ChangeLog
index 7ef1035..09709e0 100644
--- a/plugins/fn-financial/ChangeLog
+++ b/plugins/fn-financial/ChangeLog
@@ -1,3 +1,8 @@
+2017-11-13 Morten Welinder <terra gnome org>
+
+ * sc-fin.c (get_vdb): Fix handling of partial periods. Protect
+ against crazy values.
+
2017-07-06 Morten Welinder <terra gnome org>
* Release 1.12.35
diff --git a/plugins/fn-financial/sc-fin.c b/plugins/fn-financial/sc-fin.c
index affbe71..e81ed2d 100644
--- a/plugins/fn-financial/sc-fin.c
+++ b/plugins/fn-financial/sc-fin.c
@@ -386,13 +386,18 @@ get_vdb (gnm_float cost, gnm_float salvage, gnm_float life,
gnm_float fVdb;
gnm_float fIntStart = gnm_floor (start_period);
gnm_float fIntEnd = gnm_ceil (end_period);
- int i;
- int nLoopStart = (int) fIntStart;
- int nLoopEnd = (int) fIntEnd;
fVdb = 0.0;
if ( flag ) {
+ int i, nLoopStart, nLoopEnd;
+
+ if (fIntEnd > G_MAXINT ||
+ fIntEnd - fIntStart > 10000 /* arbitrary */)
+ return value_new_error_VALUE (NULL);
+
+ nLoopStart = (int) fIntStart;
+ nLoopEnd = (int) fIntEnd;
for (i = nLoopStart + 1; i <= nLoopEnd; i++) {
gnm_float fTerm;
@@ -405,23 +410,36 @@ get_vdb (gnm_float cost, gnm_float salvage, gnm_float life,
fVdb += fTerm;
}
} else {
- gnm_float life1 = life;
- gnm_float fPart;
-
- if ( start_period != gnm_floor (start_period) )
- if (factor > 1) {
- if (start_period >= life / 2) {
- fPart = start_period - life / 2;
- start_period = life / 2;
- end_period -= fPart;
- life1 += 1;
- }
- }
-
- cost -= ScInterVDB (cost, salvage, life, life1, start_period,
- factor);
- fVdb = ScInterVDB (cost, salvage, life, life - start_period,
- end_period - start_period, factor);
+ gnm_float fPart = 0;
+ double fIntEnd = gnm_ceil (end_period);
+
+ if (start_period > fIntStart) {
+ // First period is partial. Calculate the excess as
+ // the pro-rata value of the first period as-if it
+ // was not partial.
+ double tempcost = cost -
+ ScInterVDB( cost, salvage, life, life, fIntStart, factor);
+ fPart += (start_period - fIntStart) *
+ ScInterVDB( tempcost, salvage, life, life - fIntStart,
+ 1, factor);
+ }
+
+ if (end_period < fIntEnd) {
+ // Last period is partial. Calculate the excess as
+ // the pro-rata value of the last period as-if it
+ // was not partial.
+ double em1 = fIntEnd - 1; // Start of last period
+ double tempcost = cost -
+ ScInterVDB (cost, salvage, life, life, em1, factor);
+ fPart += (fIntEnd - end_period) *
+ ScInterVDB (tempcost, salvage, life, life - em1,
+ 1, factor);
+ }
+
+ cost -= ScInterVDB (cost, salvage, life, life, fIntStart, factor);
+ fVdb = ScInterVDB (cost, salvage, life, life - fIntStart,
+ fIntEnd - fIntStart, factor);
+ fVdb -= fPart;
}
return value_new_float (fVdb);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]