lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] odd/c0 fa245ac: Replace 'C0' with '0_cents'?


From: Greg Chicares
Subject: [lmi-commits] [lmi] odd/c0 fa245ac: Replace 'C0' with '0_cents'?
Date: Sat, 8 May 2021 18:06:16 -0400 (EDT)

branch: odd/c0
commit fa245ac27de715c88244ac488ce4c9f31bd51004
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Replace 'C0' with '0_cents'?
    
    '0_cents' is more unmistakably clear.
    
    However, 'C0' is guaranteed to be a compile-time constant, and it's
    two characters rather than seven.
    
    The speed tests show no noticeable difference.
    
    Is this a good change?
---
 Speed_gcc_i686-w64-mingw32    |  12 +-
 Speed_gcc_x86_64-pc-linux-gnu |  12 +-
 Speed_gcc_x86_64-w64-mingw32  |  12 +-
 accountvalue.cpp              |  50 ++++----
 currency.hpp                  |  14 +--
 currency_test.cpp             |   4 +-
 gpt_specamt.cpp               |   2 +-
 group_values.cpp              |   2 +-
 ihs_acctval.cpp               | 124 +++++++++----------
 ihs_avdebug.cpp               |   2 +-
 ihs_avmly.cpp                 | 270 +++++++++++++++++++++---------------------
 ihs_avsolve.cpp               |   8 +-
 ihs_avstrtgy.cpp              |   2 +-
 ihs_basicval.cpp              |   8 +-
 solve.cpp                     |   6 +-
 15 files changed, 261 insertions(+), 267 deletions(-)

diff --git a/Speed_gcc_i686-w64-mingw32 b/Speed_gcc_i686-w64-mingw32
index 1d342d7..bae0cd5 100644
--- a/Speed_gcc_i686-w64-mingw32
+++ b/Speed_gcc_i686-w64-mingw32
@@ -1,7 +1,7 @@
 Test speed:
-  naic, no solve      : 2.640e-02 s mean;      26257 us least of  38 runs
-  naic, specamt solve : 4.948e-02 s mean;      49281 us least of  21 runs
-  naic, ee prem solve : 4.558e-02 s mean;      45249 us least of  22 runs
-  finra, no solve     : 1.132e-02 s mean;      10817 us least of  89 runs
-  finra, specamt solve: 3.231e-02 s mean;      32119 us least of  31 runs
-  finra, ee prem solve: 2.991e-02 s mean;      29754 us least of  34 runs
+  naic, no solve      : 2.649e-02 s mean;      26146 us least of  38 runs
+  naic, specamt solve : 4.990e-02 s mean;      49250 us least of  21 runs
+  naic, ee prem solve : 4.564e-02 s mean;      45086 us least of  22 runs
+  finra, no solve     : 1.094e-02 s mean;      10743 us least of  92 runs
+  finra, specamt solve: 3.242e-02 s mean;      31975 us least of  31 runs
+  finra, ee prem solve: 3.004e-02 s mean;      29654 us least of  34 runs
diff --git a/Speed_gcc_x86_64-pc-linux-gnu b/Speed_gcc_x86_64-pc-linux-gnu
index e3d4834..bc65b34 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.908e-02 s mean;      18267 us least of  53 runs
-  naic, specamt solve : 3.415e-02 s mean;      33666 us least of  30 runs
-  naic, ee prem solve : 3.100e-02 s mean;      30658 us least of  33 runs
-  finra, no solve     : 5.325e-03 s mean;       5094 us least of 100 runs
-  finra, specamt solve: 1.939e-02 s mean;      19001 us least of  52 runs
-  finra, ee prem solve: 1.794e-02 s mean;      17598 us least of  56 runs
+  naic, no solve      : 1.846e-02 s mean;      18131 us least of  55 runs
+  naic, specamt solve : 3.384e-02 s mean;      33342 us least of  30 runs
+  naic, ee prem solve : 3.087e-02 s mean;      30364 us least of  33 runs
+  finra, no solve     : 5.274e-03 s mean;       5077 us least of 100 runs
+  finra, specamt solve: 1.928e-02 s mean;      18962 us least of  52 runs
+  finra, ee prem solve: 1.777e-02 s mean;      17459 us least of  57 runs
diff --git a/Speed_gcc_x86_64-w64-mingw32 b/Speed_gcc_x86_64-w64-mingw32
index 991d777..a69ce56 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.671e-02 s mean;      25961 us least of  38 runs
-  naic, specamt solve : 4.546e-02 s mean;      44616 us least of  22 runs
-  naic, ee prem solve : 4.123e-02 s mean;      40871 us least of  25 runs
-  finra, no solve     : 9.519e-03 s mean;       9293 us least of 100 runs
-  finra, specamt solve: 2.641e-02 s mean;      25949 us least of  38 runs
-  finra, ee prem solve: 2.451e-02 s mean;      24337 us least of  41 runs
+  naic, no solve      : 2.706e-02 s mean;      25920 us least of  37 runs
+  naic, specamt solve : 4.512e-02 s mean;      44575 us least of  23 runs
+  naic, ee prem solve : 4.138e-02 s mean;      40834 us least of  25 runs
+  finra, no solve     : 9.698e-03 s mean;       9393 us least of 100 runs
+  finra, specamt solve: 2.651e-02 s mean;      26138 us least of  38 runs
+  finra, ee prem solve: 2.473e-02 s mean;      24339 us least of  41 runs
diff --git a/accountvalue.cpp b/accountvalue.cpp
index f428db9..1808b7d 100644
--- a/accountvalue.cpp
+++ b/accountvalue.cpp
@@ -229,13 +229,13 @@ void AccountValue::RunOneCell(mcenum_run_basis TheBasis)
     LapseMonth       = 0;
     LapseYear        = 0;
 
-    TaxBasis         = C0;
+    TaxBasis         = 0_cents;
 
-    MaxLoan          = C0;
-    RegLnBal         = C0;
-    PrfLnBal         = C0;
-    AVRegLn          = C0;
-    AVPrfLn          = C0;
+    MaxLoan          = 0_cents;
+    RegLnBal         = 0_cents;
+    PrfLnBal         = 0_cents;
+    AVRegLn          = 0_cents;
+    AVPrfLn          = 0_cents;
 
     // 'InforceAVGenAcct' is unloaned only; this branch wasn't
     // designed to allow inforce loans.
@@ -324,8 +324,8 @@ void AccountValue::DoYear
 
     YearsCorridorFactor = BasicValues::GetCorridorFactor()[Year];
 
-    GrossPmts  .assign(12, C0);
-    NetPmts    .assign(12, C0);
+    GrossPmts  .assign(12, 0_cents);
+    NetPmts    .assign(12, 0_cents);
 
     // IHS !! Strategy here?
 
@@ -347,7 +347,9 @@ void AccountValue::DoYear
     VariantValues().EOYDeathBft[Year] = dblize(deathbft);
 
     // IHS !! Change one of these names, which differ only in the terminal 's'.
-    InvariantValues().GrossPmt[Year] += 
dblize(std::accumulate(GrossPmts.begin(), GrossPmts.end(), C0));
+    InvariantValues().GrossPmt[Year] += dblize
+        (std::accumulate(GrossPmts.begin(), GrossPmts.end(), 0_cents)
+        );
     InvariantValues().Outlay[Year] =
             InvariantValues().GrossPmt   [Year]
         -   InvariantValues().NetWD      [Year]
