lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] master 9d991b0 15/15: Round currency as such


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 9d991b0 15/15: Round currency as such
Date: Mon, 25 Jan 2021 09:58:07 -0500 (EST)

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

    Round currency as such
    
    When assigning from floating point to currency, use round_to<>.c()
    (which, when class currency is used, returns whole cents, e.g., the
    exact integer 1 meaning $0.01) instead of round_to<>.operator()
    (which returns floating-point dollars, e.g., 0.01000000000000000020817
    meaning $0.01).
    
    Some calculations must be rearranged so that, when class currency is
    used, no non-integral value is assigned to a currency variable; e.g.,
    instead of rounding after assignment:
    
    -        AdbCharge = YearsAdbRate * std::min(ActualSpecAmt, AdbLimit);
    -        AdbCharge = round_rider_charges()(AdbCharge);
    
    round the amount to be assigned:
    
    +        AdbCharge = round_rider_charges().c
    +            (YearsAdbRate * std::min(ActualSpecAmt, AdbLimit)
    +            );
    
    Speed is affected unremarkably: plus or minus a couple percent, mostly.
    
    Incidentally noted some members that aren't rounded because they're
    unused (and presumably ought to be removed).
---
 Speed_gcc_i686-w64-mingw32    | 12 ++++-----
 Speed_gcc_x86_64-pc-linux-gnu | 12 ++++-----
 Speed_gcc_x86_64-w64-mingw32  | 12 ++++-----
 account_value.hpp             |  4 +--
 accountvalue.cpp              | 30 +++++++++++-----------
 ihs_acctval.cpp               | 18 ++++++-------
 ihs_avmly.cpp                 | 60 ++++++++++++++++++++++---------------------
 7 files changed, 75 insertions(+), 73 deletions(-)

diff --git a/Speed_gcc_i686-w64-mingw32 b/Speed_gcc_i686-w64-mingw32
index 09c5264..294d586 100644
--- a/Speed_gcc_i686-w64-mingw32
+++ b/Speed_gcc_i686-w64-mingw32
@@ -1,7 +1,7 @@
 Test speed:
-  naic, no solve      : 5.240e-02 s mean;      52171 us least of  20 runs
-  naic, specamt solve : 9.321e-02 s mean;      93012 us least of  11 runs
-  naic, ee prem solve : 8.558e-02 s mean;      85310 us least of  12 runs
-  finra, no solve     : 2.216e-02 s mean;      21918 us least of  46 runs
-  finra, specamt solve: 5.944e-02 s mean;      59112 us least of  17 runs
-  finra, ee prem solve: 5.534e-02 s mean;      55072 us least of  19 runs
+  naic, no solve      : 5.176e-02 s mean;      51559 us least of  20 runs
+  naic, specamt solve : 9.231e-02 s mean;      92006 us least of  11 runs
+  naic, ee prem solve : 8.838e-02 s mean;      84505 us least of  12 runs
+  finra, no solve     : 2.179e-02 s mean;      21605 us least of  46 runs
+  finra, specamt solve: 5.896e-02 s mean;      58739 us least of  17 runs
+  finra, ee prem solve: 5.492e-02 s mean;      54687 us least of  19 runs
diff --git a/Speed_gcc_x86_64-pc-linux-gnu b/Speed_gcc_x86_64-pc-linux-gnu
index ce63826..3cda0e3 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.945e-02 s mean;      18794 us least of  52 runs
-  naic, specamt solve : 3.309e-02 s mean;      32559 us least of  31 runs
-  naic, ee prem solve : 3.035e-02 s mean;      29728 us least of  33 runs
-  finra, no solve     : 7.616e-03 s mean;       7196 us least of 100 runs
-  finra, specamt solve: 2.055e-02 s mean;      19831 us least of  49 runs
-  finra, ee prem solve: 1.909e-02 s mean;      18530 us least of  53 runs
+  naic, no solve      : 1.930e-02 s mean;      18877 us least of  52 runs
+  naic, specamt solve : 3.380e-02 s mean;      32990 us least of  30 runs
+  naic, ee prem solve : 3.104e-02 s mean;      30405 us least of  33 runs
+  finra, no solve     : 7.782e-03 s mean;       7468 us least of 100 runs
+  finra, specamt solve: 2.096e-02 s mean;      20403 us least of  48 runs
+  finra, ee prem solve: 1.958e-02 s mean;      18668 us least of  52 runs
diff --git a/Speed_gcc_x86_64-w64-mingw32 b/Speed_gcc_x86_64-w64-mingw32
index 29b7c5e..5eff62d 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.674e-02 s mean;      26472 us least of  38 runs
-  naic, specamt solve : 4.205e-02 s mean;      41760 us least of  24 runs
-  naic, ee prem solve : 3.931e-02 s mean;      38935 us least of  26 runs
-  finra, no solve     : 1.481e-02 s mean;      14644 us least of  68 runs
-  finra, specamt solve: 2.909e-02 s mean;      28845 us least of  35 runs
-  finra, ee prem solve: 2.749e-02 s mean;      27273 us least of  37 runs
+  naic, no solve      : 2.688e-02 s mean;      26723 us least of  38 runs
+  naic, specamt solve : 4.241e-02 s mean;      42159 us least of  24 runs
+  naic, ee prem solve : 3.941e-02 s mean;      39256 us least of  26 runs
+  finra, no solve     : 1.471e-02 s mean;      14582 us least of  68 runs
+  finra, specamt solve: 2.898e-02 s mean;      28827 us least of  35 runs
+  finra, ee prem solve: 2.740e-02 s mean;      27285 us least of  37 runs
diff --git a/account_value.hpp b/account_value.hpp
index 8ce044a..ee5ce9b 100644
--- a/account_value.hpp
+++ b/account_value.hpp
@@ -403,10 +403,10 @@ class LMI_SO AccountValue final
     currency InforceRegLnBal;
     currency InforcePrfLnBal;
     currency InforceCumNoLapsePrem;
-    currency InforceBasis;
+    currency InforceBasis; // CURRENCY !! unused
     currency InforceCumPmts;
     currency InforceTaxBasis;
-    currency InforceLoanBalance;
+    currency InforceLoanBalance; // CURRENCY !! unused
 
     // Intermediate values.
     int      Year;
diff --git a/accountvalue.cpp b/accountvalue.cpp
index 7d4d81a..f878312 100644
--- a/accountvalue.cpp
+++ b/accountvalue.cpp
@@ -128,7 +128,8 @@ AccountValue::AccountValue(Input const& input)
 
 currency AccountValue::base_specamt(int year) const
 {
-    return InvariantValues().SpecAmt[year];
+    // CURRENCY !! Cents in ledger will make rounding unnecessary.
+    return round_specamt().c(InvariantValues().SpecAmt[year]);
 }
 
 //============================================================================
@@ -222,7 +223,7 @@ void AccountValue::RunOneCell(mcenum_run_basis TheBasis)
 
     InforceYear      = yare_input_.InforceYear;
     InforceMonth     = yare_input_.InforceMonth;
-    InforceAVGenAcct = yare_input_.InforceGeneralAccountValue;
+    InforceAVGenAcct = 
round_minutiae().c(yare_input_.InforceGeneralAccountValue);
 
     ItLapsed         = false;
     LapseMonth       = 0;
@@ -282,7 +283,7 @@ void AccountValue::DoYear
 
     pmt                   = stored_pmts[Year];
     YearsPremLoadTgt      = Loads_->target_premium_load(GenBasis_)[Year];
-    YearsMonthlyPolicyFee = Loads_->monthly_policy_fee(GenBasis_)[Year];
+    YearsMonthlyPolicyFee = Loads_->monthly_policy_fee (GenBasis_)[Year];
     ActualSpecAmt         = base_specamt(Year);
 
     // These variables are set for each pass independently.
@@ -485,7 +486,7 @@ void AccountValue::PerformSpecAmtStrategy()
             }
         }
 
