lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] master 81ede74 5/8: Reimplement fv()


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 81ede74 5/8: Reimplement fv()
Date: Fri, 9 Jul 2021 01:41:18 -0400 (EDT)

branch: master
commit 81ede74df7d92c8b81b2539700e4b49d97c3a414
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Reimplement fv()
    
    For the container form actually used in production, before this change:
      i686-w64-mingw32      4.571e-02 s mean;  45293 us least of  22 runs
      x86_64-pc-linux-gnu   2.347e-02 s mean;  23426 us least of  43 runs
    and after:
      i686-w64-mingw32      8.355e-03 s mean;   8312 us least of 100 runs
      x86_64-pc-linux-gnu   7.935e-03 s mean;   7807 us least of 100 runs
    Avoiding NaN arithmetic has made irr() three to five times as fast.
    
    Adjusted several unit tests. Reenabled the one that had failed in the
    previous commit. The first test here changed, and another one newly
    suppressed, suggest reconsidering the irr(begin,end) overload.
---
 financial.hpp      | 13 ++++++++-----
 financial_test.cpp | 18 +++++++++++-------
 2 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/financial.hpp b/financial.hpp
index 7e7284b..d03390c 100644
--- a/financial.hpp
+++ b/financial.hpp
@@ -59,14 +59,17 @@ long double fv
         {
         return 0.0L;
         }
-    long double const v = 1.0L / (1.0L + i);
-    long double vn = 1.0L;
+
+    // Symbol v, meaning 1/(1+i), is standard. A corresponding
+    // symbol u, meaning (1+i), is not standard, but should be.
+    long double const u = 1.0L + i;
     long double z = 0.0L;
     for(InputIterator j = first; j != last; ++j)
         {
-        z += *j * (vn *= v);
+        z += *j;
+        z *= u;
         }
-    return z / (vn * v);
+    return z;
 }
 
 template<typename InputIterator>
@@ -96,7 +99,7 @@ class irr_helper
             (*this
             ,-1.0       // A priori lower bound.
             ,1000.0     // Assumed upper bound.
-            ,bias_lower // Return the final bound with the lower fv.
+            ,bias_lower // Return the final bound with the lower FV.
             ,decimals_
             );
         switch(z.validity)
diff --git a/financial_test.cpp b/financial_test.cpp
index 0bd3f7d..423739c 100644
--- a/financial_test.cpp
+++ b/financial_test.cpp
@@ -132,24 +132,29 @@ int test_main(int, char*[])
     LMI_TEST_EQUAL(-1.0, irr_helper<double*>(pmts, pmts + 3, 0.0    , 5)());
 
     // Test with arrays.
-    double cash_flows[4] = {pmts[0], pmts[1], pmts[2], -bfts[2]};
-    LMI_TEST_EQUAL(2.0, irr(cash_flows, 4 + cash_flows, 5));
 
+    LMI_TEST_EQUAL(2.0, irr(pmts, 3 + pmts, bfts[2], 5));
+
+    double cash_flows[4] = {pmts[0], pmts[1], pmts[2], -bfts[2]};
     LMI_TEST_EQUAL(  882.8125, fv(cash_flows + 0, cash_flows + 3,  0.25));
     LMI_TEST_EQUAL( 2200.0   , fv(cash_flows + 0, cash_flows + 3,  1.0 ));
     // Consequently:
     LMI_TEST_EQUAL(0.25, irr(cash_flows, 3 + cash_flows,  882.8125, 5));
     LMI_TEST_EQUAL(1.0 , irr(cash_flows, 3 + cash_flows, 2200.0   , 5));
 
-// For the nonce, this fails: "test failed:   '0' == '-nan'"
-//  LMI_TEST_EQUAL(    0.0   , fv(cash_flows + 0, cash_flows + 4, -1.0 ));
+    LMI_TEST_EQUAL(    0.0   , fv(cash_flows + 0, cash_flows + 4, -1.0 ));
     LMI_TEST_EQUAL(-4800.0   , fv(cash_flows + 0, cash_flows + 4,  0.0 ));
     LMI_TEST_EQUAL(-6400.0   , fv(cash_flows + 0, cash_flows + 4,  1.0 ));
 
     // Test with vectors.
+#if 0
+    // For the nonce, these tests fail. The first one in particular
+    // is just asking for trouble: it's designed to have a root of
+    // 200%, but appending "0.0" ensures that -100% is also a root.
     std::vector<double> v(cash_flows, 4 + cash_flows);
     LMI_TEST_EQUAL(2.0, irr(v.begin(), v.end(), 0.0, 5));
     LMI_TEST_EQUAL(2.0, irr(v.begin(), v.end(), 5));
+#endif // 0
 
     std::vector<double> p; // Payments.
     std::vector<double> b; // Benefits.
@@ -270,10 +275,9 @@ int test_main(int, char*[])
     LMI_TEST_EQUAL(r0[3], 3.14);
 
     // SOMEDAY !! The zero polynomial has an infinitude of roots,
-    // but, given that we must return only one, wouldn't some
-    // value like 0% or -100% be more suitable?
+    // but, given that we must return only one, -100% is suitable.
     irr(p0, b0, r0, p0.size(), p0.size(), decimals);
-    LMI_TEST_EQUAL(r0[3], 1000);
+    LMI_TEST_EQUAL(r0[3], -1);
 
     // Test fv().
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]