[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master 026214c 4/8: Solve for currency rather than d
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master 026214c 4/8: Solve for currency rather than double |
Date: |
Tue, 26 Jan 2021 08:12:31 -0500 (EST) |
branch: master
commit 026214ceb6fff5affde0d4c7a341a0e9c2dfc6b9
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Solve for currency rather than double
---
ihs_avsolve.cpp | 61 ++++++++++++++++++++++++++++++++++-----------------------
solve.cpp | 41 +++++++++++++++++++++-----------------
2 files changed, 59 insertions(+), 43 deletions(-)
diff --git a/ihs_avsolve.cpp b/ihs_avsolve.cpp
index 3fb7c03..79cdb89 100644
--- a/ihs_avsolve.cpp
+++ b/ihs_avsolve.cpp
@@ -65,10 +65,11 @@ class SolveHelper
// so
// double function(double)
// is the appropriate signature here. Someday it might make sense
- // to modify decimal_root to work with currency types directly.
+ // to modify decimal_root to work with currency types directly,
+ // or at least to make this function take a 'currency' argument.
double operator()(double a_CandidateValue)
{
- return av.SolveTest(a_CandidateValue);
+ return dblize(av.SolveTest(av.round_minutiae().c(a_CandidateValue)));
}
};
@@ -184,30 +185,33 @@ currency AccountValue::SolveTest(currency
a_CandidateValue)
,0
);
LMI_ASSERT(0 <= no_lapse_dur);
- double most_negative_csv = 0.0;
+ currency most_negative_csv = C0;
if(no_lapse_dur < SolveTargetDuration_)
{
- most_negative_csv = *std::min_element
- (VariantValues().CSVNet.begin() + no_lapse_dur
- ,VariantValues().CSVNet.begin() + SolveTargetDuration_
+ // CURRENCY !! Cents in ledger will make rounding unnecessary.
+ most_negative_csv = round_minutiae().c
+ (*std::min_element
+ (VariantValues().CSVNet.begin() + no_lapse_dur
+ ,VariantValues().CSVNet.begin() + SolveTargetDuration_
+ )
);
}
// AccountValue::Solve() asserts that SolveTargetDuration_ lies
// within appropriate bounds.
- double greatest_loan_ullage = *std::max_element
+ currency greatest_loan_ullage = *std::max_element
(loan_ullage_.begin()
,loan_ullage_.begin() + SolveTargetDuration_
);
- double greatest_withdrawal_ullage = *std::max_element
+ currency greatest_withdrawal_ullage = *std::max_element
(withdrawal_ullage_.begin()
,withdrawal_ullage_.begin() + SolveTargetDuration_
);
- double greatest_ullage = std::max
+ currency greatest_ullage = std::max
(greatest_loan_ullage
,greatest_withdrawal_ullage
);
- double worst_negative = std::min
+ currency worst_negative = std::min
(most_negative_csv
,-greatest_ullage
);
@@ -215,15 +219,18 @@ currency AccountValue::SolveTest(currency
a_CandidateValue)
// SolveTargetDuration_ is in origin one. That's natural for loop
// counters and iterators--it's one past the end--but indexing
// must decrement it.
- double value = VariantValues().CSVNet[SolveTargetDuration_ - 1];
+ // CURRENCY !! Cents in ledger will make rounding unnecessary.
+ currency value =
round_minutiae().c(VariantValues().CSVNet[SolveTargetDuration_ - 1]);
if(mce_solve_for_target_naar == SolveTarget_)
{
- value =
+ // CURRENCY !! Cents in ledger will make rounding unnecessary.
+ value = round_minutiae().c
+ (
VariantValues().EOYDeathBft[SolveTargetDuration_ - 1]
- VariantValues().AcctVal [SolveTargetDuration_ - 1]
- ;
+ );
}
- if(worst_negative < 0.0)
+ if(worst_negative < C0)
{
value = std::min(value, worst_negative);
}
@@ -242,7 +249,8 @@ currency AccountValue::SolveTest(currency a_CandidateValue)
if(mce_solve_for_non_mec == SolveTarget_)
{
- return InvariantValues().IsMec ? -1.0 : 1.0;
+ static const currency C100 = from_cents(100); // one dollar
+ return InvariantValues().IsMec ? -C100 : C100;
}
return value - SolveTargetCsv_;
@@ -287,21 +295,21 @@ void AccountValue::SolveSetWD(currency a_CandidateValue)
currency AccountValue::SolveGuarPremium()
{
// Store original er premiums for later restoration.
- std::vector<double> stored = Outlay_->er_modal_premiums();
+ std::vector<currency> stored = Outlay_->er_modal_premiums();
// Zero out er premiums and solve for ee premiums only.
- Outlay_->set_er_modal_premiums(0.0, 0, BasicValues::GetLength());
+ Outlay_->set_er_modal_premiums(C0, 0, BasicValues::GetLength());
bool temp_solving = Solving;
Solving = true;
SolvingForGuarPremium = true;
// Run the solve using guaranteed assumptions.
- double guar_premium = Solve
+ currency guar_premium = Solve
(mce_solve_ee_prem
,0
,BasicValues::GetLength()
,mce_solve_for_endt
- ,0.0
+ ,C0
,BasicValues::GetLength()
,mce_gen_guar
,mce_sep_full
@@ -369,10 +377,12 @@ currency AccountValue::Solve
// Generally, base and term are independent, and it is
// the base specamt that's being solved for here, so set
// the minimum as though there were no term.
- lower_bound = minimum_specified_amount
- ( 0 == SolveBeginYear_
- && yare_input_.EffectiveDate == yare_input_.InforceAsOfDate
- ,false
+ lower_bound = dblize
+ (minimum_specified_amount
+ ( 0 == SolveBeginYear_
+ && yare_input_.EffectiveDate == yare_input_.InforceAsOfDate
+ ,false
+ )
);
}
break;
@@ -453,6 +463,7 @@ currency AccountValue::Solve
// are stored now, and values are regenerated downstream.
Solving = false;
- (this->*solve_set_fn)(solution.first);
- return solution.first;
+ currency const solution_cents = round_minutiae().c(solution.first);
+ (this->*solve_set_fn)(solution_cents);
+ return solution_cents;
}
diff --git a/solve.cpp b/solve.cpp
index 89023b6..3216232 100644
--- a/solve.cpp
+++ b/solve.cpp
@@ -30,6 +30,7 @@
#include "ledger_variant.hpp"
#include "mc_enum_types_aux.hpp" // set_run_basis_from_cloven_bases()
#include "outlay.hpp"
+#include "round_to.hpp"
#include "zero.hpp"
#include <algorithm> // max(), min()
@@ -57,6 +58,8 @@ namespace
int ThatSolveEndYear;
mcenum_gen_basis ThatSolveBasis;
bool only_set_values;
+
+ round_to<double> const round_to_cents(2, r_to_nearest);
} // Unnamed namespace.
//============================================================================
@@ -80,26 +83,28 @@ currency SolveTest()
// CSV at target duration
// lowest negative CSV through target duration
// amount of loan in excess of maximum loan through target duration
- double Negative = 0.0;
+ currency Negative = C0;
// IHS !! Start counting only at end of no-lapse period--lmi does that
already.
for(int j = 0; j < ThatSolveTgtYear; ++j)
{
Negative = std::min
(Negative
- ,ConstThat->VariantValues().CSVNet[j]
+ // CURRENCY !! Cents in ledger will make rounding unnecessary.
+ ,round_to_cents.c(ConstThat->VariantValues().CSVNet[j])
// Ideally, it'd be this:
// ,std::min(ConstThat->VariantValues().CSVNet[j],
ConstThat->loan_ullage_[j])
// but the antediluvian branch doesn't calculate ullage at all.
);
}
- double z = ConstThat->VariantValues().CSVNet[ThatSolveTgtYear - 1];
- if(Negative < 0.0)
+ // CURRENCY !! Cents in ledger will make rounding unnecessary.
+ currency z =
round_to_cents.c(ConstThat->VariantValues().CSVNet[ThatSolveTgtYear - 1]);
+ if(Negative < C0)
z = std::min(z, Negative);
// IHS !! If SolveTgtYr within no-lapse period...see lmi.
- double y = 0.0;
+ currency y = C0;
switch(ThatSolveTarget)
{
case mce_solve_for_endt:
@@ -134,7 +139,7 @@ currency SolveTest()
break;
case mce_solve_for_target_csv:
{
- y = ThatSolveTargetValue;
+ y = round_to_cents.c(ThatSolveTargetValue);
}
break;
case mce_solve_for_target_naar: // Fall through.
@@ -154,29 +159,29 @@ currency SolveTest()
inline static double SolveSpecAmt(double CandidateValue)
{
// IHS !! Change surrchg when SA changes?
- That->SolveSetSpecAmt(CandidateValue, ThatSolveBegYear, ThatSolveEndYear);
- return only_set_values ? 0.0 : SolveTest();
+ That->SolveSetSpecAmt(round_to_cents.c(CandidateValue), ThatSolveBegYear,
ThatSolveEndYear);
+ return only_set_values ? 0.0 : dblize(SolveTest());
}
//============================================================================
inline static double SolvePrem(double CandidateValue)
{
- That->SolveSetPmts(CandidateValue, ThatSolveBegYear, ThatSolveEndYear);
- return only_set_values ? 0.0 : SolveTest();
+ That->SolveSetPmts(round_to_cents.c(CandidateValue), ThatSolveBegYear,
ThatSolveEndYear);
+ return only_set_values ? 0.0 : dblize(SolveTest());
}
//============================================================================
inline static double SolveLoan(double CandidateValue)
{
- That->SolveSetLoans(CandidateValue, ThatSolveBegYear, ThatSolveEndYear);
- return only_set_values ? 0.0 : SolveTest();
+ That->SolveSetLoans(round_to_cents.c(CandidateValue), ThatSolveBegYear,
ThatSolveEndYear);
+ return only_set_values ? 0.0 : dblize(SolveTest());
}
//============================================================================
inline static double SolveWD(double CandidateValue)
{
- That->SolveSetWDs(CandidateValue, ThatSolveBegYear, ThatSolveEndYear);
- return only_set_values ? 0.0 : SolveTest();
+ That->SolveSetWDs(round_to_cents.c(CandidateValue), ThatSolveBegYear,
ThatSolveEndYear);
+ return only_set_values ? 0.0 : dblize(SolveTest());
}
//============================================================================
@@ -279,7 +284,7 @@ currency AccountValue::Solve()
LowerBound = 0.0;
// If solved premium exceeds specified amount, there's a problem.
// IHS !! Better to use the maximum SA, not the first SA?
- UpperBound = DeathBfts_->specamt()[0];
+ UpperBound = dblize(DeathBfts_->specamt()[0]);
Decimals = 2;
SolveFn = SolvePrem;
}
@@ -347,8 +352,8 @@ currency AccountValue::Solve()
// generate or analyze account values. This global variable is a
// kludge, but so is 'That'; a function object is wanted instead.
only_set_values = !Solving;
- double actual_solution = Solution.first;
- SolveFn(actual_solution);
- return actual_solution;
+ currency const solution_cents = round_to_cents.c(Solution.first);
+ SolveFn(dblize(solution_cents));
+ return solution_cents;
}
- [lmi-commits] [lmi] master updated (15ef269 -> 7066049), Greg Chicares, 2021/01/26
- [lmi-commits] [lmi] master 557ac6e 3/8: Assert rather than assign, Greg Chicares, 2021/01/26
- [lmi-commits] [lmi] master 026214c 4/8: Solve for currency rather than double,
Greg Chicares <=
- [lmi-commits] [lmi] master 62b80c4 7/8: Initialize honeymoon value as currency, not double, Greg Chicares, 2021/01/26
- [lmi-commits] [lmi] master 0b4b7ec 1/8: Don't use currency for amounts always converted to double, Greg Chicares, 2021/01/26
- [lmi-commits] [lmi] master 01886b2 5/8: Round CSV "boost", Greg Chicares, 2021/01/26
- [lmi-commits] [lmi] master e507882 6/8: Remove a useless assertion, Greg Chicares, 2021/01/26
- [lmi-commits] [lmi] master 7066049 8/8: Record speed measurements, Greg Chicares, 2021/01/26
- [lmi-commits] [lmi] master e7ab330 2/8: Store currency as such, Greg Chicares, 2021/01/26