-    SA = round_specamt()(SA);
+    SA = round_specamt().c(SA);
 
     for(int j = 0; j < BasicValues::GetLength(); ++j)
         {
@@ -544,7 +545,7 @@ void AccountValue::TxOptionChange()
             alarum() << "Case " << YearsDBOpt << " not found." << LMI_FLUSH;
             }
         }
-    ActualSpecAmt = round_specamt()(ActualSpecAmt);
+    ActualSpecAmt = round_specamt().c(ActualSpecAmt);
 
     // Carry the new spec amt forward into all future years.
     for(int j = Year; j < BasicValues::GetLength(); ++j)
@@ -698,7 +699,7 @@ void AccountValue::TxPmt()
 //            (DB-AV)/YearsCorridorFactor - AV
 
     // Subtract premium load from gross premium yielding net premium.
-    NetPmts[Month] = round_net_premium()
+    NetPmts[Month] = round_net_premium().c
         (GrossPmts[Month] * (1.0 - YearsPremLoadTgt)
         );
     // Should we instead do the following?
@@ -769,7 +770,7 @@ void AccountValue::TxSetDeathBft()
             }
         }
 
-    deathbft = round_death_benefit()(deathbft);
+    deathbft = round_death_benefit().c(deathbft);
 
     // SOMEDAY !! Accumulate average death benefit for profit testing here.
 }
@@ -783,7 +784,7 @@ void AccountValue::TxSetCoiCharge()
     // Negative AV doesn't increase NAAR.
     NAAR = round_naar()(deathbft * mlyguarv - (AVUnloaned + AVRegLn + 
AVPrfLn));
 
-    CoiCharge = round_coi_charge()(NAAR * YearsCoiRate0);
+    CoiCharge = round_coi_charge().c(NAAR * YearsCoiRate0);
 }
 
 /// Calculate rider charges.
@@ -825,8 +826,7 @@ void AccountValue::TxCreditInt()
     if(C0 < AVUnloaned)
         {
         // IHS !! Each interest increment is rounded separately in lmi.
-        double z = round_interest_credit()(AVUnloaned * YearsGenAcctIntRate);
-        AVUnloaned += z;
+        AVUnloaned += round_interest_credit().c(AVUnloaned * 
YearsGenAcctIntRate);
         }
     // Loaned account value cannot be negative.
     LMI_ASSERT(C0 <= AVRegLn + AVPrfLn);
@@ -844,14 +844,14 @@ void AccountValue::TxLoanInt()
 
     // We may want to display credited interest separately.
     // IHS !! Each interest increment is rounded separately in lmi.
-    RegLnIntCred = round_interest_credit()(AVRegLn * YearsRegLnIntCredRate);
-    PrfLnIntCred = round_interest_credit()(AVPrfLn * YearsPrfLnIntCredRate);
+    RegLnIntCred = round_interest_credit().c(AVRegLn * YearsRegLnIntCredRate);
+    PrfLnIntCred = round_interest_credit().c(AVPrfLn * YearsPrfLnIntCredRate);
 
     AVRegLn += RegLnIntCred;
     AVPrfLn += PrfLnIntCred;
 
-    double RegLnIntAccrued = round_interest_credit()(RegLnBal * 
YearsRegLnIntDueRate);
-    double PrfLnIntAccrued = round_interest_credit()(PrfLnBal * 
YearsPrfLnIntDueRate);
+    currency RegLnIntAccrued = round_interest_credit().c(RegLnBal * 
YearsRegLnIntDueRate);
+    currency PrfLnIntAccrued = round_interest_credit().c(PrfLnBal * 
YearsPrfLnIntDueRate);
 
     RegLnBal += RegLnIntAccrued;
     PrfLnBal += PrfLnIntAccrued;
@@ -917,7 +917,7 @@ void AccountValue::TxTakeWD()
 // IHS !!            ActualSpecAmt = std::min(ActualSpecAmt, deathbft - wd);
             ActualSpecAmt -= wd;
             ActualSpecAmt = std::max(ActualSpecAmt, MinSpecAmt);