@@ -434,7 +436,7 @@ inline int AccountValue::MonthsToNextModalPmtDate() const
 // Set specamt according to selected strategy, in every year.
 void AccountValue::PerformSpecAmtStrategy()
 {
-    currency SA = C0;
+    currency SA = 0_cents;
     switch(yare_input_.SpecifiedAmountStrategy[0])
         {
         case mce_sa_input_scalar:
@@ -514,7 +516,7 @@ void AccountValue::TxOptionChange()
 
     // Nothing to do unless AV is positive.
     currency AV = AVUnloaned + AVRegLn + AVPrfLn;
-    if(AV <= C0)
+    if(AV <= 0_cents)
         {
         return;
         }
@@ -719,7 +721,7 @@ void AccountValue::TxLoanRepay()
         }
 
     // Nothing to do if no loan repayment requested.
-    if(C0 <= RequestedLoan)
+    if(0_cents <= RequestedLoan)
         {
         return;
         }
@@ -757,7 +759,7 @@ void AccountValue::TxSetDeathBft()
         case mce_option2:
             // Option 2: specamt plus AV, or corridor times AV if greater.
             // Negative AV doesn't decrease death benefit.
-            deathbft = std::max(ActualSpecAmt + std::max(C0, AV), corr);
+            deathbft = std::max(ActualSpecAmt + std::max(0_cents, AV), corr);
             break;
         case mce_rop: // fall through
         case mce_mdb: // fall through
@@ -788,7 +790,7 @@ void AccountValue::TxSetCoiCharge()
 
 void AccountValue::TxSetRiderDed()
 {
-    WpCharge = C0;
+    WpCharge = 0_cents;
     if(haswp)
         {
         WpCharge = round_rider_charges().c
@@ -797,7 +799,7 @@ void AccountValue::TxSetRiderDed()
             );
         }
 
-    AdbCharge = C0;
+    AdbCharge = 0_cents;
     if(hasadb)
         {
         AdbCharge = round_rider_charges().c
@@ -823,13 +825,13 @@ void AccountValue::TxCreditInt()
 {
     // Accrue interest on unloaned and loaned account value separately,
     //   but do not charge interest on negative account value.
-    if(C0 < AVUnloaned)
+    if(0_cents < AVUnloaned)
         {
         // IHS !! Each interest increment is rounded separately in lmi.
         AVUnloaned += round_interest_credit().c(AVUnloaned * 
YearsGenAcctIntRate);
         }
     // Loaned account value cannot be negative.
-    LMI_ASSERT(C0 <= AVRegLn + AVPrfLn);
+    LMI_ASSERT(0_cents <= AVRegLn + AVPrfLn);
 }
 
 /// Accrue loan interest, and calculate interest credit on loaned AV.
@@ -837,7 +839,7 @@ void AccountValue::TxCreditInt()
 void AccountValue::TxLoanInt()
 {
     // Nothing to do if there's no loan outstanding.
-    if(C0 == RegLnBal && C0 == PrfLnBal)
+    if(0_cents == RegLnBal && 0_cents == PrfLnBal)
         {
         return;
         }
@@ -871,7 +873,7 @@ void AccountValue::TxTakeWD()
         }
 
     // Nothing to do if no withdrawal requested.
-    if(C0 == wd)
+    if(0_cents == wd)
         {
         return;
         }
@@ -881,7 +883,7 @@ void AccountValue::TxTakeWD()
     // Impose minimum amount (if nonzero) on withdrawals.
     if(wd < MinWD)
         {
-        wd = C0;
+        wd = 0_cents;
         }
 
     // Impose maximum amount.
@@ -960,7 +962,7 @@ void AccountValue::TxTakeLoan()
         }
 
     // Nothing to do if no loan requested.
-    if(RequestedLoan <= C0)
+    if(RequestedLoan <= 0_cents)
         {
         return;
         }
@@ -1014,7 +1016,7 @@ void AccountValue::TxTestLapse()
     // Otherwise if AV is negative or if overloaned, then lapse the policy.
     else if
         (
-            (AVUnloaned + AVRegLn + AVPrfLn < C0)
+            (AVUnloaned + AVRegLn + AVPrfLn < 0_cents)
         ||  (MaxLoan < RegLnBal + PrfLnBal)
         )
         {
@@ -1049,9 +1051,9 @@ void   AccountValue::FinalizeLife(mcenum_run_basis)
 void   AccountValue::FinalizeLifeAllBases()
     {return;}
 currency AccountValue::GetSepAcctAssetsInforce() const
-    {return C0;}
+    {return 0_cents;}
 currency AccountValue::IncrementBOM(int, int)
-    {return C0;}
+    {return 0_cents;}
 void   AccountValue::IncrementEOM(int, int, currency, currency)
     {return;}
 void   AccountValue::IncrementEOY(int)
diff --git a/currency.hpp b/currency.hpp
index 3f4a6f7..d1de20f 100644
--- a/currency.hpp
+++ b/currency.hpp
@@ -39,7 +39,7 @@ class currency
     friend currency from_cents(double);       // private ctor
     template<typename> friend class round_to; // private ctor
     friend class round_to_test;               // currency::cents_digits
-    friend constexpr currency operator"" _cents(unsigned long long int);
+    friend constexpr currency operator""_cents(unsigned long long int);
 
     static constexpr int    cents_digits     = 2;
     static constexpr double cents_per_dollar = 100.0;
@@ -70,7 +70,7 @@ class currency
     data_type m_ = {};
 };
 
-constexpr currency operator"" _cents(unsigned long long int cents)
+inline constexpr currency operator""_cents(unsigned long long int cents)
 {
     constexpr auto mant_dig = std::numeric_limits<currency::data_type>::digits;
     constexpr unsigned long long int limit = 1ULL << mant_dig;
@@ -145,14 +145,4 @@ inline std::vector<double> dblize(std::vector<currency> 
const& z)
     return r;
 }
 
-/// Zero cents--akin to a user-defined literal.
-///
-/// UDLs seem less convenient because the obvious "0_c" is likely to
-/// collide with some other UDL, and "currency::0_c" is too verbose.
-/// "0_cents" may avoid both those problems, but "C0" is terser.
-/// "C0" is chosen instead of "c0" only for the pixilated reason that
-/// the capital letter looks kind of like a "0".
-
-inline constexpr currency C0 = {};
-
 #endif // currency_hpp
diff --git a/currency_test.cpp b/currency_test.cpp
index c0f08f2..4d8a892 100644
--- a/currency_test.cpp
+++ b/currency_test.cpp
@@ -218,7 +218,7 @@ void currency_test::test_plus_or_minus()
     a2 = currency() - a1;
     LMI_TEST_EQUAL(-6.50, a2.d());
     LMI_TEST_EQUAL( -650, a2.m_);
-    a2 = C0 - a1;
+    a2 = 0_cents - a1;
     LMI_TEST_EQUAL(-6.50, a2.d());
     LMI_TEST_EQUAL( -650, a2.m_);
 }
