lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] valyuta/004 c5f666f 08/11: Improve rounding to cents


From: Greg Chicares
Subject: [lmi-commits] [lmi] valyuta/004 c5f666f 08/11: Improve rounding to cents for solves
Date: Sun, 20 Dec 2020 17:40:10 -0500 (EST)

branch: valyuta/004
commit c5f666f7c090d638a0c602ec31b242b98d124766
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Improve rounding to cents for solves
    
    * currency.hpp: Temporarily assert that currency amounts constructed
    from 'double' values are exact integers. This assertion is costly
    enough that it will soon be reverted.
    * ihs_avsolve.cpp: Convert 'double' values to cents with explicit
    rounding. These changes are required to keep the temporary assertion
    (above) from firing.
    * solve.cpp: Likewise.
---
 Speed_gcc_i686-w64-mingw32    | 12 ++++++------
 Speed_gcc_x86_64-pc-linux-gnu | 12 ++++++------
 Speed_gcc_x86_64-w64-mingw32  | 12 ++++++------
 currency.hpp                  |  8 +++++++-
 ihs_avsolve.cpp               | 18 ++++++++++++------
 solve.cpp                     | 26 ++++++++++++++++----------
 6 files changed, 53 insertions(+), 35 deletions(-)

diff --git a/Speed_gcc_i686-w64-mingw32 b/Speed_gcc_i686-w64-mingw32
index f28fcd2..9971b0f 100644
--- a/Speed_gcc_i686-w64-mingw32
+++ b/Speed_gcc_i686-w64-mingw32
@@ -1,7 +1,7 @@
 Test speed:
-  naic, no solve      : 6.467e-02 s mean;      64198 us least of  16 runs
-  naic, specamt solve : 1.134e-01 s mean;     113224 us least of   9 runs
-  naic, ee prem solve : 1.038e-01 s mean;     103612 us least of  10 runs
-  finra, no solve     : 2.448e-02 s mean;      23548 us least of  41 runs
-  finra, specamt solve: 6.828e-02 s mean;      68023 us least of  15 runs
-  finra, ee prem solve: 6.344e-02 s mean;      63140 us least of  16 runs
+  naic, no solve      : 6.594e-02 s mean;      65604 us least of  16 runs
+  naic, specamt solve : 1.163e-01 s mean;     115862 us least of   9 runs
+  naic, ee prem solve : 1.063e-01 s mean;     106045 us least of  10 runs
+  finra, no solve     : 2.386e-02 s mean;      23704 us least of  42 runs
+  finra, specamt solve: 6.942e-02 s mean;      69231 us least of  15 runs
+  finra, ee prem solve: 6.444e-02 s mean;      64223 us least of  16 runs
diff --git a/Speed_gcc_x86_64-pc-linux-gnu b/Speed_gcc_x86_64-pc-linux-gnu
index 34ba62b..dc0bcf6 100644
--- a/Speed_gcc_x86_64-pc-linux-gnu
+++ b/Speed_gcc_x86_64-pc-linux-gnu
@@ -1,7 +1,7 @@
 Test speed:
-  naic, no solve      : 1.934e-02 s mean;      18847 us least of  52 runs
-  naic, specamt solve : 3.334e-02 s mean;      32772 us least of  31 runs
-  naic, ee prem solve : 3.055e-02 s mean;      29841 us least of  33 runs
-  finra, no solve     : 7.784e-03 s mean;       7317 us least of 100 runs
-  finra, specamt solve: 2.056e-02 s mean;      20189 us least of  49 runs
-  finra, ee prem solve: 1.924e-02 s mean;      18760 us least of  52 runs
+  naic, no solve      : 2.692e-02 s mean;      25779 us least of  38 runs
+  naic, specamt solve : 4.551e-02 s mean;      44600 us least of  22 runs
+  naic, ee prem solve : 4.443e-02 s mean;      40609 us least of  23 runs
+  finra, no solve     : 8.529e-03 s mean;       8269 us least of 100 runs
+  finra, specamt solve: 2.583e-02 s mean;      25023 us least of  39 runs
+  finra, ee prem solve: 2.523e-02 s mean;      23776 us least of  40 runs
diff --git a/Speed_gcc_x86_64-w64-mingw32 b/Speed_gcc_x86_64-w64-mingw32
index dc1c45c..d0a2a4b 100644
--- a/Speed_gcc_x86_64-w64-mingw32
+++ b/Speed_gcc_x86_64-w64-mingw32
@@ -1,7 +1,7 @@
 Test speed:
-  naic, no solve      : 2.687e-02 s mean;      26503 us least of  38 runs
-  naic, specamt solve : 4.217e-02 s mean;      41668 us least of  24 runs
-  naic, ee prem solve : 3.923e-02 s mean;      38847 us least of  26 runs
-  finra, no solve     : 1.499e-02 s mean;      14714 us least of  67 runs
-  finra, specamt solve: 2.901e-02 s mean;      28656 us least of  35 runs
-  finra, ee prem solve: 2.745e-02 s mean;      27094 us least of  37 runs
+  naic, no solve      : 3.510e-02 s mean;      34921 us least of  29 runs
+  naic, specamt solve : 5.626e-02 s mean;      55968 us least of  18 runs
+  naic, ee prem solve : 5.199e-02 s mean;      51731 us least of  20 runs
+  finra, no solve     : 1.593e-02 s mean;      15823 us least of  63 runs
+  finra, specamt solve: 3.603e-02 s mean;      34815 us least of  28 runs
+  finra, ee prem solve: 3.359e-02 s mean;      32930 us least of  31 runs
diff --git a/currency.hpp b/currency.hpp
index d69dd69..c541f64 100644
--- a/currency.hpp
+++ b/currency.hpp
@@ -24,6 +24,7 @@
 
 #include "config.hpp"
 
+#include "assert_lmi.hpp"
 #include "bourn_cast.hpp"
 ////#include "round_to.hpp"
 
@@ -144,7 +145,12 @@ class currency
     // suitable for the context should be used, e.g.:
     //   double d = loan_value()
     //   currency c = round_loan_.c(d);
-    data_type from_double(double d) const {return       cents_per_dollar * d ;}
+//  data_type from_double(double d) const {return       cents_per_dollar * d ;}
+    data_type from_double(double d) const
+        {
+        LMI_ASSERT(cents_per_dollar * d == round(cents_per_dollar * d));
+        return cents_per_dollar * d;
+        }
     // Here, bourn_cast costs something, but does nothing:
 //  double to_double() const {return bourn_cast<double>(m_) / 
cents_per_dollar;}
     double to_double() const {return static_cast<double>(m_) / 
cents_per_dollar;}
diff --git a/ihs_avsolve.cpp b/ihs_avsolve.cpp
index b308bfd..893499c 100644
--- a/ihs_avsolve.cpp
+++ b/ihs_avsolve.cpp
@@ -67,7 +67,8 @@ class SolveHelper
 //  double operator()(currency a_CandidateValue)
     double operator()(double a_CandidateValue)
         {
-        return av.SolveTest(currency(a_CandidateValue)).d();
+// CURRENCY !! Consider using zero<currency> instead of double.
+        return av.SolveTest(av.round_minutiae().c(a_CandidateValue)).d();
         }
 };
 
