lmi
[Top][All Lists]
Advanced

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

[lmi] [PATCH 1/4] multi-dimensional tables


From: Vaclav Slavik
Subject: [lmi] [PATCH 1/4] multi-dimensional tables
Date: Thu, 02 Aug 2012 14:32:17 +0200
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:14.0) Gecko/20120713 Thunderbird/14.0

Hi,

this series of patches implements reading of multi-dimensional (i.e.
> 2D, with gender or smoking axes, as already described in the RNC
schema) actuarial tables.

I split the change into smaller pieces for easier reviewing: the first 3
of them are just some tedious refactoring and the real changes would
easily drown in the noise.

Note that they break so_stress_test due to removal of access to some
metadata that was never used anywhere else.


Still missing:

* Actually using this capability. Up until now, things remain API
  compatible and files in the .xtable format can be used in place of the
  SOA ones. The next step would be to start using multi-dim API in
  parallel with the current code to test. I think it would be prudent to
  first incorporate all the pending patches before continuing further.

* One smoking and gender axes are implemented, both in the format and
  the API. The remaining ones from database_index should be added, but I
  didn't want to spend time on it until I have some feedback on the API
  (or the file format, if you have reservations).


This 1st patch removes the actuarial_table_base class, at the cost of
duplicating some code. We'll eventually remove soa_actuarial_table
anyway, so I don't think it matters, and it would only complicate things
as the two implementations diverge further.

Regards,
Vaclav


---
 actuarial_table.cpp | 258 ++++++++++++++++++++++++++++++++++------------------
 actuarial_table.hpp |  82 +++++++++--------
 2 files changed, 214 insertions(+), 126 deletions(-)

diff --git a/actuarial_table.cpp b/actuarial_table.cpp
index 779f91b..3fd7d3b 100644
--- a/actuarial_table.cpp
+++ b/actuarial_table.cpp
@@ -90,104 +90,22 @@ namespace
     }
 } // Unnamed namespace.
 
-actuarial_table_base::actuarial_table_base()
+xml_actuarial_table::xml_actuarial_table(std::string const& filename)
     :table_type_     (e_table_invalid)
     ,min_age_        (-1)
     ,max_age_        (-1)
     ,select_period_  (-1)
     ,max_select_age_ (-1)
 {
-}
-
-actuarial_table_base::~actuarial_table_base()
-{
-}
-
-/// Read a given number of values for a given issue age.
-
-std::vector<double> actuarial_table_base::values(int issue_age, int length) 
const
-{
-    return specific_values(issue_age, length);
-}
-
-/// Read a given number of values for a given issue age, using a
-/// nondefault lookup method.
-///
-/// Assertions require that arguments be sane on entry, regardless of
-/// method: method-specific adjustments are not permitted to render
-/// sane what was insane ab ovo.
-
-std::vector<double> actuarial_table_base::values_elaborated
-    (int                      issue_age
-    ,int                      length
-    ,e_actuarial_table_method method
-    ,int                      inforce_duration
-    ,int                      reset_duration
-    ) const
-{
-    LMI_ASSERT(min_age_ <= issue_age && issue_age <= max_age_);
-    LMI_ASSERT(0 <= length && length <= 1 + max_age_ - issue_age);
-    LMI_ASSERT(0 <= inforce_duration);
-    LMI_ASSERT(inforce_duration < 1 + max_age_ - issue_age);
-    LMI_ASSERT(reset_duration <= inforce_duration);
-
-    if('S' != table_type_)
-        {
-        return specific_values(issue_age, length);
-        }
-
-    switch(method)
-        {
-        case e_reenter_at_inforce_duration:
-            {
-            int const delta = inforce_duration;
-            std::vector<double> v = specific_values
-                (issue_age + delta
-                ,length    - delta
-                );
-            v.insert(v.begin(), delta, 0.0);
-            return v;
-            }
-            // break;
-        case e_reenter_upon_rate_reset:
-            {
-            int const age_setback_limit = issue_age - min_age_;
-            int const delta = std::max(reset_duration, -age_setback_limit);
-            std::vector<double> v = specific_values
-                (issue_age + delta
-                ,length    - delta
-                );
-            if(delta < 0)
-                {
-                v.erase(v.begin(), v.begin() - delta);
-                }
-            else
-                {
-                v.insert(v.begin(), delta, 0.0);
-                }
-            return v;
-            }
-            // break;
-        case e_reenter_never: // Fall through.
-        default:
-            {
-            fatal_error()
-                << "Table-lookup method "
-                << method
-                << " is not valid in this context."
-                << LMI_FLUSH
-                ;
-            throw "Unreachable--silences a compiler diagnostic.";
-            }
-        }
-}
-
-xml_actuarial_table::xml_actuarial_table(std::string const& filename)
-{
     load_xml_table(filename);
 }
 
 xml_actuarial_table::xml_actuarial_table(std::string const& filename, int 
table_number)
+    :table_type_     (e_table_invalid)
+    ,min_age_        (-1)
+    ,max_age_        (-1)
+    ,select_period_  (-1)
+    ,max_select_age_ (-1)
 {
     // SOA !! This is temporary code for API compatibility with 
soa_actuarial_table.
     // It should be changed so that the constructor takes only a single
@@ -512,10 +430,95 @@ std::vector<double> xml_actuarial_table::specific_values
     return v;
 }
 