@@ -251,7 +251,7 @@ void currency_test::test_relops()
 {
     currency const a0;
     currency const a1(1728, raw_cents{});
-    LMI_TEST(  C0 == a0);
+    LMI_TEST(  a0 == 0_cents);
     LMI_TEST(  a1 == a1);
     LMI_TEST(  a0 <  a1);
     LMI_TEST(  a0 <= a1);
diff --git a/gpt_specamt.cpp b/gpt_specamt.cpp
index a09d012..e444a13 100644
--- a/gpt_specamt.cpp
+++ b/gpt_specamt.cpp
@@ -92,7 +92,7 @@ class FindSpecAmt
         ,Premium         {a_Premium}
         ,NetPmtFactorTgt {a_NetPmtFactorTgt}
         ,NetPmtFactorExc {a_NetPmtFactorExc}
-        ,SpecAmt         {C0}
+        ,SpecAmt         {0_cents}
         {
         }
     // CURRENCY !! decimal_root() expects this; but see 'ihs_avsolve.cpp'.
diff --git a/group_values.cpp b/group_values.cpp
index 50cda81..e08e443 100644
--- a/group_values.cpp
+++ b/group_values.cpp
@@ -323,7 +323,7 @@ census_run_result run_census_in_parallel::operator()
                     ;
             for(int month = inforce_month; month < 12; ++month)
                 {
-                currency assets = C0;
+                currency assets = 0_cents;
 
                 // Get total case assets prior to interest crediting because
                 // those assets may determine the M&E charge.
diff --git a/ihs_acctval.cpp b/ihs_acctval.cpp
index 980e330..3898357 100644
--- a/ihs_acctval.cpp
+++ b/ihs_acctval.cpp
@@ -115,16 +115,16 @@ AccountValue::AccountValue(Input const& input)
     // all be kept together.
     LapseMonth               = 0;          // Antediluvian.
     LapseYear                = 0;          // Antediluvian.
-    AVUnloaned               = C0;         // Antediluvian.
-    pmt                      = C0;         // Antediluvian.
+    AVUnloaned               = 0_cents;    // Antediluvian.
+    pmt                      = 0_cents;    // Antediluvian.
     pmt_mode                 = mce_annual; // Antediluvian.
     ModeIndex                = 0;          // Antediluvian.
-    wd                       = C0;         // Antediluvian.
+    wd                       = 0_cents;    // Antediluvian.
     mlyguarv                 = 0.0;        // Antediluvian.
-    deathbft                 = C0;         // Antediluvian.
+    deathbft                 = 0_cents;    // Antediluvian.
     haswp                    = false;      // Antediluvian.
     hasadb                   = false;      // Antediluvian.
-    mlydedtonextmodalpmtdate = C0;         // Antediluvian.
+    mlydedtonextmodalpmtdate = 0_cents;    // Antediluvian.
 
     set_list_bill_year_and_month();
 
@@ -164,7 +164,7 @@ currency AccountValue::specamt_for_7702(int year) const
 {
     return
                               base_specamt(year)
-        + (TermIsDbFor7702  ? term_specamt(year) : C0)
+        + (TermIsDbFor7702  ? term_specamt(year) : 0_cents)
         ;
 }
 
@@ -174,7 +174,7 @@ currency AccountValue::specamt_for_7702A(int year) const
 {
     return
                               base_specamt(year)
-        + (TermIsDbFor7702A ? term_specamt(year) : C0)
+        + (TermIsDbFor7702A ? term_specamt(year) : 0_cents)
         ;
 }
 
@@ -243,7 +243,7 @@ Then run other bases.
 // this rather expensive function.
 void AccountValue::SetGuarPrem()
 {
-    GuarPremium = C0;
+    GuarPremium = 0_cents;
     if(BasicValues::IsSubjectToIllustrationReg())
         {
         GuarPremium = SolveGuarPremium();
@@ -410,7 +410,7 @@ void AccountValue::InitializeLife(mcenum_run_basis a_Basis)
     // TODO ?? TAXATION !! Shouldn't we increase initial SA if contract in 
corridor at issue?
     OldDB = OldSA;
 
-    SurrChg_.assign(BasicValues::GetLength(), C0);
+    SurrChg_.assign(BasicValues::GetLength(), 0_cents);
 
     // TAXATION !! Input::InforceAnnualTargetPremium should be used here.
     currency annual_target_premium = GetModalTgtPrem
@@ -446,9 +446,9 @@ void AccountValue::InitializeLife(mcenum_run_basis a_Basis)
     InvariantValues().InforceIsMec = inforce_is_mec;
     bool mec_1035 =
               yare_input_.External1035ExchangeFromMec
-           && C0 != Outlay_->external_1035_amount()
+           && 0_cents != Outlay_->external_1035_amount()
         ||    yare_input_.Internal1035ExchangeFromMec
-           && C0 != Outlay_->internal_1035_amount()
+           && 0_cents != Outlay_->internal_1035_amount()
         ;
     bool is_already_a_mec = inforce_is_mec || mec_1035;
     if(is_already_a_mec)
@@ -542,7 +542,7 @@ void AccountValue::SetInitialValues()
     Month                 = InforceMonth;
     CoordinateCounters();
 
-    DB7702A               = C0;  // TODO ?? TAXATION !! This seems silly.
+    DB7702A               = 0_cents; // TODO ?? TAXATION !! This seems silly.
 
     AVRegLn               = InforceAVRegLn;
     AVPrfLn               = InforceAVPrfLn;
@@ -583,28 +583,28 @@ void AccountValue::SetInitialValues()
             ;
         }
 
-    MaxLoan                     = C0;
+    MaxLoan                     = 0_cents;
 
-    GenAcctIntCred              = C0;
-    SepAcctIntCred              = C0;
-    RegLnIntCred                = C0;
-    PrfLnIntCred                = C0;
+    GenAcctIntCred              = 0_cents;
+    SepAcctIntCred              = 0_cents;
+    RegLnIntCred                = 0_cents;
+    PrfLnIntCred                = 0_cents;
 
-    MaxWD                       = C0;
-    GrossWD                     = C0;
-    NetWD                       = C0;
+    MaxWD                       = 0_cents;
+    GrossWD                     = 0_cents;
+    NetWD                       = 0_cents;
 
     CumPmts                     = InforceCumPmts;
     TaxBasis                    = InforceTaxBasis;
-    YearlyTaxBasis.assign(BasicValues::GetLength(), C0);
-    MlyNoLapsePrem              = C0;
+    YearlyTaxBasis.assign(BasicValues::GetLength(), 0_cents);
+    MlyNoLapsePrem              = 0_cents;
     CumNoLapsePrem              = InforceCumNoLapsePrem;
 
     // Initialize all elements of this vector to 'false'. Then, when
     // the no-lapse criteria fail to be met, future values are right.
     YearlyNoLapseActive.assign(BasicValues::GetLength(), false);
-    loan_ullage_       .assign(BasicValues::GetLength(), C0);
-    withdrawal_ullage_ .assign(BasicValues::GetLength(), C0);
+    loan_ullage_       .assign(BasicValues::GetLength(), 0_cents);
+    withdrawal_ullage_ .assign(BasicValues::GetLength(), 0_cents);
     NoLapseActive               = true;
     if(NoLapseDboLvlOnly && mce_option1 != DeathBfts_->dbopt()[0])
         {
@@ -620,16 +620,16 @@ void AccountValue::SetInitialValues()
 
     database().query_into(DB_TermCanLapse       , TermCanLapse);
     TermRiderActive             = true;
-    TermDB                      = C0;
+    TermDB                      = 0_cents;
 
     ItLapsed                    = false;
 
     Dcv                         = round_minutiae().c(yare_input_.InforceDcv);
-    DcvDeathBft                 = C0;
-    DcvNaar                     = C0;
-    DcvCoiCharge                = C0;
-    DcvTermCharge               = C0;
-    DcvWpCharge                 = C0;
+    DcvDeathBft                 = 0_cents;
+    DcvNaar                     = 0_cents;
+    DcvCoiCharge                = 0_cents;
+    DcvTermCharge               = 0_cents;
+    DcvWpCharge                 = 0_cents;
 
     HoneymoonActive             = false;
     // Identity element for std::max(), disregarding -INF and NaN.
@@ -651,9 +651,9 @@ void AccountValue::SetInitialValues()
             }
         }
 
-    CoiCharge                   = C0;
-    RiderCharges                = C0;
-    MlyDed                      = C0;
+    CoiCharge                   = 0_cents;
+    RiderCharges                = 0_cents;
+    MlyDed                      = 0_cents;
     CumulativeSalesLoad         = 
round_minutiae().c(yare_input_.InforceCumulativeSalesLoad);
 
     Dumpin             = Outlay_->dumpin();
@@ -704,7 +704,7 @@ currency AccountValue::IncrementBOM
         {
         // Return value is total assets. After the policy has lapsed or
         // matured, there are no assets.
-        return C0;
+        return 0_cents;
         }
 
     // Paranoid check.
@@ -767,8 +767,8 @@ void AccountValue::IncrementEOM
 
     // Save arguments, constraining their values to be nonnegative,
     // for calculating banded and tiered quantities.
-    AssetsPostBom  = std::max(C0, assets_post_bom  );
-    CumPmtsPostBom = std::max(C0, cum_pmts_post_bom);
+    AssetsPostBom  = std::max(0_cents, assets_post_bom  );
+    CumPmtsPostBom = std::max(0_cents, cum_pmts_post_bom);
 
     DoMonthCR();
 }
@@ -815,28 +815,28 @@ void AccountValue::InitializeYear()
         Irc7702A_->UpdateBOY7702A(Year);
         }
 
-    MonthsPolicyFees            = C0;
-    SpecAmtLoad                 = C0;
+    MonthsPolicyFees            = 0_cents;
+    SpecAmtLoad                 = 0_cents;
 
-    AssetsPostBom               = C0;
-    CumPmtsPostBom              = C0;
-    SepAcctLoad                 = C0;
+    AssetsPostBom               = 0_cents;
+    CumPmtsPostBom              = 0_cents;
+    SepAcctLoad                 = 0_cents;
 
-    YearsTotalCoiCharge         = C0;
-    YearsTotalRiderCharges      = C0;
+    YearsTotalCoiCharge         = 0_cents;
+    YearsTotalRiderCharges      = 0_cents;
     YearsAVRelOnDeath           = 0.0;
     YearsLoanRepaidOnDeath      = 0.0;
     YearsGrossClaims            = 0.0;
     YearsDeathProceeds          = 0.0;
     YearsNetClaims              = 0.0;
-    YearsTotalNetIntCredited    = C0;
-    YearsTotalGrossIntCredited  = C0;
-    YearsTotalLoanIntAccrued    = C0;
-    YearsTotalPolicyFee         = C0;
+    YearsTotalNetIntCredited    = 0_cents;
+    YearsTotalGrossIntCredited  = 0_cents;
+    YearsTotalLoanIntAccrued    = 0_cents;
+    YearsTotalPolicyFee         = 0_cents;
     YearsTotalDacTaxLoad        = 0.0;
-    YearsTotalSpecAmtLoad       = C0;
-    YearsTotalSepAcctLoad       = C0;
-    YearsTotalGptForceout       = C0;
+    YearsTotalSpecAmtLoad       = 0_cents;
+    YearsTotalSepAcctLoad       = 0_cents;
+    YearsTotalGptForceout       = 0_cents;
 
     DacTaxRsv                   = 0.0;
 
@@ -845,12 +845,12 @@ void AccountValue::InitializeYear()
     // variable in each function might have sufficed, except that this
     // quantity is used in the optional monthly detail report. Its
     // value depends on the maximum loan, so it cannot be known here.
-    ActualLoan                  = C0;
+    ActualLoan                  = 0_cents;
 
-    GrossPmts   .assign(12, C0);
-    EeGrossPmts .assign(12, C0);
-    ErGrossPmts .assign(12, C0);
-    NetPmts     .assign(12, C0);
+    GrossPmts   .assign(12, 0_cents);
+    EeGrossPmts .assign(12, 0_cents);
+    ErGrossPmts .assign(12, 0_cents);
+    NetPmts     .assign(12, 0_cents);
 
     InitializeSpecAmt();
 }
