lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] master 74077f9 2/2: Adapt to currency class, again


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 74077f9 2/2: Adapt to currency class, again
Date: Tue, 26 Jan 2021 16:30:37 -0500 (EST)

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

    Adapt to currency class, again
    
    This commit causes a small handful of tiny regressions.
---
 ihs_avmly.cpp | 177 ++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 103 insertions(+), 74 deletions(-)

diff --git a/ihs_avmly.cpp b/ihs_avmly.cpp
index d448201..cde7d22 100644
--- a/ihs_avmly.cpp
+++ b/ihs_avmly.cpp
@@ -135,14 +135,14 @@ void AccountValue::DoMonthDR()
     TxExch1035();
     // TODO ?? TAXATION !! Is this where spec amt should be increased by GPT?
 
-    double kludge_account_value = std::max(TotalAccountValue(), 
HoneymoonValue);
+    currency kludge_account_value = std::max(TotalAccountValue(), 
HoneymoonValue);
     if(0 == Year && 0 == Month)
         {
         // This special case was apparently intended for 1035
         // exchanges, but now seems unnecessary because this
         // assertion never fires:
         //   LMI_ASSERT(kludge_account_value == Dcv);
-        kludge_account_value = Dcv;
+        kludge_account_value = round_minutiae().c(Dcv);
         }
     kludge_account_value = std::max
         (HoneymoonValue
@@ -169,8 +169,8 @@ void AccountValue::DoMonthDR()
     // Saved for monthly detail report only. TAXATION !! Then are
     // these still needed...perhaps in order to report their values
     // prior to accepting any payment?
-    NetMaxNecessaryPremium   = Irc7702A_->DebugGetNetMaxNecPm  ();
-    GrossMaxNecessaryPremium = Irc7702A_->DebugGetGrossMaxNecPm();
+    NetMaxNecessaryPremium   = 
round_minutiae().c(Irc7702A_->DebugGetNetMaxNecPm  ());
+    GrossMaxNecessaryPremium = 
round_minutiae().c(Irc7702A_->DebugGetGrossMaxNecPm());
 
     // Determine list-bill premiums only after transactions that
     // might change specamt have been processed.
@@ -196,7 +196,7 @@ void AccountValue::DoMonthDR()
             );
         }
 
