[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);
- [lmi-commits] [lmi] master da240e8 03/15: Eliminate a return code that was always zero, (continued)
- [lmi-commits] [lmi] master da240e8 03/15: Eliminate a return code that was always zero, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master d280c59 05/15: Fix a unit test, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master 7b51fab 07/15: Adapt to currency class, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master f7a1129 08/15: Store policy fees as currency, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master 2666c48 06/15: Test rounding double to currency, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master 5ed8f75 04/15: Refactor a unit test, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master 6a6ebe3 11/15: Adapt to currency class, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master 1d5c923 01/15: Change some internal names, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master 1e5d1ea 12/15: Adapt to currency class, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master 27bd748 13/15: Write $0.00 as a currency rather than floating-point constant, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master 9d991b0 15/15: Round currency as such,
Greg Chicares <=
- [lmi-commits] [lmi] master 306ba4e 02/15: Introduce optional (for now) currency class, Greg Chicares, 2021/01/25
- [lmi-commits] [lmi] master fd106fc 14/15: Reformat, Greg Chicares, 2021/01/25