@@ -1007,7 +1007,7 @@ void AccountValue::set_modal_min_premium()
 
 currency AccountValue::SurrChg() const
 {
-    LMI_ASSERT(C0 <= SurrChg_[Year]);
+    LMI_ASSERT(0_cents <= SurrChg_[Year]);
     // For the nonce, CSVBoost() is netted against surrender charge.
     // This class's implementation should be revised to distinguish
     // these additive and subtractive components of CSV.
@@ -1020,13 +1020,13 @@ currency AccountValue::SurrChg() const
 
 currency AccountValue::CSVBoost() const
 {
-    if(!AllowCashValueEnh) return C0;
+    if(!AllowCashValueEnh) return 0_cents;
     double const z =
           CashValueEnhMult[Year]
         + yare_input_.CashValueEnhancementRate[Year]
         ;
     LMI_ASSERT(0.0 <= z);
-    return round_minutiae().c(z * std::max(C0, TotalAccountValue()));
+    return round_minutiae().c(z * std::max(0_cents, TotalAccountValue()));
 }
 
 //============================================================================
@@ -1116,7 +1116,7 @@ void AccountValue::FinalizeYear()
 
     // While performing a solve, ignore any positive surrender charge
     // that cannot cause the contract to lapse.
-    if(Solving && C0 < surr_chg && LapseIgnoresSurrChg)
+    if(Solving && 0_cents < surr_chg && LapseIgnoresSurrChg)
         {
         ; // Do nothing.
         }
@@ -1129,7 +1129,7 @@ void AccountValue::FinalizeYear()
 
     if(!Solving)
         {
-        csv_net = std::max(csv_net, C0);
+        csv_net = std::max(csv_net, 0_cents);
         }
 
     if(Solving)
@@ -1146,7 +1146,7 @@ void AccountValue::FinalizeYear()
     // the surrender charge are negative while others are positive,
     // consider only their sum here, instead of considering the sign
     // of each component individually.
-    if(surr_chg < C0)
+    if(surr_chg < 0_cents)
         {
         cv_7702 -= surr_chg;
         }
@@ -1388,7 +1388,7 @@ currency AccountValue::GetSepAcctAssetsInforce() const
 {
     if(ItLapsed || BasicValues::GetLength() <= Year)
         {
-        return C0;
+        return 0_cents;
         }
 
     return round_minutiae().c(SepAcctValueAfterDeduction * 
partial_mortality_lx()[Year]);
diff --git a/ihs_avdebug.cpp b/ihs_avdebug.cpp
index 22ecfc3..7cb6917 100644
--- a/ihs_avdebug.cpp
+++ b/ihs_avdebug.cpp
@@ -420,7 +420,7 @@ void AccountValue::DebugPrint()
     SetMonthlyDetail(eCumNoLapsePrem     ,CumNoLapsePrem                   );
     SetMonthlyDetail(eNoLapseActive      ,NoLapseActive                    );
     SetMonthlyDetail(eEOMAV              ,TotalAccountValue()              );
-    SetMonthlyDetail(eHMValue            ,std::max(HoneymoonValue, C0)     );
+    SetMonthlyDetail(eHMValue            ,std::max(HoneymoonValue, 0_cents));
     SetMonthlyDetail(eSurrChg            ,SurrChg()                        );
 
 // TODO ?? Unfortunately duplicated from AccountValue::FinalizeYear().
diff --git a/ihs_avmly.cpp b/ihs_avmly.cpp
index 921e7d7..eecdb58 100644
--- a/ihs_avmly.cpp
+++ b/ihs_avmly.cpp
@@ -115,7 +115,7 @@ void AccountValue::DoMonthDR()
 
     TxTestGPT();
     // TODO ?? TAXATION !! Doesn't this mean dumpins and 1035s get ignored?
-    LMI_ASSERT(C0 <= Dcv);
+    LMI_ASSERT(0_cents <= Dcv);
     // TAXATION !! Is it really useful to comment the arguments here?
     Irc7702A_->UpdateBft7702A
         (dblize(Dcv)
@@ -129,8 +129,8 @@ void AccountValue::DoMonthDR()
         ,dblize(CashValueFor7702())
         );
 
-    NetPmts  [Month] = C0; // TODO ?? expunge as being unnecessary
-    GrossPmts[Month] = C0; // TODO ?? expunge as being unnecessary
+    NetPmts  [Month] = 0_cents; // TODO ?? expunge as being unnecessary
+    GrossPmts[Month] = 0_cents; // TODO ?? expunge as being unnecessary
     TxExch1035();
     // TODO ?? TAXATION !! Is this where spec amt should be increased by GPT?
 
@@ -197,7 +197,7 @@ void AccountValue::DoMonthDR()
             );
         }
 
-    currency gross_1035 = C0;
+    currency gross_1035 = 0_cents;
     if(0 == Year && 0 == Month)
         {
         gross_1035 = External1035Amount + Internal1035Amount;
@@ -243,7 +243,7 @@ void AccountValue::DoMonthDR()
         );
     Dcv = round_minutiae().c(z);
     }
-    LMI_ASSERT(C0 <= Dcv);
+    LMI_ASSERT(0_cents <= Dcv);
 
     TxRecognizePaymentFor7702A(UnnecessaryPremium, true);
     TxAcceptPayment(UnnecessaryPremium);
@@ -281,18 +281,18 @@ void AccountValue::process_payment(currency payment)
     // contracts. We deem net payments to have the same proportion
     // as gross payments, which we do have for ee and er separately.
 
-    LMI_ASSERT(C0 <=   GrossPmts[Month]);
-    LMI_ASSERT(C0 <= EeGrossPmts[Month]);
-    LMI_ASSERT(C0 <= ErGrossPmts[Month]);
+    LMI_ASSERT(0_cents <=   GrossPmts[Month]);
+    LMI_ASSERT(0_cents <= EeGrossPmts[Month]);
+    LMI_ASSERT(0_cents <= ErGrossPmts[Month]);
 
-    currency gross_1035 = C0;
+    currency gross_1035 = 0_cents;
     if(0 == Year && 0 == Month)
         {
         gross_1035 = External1035Amount + Internal1035Amount;
         }
     currency gross_non_1035_pmts = GrossPmts[Month] - gross_1035;
     double er_proportion = 0.0;
-    if(C0 != gross_non_1035_pmts)
+    if(0_cents != gross_non_1035_pmts)
         {
         er_proportion = ErGrossPmts[Month] / gross_non_1035_pmts;
         }
@@ -430,18 +430,18 @@ void AccountValue::DecrementAVProportionally(currency 
decrement)
 
     if(decrement == AVGenAcct + AVSepAcct)
         {
-        AVGenAcct = C0;
-        AVSepAcct = C0;
+        AVGenAcct = 0_cents;
+        AVSepAcct = 0_cents;
         return;
         }
 
     double general_account_proportion  = 0.0;
     double separate_account_proportion = 0.0;
-    currency general_account_nonnegative_assets  = std::max(C0, AVGenAcct);
-    currency separate_account_nonnegative_assets = std::max(C0, AVSepAcct);
+    currency general_account_nonnegative_assets  = std::max(0_cents, 
AVGenAcct);
+    currency separate_account_nonnegative_assets = std::max(0_cents, 
AVSepAcct);
     if