@@ -186,7 +187,8 @@ currency AccountValue::SolveTest(currency a_CandidateValue)
     currency most_negative_csv = C0;
     if(no_lapse_dur < SolveTargetDuration_)
         {
-        most_negative_csv = currency
+        // CURRENCY !! Cents in ledger will make rounding unnecessary.
+        most_negative_csv = round_minutiae().c
             (*std::min_element
                 (VariantValues().CSVNet.begin() + no_lapse_dur
                 ,VariantValues().CSVNet.begin() + SolveTargetDuration_
@@ -216,10 +218,13 @@ currency AccountValue::SolveTest(currency 
a_CandidateValue)
     // SolveTargetDuration_ is in origin one. That's natural for loop
     // counters and iterators--it's one past the end--but indexing
     // must decrement it.
-    currency value {VariantValues().CSVNet[SolveTargetDuration_ - 1]};
+    // CURRENCY !! Cents in ledger will make rounding unnecessary.
+//  currency value {VariantValues().CSVNet[SolveTargetDuration_ - 1]};
+    currency value = 
round_minutiae().c(VariantValues().CSVNet[SolveTargetDuration_ - 1]);
     if(mce_solve_for_target_naar == SolveTarget_)
         {
-        value = currency
+        // CURRENCY !! Cents in ledger will make rounding unnecessary.
+        value = round_minutiae().c
             (
               VariantValues().EOYDeathBft[SolveTargetDuration_ - 1]
             - VariantValues().AcctVal    [SolveTargetDuration_ - 1]
@@ -456,6 +461,7 @@ currency AccountValue::Solve
     // are stored now, and values are regenerated downstream.
 
     Solving = false;
-    (this->*solve_set_fn)(currency(solution.first));
-    return currency(solution.first);
+    currency const solution_cents = round_minutiae().c(solution.first);
+    (this->*solve_set_fn)(solution_cents);
+    return solution_cents;
 }
diff --git a/solve.cpp b/solve.cpp
index ef64d9b..03173ec 100644
--- a/solve.cpp
+++ b/solve.cpp
@@ -30,6 +30,7 @@
 #include "ledger_variant.hpp"
 #include "mc_enum_types_aux.hpp"        // set_run_basis_from_cloven_bases()
 #include "outlay.hpp"
+#include "round_to.hpp"
 #include "zero.hpp"
 
 #include <algorithm>                    // max(), min()
@@ -57,6 +58,8 @@ namespace
     int                 ThatSolveEndYear;
     mcenum_gen_basis    ThatSolveBasis;
     bool                only_set_values;
+
+    round_to<double> const round_to_cents(2, r_to_nearest);
 } // Unnamed namespace.
 
 //============================================================================
@@ -87,14 +90,17 @@ currency SolveTest()
         {
         Negative = std::min
             (Negative
-            ,currency(ConstThat->VariantValues().CSVNet[j])
+            // CURRENCY !! Cents in ledger will make rounding unnecessary.
+            ,round_to_cents.c(ConstThat->VariantValues().CSVNet[j])
 // Ideally, it'd be this:
 //          ,std::min(ConstThat->VariantValues().CSVNet[j], 
ConstThat->loan_ullage_[j])
 // but the antediluvian branch doesn't calculate ullage at all.
             );
         }
 
-    currency z {ConstThat->VariantValues().CSVNet[ThatSolveTgtYear - 1]};
+// CURRENCY !! Cents in ledger will make rounding unnecessary.
+//  currency z {ConstThat->VariantValues().CSVNet[ThatSolveTgtYear - 1]};
+    currency z = 
round_to_cents.c(ConstThat->VariantValues().CSVNet[ThatSolveTgtYear - 1]);
     if(Negative < C0)
         z = std::min(z, Negative);
     // IHS !! If SolveTgtYr within no-lapse period...see lmi.
@@ -134,7 +140,7 @@ currency SolveTest()
             break;
         case mce_solve_for_target_csv:
             {
-            y = currency(ThatSolveTargetValue);
+            y = round_to_cents.c(ThatSolveTargetValue);
             }
             break;
         case mce_solve_for_target_naar: // Fall through.
@@ -155,7 +161,7 @@ inline static double SolveSpecAmt(double CandidateValue)
 //inline static double SolveSpecAmt(currency CandidateValue)
 {
 // IHS !! Change surrchg when SA changes?
-    That->SolveSetSpecAmt(currency(CandidateValue), ThatSolveBegYear, 
ThatSolveEndYear);
+    That->SolveSetSpecAmt(round_to_cents.c(CandidateValue), ThatSolveBegYear, 
ThatSolveEndYear);
     return only_set_values ? 0.0 : SolveTest().d();
 }
 
@@ -163,7 +169,7 @@ inline static double SolveSpecAmt(double CandidateValue)
 inline static double SolvePrem(double CandidateValue)
 //inline static double SolvePrem(currency CandidateValue)
 {
-    That->SolveSetPmts(currency(CandidateValue), ThatSolveBegYear, 
ThatSolveEndYear);
+    That->SolveSetPmts(round_to_cents.c(CandidateValue), ThatSolveBegYear, 
ThatSolveEndYear);
     return only_set_values ? 0.0 : SolveTest().d();
 }
 
@@ -171,7 +177,7 @@ inline static double SolvePrem(double CandidateValue)
 inline static double SolveLoan(double CandidateValue)
 //inline static double SolveLoan(currency CandidateValue)
 {
-    That->SolveSetLoans(currency(CandidateValue), ThatSolveBegYear, 
ThatSolveEndYear);
+    That->SolveSetLoans(round_to_cents.c(CandidateValue), ThatSolveBegYear, 
ThatSolveEndYear);
     return only_set_values ? 0.0 : SolveTest().d();
 }
 
@@ -179,7 +185,7 @@ inline static double SolveLoan(double CandidateValue)
 inline static double SolveWD(double CandidateValue)
 //inline static double SolveWD(currency CandidateValue)
 {
-    That->SolveSetWDs(currency(CandidateValue), ThatSolveBegYear, 
ThatSolveEndYear);
+    That->SolveSetWDs(round_to_cents.c(CandidateValue), ThatSolveBegYear, 
ThatSolveEndYear);
     return only_set_values ? 0.0 : SolveTest().d();
 }
 
@@ -352,8 +358,8 @@ currency AccountValue::Solve()
     // generate or analyze account values. This global variable is a
     // kludge, but so is 'That'; a function object is wanted instead.
     only_set_values = !Solving;
-    currency actual_solution {Solution.first};
+    currency const solution_cents = round_to_cents.c(Solution.first);
 
-    SolveFn(actual_solution.d());
-    return actual_solution;
+    SolveFn(solution_cents.d());
+    return solution_cents;
 }



reply via email to

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