+/// Read a given number of values for a given issue age.
+
+std::vector<double> xml_actuarial_table::values(int issue_age, int length) 
const
+{
+    return specific_values(issue_age, length);
+}
+
+/// Read a given number of values for a given issue age, using a
+/// nondefault lookup method.
+///
+/// Assertions require that arguments be sane on entry, regardless of
+/// method: method-specific adjustments are not permitted to render
+/// sane what was insane ab ovo.
+
+std::vector<double> xml_actuarial_table::values_elaborated
+    (int                      issue_age
+    ,int                      length
+    ,e_actuarial_table_method method
+    ,int                      inforce_duration
+    ,int                      reset_duration
+    ) const
+{
+    LMI_ASSERT(min_age_ <= issue_age && issue_age <= max_age_);
+    LMI_ASSERT(0 <= length && length <= 1 + max_age_ - issue_age);
+    LMI_ASSERT(0 <= inforce_duration);
+    LMI_ASSERT(inforce_duration < 1 + max_age_ - issue_age);
+    LMI_ASSERT(reset_duration <= inforce_duration);
+
+    if('S' != table_type_)
+        {
+        return specific_values(issue_age, length);
+        }
+
+    switch(method)
+        {
+        case e_reenter_at_inforce_duration:
+            {
+            int const delta = inforce_duration;
+            std::vector<double> v = specific_values
+                (issue_age + delta
+                ,length    - delta
+                );
+            v.insert(v.begin(), delta, 0.0);
+            return v;
+            }
+            // break;
+        case e_reenter_upon_rate_reset:
+            {
+            int const age_setback_limit = issue_age - min_age_;
+            int const delta = std::max(reset_duration, -age_setback_limit);
+            std::vector<double> v = specific_values
+                (issue_age + delta
+                ,length    - delta
+                );
+            if(delta < 0)
+                {
+                v.erase(v.begin(), v.begin() - delta);
+                }
+            else
+                {
+                v.insert(v.begin(), delta, 0.0);
+                }
+            return v;
+            }
+            // break;
+        case e_reenter_never: // Fall through.
+        default:
+            {
+            fatal_error()
+                << "Table-lookup method "
+                << method
+                << " is not valid in this context."
+                << LMI_FLUSH
+                ;
+            throw "Unreachable--silences a compiler diagnostic.";
+            }
+        }
+}
+
 soa_actuarial_table::soa_actuarial_table(std::string const& filename, int 
table_number)
     :filename_       (filename)
     ,table_number_   (table_number)
     ,table_offset_   (-1)
