lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] valyuta/002 c95db3d 2/5: Improve currency conversion


From: Greg Chicares
Subject: [lmi-commits] [lmi] valyuta/002 c95db3d 2/5: Improve currency conversions and rounding
Date: Sun, 20 Sep 2020 12:55:18 -0400 (EDT)

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

    Improve currency conversions and rounding
    
    In particular, this:
    -    return currency([floating-point expression]);
    +    return round_net_premium().c([floating-point expression]);
    is a difference between haphazard and contextually appropriate rounding.
    The currency(double) ctor should be used only when its argument is
    either known or assumed to have been appropriately rounded (and it would
    be good if a low-cost assertion to that effect could be devised).
---
 gpt_specamt.cpp  | 10 +++++-----
 ihs_avmly.cpp    | 16 ++++++++--------
 ihs_avsolve.cpp  |  3 ++-
 ihs_avstrtgy.cpp | 12 ++++++------
 4 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/gpt_specamt.cpp b/gpt_specamt.cpp
index e2b9c11..e5b14e3 100644
--- a/gpt_specamt.cpp
+++ b/gpt_specamt.cpp
@@ -92,12 +92,12 @@ class FindSpecAmt
         ,Premium         {a_Premium}
         ,NetPmtFactorTgt {a_NetPmtFactorTgt}
         ,NetPmtFactorExc {a_NetPmtFactorExc}
-        ,SpecAmt         {currency {}}
+        ,SpecAmt         {}
         {
         }
     double operator()(double a_Trial)
         {
-        SpecAmt = currency(a_Trial);
+        SpecAmt = Values_.round_min_specamt().c(a_Trial);
         return
                 Irc7702_.CalculatePremium
                     (EIOBasis_
@@ -112,9 +112,9 @@ class FindSpecAmt
             -   Premium
             ;
         }
-    double Get()
+    currency Get()
         {
-        return SpecAmt.d();
+        return SpecAmt;
         }
 };
 
@@ -166,5 +166,5 @@ currency gpt_specamt::CalculateSpecAmt
         ,true
         );
 
-    return currency(fsa.Get());
+    return fsa.Get();
 }
diff --git a/ihs_avmly.cpp b/ihs_avmly.cpp
index b061285..bac70cc 100644
--- a/ihs_avmly.cpp
+++ b/ihs_avmly.cpp
@@ -1338,7 +1338,7 @@ void AccountValue::TxLimitPayment(double a_maxpmt)
             gross_1035 = External1035Amount + Internal1035Amount;
             }
         currency gross_pmt_without_1035 = GrossPmts[Month] - gross_1035;
-        gross_pmt_without_1035 = currency(std::min(gross_pmt_without_1035.d(), 
a_maxpmt));
+        gross_pmt_without_1035 = 
round_gross_premium().c(std::min(gross_pmt_without_1035.d(), a_maxpmt));
         // TODO ?? For now at least, reduce employee premium first.
         progressively_limit
             (EeGrossPmts[Month]
@@ -1555,7 +1555,7 @@ currency AccountValue::GetPremLoad
 //============================================================================
 currency AccountValue::GetRefundableSalesLoad() const
 {
-    return currency(CumulativeSalesLoad * YearsSalesLoadRefundRate);
+    return round_net_premium().c(CumulativeSalesLoad * 
YearsSalesLoadRefundRate);
 #if 0
     // CURRENCY !! Assertions such as these are desirable, but adding
     // them now would cause regression artifacts.
@@ -2347,19 +2347,19 @@ currency AccountValue::anticipated_deduction
         {
         case mce_twelve_times_last:
             {
-            return currency(12.0 * MlyDed);
+            return 12 * MlyDed;
             }
         case mce_eighteen_times_last:
             {
-            return currency(18.0 * MlyDed);
+            return 18 * MlyDed;
             }
         case mce_to_next_anniversary:
             {
-            return currency(MlyDed * (13.0 - Month));
+            return MlyDed * (13 - Month);
             }
         case mce_to_next_modal_pmt_date:
             {
-            return currency(MlyDed * (1.0 + MonthsToNextModalPmtDate()));
+            return MlyDed * (1 + MonthsToNextModalPmtDate());
             }
         }
     throw "Unreachable--silences a compiler diagnostic.";
@@ -2582,8 +2582,8 @@ void AccountValue::TxTakeWD()
         LMI_ASSERT(AVRegLn == RegLnBal);
         LMI_ASSERT(AVPrfLn == PrfLnBal);
         LMI_ASSERT(av == AVGenAcct + AVSepAcct);
-        double free_wd = FreeWDProportion[Year] * av;
-        non_free_wd = currency(std::max(0.0, GrossWD.d() - free_wd));
+        currency free_wd = round_withdrawal().c(FreeWDProportion[Year] * av);
+        non_free_wd = std::max({}, GrossWD - free_wd);
         }
     double partial_surrchg = non_free_wd * surrchg_proportion;
     GrossWD += round_withdrawal().c(partial_surrchg);
diff --git a/ihs_avsolve.cpp b/ihs_avsolve.cpp
index 93f7336..1e3103f 100644
--- a/ihs_avsolve.cpp
+++ b/ihs_avsolve.cpp
@@ -242,7 +242,8 @@ currency AccountValue::SolveTest(currency a_CandidateValue)
 
     if(mce_solve_for_non_mec == SolveTarget_)
         {
-        return currency(InvariantValues().IsMec ? -1.0 : 1.0);
+        static const currency C1(100, true); // One hundred cents.
+        return InvariantValues().IsMec ? -C1 : C1;
         }
 
     return value - SolveTargetCsv_;
diff --git a/ihs_avstrtgy.cpp b/ihs_avstrtgy.cpp
index 41f81d8..e7c2306 100644
--- a/ihs_avstrtgy.cpp
+++ b/ihs_avstrtgy.cpp
@@ -145,9 +145,9 @@ void AccountValue::PerformSpecAmtStrategy()
             strategy = mce_sa_input_scalar;
             }
         currency z = CalculateSpecAmtFromStrategy(j, 0, explicit_value, 
strategy);
-        // Shouldn't rounding be done upstream? Was it?
-        DeathBfts_->set_specamt(currency(std::max(m, z)), j, 1 + j); // 
round(currency)?
-//      DeathBfts_->set_specamt(currency(round_specamt()(std::max(m, z))), j, 
1 + j); // round(currency)?
+        // This should have been rounded upstream. It would be nice to
+        // devise a good way to assert that it was.
+        DeathBfts_->set_specamt(std::max(m, z), j, 1 + j);
         if
             (  j == InforceYear
             && yare_input_.EffectiveDate != yare_input_.InforceAsOfDate
@@ -178,9 +178,9 @@ void AccountValue::PerformSupplAmtStrategy()
         currency explicit_value = DeathBfts_->supplamt()[j];
         mcenum_sa_strategy strategy = 
yare_input_.SupplementalAmountStrategy[j];
         currency z = CalculateSpecAmtFromStrategy(j, 0, explicit_value, 
strategy);
-        // Shouldn't rounding be done upstream? Was it?
-//      DeathBfts_->set_supplamt(currency(round_specamt()(std::max(m, z))), j, 
1 + j); // round(currency)?
-        DeathBfts_->set_supplamt(currency(std::max(m, z)), j, 1 + j); // 
round(currency)?
+        // This should have been rounded upstream. It would be nice to
+        // devise a good way to assert that it was.
+        DeathBfts_->set_supplamt(std::max(m, z), j, 1 + j);
         }
 }
 



reply via email to

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