[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [5777] Implement special commutation functions for GPT
From: |
Greg Chicares |
Subject: |
[lmi-commits] [5777] Implement special commutation functions for GPT |
Date: |
Mon, 30 Sep 2013 21:19:16 +0000 |
Revision: 5777
http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=5777
Author: chicares
Date: 2013-09-30 21:19:16 +0000 (Mon, 30 Sep 2013)
Log Message:
-----------
Implement special commutation functions for GPT
Modified Paths:
--------------
lmi/trunk/ChangeLog
lmi/trunk/gpt_commutation_functions.hpp
Added Paths:
-----------
lmi/trunk/gpt_commutation_functions.cpp
Modified: lmi/trunk/ChangeLog
===================================================================
--- lmi/trunk/ChangeLog 2013-09-30 20:51:19 UTC (rev 5776)
+++ lmi/trunk/ChangeLog 2013-09-30 21:19:16 UTC (rev 5777)
@@ -32584,3 +32584,29 @@
gpt_commutation_functions.hpp
Refactor.
+20130930T2042Z <address@hidden> [542]
+
+ mc_enum_types.xpp
+Improve documentation.
+
+20130930T2043Z <address@hidden> [542]
+
+ oecumenic_enumerations.hpp
+Add an enumerator for GPT use.
+
+20130930T2044Z <address@hidden> [542]
+
+ gpt_commutation_functions.hpp
+Rename classes and members.
+
+20130930T2051Z <address@hidden> [542]
+
+ gpt_commutation_functions.hpp
+Improve documentation.
+
+20130930T2119Z <address@hidden> [542]
+
+ gpt_commutation_functions.cpp [new file]
+ gpt_commutation_functions.hpp
+Implement special commutation functions for GPT.
+
Added: lmi/trunk/gpt_commutation_functions.cpp
===================================================================
--- lmi/trunk/gpt_commutation_functions.cpp (rev 0)
+++ lmi/trunk/gpt_commutation_functions.cpp 2013-09-30 21:19:16 UTC (rev
5777)
@@ -0,0 +1,192 @@
+// Internal Revenue Code section 7702: GPT commutation functions.
+//
+// Copyright (C) 2013 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+# include "pchfile.hpp"
+# pragma hdrstop
+#endif // __BORLANDC__
+
+#include "gpt_commutation_functions.hpp"
+
+#include "assert_lmi.hpp"
+#include "commutation_functions.hpp"
+#include "et_vector.hpp"
+
+#include <numeric> // std::partial_sum()
+#include <stdexcept>
+
+namespace
+{
+/// Backward sum of a PETE expression.
+///
+/// PETE provides only what APL calls "primitive scalar functions",
+/// which apply to each element or pair of elements. This function
+/// performs the equivalent of APL "rotate plus scan rotate". It
+/// would be nice to extend PETE along these lines, but that's too
+/// ambitious for now; apparently Mullin's 'psi calculus' does
+/// exactly that, but the code is unpublished.
+
+template<typename T, typename E>
+std::vector<T>& back_sum(std::vector<T>& vt, E e)
+{
+ assign(vt, e);
+ std::partial_sum(vt.rbegin(), vt.rend(), vt.rbegin());
+ return vt;
+}
+} // Unnamed namespace.
+
+/// Constructor.
+///
+/// All vectors, including those in the parameter object, must have
+/// the same length. It may at first appear that assertions to this
+/// effect belong upstream; however, writing them in the body of
+/// gpt_cf_triad::gpt_cf_triad() would cause them to be executed
+/// after the present ctor is called.
+
+gpt_commfns::gpt_commfns
+ (std::vector<double> const& qc
+ ,std::vector<double> const& ic
+ ,std::vector<double> const& ig
+ ,mcenum_dbopt_7702 const dbo
+ ,gpt_vector_parms const& charges
+ )
+ :length_ (qc.size())
+ ,M_ (length_)
+ ,D_endt_ (0.0)
+ ,D_net_tgt_ (length_)
+ ,D_net_exc_ (length_)
+ ,N_net_tgt_ (length_)
+ ,N_net_exc_ (length_)
+ ,N_chg_pol_ (length_)
+ ,N_chg_sa_ (length_)
+ ,N_qab_gio_ (length_)
+ ,N_qab_adb_ (length_)
+ ,N_qab_term_ (length_)
+ ,N_qab_spouse_ (length_)
+ ,N_qab_child_ (length_)
+ ,N_qab_waiver_ (length_)
+{
+ LMI_ASSERT(length_ == qc .size());
+ LMI_ASSERT(length_ == ic .size());
+ LMI_ASSERT(length_ == ig .size());
+ LMI_ASSERT(length_ == charges.prem_load_target .size());
+ LMI_ASSERT(length_ == charges.prem_load_excess .size());
+ LMI_ASSERT(length_ == charges.policy_fee_monthly .size());
+ LMI_ASSERT(length_ == charges.policy_fee_annual .size());
+ LMI_ASSERT(length_ == charges.specamt_load_monthly.size());
+ LMI_ASSERT(length_ == charges.qab_gio_rate .size());
+ LMI_ASSERT(length_ == charges.qab_adb_rate .size());
+ LMI_ASSERT(length_ == charges.qab_term_rate .size());
+ LMI_ASSERT(length_ == charges.qab_spouse_rate .size());
+ LMI_ASSERT(length_ == charges.qab_child_rate .size());
+ LMI_ASSERT(length_ == charges.qab_waiver_rate .size());
+
+ ULCommFns const cf(qc, ic, ig, dbo, mce_monthly);
+
+ M_ = cf.kM();
+ D_endt_ = cf.aDomega();
+ assign (D_net_tgt_ , cf.aD() * (1.0 - charges.prem_load_target));
+ assign (D_net_exc_ , cf.aD() * (1.0 - charges.prem_load_excess));
+ back_sum(N_net_tgt_ , cf.aD() * (1.0 - charges.prem_load_target));
+ back_sum(N_net_exc_ , cf.aD() * (1.0 - charges.prem_load_excess));
+ back_sum(N_chg_pol_ , cf.aD() * charges.policy_fee_annual
+ + cf.kD() * charges.policy_fee_monthly);
+ back_sum(N_chg_sa_ , cf.kD() * charges.specamt_load_monthly);
+ back_sum(N_qab_gio_ , cf.kD() * charges.qab_gio_rate);
+ back_sum(N_qab_adb_ , cf.kD() * charges.qab_adb_rate);
+ back_sum(N_qab_term_ , cf.kD() * charges.qab_term_rate);
+ back_sum(N_qab_spouse_, cf.kD() * charges.qab_spouse_rate);
+ back_sum(N_qab_child_ , cf.kD() * charges.qab_child_rate);
+ back_sum(N_qab_waiver_, cf.kD() * charges.qab_waiver_rate);
+}
+
+gpt_commfns::~gpt_commfns()
+{}
+
+/// Calculate GLP or GSP.
+
+double gpt_commfns::calculate_premium
+ (oenum_glp_or_gsp glp_or_gsp
+ ,gpt_scalar_parms const& args
+ ) const
+{
+ double endowment = D_endt_ * args.endt_bft;
+ double charges =
+ M_ [args.duration] * args.f3bft
+ + N_chg_pol_ [args.duration]
+ + N_chg_sa_ [args.duration] * args.chg_sa_amt
+ + N_qab_gio_ [args.duration] * args.qab_gio_amt
+ + N_qab_adb_ [args.duration] * args.qab_adb_amt
+ + N_qab_term_ [args.duration] * args.qab_term_amt
+ + N_qab_spouse_[args.duration] * args.qab_spouse_amt
+ + N_qab_child_ [args.duration] * args.qab_child_amt
+ + N_qab_waiver_[args.duration] * args.qab_waiver_amt
+ ;
+ double den_tgt = (glp_or_gsp ? D_net_tgt_ : N_net_tgt_)[args.duration];
+ double den_exc = (glp_or_gsp ? D_net_exc_ : N_net_exc_)[args.duration];
+ double z = (endowment + charges) / den_tgt;
+ if(z <= args.target)
+ {
+ return z;
+ }
+
+ charges += args.target * (den_exc - den_tgt);
+ return (endowment + charges) / den_exc;
+}
+
+gpt_cf_triad::gpt_cf_triad
+ (std::vector<double> const& qc
+ ,std::vector<double> const& glp_ic
+ ,std::vector<double> const& glp_ig
+ ,std::vector<double> const& gsp_ic
+ ,std::vector<double> const& gsp_ig
+ ,gpt_vector_parms const& charges
+ )
+ :cf_glp_dbo_1(qc, glp_ic, glp_ig, mce_option1_for_7702, charges)
+ ,cf_glp_dbo_2(qc, glp_ic, glp_ig, mce_option2_for_7702, charges)
+ ,cf_gsp (qc, gsp_ic, gsp_ig, mce_option1_for_7702, charges)
+{
+}
+
+gpt_cf_triad::~gpt_cf_triad()
+{}
+
+/// Calculate GLP or GSP.
+///
+/// For GSP, 'dbo' is disregarded.
+
+double gpt_cf_triad::calculate_premium
+ (oenum_glp_or_gsp glp_or_gsp
+ ,mcenum_dbopt_7702 dbo
+ ,gpt_scalar_parms const& args
+ ) const
+{
+ gpt_commfns const& cf =
+ (oe_glp == glp_or_gsp && mce_option1_for_7702 == dbo) ? cf_glp_dbo_1
+ : (oe_glp == glp_or_gsp && mce_option2_for_7702 == dbo) ? cf_glp_dbo_2
+ : (oe_gsp == glp_or_gsp ) ? cf_gsp
+ : throw std::runtime_error("Cannot determine GPT assumptions.")
+ ;
+ return cf.calculate_premium(glp_or_gsp, args);
+}
+
Property changes on: lmi/trunk/gpt_commutation_functions.cpp
___________________________________________________________________
Added: svn:keywords
+ Id
Modified: lmi/trunk/gpt_commutation_functions.hpp
===================================================================
--- lmi/trunk/gpt_commutation_functions.hpp 2013-09-30 20:51:19 UTC (rev
5776)
+++ lmi/trunk/gpt_commutation_functions.hpp 2013-09-30 21:19:16 UTC (rev
5777)
@@ -27,6 +27,7 @@
#include "config.hpp"
#include "mc_enum_type_enums.hpp" // mcenum_dbopt_7702
+#include "oecumenic_enumerations.hpp" // oenum_glp_or_gsp
#include <vector>
@@ -59,8 +60,39 @@
std::vector<double> qab_waiver_rate ;
};
+/// Arguments used identically for calculating both GLP and GSP.
+///
+/// The 'oenum_glp_or_gsp' argument is excluded here because it
+/// differs between GLP and GSP. The 'mcenum_dbopt_7702' argument
+/// is excluded here because it's irrelevant for GSP.
+///
+/// 'chg_sa_amt' is the base for any specified-amount load. It may
+/// differ from 'specamt', e.g., by being limited to a scalar maximum,
+/// by including a term amount, or by being set immutably at issue.
+
+struct gpt_scalar_parms
+{
+ int duration ;
+ double target ;
+ double f3bft ;
+ double endt_bft ;
+ double chg_sa_amt ;
+ double qab_gio_amt ;
+ double qab_adb_amt ;
+ double qab_term_amt ;
+ double qab_spouse_amt ;
+ double qab_child_amt ;
+ double qab_waiver_amt ;
+};
+
/// Commutation functions specialized for GPT calculations.
///
+/// All members are private: only its one friend can use this class.
+/// It could have been written as a nested class enclosed in that
+/// friend, but that would have given it access to the friend's
+/// private members, without protecting it better against accidental
+/// (mis)use.
+///
/// See section 14.3 here:
/// http://www.nongnu.org/lmi/7702.html
///
@@ -89,13 +121,18 @@
/// any QAB that is not offered or not elected, or that the insurer
/// chooses not to treat as a QAB.
///
+/// Data member 'length_' is a dispensable convenience that makes
+/// initialization and precondition checks a little clearer.
+///
/// Implicitly-declared special member functions do the right thing.
class gpt_commfns
{
+ friend class gpt_cf_triad;
+
+ private:
gpt_commfns
- (unsigned int const length
- ,std::vector<double> const& qc
+ (std::vector<double> const& qc
,std::vector<double> const& ic
,std::vector<double> const& ig
,mcenum_dbopt_7702 const dbo
@@ -103,6 +140,9 @@
);
~gpt_commfns();
+ double calculate_premium(oenum_glp_or_gsp, gpt_scalar_parms const&) const;
+
+ unsigned int const length_;
std::vector<double> M_;
double D_endt_;
std::vector<double> D_net_tgt_;
@@ -119,5 +159,34 @@
std::vector<double> N_qab_waiver_;
};
+/// Specialized GPT commutation functions on the three required bases.
+///
+/// Implicitly-declared special member functions do the right thing.
+
+class gpt_cf_triad
+{
+ public:
+ gpt_cf_triad
+ (std::vector<double> const& qc
+ ,std::vector<double> const& glp_ic
+ ,std::vector<double> const& glp_ig
+ ,std::vector<double> const& gsp_ic
+ ,std::vector<double> const& gsp_ig
+ ,gpt_vector_parms const& charges
+ );
+ ~gpt_cf_triad();
+
+ double calculate_premium
+ (oenum_glp_or_gsp
+ ,mcenum_dbopt_7702
+ ,gpt_scalar_parms const&
+ ) const;
+
+ private:
+ gpt_commfns cf_glp_dbo_1;
+ gpt_commfns cf_glp_dbo_2;
+ gpt_commfns cf_gsp;
+};
+
#endif // gpt_commutation_functions_hpp
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lmi-commits] [5777] Implement special commutation functions for GPT,
Greg Chicares <=