+    ,table_type_     (e_table_invalid)
+    ,min_age_        (-1)
+    ,max_age_        (-1)
+    ,select_period_  (-1)
+    ,max_select_age_ (-1)
+
 {
     if(table_number_ <= 0)
         {
@@ -921,6 +924,85 @@ std::vector<double> soa_actuarial_table::specific_values
     return v;
 }
 
+/// Read a given number of values for a given issue age.
+
+std::vector<double> soa_actuarial_table::values(int issue_age, int length) 
const
+{
+    return specific_values(issue_age, length);
+}
+
+/// Read a given number of values for a given issue age, using a
+/// nondefault lookup method.
+///
+/// Assertions require that arguments be sane on entry, regardless of
+/// method: method-specific adjustments are not permitted to render
+/// sane what was insane ab ovo.
+
+std::vector<double> soa_actuarial_table::values_elaborated
+    (int                      issue_age
+    ,int                      length
+    ,e_actuarial_table_method method
+    ,int                      inforce_duration
+    ,int                      reset_duration
+    ) const
+{
+    LMI_ASSERT(min_age_ <= issue_age && issue_age <= max_age_);
+    LMI_ASSERT(0 <= length && length <= 1 + max_age_ - issue_age);
+    LMI_ASSERT(0 <= inforce_duration);
+    LMI_ASSERT(inforce_duration < 1 + max_age_ - issue_age);
+    LMI_ASSERT(reset_duration <= inforce_duration);
+
+    if('S' != table_type_)
+        {
+        return specific_values(issue_age, length);
+        }
+
+    switch(method)
+        {
+        case e_reenter_at_inforce_duration:
+            {
+            int const delta = inforce_duration;
+            std::vector<double> v = specific_values
+                (issue_age + delta
+                ,length    - delta
+                );
+            v.insert(v.begin(), delta, 0.0);
+            return v;
+            }
+            // break;
+        case e_reenter_upon_rate_reset:
+            {
+            int const age_setback_limit = issue_age - min_age_;
+            int const delta = std::max(reset_duration, -age_setback_limit);
+            std::vector<double> v = specific_values
+                (issue_age + delta
+                ,length    - delta
+                );
+            if(delta < 0)
+                {
+                v.erase(v.begin(), v.begin() - delta);
+                }
+            else
+                {
+                v.insert(v.begin(), delta, 0.0);
+                }
+            return v;
+            }
+            // break;
+        case e_reenter_never: // Fall through.
+        default:
+            {
+            fatal_error()
+                << "Table-lookup method "
+                << method
+                << " is not valid in this context."
+                << LMI_FLUSH
+                ;
+            throw "Unreachable--silences a compiler diagnostic.";
+            }
+        }
+}
+
 namespace
 {
     bool almost_equal_doubles(std::vector<double> const& a, 
std::vector<double> const& b)
diff --git a/actuarial_table.hpp b/actuarial_table.hpp
index 044aa10..53f699c 100644
--- a/actuarial_table.hpp
+++ b/actuarial_table.hpp
@@ -126,15 +126,23 @@ enum e_table_type
     ,e_table_select_and_ultimate   = 'S'
     };
 
-/// Base class for actuarial tables, both XML and binary.
-/// SOA !! This is only temporary, merge with xml_actuarial_table into
-/// single class once we remove binary SOA format support
+/// Read actuarial table from XML file.
 
-class actuarial_table_base
+class xml_actuarial_table
+    :        private lmi::uncopyable<xml_actuarial_table>
+    ,        public  loaded_from_cache<xml_actuarial_table>
+    ,virtual private obstruct_slicing<xml_actuarial_table>
 {
   public:
-    actuarial_table_base();
-    virtual ~actuarial_table_base();
+    xml_actuarial_table(std::string const& filename);
+    xml_actuarial_table(std::string const& filename, int table_number);
+    virtual ~xml_actuarial_table();
+
+    // SOA !! This is temporary code for API compatibility with 
soa_actuarial_table.
+    static std::string compatibility_filename
+        (std::string const& filename
+        ,int table_number
+        );
 
     std::vector<double> values(int issue_age, int length) const;
     std::vector<double> values_elaborated
@@ -152,36 +160,6 @@ class actuarial_table_base
     int                max_select_age () const {return max_select_age_ ;}
 
   protected:
-    virtual std::vector<double> specific_values(int issue_age, int length) 
const = 0;
-
-    // Table parameters, in order read from table header.
-    char table_type_     ;
-    int  min_age_        ;
-    int  max_age_        ;
-    int  select_period_  ;
-    int  max_select_age_ ;
-};
-
-/// Read actuarial table from XML file.
-
-class xml_actuarial_table
-    :        public  actuarial_table_base
-    ,        private lmi::uncopyable <xml_actuarial_table>
-    ,        public  loaded_from_cache<xml_actuarial_table>
-    ,virtual private obstruct_slicing<xml_actuarial_table>
-{
-  public:
-    xml_actuarial_table(std::string const& filename);
-    xml_actuarial_table(std::string const& filename, int table_number);
-    virtual ~xml_actuarial_table();
-
-    // SOA !! This is temporary code for API compatibility with 
soa_actuarial_table.
-    static std::string compatibility_filename
-        (std::string const& filename
-        ,int table_number
-        );
-
-  protected:
     std::vector<double> specific_values(int issue_age, int length) const;
 
   private:
@@ -197,6 +175,13 @@ class xml_actuarial_table
         ,int& max_age
         );
 
+    // Table parameters, in order read from table header.
+    char table_type_     ;
+    int  min_age_        ;
+    int  max_age_        ;
+    int  select_period_  ;
+    int  max_select_age_ ;
+
     // Table data. For 1D tables (e_table_aggregate and e_table_duration), this
     // is the vector of values from min_age_ to max_age_.
     // For e_table_select_and_ultimate, the content is organized by rows, with
@@ -230,8 +215,7 @@ class xml_actuarial_table
 /// compatibility.
 
 class soa_actuarial_table
-    :        public  actuarial_table_base
-    ,        private lmi::uncopyable <soa_actuarial_table>
+    :        private lmi::uncopyable <soa_actuarial_table>
     ,virtual private obstruct_slicing<soa_actuarial_table>
 {
   public:
@@ -240,6 +224,21 @@ class soa_actuarial_table
 
     std::string const& filename       () const {return filename_       ;}
 
+    std::vector<double> values(int issue_age, int length) const;
+    std::vector<double> values_elaborated
+        (int                      issue_age
+        ,int                      length
+        ,e_actuarial_table_method method
+        ,int                      inforce_duration
+        ,int                      reset_duration
+        ) const;
+
+    char               table_type     () const {return table_type_     ;}
+    int                min_age        () const {return min_age_        ;}
+    int                max_age        () const {return max_age_        ;}
+    int                select_period  () const {return select_period_  ;}
+    int                max_select_age () const {return max_select_age_ ;}
+
   private:
     void find_table();
     void parse_table();
@@ -250,6 +249,13 @@ class soa_actuarial_table
     std::string filename_     ;
     int         table_number_ ;
 
+    // Table parameters, in order read from table header.
+    char table_type_     ;
+    int  min_age_        ;
+    int  max_age_        ;
+    int  select_period_  ;
+    int  max_select_age_ ;
+
     // Table data.
     std::vector<double> data_;
 
-- 
1.7.11.3




reply via email to

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