-            ActualSpecAmt = round_specamt()(ActualSpecAmt);
+            ActualSpecAmt = round_specamt().c(ActualSpecAmt);
             // IHS !! If WD causes AV < min AV, do we:
             //   reduce the WD?
             //   lapse the policy?
diff --git a/ihs_acctval.cpp b/ihs_acctval.cpp
index df576a8..5a2d4e5 100644
--- a/ihs_acctval.cpp
+++ b/ihs_acctval.cpp
@@ -539,15 +539,15 @@ void AccountValue::SetInitialValues()
 {
     InforceYear           = yare_input_.InforceYear                     ;
     InforceMonth          = yare_input_.InforceMonth                    ;
-    InforceAVGenAcct      = yare_input_.InforceGeneralAccountValue      ;
-    InforceAVSepAcct      = yare_input_.InforceSeparateAccountValue     ;
-    InforceAVRegLn        = yare_input_.InforceRegularLoanValue         ;
-    InforceAVPrfLn        = yare_input_.InforcePreferredLoanValue       ;
-    InforceRegLnBal       = yare_input_.InforceRegularLoanBalance       ;
-    InforcePrfLnBal       = yare_input_.InforcePreferredLoanBalance     ;
-    InforceCumNoLapsePrem = yare_input_.InforceCumulativeNoLapsePremium ;
-    InforceCumPmts        = yare_input_.InforceCumulativeNoLapsePayments;
-    InforceTaxBasis       = yare_input_.InforceTaxBasis                 ;
+    InforceAVGenAcct      = 
round_minutiae().c(yare_input_.InforceGeneralAccountValue      );
+    InforceAVSepAcct      = 
round_minutiae().c(yare_input_.InforceSeparateAccountValue     );
+    InforceAVRegLn        = 
round_minutiae().c(yare_input_.InforceRegularLoanValue         );
+    InforceAVPrfLn        = 
round_minutiae().c(yare_input_.InforcePreferredLoanValue       );
+    InforceRegLnBal       = 
round_minutiae().c(yare_input_.InforceRegularLoanBalance       );
+    InforcePrfLnBal       = 
round_minutiae().c(yare_input_.InforcePreferredLoanBalance     );
+    InforceCumNoLapsePrem = 
round_minutiae().c(yare_input_.InforceCumulativeNoLapsePremium );
+    InforceCumPmts        = 
round_minutiae().c(yare_input_.InforceCumulativeNoLapsePayments);
+    InforceTaxBasis       = round_minutiae().c(yare_input_.InforceTaxBasis     
            );
 
     Year                  = InforceYear;
     Month                 = InforceMonth;
diff --git a/ihs_avmly.cpp b/ihs_avmly.cpp
index c6c364a..f463589 100644
--- a/ihs_avmly.cpp
+++ b/ihs_avmly.cpp
@@ -333,7 +333,7 @@ void AccountValue::process_payment(currency payment)
 // portions of unloaned account value according to input allocations.
 void AccountValue::IncrementAVProportionally(currency increment)
 {
-    increment = round_minutiae()(increment);
+    increment = round_minutiae().c(increment);
     double genacct_increment = increment * GenAcctPaymentAllocation;
     genacct_increment = round_minutiae()(genacct_increment);
     AVGenAcct += genacct_increment;
@@ -415,7 +415,7 @@ void AccountValue::process_distribution(currency decrement)
 
 void AccountValue::DecrementAVProportionally(currency decrement)
 {
-    decrement = round_minutiae()(decrement);
+    decrement = round_minutiae().c(decrement);
 
     if(materially_equal(decrement, AVGenAcct + AVSepAcct))
         {
@@ -653,7 +653,7 @@ currency AccountValue::InterestCredited
     ,double   monthly_rate
     ) const
 {
-    return round_interest_credit()(principal * 
ActualMonthlyRate(monthly_rate));
+    return round_interest_credit().c(principal * 
ActualMonthlyRate(monthly_rate));
 }
 
 //============================================================================
@@ -696,7 +696,7 @@ currency AccountValue::minimum_specified_amount(bool 
issuing_now, bool term_ride
 // Make sure ActualSpecAmt is never less than minimum specamt.
 void AccountValue::ChangeSpecAmtBy(currency delta)
 {
-    delta = round_specamt()(delta);
+    delta = round_specamt().c(delta);
     double term_proportion = 0.0;
     double const old_total_specamt = ActualSpecAmt + TermSpecAmt;
     // Adjust term here only if it's formally a rider.
@@ -721,8 +721,7 @@ void AccountValue::ChangeSpecAmtBy(currency delta)
                 break;
             }
 
-        ActualSpecAmt += delta * (1.0 - term_proportion);
-        ActualSpecAmt = round_specamt()(ActualSpecAmt);
+        ActualSpecAmt += round_specamt().c(delta * (1.0 - term_proportion));
         TermSpecAmt = old_total_specamt + delta - ActualSpecAmt;
 
         if(TermSpecAmt < C0)
@@ -746,7 +745,7 @@ void AccountValue::ChangeSpecAmtBy(currency delta)
                     - ActualSpecAmt
                     ;
                 }
-            TermSpecAmt = round_specamt()(TermSpecAmt);
+            TermSpecAmt = round_specamt().c(TermSpecAmt); // CURRENCY !! 
already rounded?
             }
         }
     else
@@ -760,7 +759,7 @@ void AccountValue::ChangeSpecAmtBy(currency delta)
         (ActualSpecAmt
         ,minimum_specified_amount(0 == Year && 0 == Month, TermRiderActive)
         );
-    ActualSpecAmt = round_specamt()(ActualSpecAmt);
+    ActualSpecAmt = round_specamt().c(ActualSpecAmt); // CURRENCY !! already 
rounded?
 
     // Carry the new specamt forward into all future years.
     for(int j = Year; j < BasicValues::GetLength(); ++j)
@@ -790,17 +789,15 @@ void AccountValue::ChangeSpecAmtBy(currency delta)
 
 void AccountValue::ChangeSupplAmtBy(currency delta)
 {
-    delta = round_specamt()(delta);
+    delta = round_specamt().c(delta);
     TermSpecAmt += delta;
 
-    TermSpecAmt = std::max
-        (TermSpecAmt
-        ,C0 // No minimum other than zero is defined.
-        );
-    TermSpecAmt = round_specamt()(TermSpecAmt);
-    // At least for now, there is no effect on surrender charges.
+    // No minimum other than zero is defined.
+    TermSpecAmt = std::max(TermSpecAmt, C0);
+    TermSpecAmt = round_specamt().c(TermSpecAmt); // CURRENCY !! already 
rounded?
 
     // Carry the new supplemental amount forward into all future years.
+    // At least for now, there is no effect on surrender charges.
     for(int j = Year; j < BasicValues::GetLength(); ++j)
         {
         InvariantValues().TermSpecAmt[j] = TermSpecAmt;
@@ -1468,6 +1465,7 @@ currency AccountValue::GetPremLoad
 //============================================================================
 currency AccountValue::GetRefundableSalesLoad() const
 {
+    // CURRENCY !! This needs to be rounded.
     return CumulativeSalesLoad * YearsSalesLoadRefundRate;
 #if 0
     // CURRENCY !! Assertions such as these are desirable, but adding
@@ -1547,7 +1545,7 @@ void AccountValue::TxSetBOMAV()
         }
     YearsTotalPolicyFee += MonthsPolicyFees;
 
-    SpecAmtLoad = round_minutiae()(YearsSpecAmtLoadRate * SpecAmtLoadBase);
+    SpecAmtLoad = round_minutiae().c(YearsSpecAmtLoadRate * SpecAmtLoadBase);
     YearsTotalSpecAmtLoad += SpecAmtLoad;
 
     process_deduction(MonthsPolicyFees + SpecAmtLoad);
@@ -1789,7 +1787,7 @@ void AccountValue::TxSetCoiCharge()
         retention_charge = round_coi_charge()(NAAR * retention_rate);
         }
 
-    CoiCharge    = round_coi_charge()(NAAR * ActualCoiRate);
+    CoiCharge    = round_coi_charge().c(NAAR * ActualCoiRate);
     NetCoiCharge = CoiCharge - retention_charge;
     YearsTotalCoiCharge += CoiCharge;
 
@@ -1804,30 +1802,34 @@ void AccountValue::TxSetRiderDed()
     AdbCharge = C0;
     if(yare_input_.AccidentalDeathBenefit)
         {
-        AdbCharge = YearsAdbRate * std::min(ActualSpecAmt, AdbLimit);
-        AdbCharge = round_rider_charges()(AdbCharge);
+        AdbCharge = round_rider_charges().c
+            (YearsAdbRate * std::min(ActualSpecAmt, AdbLimit)
+            );
         }
 
     SpouseRiderCharge = C0;
     if(yare_input_.SpouseRider)
         {
-        SpouseRiderCharge = YearsSpouseRiderRate * 
yare_input_.SpouseRiderAmount;
-        SpouseRiderCharge = round_rider_charges()(SpouseRiderCharge);
+        SpouseRiderCharge = round_rider_charges().c
+            (YearsSpouseRiderRate * yare_input_.SpouseRiderAmount
+            );
         }
 
     ChildRiderCharge = C0;
     if(yare_input_.ChildRider)
         {
-        ChildRiderCharge = YearsChildRiderRate * yare_input_.ChildRiderAmount;
-        ChildRiderCharge = round_rider_charges()(ChildRiderCharge);
+        ChildRiderCharge = round_rider_charges().c
+            (YearsChildRiderRate * yare_input_.ChildRiderAmount
+            );
         }
 
-    TermCharge = C0;
+    TermCharge    = C0;
     DcvTermCharge = 0.0;
     if(TermRiderActive)
         {
-        TermCharge    = YearsTermRate   * TermDB * DBDiscountRate[Year];
-        TermCharge    = round_rider_charges()(TermCharge);
+        TermCharge    = round_rider_charges().c
+            (YearsTermRate   * TermDB * DBDiscountRate[Year]
+            );
         // TAXATION !! Integrated term: s/TermDB/TermSpecAmt/ because
         // it can't go into the corridor under tax assumptions.
         // TAXATION !! Use a distinct discount rate for taxation? Or
@@ -1835,7 +1837,7 @@ void AccountValue::TxSetRiderDed()
         DcvTermCharge = YearsDcvCoiRate * TermDB * DBDiscountRate[Year];
         }
 
-    WpCharge = C0;
+    WpCharge    = C0;
     DcvWpCharge = 0.0;
     if(yare_input_.WaiverOfPremiumBenefit)
         {
@@ -2011,7 +2013,7 @@ void AccountValue::TxTakeSepAcctLoad()
         YearsSepAcctLoadRate = round_interest_rate()(YearsSepAcctLoadRate);
         }
 
-    SepAcctLoad = round_interest_credit()(YearsSepAcctLoadRate * AVSepAcct);
+    SepAcctLoad = round_interest_credit().c(YearsSepAcctLoadRate * AVSepAcct);
     process_deduction(SepAcctLoad);
     YearsTotalSepAcctLoad += SepAcctLoad;
     Dcv -= SepAcctLoad;
@@ -2646,7 +2648,7 @@ void AccountValue::SetMaxLoan()
     //
     MaxLoan *= 1.0 - (reg_loan_factor) / (1.0 + reg_loan_factor);
 
-    MaxLoan = round_loan()(MaxLoan);
+    MaxLoan = round_loan().c(MaxLoan);
 
     // I do not think we want a MaxLoan < current level of indebtedness.
     MaxLoan = std::max((AVRegLn + AVPrfLn), MaxLoan);



reply via email to

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