-        (  C0 == general_account_nonnegative_assets
-        && C0 == separate_account_nonnegative_assets
+        (  0_cents == general_account_nonnegative_assets
+        && 0_cents == separate_account_nonnegative_assets
         )
         {
         general_account_proportion  = GenAcctPaymentAllocation;
@@ -493,8 +493,8 @@ void AccountValue::DecrementAVProgressively
 {
     if(decrement == AVGenAcct + AVSepAcct)
         {
-        AVGenAcct = C0;
-        AVSepAcct = C0;
+        AVGenAcct = 0_cents;
+        AVSepAcct = 0_cents;
         return;
         }
 
@@ -521,18 +521,18 @@ void AccountValue::TxExch1035()
         return;
         }
 
-    LMI_ASSERT(Year == InforceYear);
+    LMI_ASSERT(Year  == InforceYear);
     LMI_ASSERT(Month == InforceMonth);
-    LMI_ASSERT(C0 ==   GrossPmts[Month]);
-    LMI_ASSERT(C0 == EeGrossPmts[Month]);
-    LMI_ASSERT(C0 == ErGrossPmts[Month]);
+    LMI_ASSERT(0_cents ==   GrossPmts[Month]);
+    LMI_ASSERT(0_cents == EeGrossPmts[Month]);
+    LMI_ASSERT(0_cents == ErGrossPmts[Month]);
 
     // Policy issue date is always a modal payment date.
     GrossPmts[Month] = External1035Amount + Internal1035Amount;
 
 // TODO ?? TAXATION !! This looks like a good idea, but it would prevent the
 // initial seven-pay premium from being set.
-//    if(C0 == GrossPmts[Month])
+//    if(0_cents == GrossPmts[Month])
 //        {
 //        return;
 //        }
@@ -569,7 +569,7 @@ void AccountValue::TxExch1035()
 
     // TODO ?? Assume for now that all 1035 exchanges represent ee payments.
     EeGrossPmts[Month] = GrossPmts[Month];
-    currency amount_exempt_from_premium_tax = C0;
+    currency amount_exempt_from_premium_tax = 0_cents;
     if(WaivePmTxInt1035)
         {
         amount_exempt_from_premium_tax = Internal1035Amount;
@@ -581,15 +581,15 @@ void AccountValue::TxExch1035()
 
     NetPmts[Month] = GrossPmts[Month] - actual_load;
 
-    LMI_ASSERT(C0 == AVGenAcct);
-    LMI_ASSERT(C0 == AVSepAcct);
+    LMI_ASSERT(0_cents == AVGenAcct);
+    LMI_ASSERT(0_cents == AVSepAcct);
     process_payment(NetPmts[Month]);
 
-    DBReflectingCorr = C0;
+    DBReflectingCorr = 0_cents;
     TxSetDeathBft();
     TxSetTermAmt();
     // TODO ?? TAXATION !! Should 1035 exchanges be handled somewhere else?
-    LMI_ASSERT(C0 == Dcv);
+    LMI_ASSERT(0_cents == Dcv);
     {
     // CURRENCY !! return modified value instead of altering argument
     double z = dblize(Dcv);
@@ -606,7 +606,7 @@ void AccountValue::TxExch1035()
 
     if(HoneymoonActive)
         {
-        HoneymoonValue += std::max(C0, GrossPmts[Month]);
+        HoneymoonValue += std::max(0_cents, GrossPmts[Month]);
         }
 
     CumPmts += GrossPmts[Month];
@@ -745,7 +745,7 @@ void AccountValue::ChangeSpecAmtBy(currency delta)
         ActualSpecAmt += round_specamt().c(delta * (1.0 - term_proportion));
         TermSpecAmt = old_total_specamt + delta - ActualSpecAmt;
 
-        if(TermSpecAmt < C0)
+        if(TermSpecAmt < 0_cents)
             {
             // Reducing the term rider's specified amount to a value
             // less than zero is taken as a request to terminate the
@@ -812,7 +812,7 @@ void AccountValue::ChangeSupplAmtBy(currency delta)
     TermSpecAmt += delta;
 
     // No minimum other than zero is defined.
-    TermSpecAmt = std::max(TermSpecAmt, C0);
+    TermSpecAmt = std::max(TermSpecAmt, 0_cents);
 
     // Carry the new supplemental amount forward into all future years.
     // At least for now, there is no effect on surrender charges.
@@ -828,7 +828,7 @@ void AccountValue::ChangeSupplAmtBy(currency delta)
 //============================================================================
 void AccountValue::InitializeMonth()
 {
-    GptForceout       = C0;
+    GptForceout       = 0_cents;
     premium_load_     = 0.0;
     sales_load_       = 0.0;
     premium_tax_load_ = 0.0;
@@ -901,18 +901,18 @@ void AccountValue::TxOptionChange()
                 {
                 if(mce_option2 == old_option)
                     {
-                    ChangeSpecAmtBy(std::max(C0, TotalAccountValue()));
+                    ChangeSpecAmtBy(std::max(0_cents, TotalAccountValue()));
                     }
                 else if(mce_rop == old_option)
                     {
-                    ChangeSpecAmtBy(std::max(C0, CumPmts));
+                    ChangeSpecAmtBy(std::max(0_cents, CumPmts));
                     }
                 else if(mce_mdb == old_option)
                     {
                     // Do nothing. An argument could be made for this
                     // alternative:
                     //   TxSetDeathBft(); // update DBReflectingCorr
-                    //   ChangeSpecAmtBy(std::max(C0, DBReflectingCorr));
+                    //   ChangeSpecAmtBy(std::max(0_cents, DBReflectingCorr));
                     // but that takes more work and is not clearly
                     // preferable.
                     }
@@ -932,7 +932,7 @@ void AccountValue::TxOptionChange()
         case mce_option2:
             if(OptChgCanDecrSA)
                 {
-                ChangeSpecAmtBy(-std::max(C0, TotalAccountValue()));
+                ChangeSpecAmtBy(-std::max(0_cents, TotalAccountValue()));
                 }
             else
                 {
@@ -942,7 +942,7 @@ void AccountValue::TxOptionChange()
         case mce_rop:
             if(OptChgCanDecrSA)
                 {
-                ChangeSpecAmtBy(-std::max(C0, CumPmts));
+                ChangeSpecAmtBy(-std::max(0_cents, CumPmts));
                 }
             else
                 {
@@ -976,7 +976,7 @@ void AccountValue::TxSpecAmtChange()
 // > post-1035 exchange calculation of the seven pay will have a death benefit
 // > amount to base its calculations on.
 #if 1
-        ChangeSpecAmtBy(C0);
+        ChangeSpecAmtBy(0_cents);
 #else // 0
         // TODO ?? Changing specamt by zero is absurd. The following
         // commented-out alternative seems to do the same thing as
@@ -1206,7 +1206,7 @@ void AccountValue::TxAscertainDesiredPayment()
 
     assert_pmts_add_up(__FILE__, __LINE__, Month);
 
-    currency eepmt = C0;
+    currency eepmt = 0_cents;
     if(ee_pay_this_month)
         {
         eepmt = PerformEePmtStrategy();
@@ -1222,7 +1222,7 @@ void AccountValue::TxAscertainDesiredPayment()
         GrossPmts  [Month] += eepmt;
         }
 
-    currency erpmt = C0;
+    currency erpmt = 0_cents;
     if(er_pay_this_month)
         {
         erpmt = PerformErPmtStrategy();
@@ -1319,7 +1319,7 @@ void AccountValue::TxLimitPayment(double a_maxpmt)
 
     if(mce_reduce_prem == yare_input_.AvoidMecMethod && 
!Irc7702A_->IsMecAlready())
         {
-        currency gross_1035 = C0;
+        currency gross_1035 = 0_cents;
         if(0 == Year && 0 == Month)
             {
             gross_1035 = External1035Amount + Internal1035Amount;
@@ -1364,7 +1364,7 @@ void AccountValue::TxRecognizePaymentFor7702A
     ,bool     a_this_payment_is_unnecessary
     )
 {
-    if(C0 == a_pmt)
+    if(0_cents == a_pmt)
         {
         return;
         }
@@ -1383,7 +1383,7 @@ void AccountValue::TxRecognizePaymentFor7702A
         ,   kludge_account_value
           + GetRefundableSalesLoad()
         );
-    LMI_ASSERT(C0 <= Dcv);
+    LMI_ASSERT(0_cents <= Dcv);
 
     // 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
@@ -1403,17 +1403,17 @@ void AccountValue::TxRecognizePaymentFor7702A
 //============================================================================
 void AccountValue::TxAcceptPayment(currency a_pmt)
 {
-    if(C0 == a_pmt)
+    if(0_cents == a_pmt)
         {
         return;
         }
 
-    LMI_ASSERT(C0 <= a_pmt);
+    LMI_ASSERT(0_cents <= a_pmt);
     // Internal 1035 exchanges may be exempt from premium tax; they're
     // handled elsewhere, so here the exempt amount is always zero.
-    currency actual_load = GetPremLoad(a_pmt, C0);
+    currency actual_load = GetPremLoad(a_pmt, 0_cents);
     currency net_pmt = a_pmt - actual_load;
-    LMI_ASSERT(C0 <= net_pmt);
+    LMI_ASSERT(0_cents <= net_pmt);
     NetPmts[Month] += net_pmt;
 
     // If a payment on an ROP contract is treated as an adjustable event,
@@ -1424,12 +1424,12 @@ void AccountValue::TxAcceptPayment(currency a_pmt)
 
     process_payment(net_pmt);
 
-    Dcv += std::max(C0, net_pmt);
-    LMI_ASSERT(C0 <= Dcv);
+    Dcv += std::max(0_cents, net_pmt);
+    LMI_ASSERT(0_cents <= Dcv);
 
     if(HoneymoonActive)
         {
-        HoneymoonValue += std::max(C0, a_pmt);
+        HoneymoonValue += std::max(0_cents, a_pmt);
         }
 
     CumPmts += a_pmt;
@@ -1470,7 +1470,7 @@ currency AccountValue::GetPremLoad
 {
     currency excess_portion;
     // All excess.
-    if(C0 == UnusedTargetPrem)
+    if(0_cents == UnusedTargetPrem)
         {
         excess_portion = a_pmt;
         }
@@ -1478,12 +1478,12 @@ currency AccountValue::GetPremLoad
     else if(UnusedTargetPrem < a_pmt)
         {
         excess_portion = a_pmt - UnusedTargetPrem;
-        UnusedTargetPrem = C0;
+        UnusedTargetPrem = 0_cents;
         }
     // All target.
     else
         {
-        excess_portion = C0;
+        excess_portion = 0_cents;
         UnusedTargetPrem -= a_pmt;
         }
     currency target_portion = a_pmt - excess_portion;
@@ -1536,10 +1536,10 @@ currency AccountValue::GetRefundableSalesLoad() const
 #if 0
     // CURRENCY !! Assertions such as these are desirable, but adding
     // them now would cause regression artifacts.
-    LMI_ASSERT(C0 <= CumulativeSalesLoad);
-    LMI_ASSERT(C0 <= YearsSalesLoadRefundRate);
+    LMI_ASSERT(0_cents <= CumulativeSalesLoad);
+    LMI_ASSERT(0_cents <= YearsSalesLoadRefundRate);
     double const z = CumulativeSalesLoad * YearsSalesLoadRefundRate;
-    LMI_ASSERT(C0 <= z);
+    LMI_ASSERT(0_cents <= z);
     return z;
 #endif // 0
 }
@@ -1555,7 +1555,7 @@ void AccountValue::TxLoanRepay()
         }
 
     // Nothing to do if no loan repayment requested.
-    if(C0 <= RequestedLoan)
+    if(0_cents <= RequestedLoan)
         {
         return;
         }
@@ -1566,8 +1566,8 @@ void AccountValue::TxLoanRepay()
     ActualLoan = -std::min(-RequestedLoan, RegLnBal + PrfLnBal);
 
     process_distribution(ActualLoan);
-    LMI_ASSERT(C0 == progressively_reduce(AVRegLn , AVPrfLn , -ActualLoan));
-    LMI_ASSERT(C0 == progressively_reduce(RegLnBal, PrfLnBal, -ActualLoan));
+    LMI_ASSERT(0_cents == progressively_reduce(AVRegLn , AVPrfLn , 
-ActualLoan));
+    LMI_ASSERT(0_cents == progressively_reduce(RegLnBal, PrfLnBal, 
-ActualLoan));
 
 // This seems wrong. If we're changing something that's invariant among
 // bases, why do we change it for each basis?
@@ -1589,7 +1589,7 @@ void AccountValue::TxSetBOMAV()
         {
         if(!yare_input_.TermRider && !TermIsNotRider)
             {
-            LMI_ASSERT(C0 == term_specamt(0));
+            LMI_ASSERT(0_cents == term_specamt(0));
             }
         // CURRENCY !! Should yare_input convert currency inputs to
         // type currency, which is more yare than double?
@@ -1620,7 +1620,7 @@ void AccountValue::TxSetBOMAV()
     process_deduction(MonthsPolicyFees + SpecAmtLoad);
 
     Dcv -= MonthsPolicyFees + SpecAmtLoad;
-    Dcv = std::max(C0, Dcv);
+    Dcv = std::max(0_cents, Dcv);
 }
 
 /// Set death benefit reflecting corridor and death benefit option.
@@ -1651,7 +1651,7 @@ void AccountValue::TxSetBOMAV()
 ///    currency prior_sa_7702A = ActualSpecAmt;
 /// toward the beginning, and:
 ///    Irc7702A_->UpdateBft7702A(...);
-///    LMI_ASSERT(C0 <= Dcv);
+///    LMI_ASSERT(0_cents <= Dcv);
 /// toward the end.
 
 void AccountValue::TxSetDeathBft()
@@ -1667,7 +1667,7 @@ void AccountValue::TxSetDeathBft()
         case mce_option2:
             {
             // Negative AV doesn't decrease death benefit.
-            DBIgnoringCorr = ActualSpecAmt + std::max(C0, TotalAccountValue());
+            DBIgnoringCorr = ActualSpecAmt + std::max(0_cents, 
TotalAccountValue());
             DB7702A        = ActualSpecAmt;
             }
             break;
@@ -1676,8 +1676,8 @@ void AccountValue::TxSetDeathBft()
             // SA + sum of premiums less withdrawals, but not < SA;
             // i.e., ignore 'CumPmts' if it is less than zero, as it
             // easily can be, e.g., if WDs are not limited to basis.
-            DBIgnoringCorr = ActualSpecAmt + std::max(C0, CumPmts);
-            DB7702A        = ActualSpecAmt + std::max(C0, CumPmts);
+            DBIgnoringCorr = ActualSpecAmt + std::max(0_cents, CumPmts);
+            DB7702A        = ActualSpecAmt + std::max(0_cents, CumPmts);
             }
             break;
         case mce_mdb:
@@ -1685,18 +1685,18 @@ void AccountValue::TxSetDeathBft()
             // Specamt is a floor under DB (and therefore zero here)
             // because this option defines the DB as the minimum
             // required by the corridor (but not less than zero).
-            DBIgnoringCorr = C0;
-            DB7702A        = C0;
+            DBIgnoringCorr = 0_cents;
+            DB7702A        = 0_cents;
             }
             break;
         }
-    LMI_ASSERT(C0 <= DBIgnoringCorr);
+    LMI_ASSERT(0_cents <= DBIgnoringCorr);
 
     // Surrender charges are generally ignored here, but any negative
     // surrender charge must be subtracted, increasing the account value.
     currency cash_value_for_corridor =
           TotalAccountValue()
-        - std::min(C0, SurrChg())
+        - std::min(0_cents, SurrChg())
         + GetRefundableSalesLoad()
         ;
 
@@ -1707,9 +1707,11 @@ void AccountValue::TxSetDeathBft()
 
     DBReflectingCorr = std::max
         (DBIgnoringCorr
-        ,round_death_benefit().c(YearsCorridorFactor * std::max(C0, 
cash_value_for_corridor))
+        ,round_death_benefit().c
+            (YearsCorridorFactor * std::max(0_cents, cash_value_for_corridor)
+            )
         );
-    LMI_ASSERT(C0 <= DBReflectingCorr);
+    LMI_ASSERT(0_cents <= DBReflectingCorr);
     // This overrides the value assigned above. There's more than one
     // way to interpret 7702A "death benefit"; this is just one.
     // TAXATION !! Use DB_Irc7702BftIsSpecAmt
@@ -1721,7 +1723,7 @@ void AccountValue::TxSetDeathBft()
             (
                 YearsCorridorFactor
             *   (   Dcv
-                -   std::min(C0, SurrChg())
+                -   std::min(0_cents, SurrChg())
                 +   GetRefundableSalesLoad()
                 )
             )
@@ -1755,7 +1757,7 @@ void AccountValue::TxSetTermAmt()
         return;
         }
 
-    TermDB = std::max(C0, TermSpecAmt + DBIgnoringCorr - DBReflectingCorr);
+    TermDB = std::max(0_cents, TermSpecAmt + DBIgnoringCorr - 
DBReflectingCorr);
 }
 
 /// Terminate the term rider, optionally converting it to base.
@@ -1785,8 +1787,8 @@ void AccountValue::EndTermRider(bool convert)
         {
         ChangeSpecAmtBy(TermSpecAmt);
         }
-    TermSpecAmt = C0;
-    TermDB      = C0;
+    TermSpecAmt = 0_cents;
+    TermDB      = 0_cents;
     // Carry the new term spec amt forward into all future years.
     for(int j = Year; j < BasicValues::GetLength(); ++j)
         {
@@ -1810,9 +1812,9 @@ void AccountValue::TxSetCoiCharge()
     // the account value by deducting a negative mortality charge.
     NAAR = round_naar().c
         ( DBReflectingCorr * DBDiscountRate[Year]
-        - dblize(std::max(C0, TotalAccountValue()))
+        - dblize(std::max(0_cents, TotalAccountValue()))
         );
-    NAAR = std::max(C0, NAAR);
+    NAAR = std::max(0_cents, NAAR);
 
 // TODO ?? This doesn't work. We need to reconsider the basic transactions.
 //  currency naar_forceout = std::max(0.0, NAAR - MaxNAAR);
@@ -1821,9 +1823,9 @@ void AccountValue::TxSetCoiCharge()
 
     DcvNaar = round_naar().c
         ( std::max(DcvDeathBft, DBIgnoringCorr) * DcvDBDiscountRate[Year]
-        - dblize(std::max(C0, Dcv))
+        - dblize(std::max(0_cents, Dcv))
         );
-    DcvNaar = std::max(C0, DcvNaar);
+    DcvNaar = std::max(0_cents, DcvNaar);
 
     double coi_rate = GetBandedCoiRates(GenBasis_, ActualSpecAmt)[Year];
     ActualCoiRate = coi_rate;
@@ -1838,7 +1840,7 @@ void AccountValue::TxSetCoiCharge()
 
 void AccountValue::TxSetRiderDed()
 {
-    AdbCharge = C0;
+    AdbCharge = 0_cents;
     if(yare_input_.AccidentalDeathBenefit)
         {
         AdbCharge = round_rider_charges().c
@@ -1846,7 +1848,7 @@ void AccountValue::TxSetRiderDed()
             );
         }
 
-    SpouseRiderCharge = C0;
+    SpouseRiderCharge = 0_cents;
     if(yare_input_.SpouseRider)
         {
         SpouseRiderCharge = round_rider_charges().c
@@ -1854,7 +1856,7 @@ void AccountValue::TxSetRiderDed()
             );
         }
 
-    ChildRiderCharge = C0;
+    ChildRiderCharge = 0_cents;
     if(yare_input_.ChildRider)
         {
         ChildRiderCharge = round_rider_charges().c
@@ -1862,8 +1864,8 @@ void AccountValue::TxSetRiderDed()
             );
         }
 
-    TermCharge    = C0;
-    DcvTermCharge = C0;
+    TermCharge    = 0_cents;
+    DcvTermCharge = 0_cents;
     if(TermRiderActive)
         {
         TermCharge    = round_rider_charges().c
@@ -1878,8 +1880,8 @@ void AccountValue::TxSetRiderDed()
             );
         }
 
-    WpCharge    = C0;
-    DcvWpCharge = C0;
+    WpCharge    = 0_cents;
+    DcvWpCharge = 0_cents;
     if(yare_input_.WaiverOfPremiumBenefit)
         {
         switch(WaiverChargeMethod)
@@ -1933,7 +1935,7 @@ void AccountValue::TxDoMlyDed()
     if(TermRiderActive && TermCanLapse && (AVGenAcct + AVSepAcct - CoiCharge) 
< TermCharge)
         {
         EndTermRider(false);
-        TermCharge = C0;
+        TermCharge = 0_cents;
         }
 
     // 'Simple' riders are the same for AV and DCV.
@@ -1958,7 +1960,7 @@ void AccountValue::TxDoMlyDed()
 
     process_deduction(MlyDed);
     Dcv -= dcv_mly_ded;
-    Dcv = std::max(C0, Dcv);
+    Dcv = std::max(0_cents, Dcv);
 
     // Policy and issue fees and the specified-amount load are really
     // part of the monthly deduction, yet they must be kept distinct
@@ -1996,7 +1998,7 @@ void AccountValue::TxTestHoneymoonForExpiration()
     // And it doesn't make sense for the honeymoon provision to
     // keep the contract in force if 'HoneymoonValue' is -10000
     // and CSV is -20000.
-    if(HoneymoonValue <= C0 || HoneymoonValue < csv_ignoring_loan)
+    if(HoneymoonValue <= 0_cents || HoneymoonValue < csv_ignoring_loan)
         {
         HoneymoonActive = false;
         // CURRENCY !! alternatively, use -INF
@@ -2064,7 +2066,7 @@ void AccountValue::TxTakeSepAcctLoad()
     process_deduction(SepAcctLoad);
     YearsTotalSepAcctLoad += SepAcctLoad;
     Dcv -= SepAcctLoad;
-    Dcv = std::max(C0, Dcv);
+    Dcv = std::max(0_cents, Dcv);
 }
 
 //============================================================================
@@ -2158,22 +2160,22 @@ void AccountValue::TxCreditInt()
 {
     ApplyDynamicMandE(AssetsPostBom);
 
-    currency notional_sep_acct_charge = C0;
+    currency notional_sep_acct_charge = 0_cents;
 
-    if(C0 < AVSepAcct)
+    if(0_cents < AVSepAcct)
         {
         SepAcctIntCred = InterestCredited(AVSepAcct, YearsSepAcctIntRate);
         currency gross = InterestCredited(AVSepAcct, YearsSepAcctGrossRate);
         notional_sep_acct_charge = gross - SepAcctIntCred;
         // CURRENCY !! Further simplify the local logic?
-        AVSepAcct = std::max(C0, AVSepAcct + SepAcctIntCred);
+        AVSepAcct = std::max(0_cents, AVSepAcct + SepAcctIntCred);
         }
     else
         {
-        SepAcctIntCred = C0;
+        SepAcctIntCred = 0_cents;
         }
 
-    if(C0 < AVGenAcct)
+    if(0_cents < AVGenAcct)
         {
         double effective_general_account_interest_factor = YearsGenAcctIntRate;
         if
@@ -2194,11 +2196,11 @@ void AccountValue::TxCreditInt()
         }
     else
         {
-        GenAcctIntCred = C0;
+        GenAcctIntCred = 0_cents;
         }
 
-    LMI_ASSERT(C0 <= Dcv);
-    if(C0 < Dcv)
+    LMI_ASSERT(0_cents <= Dcv);
+    if(0_cents < Dcv)
         {
         Dcv += round_interest_credit().c(YearsDcvIntRate * Dcv);
         }
@@ -2212,7 +2214,7 @@ void AccountValue::TxCreditInt()
         }
 
     // Loaned account value must not be negative.
-    LMI_ASSERT(C0 <= AVRegLn && C0 <= AVPrfLn);
+    LMI_ASSERT(0_cents <= AVRegLn && 0_cents <= AVPrfLn);
 
     currency z = RegLnIntCred + PrfLnIntCred + SepAcctIntCred + GenAcctIntCred;
     YearsTotalNetIntCredited   += z;
@@ -2225,11 +2227,11 @@ void AccountValue::TxLoanInt()
 {
     // Reinitialize to zero before potential early exit, to sweep away
     // any leftover values (e.g., after a loan has been paid off).
-    RegLnIntCred = C0;
-    PrfLnIntCred = C0;
+    RegLnIntCred = 0_cents;
+    PrfLnIntCred = 0_cents;
 
     // Nothing more to do if there's no loan outstanding.
-    if(C0 == RegLnBal && C0 == PrfLnBal)
+    if(0_cents == RegLnBal && 0_cents == PrfLnBal)
         {
         return;
         }
@@ -2318,13 +2320,13 @@ void AccountValue::SetMaxWD()
         + (AVRegLn  + AVPrfLn)
         - (RegLnBal + PrfLnBal)
         - anticipated_deduction(MaxWDDed_)
-        - std::max(C0, SurrChg())
+        - std::max(0_cents, SurrChg())
         ;
     if(MaxWD < MinWD)
         {
-        MaxWD = C0;
+        MaxWD = 0_cents;
         }
-    MaxWD = std::max(C0, MaxWD);
+    MaxWD = std::max(0_cents, MaxWD);
 }
 
 /// Take a withdrawal.
@@ -2337,20 +2339,20 @@ void AccountValue::TxTakeWD()
         return;
         }
 
-    GrossWD = C0;
+    GrossWD = 0_cents;
     RequestedWD = Outlay_->withdrawals()[Year];
 
-    if(Debugging || C0 != RequestedWD)
+    if(Debugging || 0_cents != RequestedWD)
         {
         SetMaxWD();
         }
 
-    NetWD = C0;
+    NetWD = 0_cents;
 
     // Nothing more to do if no withdrawal requested.
-    if(C0 == RequestedWD)
+    if(0_cents == RequestedWD)
         {
-        withdrawal_ullage_[Year] = C0;
+        withdrawal_ullage_[Year] = 0_cents;
 // This seems wrong. If we're changing something that's invariant among
 // bases, why do we change it for each basis?
 // TODO ?? Shouldn't this be moved to FinalizeMonth()?
@@ -2364,7 +2366,7 @@ void AccountValue::TxTakeWD()
 
     if(Solving)
         {
-        withdrawal_ullage_[Year] = std::max(C0, RequestedWD - MaxWD);
+        withdrawal_ullage_[Year] = std::max(0_cents, RequestedWD - MaxWD);
         }
 
     if(Solving || mce_run_gen_curr_sep_full == RunBasis_)
@@ -2388,8 +2390,8 @@ void AccountValue::TxTakeWD()
     // Impose minimum amount on withdrawals.
     if(RequestedWD < MinWD)
         {
-        withdrawal_ullage_[Year] = C0;
-        NetWD = C0;
+        withdrawal_ullage_[Year] = 0_cents;
+        NetWD = 0_cents;
         }
 // TODO ?? If WD zero, skip some steps? Cannot simply return in this case
 // because user may prefer to shift to loans.
@@ -2410,10 +2412,10 @@ void AccountValue::TxTakeWD()
         // Even after the entire basis has been withdrawn, we still
         // take withdrawals if payments since have increased the basis.
         // TODO ?? Should RequestedWD be constrained by MaxWD and MinWD here?
-        if(C0 == TaxBasis || std::min(TaxBasis, RequestedWD) < MinWD) // All 
loan
+        if(0_cents == TaxBasis || std::min(TaxBasis, RequestedWD) < MinWD) // 
All loan
             {
-            withdrawal_ullage_[Year] = C0;
-            NetWD = C0;
+            withdrawal_ullage_[Year] = 0_cents;
+            NetWD = 0_cents;
             }
         else if(NetWD < TaxBasis) // All WD
             {
@@ -2428,7 +2430,7 @@ void AccountValue::TxTakeWD()
         RequestedLoan += RequestedWD - NetWD;
         }
 
-    if(NetWD <= C0)
+    if(NetWD <= 0_cents)
         {
 // TODO ?? What should this be?
 //      withdrawal_ullage_[Year] = ?
@@ -2482,8 +2484,8 @@ void AccountValue::TxTakeWD()
 
     currency av = TotalAccountValue();
     currency csv = av - SurrChg_[Year];
-    LMI_ASSERT(C0 <= SurrChg_[Year]);
-    if(csv <= C0)
+    LMI_ASSERT(0_cents <= SurrChg_[Year]);
+    if(csv <= 0_cents)
         {
 // TODO ?? What should this be?
 //      withdrawal_ullage_[Year] = ?
@@ -2513,14 +2515,14 @@ void AccountValue::TxTakeWD()
         LMI_ASSERT(AVPrfLn == PrfLnBal);
         LMI_ASSERT(av == AVGenAcct + AVSepAcct);
         currency free_wd = round_withdrawal().c(FreeWDProportion[Year] * av);
-        non_free_wd = std::max(C0, GrossWD - free_wd);
+        non_free_wd = std::max(0_cents, GrossWD - free_wd);
         }
     double partial_surrchg = non_free_wd * surrchg_proportion;
     GrossWD += round_withdrawal().c(partial_surrchg);
 
     process_distribution(GrossWD);
     Dcv -= GrossWD;
-    Dcv = std::max(C0, Dcv);
+    Dcv = std::max(0_cents, Dcv);
 
     switch(YearsDBOpt)
         {
@@ -2647,7 +2649,7 @@ void AccountValue::SetMaxLoan()
         + dblize
             ( (AVRegLn + AVPrfLn)
             - anticipated_deduction(MaxLoanDed_)
-            - std::max(C0, SurrChg())
+            - std::max(0_cents, SurrChg())
             )
         ;
 
@@ -2688,15 +2690,15 @@ void AccountValue::TxTakeLoan()
 
     // Even if no loan is requested, the maximum loan is still shown
     // in a monthly trace.
-    if(Debugging || C0 <= RequestedLoan)
+    if(Debugging || 0_cents <= RequestedLoan)
         {
         SetMaxLoan();
         }
 
     // Nothing more to do if no loan requested.
-    if(RequestedLoan <= C0)
+    if(RequestedLoan <= 0_cents)
         {
-        loan_ullage_[Year] = C0;
+        loan_ullage_[Year] = 0_cents;
         return;
         }
 
@@ -2708,12 +2710,12 @@ void AccountValue::TxTakeLoan()
     if(Solving)
         {
         ActualLoan = RequestedLoan;
-        loan_ullage_[Year] = std::max(C0, RequestedLoan - max_loan_increment);
+        loan_ullage_[Year] = std::max(0_cents, RequestedLoan - 
max_loan_increment);
         }
     else
         {
         ActualLoan = std::min(max_loan_increment, RequestedLoan);
-        ActualLoan = std::max(ActualLoan, C0);
+        ActualLoan = std::max(ActualLoan, 0_cents);
         // TODO ?? Shouldn't this happen in FinalizeMonth()?
         InvariantValues().NewCashLoan[Year] = dblize(ActualLoan);
         }
@@ -2788,7 +2790,7 @@ void AccountValue::TxTestLapse()
         ;
     if(!LapseIgnoresSurrChg)
         {
-        lapse_test_csv -= std::max(C0, SurrChg());
+        lapse_test_csv -= std::max(0_cents, SurrChg());
         }
     lapse_test_csv = std::max(lapse_test_csv, HoneymoonValue);
 
@@ -2826,11 +2828,11 @@ void AccountValue::TxTestLapse()
     // Otherwise if CSV is negative or if overloaned, then lapse the policy.
     else if
         (
-            (!NoLapseActive && lapse_test_csv < C0)
+            (!NoLapseActive && lapse_test_csv < 0_cents)
         // Lapse if overloaned regardless of guar DB.
         // CSV includes a positive loan (that can offset a negative AV);
         // however, we still need to test for NoLapseActive.
-        ||  (!NoLapseActive && (AVGenAcct + AVSepAcct) < C0)
+        ||  (!NoLapseActive && (AVGenAcct + AVSepAcct) < 0_cents)
         // Test for nonnegative unloaned account value.
         // We are aware that some companies test against loan balance:
 // TODO ?? Would the explicit test
@@ -2858,14 +2860,14 @@ void AccountValue::TxTestLapse()
         }
     else
         {
-        if(NoLapseActive && lapse_test_csv < C0)
+        if(NoLapseActive && lapse_test_csv < 0_cents)
             {
-            AVGenAcct = C0;
-            AVSepAcct = C0;
+            AVGenAcct = 0_cents;
+            AVSepAcct = 0_cents;
             // TODO ?? Can't this be done elsewhere?
             VariantValues().CSVNet[Year] = 0.0;
             }
-        else if(!HoneymoonActive && !Solving && lapse_test_csv < C0)
+        else if(!HoneymoonActive && !Solving && lapse_test_csv < 0_cents)
             {
             alarum()
                 << "Unloaned value not positive,"
diff --git a/ihs_avsolve.cpp b/ihs_avsolve.cpp
index ed12df6..e5b19a2 100644
--- a/ihs_avsolve.cpp
+++ b/ihs_avsolve.cpp
@@ -185,7 +185,7 @@ currency AccountValue::SolveTest(currency a_CandidateValue)
         ,0
         );
     LMI_ASSERT(0 <= no_lapse_dur);
-    currency most_negative_csv = C0;
+    currency most_negative_csv = 0_cents;
     if(no_lapse_dur < SolveTargetDuration_)
         {
         // CURRENCY !! Cents in ledger will make rounding unnecessary.
@@ -230,7 +230,7 @@ currency AccountValue::SolveTest(currency a_CandidateValue)
             - VariantValues().AcctVal    [SolveTargetDuration_ - 1]
             );
         }
-    if(worst_negative < C0)
+    if(worst_negative < 0_cents)
         {
         value = std::min(value, worst_negative);
         }
@@ -296,7 +296,7 @@ currency AccountValue::SolveGuarPremium()
     // Store original er premiums for later restoration.
     std::vector<currency> stored = Outlay_->er_modal_premiums();
     // Zero out er premiums and solve for ee premiums only.
-    Outlay_->set_er_modal_premiums(C0, 0, BasicValues::GetLength());
+    Outlay_->set_er_modal_premiums(0_cents, 0, BasicValues::GetLength());
 
     bool temp_solving     = Solving;
     Solving               = true;
@@ -308,7 +308,7 @@ currency AccountValue::SolveGuarPremium()
         ,0
         ,BasicValues::GetLength()
         ,mce_solve_for_endt
-        ,C0
+        ,0_cents
         ,BasicValues::GetLength()
         ,mce_gen_guar
         ,mce_sep_full
diff --git a/ihs_avstrtgy.cpp b/ihs_avstrtgy.cpp
index 0fccc60..3097497 100644
--- a/ihs_avstrtgy.cpp
+++ b/ihs_avstrtgy.cpp
@@ -172,7 +172,7 @@ void AccountValue::PerformSupplAmtStrategy()
 {
     for(int j = 0; j < BasicValues::Length; ++j)
         {
-        currency m = C0; // No minimum other than zero is defined.
+        currency m = 0_cents; // No minimum other than zero is defined.
         currency explicit_value = DeathBfts_->supplamt()[j];
         mcenum_sa_strategy strategy = 
yare_input_.SupplementalAmountStrategy[j];
         currency z = CalculateSpecAmtFromStrategy(j, 0, explicit_value, 
strategy);
diff --git a/ihs_basicval.cpp b/ihs_basicval.cpp
index 4ec98fa..fb6201e 100644
--- a/ihs_basicval.cpp
+++ b/ihs_basicval.cpp
@@ -551,12 +551,12 @@ void BasicValues::SetPermanentInvariants()
     // Make sure database contents have no excess precision.
     LMI_ASSERT(round_gross_premium().c(TgtPremMonthlyPolFee) == 
TgtPremMonthlyPolFee);
     // Assertion: see comments on GetModalPremTgtFromTable().
-    LMI_ASSERT(C0 == TgtPremMonthlyPolFee || oe_modal_table == TgtPremType);
+    LMI_ASSERT(0_cents == TgtPremMonthlyPolFee || oe_modal_table == 
TgtPremType);
     database().query_into(DB_MinSinglePremiumType , MinSinglePremiumType);
     database().query_into(DB_MinSinglePremiumMult , MinSinglePremiumMult);
     database().query_into(DB_CurrCoiTable0Limit   , CurrCoiTable0Limit);
     database().query_into(DB_CurrCoiTable1Limit   , CurrCoiTable1Limit);
-    LMI_ASSERT(C0                 <= CurrCoiTable0Limit);
+    LMI_ASSERT(0_cents            <= CurrCoiTable0Limit);
     LMI_ASSERT(CurrCoiTable0Limit <= CurrCoiTable1Limit);
     // Make sure database contents have no excess precision.
     LMI_ASSERT(round_specamt().c(CurrCoiTable0Limit) == CurrCoiTable0Limit);
@@ -1198,7 +1198,7 @@ std::pair<double,double> BasicValues::approx_mly_ded_ex
     ,currency termamt
     ) const
 {
-    if(C0 != Loads_->annual_policy_fee(mce_gen_curr)[year])
+    if(0_cents != Loads_->annual_policy_fee(mce_gen_curr)[year])
         {
         return {0.0, 0.0};
         }
@@ -1526,7 +1526,7 @@ currency BasicValues::GetModalSpecAmtMlyDed(currency, 
mcenum_mode) const
         << "No maximum specified amount is defined for this product."
         << LMI_FLUSH
         ;
-    return C0;
+    return 0_cents;
 }
 
 /// 'Unusual' banding is one particular approach we needed to model.
diff --git a/solve.cpp b/solve.cpp
index 3216232..c82b7f9 100644
--- a/solve.cpp
+++ b/solve.cpp
@@ -83,7 +83,7 @@ currency SolveTest()
     //   CSV at target duration
     //   lowest negative CSV through target duration
     //   amount of loan in excess of maximum loan through target duration
-    currency Negative = C0;
+    currency Negative = 0_cents;
 
     // IHS !! Start counting only at end of no-lapse period--lmi does that 
already.
     for(int j = 0; j < ThatSolveTgtYear; ++j)
@@ -100,11 +100,11 @@ currency SolveTest()
 
     // CURRENCY !! Cents in ledger will make rounding unnecessary.
     currency z = 
round_to_cents.c(ConstThat->VariantValues().CSVNet[ThatSolveTgtYear - 1]);
-    if(Negative < C0)
+    if(Negative < 0_cents)
         z = std::min(z, Negative);
     // IHS !! If SolveTgtYr within no-lapse period...see lmi.
 
-    currency y = C0;
+    currency y = 0_cents;
     switch(ThatSolveTarget)
         {
         case mce_solve_for_endt:



reply via email to

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