-    double gross_1035 = C0;
+    currency gross_1035 = C0;
     if(0 == Year && 0 == Month)
         {
         gross_1035 = External1035Amount + Internal1035Amount;
@@ -273,29 +273,29 @@ void AccountValue::process_payment(currency payment)
     LMI_ASSERT(C0 <= EeGrossPmts[Month]);
     LMI_ASSERT(C0 <= ErGrossPmts[Month]);
 
-    double gross_1035 = C0;
+    currency gross_1035 = C0;
     if(0 == Year && 0 == Month)
         {
         gross_1035 = External1035Amount + Internal1035Amount;
         }
-    double gross_non_1035_pmts = GrossPmts[Month] - gross_1035;
+    currency gross_non_1035_pmts = GrossPmts[Month] - gross_1035;
     double er_proportion = 0.0;
     if(C0 != gross_non_1035_pmts)
         {
-        er_proportion = ErGrossPmts[Month] / gross_non_1035_pmts;
+        er_proportion = ErGrossPmts[Month] / dblize(gross_non_1035_pmts);
         }
 
     // This is a net premium that's multiplied by a gross-premium
     // proportion, because that's the only way the proportion can be
     // deduced from input. But it remains a net premium, so the
     // net-premium rounding rule is appropriate.
-    double er_net_pmt = round_net_premium()(er_proportion * payment);
+    currency er_net_pmt = round_net_premium().c(er_proportion * payment);
     // This is deliberately not rounded. The crucial invariant that
     // must be preserved is that ee + er = total; but rounding both
     // addends could break that invariant, e.g.:
     //   round(2.5) + round(2.5)
     // might not produce 5.0 as desired.
-    double ee_net_pmt = payment - er_net_pmt;
+    currency ee_net_pmt = payment - er_net_pmt;
 
     switch(ee_premium_allocation_method)
         {
@@ -414,9 +414,13 @@ void AccountValue::process_distribution(currency decrement)
 
 void AccountValue::DecrementAVProportionally(currency decrement)
 {
-    decrement = round_minutiae().c(decrement);
+    decrement = round_minutiae().c(decrement); // CURRENCY !! already rounded?
 
+#if defined USE_CURRENCY_CLASS
+    if(decrement == AVGenAcct + AVSepAcct)
+#else  // !defined USE_CURRENCY_CLASS
     if(materially_equal(decrement, AVGenAcct + AVSepAcct))
+#endif // !defined USE_CURRENCY_CLASS
         {
         AVGenAcct = C0;
         AVSepAcct = C0;
@@ -425,8 +429,8 @@ void AccountValue::DecrementAVProportionally(currency 
decrement)
 
     double general_account_proportion  = 0.0;
     double separate_account_proportion = 0.0;
-    double general_account_nonnegative_assets  = std::max(0.0, AVGenAcct);
-    double separate_account_nonnegative_assets = std::max(0.0, AVSepAcct);
+    double general_account_nonnegative_assets  = dblize(std::max(C0, 
AVGenAcct));
+    double separate_account_nonnegative_assets = dblize(std::max(C0, 
AVSepAcct));
     if
         (  0.0 == general_account_nonnegative_assets
         && 0.0 == separate_account_nonnegative_assets
@@ -479,7 +483,11 @@ void AccountValue::DecrementAVProgressively
     ,oenum_increment_account_preference preferred_account
     )
 {
+#if defined USE_CURRENCY_CLASS
+    if(decrement == AVGenAcct + AVSepAcct)
+#else  // !defined USE_CURRENCY_CLASS
     if(materially_equal(decrement, AVGenAcct + AVSepAcct))
+#endif // !defined USE_CURRENCY_CLASS
         {
         AVGenAcct = C0;
         AVSepAcct = C0;
@@ -554,12 +562,12 @@ void AccountValue::TxExch1035()
 
     // TODO ?? Assume for now that all 1035 exchanges represent ee payments.
     EeGrossPmts[Month] = GrossPmts[Month];
-    double amount_exempt_from_premium_tax = C0;
+    currency amount_exempt_from_premium_tax = C0;
     if(WaivePmTxInt1035)
         {
         amount_exempt_from_premium_tax = Internal1035Amount;
         }
-    double actual_load = GetPremLoad
+    currency actual_load = GetPremLoad
         (GrossPmts[Month]
         ,amount_exempt_from_premium_tax
         );
@@ -600,7 +608,7 @@ void AccountValue::TxExch1035()
         // Immediately after a 1035 exchange, DCV should be
         // the 1035 amount reduced by any premium-based loads,
         // but only for the current rate basis.
-        LMI_ASSERT(materially_equal(Dcv, NetPmts[Month]));
+        LMI_ASSERT(materially_equal(Dcv, dblize(NetPmts[Month])));
 
         // The initial seven-pay premium shown on the illustration
         // must be its value immediately after any 1035 exchange,
@@ -694,9 +702,9 @@ 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().c(delta);
+    delta = round_specamt().c(delta); // CURRENCY !! already rounded?
     double term_proportion = 0.0;
-    double const old_total_specamt = ActualSpecAmt + TermSpecAmt;
+    currency const old_total_specamt = ActualSpecAmt + TermSpecAmt;
     // Adjust term here only if it's formally a rider.
     if(TermRiderActive && !TermIsNotRider)
         {
@@ -709,7 +717,7 @@ void AccountValue::ChangeSpecAmtBy(currency delta)
                 break;
             case mce_adjust_both:
                 {
-                term_proportion = TermSpecAmt / old_total_specamt;
+                term_proportion = TermSpecAmt / dblize(old_total_specamt);
                 }
                 break;
             case mce_adjust_base:
@@ -787,7 +795,7 @@ void AccountValue::ChangeSpecAmtBy(currency delta)
 
 void AccountValue::ChangeSupplAmtBy(currency delta)
 {
-    delta = round_specamt().c(delta);
+    delta = round_specamt().c(delta); // CURRENCY !! already rounded?
     TermSpecAmt += delta;
 
     // No minimum other than zero is defined.
@@ -970,7 +978,7 @@ void AccountValue::TxSpecAmtChange()
                 (ActualSpecAmt
                 ,minimum_specified_amount(0 == Year && 0 == Month, 
TermRiderActive)
                 );
-            ActualSpecAmt = round_specamt().c(ActualSpecAmt);
+            ActualSpecAmt = round_specamt().c(ActualSpecAmt); // CURRENCY !! 
already rounded?
             InvariantValues().SpecAmt[j] = ActualSpecAmt;
             if(!TermIsNotRider)
                 {
@@ -1090,10 +1098,15 @@ void AccountValue::TxTestGPT()
     // TAXATION !! This assumes the term rider can be treated as death benefit;
     // use 'TermIsDbFor7702'.
     bool adj_event =
-            (
-                !materially_equal(OldSA, ActualSpecAmt + TermSpecAmt)
+#if defined USE_CURRENCY_CLASS
+            (   OldSA != ActualSpecAmt + TermSpecAmt
+            &&  OldDB != DBReflectingCorr + TermDB
+            )
+#else  // !defined USE_CURRENCY_CLASS
+            (   !materially_equal(OldSA, ActualSpecAmt + TermSpecAmt)
             &&  !materially_equal(OldDB, DBReflectingCorr + TermDB)
             )
+#endif // !defined USE_CURRENCY_CLASS
         ||  old_dbopt != new_dbopt
         ;
     if(adj_event)
@@ -1114,7 +1127,7 @@ void AccountValue::TxTestGPT()
             );
         }
 
-    GptForceout = Irc7702_->Forceout();
+    GptForceout = round_minutiae().c(Irc7702_->Forceout());
     // TODO ?? TAXATION !! On other bases, nothing is forced out, and payments 
aren't limited.
     process_distribution(GptForceout);
     YearsTotalGptForceout += GptForceout;
@@ -1186,7 +1199,7 @@ void AccountValue::TxAscertainDesiredPayment()
 
     assert_pmts_add_up(__FILE__, __LINE__, Month);
 
-    double eepmt = C0;
+    currency eepmt = C0;
     if(ee_pay_this_month)
         {
         eepmt = PerformEePmtStrategy();
@@ -1199,7 +1212,7 @@ void AccountValue::TxAscertainDesiredPayment()
         GrossPmts  [Month] += eepmt;
         }
 
-    double erpmt = C0;
+    currency erpmt = C0;
     if(er_pay_this_month)
         {
         erpmt = PerformErPmtStrategy();
@@ -1213,7 +1226,8 @@ void AccountValue::TxAscertainDesiredPayment()
         }
 
     assert_pmts_add_up(__FILE__, __LINE__, Month);
-    // bignum: the largest integer convertible to and from double.
+    // bignum: the largest integer convertible to and from double
+    // such that incrementing it by one loses that property.
     LMI_ASSERT(GrossPmts[Month] < from_cents(1LL << 53));
 
     if(0 == Year && 0 == Month)
@@ -1251,13 +1265,15 @@ void AccountValue::TxLimitPayment(double a_maxpmt)
 
     if(mce_reduce_prem == yare_input_.AvoidMecMethod && 
!Irc7702A_->IsMecAlready())
         {
-        double gross_1035 = C0;
+        currency gross_1035 = C0;
         if(0 == Year && 0 == Month)
             {
             gross_1035 = External1035Amount + Internal1035Amount;
             }
-        double gross_pmt_without_1035 = GrossPmts[Month] - gross_1035;
-        gross_pmt_without_1035 = std::min(gross_pmt_without_1035, a_maxpmt);
+        currency gross_pmt_without_1035 = GrossPmts[Month] - gross_1035;
+        // CURRENCY !! support infinities?
+//      gross_pmt_without_1035 = std::min(gross_pmt_without_1035, a_maxpmt);
+        gross_pmt_without_1035 = 
round_gross_premium().c(std::min(dblize(gross_pmt_without_1035), a_maxpmt));
         // TODO ?? For now at least, reduce employee premium first.
         progressively_limit
             (EeGrossPmts[Month]
@@ -1303,10 +1319,10 @@ void AccountValue::TxRecognizePaymentFor7702A
 
     // Policy issue date is always a modal payment date.
 
-    double kludge_account_value = std::max(TotalAccountValue(), 
HoneymoonValue);
+    currency kludge_account_value = std::max(TotalAccountValue(), 
HoneymoonValue);
     if(0 == Year && 0 == Month)
         {
-        kludge_account_value = Dcv;
+        kludge_account_value = round_minutiae().c(Dcv);
         }
     kludge_account_value = std::max
         (HoneymoonValue
@@ -1319,7 +1335,7 @@ void AccountValue::TxRecognizePaymentFor7702A
     // TODO ?? TAXATION !! Not correct yet--need to test pmt less deductible 
WD; and
     // shouldn't we deduct the *gross* WD? [Yes, if any fee is part of the
     // WD, which it normally is.]
-    double amount_paid_7702A = a_pmt;
+    currency amount_paid_7702A = a_pmt;
     Irc7702A_->UpdatePmt7702A
         (Dcv
         ,dblize(amount_paid_7702A)
@@ -1355,7 +1371,7 @@ void AccountValue::TxAcceptPayment(currency a_pmt)
 
     process_payment(net_pmt);
 
-    Dcv += std::max(0.0, net_pmt);
+    Dcv += std::max(0.0, dblize(net_pmt));
     LMI_ASSERT(0.0 <= Dcv);
 
     if(HoneymoonActive)
@@ -1527,11 +1543,12 @@ void AccountValue::TxSetBOMAV()
             (0 == Year && 0 == Month)
             ? std::max
                 (term_specamt(0) + base_specamt(0)
-                ,NetPmts[0] * YearsCorridorFactor
+                ,round_specamt().c(NetPmts[0] * YearsCorridorFactor)
                 )
-            : yare_input_.InforceSpecAmtLoadBase
+            : round_specamt().c(yare_input_.InforceSpecAmtLoadBase)
             ;
-        SpecAmtLoadBase = std::min(SpecAmtLoadBase, SpecAmtLoadLimit);
+        // CURRENCY !! support infinities?
+        SpecAmtLoadBase = round_specamt().c(std::min(dblize(SpecAmtLoadBase), 
SpecAmtLoadLimit));
         }
 
     // These assignments must happen every month.
@@ -1548,7 +1565,7 @@ void AccountValue::TxSetBOMAV()
 
     process_deduction(MonthsPolicyFees + SpecAmtLoad);
 
-    Dcv -= MonthsPolicyFees + SpecAmtLoad;
+    Dcv -= dblize(MonthsPolicyFees + SpecAmtLoad);
     Dcv = std::max(0.0, Dcv);
 }
 
@@ -1646,12 +1663,12 @@ void AccountValue::TxSetDeathBft()
     DB7702A = DBReflectingCorr + TermDB;
 
     DcvDeathBft = std::max
-        (DBIgnoringCorr
+        (   dblize(DBIgnoringCorr)
         ,   (
                 YearsCorridorFactor
             *   (   Dcv
-                -   std::min(C0, SurrChg())
-                +   GetRefundableSalesLoad()
+                -   dblize(std::min(C0, SurrChg()))
+                +   dblize(GetRefundableSalesLoad())
 //                +   std::max(0.0, ExpRatReserve) // This would be added if 
it existed.
                 )
             )
@@ -1686,7 +1703,7 @@ void AccountValue::TxSetTermAmt()
         }
 
     TermDB = std::max(C0, TermSpecAmt + DBIgnoringCorr - DBReflectingCorr);
-    TermDB = round_death_benefit().c(TermDB);
+    TermDB = round_death_benefit().c(TermDB); // CURRENCY !! already rounded?
 }
 
 /// Terminate the term rider, optionally converting it to base.
@@ -1853,7 +1870,7 @@ void AccountValue::TxSetRiderDed()
                 WpCharge = round_rider_charges().c
                     (YearsWpRate * std::min(dblize(ActualSpecAmt), WpLimit)
                     );
-                DcvWpCharge = WpCharge;
+                DcvWpCharge = dblize(WpCharge);
                 }
                 break;
             case oe_waiver_times_deductions:
@@ -1877,11 +1894,13 @@ void AccountValue::TxSetRiderDed()
                     YearsWpRate
                     *   (
                             DcvCoiCharge
-                        +   MonthsPolicyFees
-                        +   SpecAmtLoad
-                        +   AdbCharge
-                        +   SpouseRiderCharge
-                        +   ChildRiderCharge
+                        +   dblize(
+                                MonthsPolicyFees
+                            +   SpecAmtLoad
+                            +   AdbCharge
+                            +   SpouseRiderCharge
+                            +   ChildRiderCharge
+                            )
                         +   DcvTermCharge
                         );
                 }
@@ -1909,7 +1928,7 @@ void AccountValue::TxDoMlyDed()
 
     double dcv_mly_ded =
             DcvCoiCharge
-        +   simple_rider_charges
+        +   dblize(simple_rider_charges)
         +   DcvTermCharge
         +   DcvWpCharge
         ;
@@ -1990,17 +2009,18 @@ void AccountValue::TxTakeSepAcctLoad()
 {
     if(SepAcctLoadIsDynamic)
         {
+        // CURRENCY !! should class stratified_charges use currency?
         double stratified_load = StratifiedCharges_->stratified_sepacct_load
             (GenBasis_
-            ,AssetsPostBom
-            ,CumPmtsPostBom
+            ,dblize(AssetsPostBom)
+            ,dblize(CumPmtsPostBom)
             ,database().query<double>(DB_DynSepAcctLoadLimit)
             );
 
         double tiered_comp = 0.0;
         if(oe_asset_charge_load == 
database().query<oenum_asset_charge_type>(DB_AssetChargeType))
             {
-            tiered_comp = 
StratifiedCharges_->tiered_asset_based_compensation(AssetsPostBom);
+            tiered_comp = 
StratifiedCharges_->tiered_asset_based_compensation(dblize(AssetsPostBom));
             }
         if(0.0 != tiered_comp)
             {
@@ -2027,7 +2047,7 @@ void AccountValue::TxTakeSepAcctLoad()
     SepAcctLoad = round_interest_credit().c(YearsSepAcctLoadRate * AVSepAcct);
     process_deduction(SepAcctLoad);
     YearsTotalSepAcctLoad += SepAcctLoad;
-    Dcv -= SepAcctLoad;
+    Dcv -= dblize(SepAcctLoad);
     Dcv = std::max(0.0, Dcv);
 }
 
@@ -2068,8 +2088,8 @@ void AccountValue::ApplyDynamicMandE(currency assets)
 
     // Annual separate-account rates.
 
-    double m_and_e_rate = StratifiedCharges_->tiered_m_and_e(GenBasis_, 
assets);
-    double imf_rate = 
StratifiedCharges_->tiered_investment_management_fee(assets);
+    double m_and_e_rate = StratifiedCharges_->tiered_m_and_e(GenBasis_, 
dblize(assets));
+    double imf_rate = 
StratifiedCharges_->tiered_investment_management_fee(dblize(assets));
     if(0.0 != imf_rate)
         {
         alarum()
@@ -2079,7 +2099,7 @@ void AccountValue::ApplyDynamicMandE(currency assets)
         }
     double asset_comp_rate =
         (oe_asset_charge_spread == 
database().query<oenum_asset_charge_type>(DB_AssetChargeType))
-            ? StratifiedCharges_->tiered_asset_based_compensation(assets)
+            ? 
StratifiedCharges_->tiered_asset_based_compensation(dblize(assets))
             : 0.0
             ;
     if(0.0 != asset_comp_rate)
@@ -2146,8 +2166,11 @@ void AccountValue::TxCreditInt()
     if(C0 < AVSepAcct)
         {
         SepAcctIntCred = InterestCredited(AVSepAcct, YearsSepAcctIntRate);
-        currency gross   = InterestCredited(AVSepAcct, gross_sep_acct_rate);
+        currency gross = InterestCredited(AVSepAcct, gross_sep_acct_rate);
         notional_sep_acct_charge = gross - SepAcctIntCred;
+#if defined USE_CURRENCY_CLASS
+        AVSepAcct += SepAcctIntCred;
+#else  // !defined USE_CURRENCY_CLASS
         // Guard against catastrophic cancellation. Testing the
         // absolute values of the addends for material equality is not
         // sufficient, because the interest increment has already been
@@ -2161,6 +2184,7 @@ void AccountValue::TxCreditInt()
             {
             AVSepAcct = result;
             }
+#endif // !defined USE_CURRENCY_CLASS
         }
     else
         {
@@ -2305,18 +2329,20 @@ currency AccountValue::anticipated_deduction
 void AccountValue::SetMaxWD()
 {
     MaxWD =
-          AVGenAcct * MaxWdGenAcctValMult
-        + AVSepAcct * MaxWdSepAcctValMult
+          round_withdrawal().c
+              ( AVGenAcct * MaxWdGenAcctValMult
+              + AVSepAcct * MaxWdSepAcctValMult
+              )
         + (AVRegLn  + AVPrfLn)
         - (RegLnBal + PrfLnBal)
         - anticipated_deduction(MaxWDDed_)
-        - std::max(0.0, SurrChg())
+        - std::max(C0, SurrChg())
         ;
     if(MaxWD < MinWD)
         {
-        MaxWD = 0.0;
+        MaxWD = C0;
         }
-    MaxWD = std::max(0.0, MaxWD);
+    MaxWD = std::max(C0, MaxWD);
 }
 
 /// Take a withdrawal.
@@ -2361,7 +2387,7 @@ void AccountValue::TxTakeWD()
 
     if(Solving || mce_run_gen_curr_sep_full == RunBasis_)
         {
-        NetWD = round_withdrawal().c(std::min(RequestedWD, MaxWD));
+        NetWD = round_withdrawal().c(std::min(RequestedWD, MaxWD)); // 
CURRENCY !! already rounded?
         OverridingWD[Year] = NetWD;
         }
     else
@@ -2487,14 +2513,14 @@ void AccountValue::TxTakeWD()
         return;
         }
 
-    GrossWD = round_withdrawal()(NetWD + std::min(WDFee, NetWD * WDFeeRate));
+    GrossWD = NetWD + std::min(WDFee, round_withdrawal().c(NetWD * WDFeeRate));
 
     // Free partial surrenders: for instance, the first 20% of account
     // value might be withdrawn each policy year free of surrender
     // charge. This would become more complicated if we maintained
     // distinct surrender-charge layers.
 
-    double surrchg_proportion = SurrChg_[Year] / csv;
+    double surrchg_proportion = SurrChg_[Year] / dblize(csv);
     currency non_free_wd = GrossWD;
     if(0.0 != FreeWDProportion[Year])
         {
@@ -2511,7 +2537,7 @@ void AccountValue::TxTakeWD()
     GrossWD += round_withdrawal().c(partial_surrchg);
 
     process_distribution(GrossWD);
-    Dcv -= GrossWD;
+    Dcv -= dblize(GrossWD);
     Dcv = std::max(0.0, Dcv);
 
     switch(YearsDBOpt)
@@ -2593,7 +2619,7 @@ void AccountValue::TxTakeWD()
             {
             // TODO ?? TAXATION !! What if reference argument
             // 'premiums_paid_increment' is modified?
-            double premiums_paid_increment = -GrossWD;
+            double premiums_paid_increment = -dblize(GrossWD);
             Irc7702_->ProcessGptPmt(Year, premiums_paid_increment);
             }
         }
@@ -2609,7 +2635,7 @@ void AccountValue::TxTakeWD()
 void AccountValue::SetMaxLoan()
 {
     MaxLoan =
-          (AVGenAcct + AVSepAcct) * MaxLoanAVMult
+          round_loan().c((AVGenAcct + AVSepAcct) * MaxLoanAVMult)
         + (AVRegLn + AVPrfLn)
         - anticipated_deduction(MaxLoanDed_)
         - std::max(C0, SurrChg())
@@ -2647,19 +2673,19 @@ void AccountValue::SetMaxLoan()
     // the end of the policy year--but does not guarantee that, e.g.
     // because the specified amount may change between anniversaries,
     // even on illustrations.
-    MaxLoan -=
+    MaxLoan -= round_loan().c
+        (
           RegLnBal * reg_loan_factor
         + PrfLnBal * prf_loan_factor
-        ;
+        );
 
     // TODO ?? This adjustment isn't quite right because it uses only
     // the regular-loan interest factor. Is it conservative under the
     // plausible but unasserted assumption that that factor is more
     // liberal than the preferred-loan factor?
     //
-    MaxLoan *= 1.0 - (reg_loan_factor) / (1.0 + reg_loan_factor);
-
-    MaxLoan = round_loan().c(MaxLoan);
+    double adj = 1.0 - (reg_loan_factor) / (1.0 + reg_loan_factor);
+    MaxLoan = round_loan().c(MaxLoan * adj);
 
     // I do not think we want a MaxLoan < current level of indebtedness.
     MaxLoan = std::max((AVRegLn + AVPrfLn), MaxLoan);
@@ -2690,7 +2716,7 @@ void AccountValue::TxTakeLoan()
         return;
         }
 
-    double max_loan_increment = MaxLoan - (AVRegLn + AVPrfLn);
+    currency max_loan_increment = MaxLoan - (AVRegLn + AVPrfLn);
 
     // When performing a solve, let it become overloaned--otherwise
     // we'd introduce a discontinuity in the function for which we
@@ -2795,7 +2821,10 @@ void AccountValue::TxTestLapse()
             (       NoLapseMinAge <= Year + BasicValues::GetIssueAge()
                 &&  NoLapseMinDur <= Year
             ||      CumPmts < CumNoLapsePrem
+#if defined USE_CURRENCY_CLASS
+#else  // !defined USE_CURRENCY_CLASS
                 &&  !materially_equal(CumPmts, CumNoLapsePrem)
+#endif // !defined USE_CURRENCY_CLASS
             )
             {
             NoLapseActive = false;



reply via email to

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