lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [4884] Merge two TUs, as if by renaming 'ihs_dbvalue.cpp'


From: Greg Chicares
Subject: [lmi-commits] [4884] Merge two TUs, as if by renaming 'ihs_dbvalue.cpp' to 'dbvalue.cpp'
Date: Sat, 01 May 2010 13:14:15 +0000

Revision: 4884
          http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=4884
Author:   chicares
Date:     2010-05-01 13:14:15 +0000 (Sat, 01 May 2010)
Log Message:
-----------
Merge two TUs, as if by renaming 'ihs_dbvalue.cpp' to 'dbvalue.cpp'

Modified Paths:
--------------
    lmi/trunk/ChangeLog
    lmi/trunk/Makefile.am
    lmi/trunk/dbvalue.cpp
    lmi/trunk/objects.make

Removed Paths:
-------------
    lmi/trunk/ihs_dbvalue.cpp

Modified: lmi/trunk/ChangeLog
===================================================================
--- lmi/trunk/ChangeLog 2010-05-01 12:29:26 UTC (rev 4883)
+++ lmi/trunk/ChangeLog 2010-05-01 13:14:15 UTC (rev 4884)
@@ -25227,3 +25227,28 @@
   ihs_dbvalue.hpp [expunged]
 Merge two headers.
 
+20100501T1131Z <address@hidden> [733]
+
+  dbvalue.cpp
+  dbvalue.hpp
+  ihs_dbvalue.cpp
+Consolidate and simplify documentation.
+
+20100501T1228Z <address@hidden> [733]
+
+  database.cpp
+Remove a gratuitous difference versus 'ihs_database.cpp'.
+
+20100501T1229Z <address@hidden> [733]
+
+  dbvalue.cpp
+Demonstrate that this file's contents are unneeded.
+
+20100501T1314Z <address@hidden> [732]
+
+  Makefile.am
+  dbvalue.cpp
+  ihs_dbvalue.cpp [expunged]
+  objects.make
+Merge two TUs, as if by renaming 'ihs_dbvalue.cpp' to 'dbvalue.cpp'.
+

Modified: lmi/trunk/Makefile.am
===================================================================
--- lmi/trunk/Makefile.am       2010-05-01 12:29:26 UTC (rev 4883)
+++ lmi/trunk/Makefile.am       2010-05-01 13:14:15 UTC (rev 4884)
@@ -243,6 +243,7 @@
     custom_io_0.cpp \
     data_directory.cpp \
     dbnames.cpp \
+    dbvalue.cpp \
     death_benefits.cpp \
     emit_ledger.cpp \
     expm1.c \
@@ -303,7 +304,6 @@
     basicvalues.cpp \
     database.cpp \
     dbdict.cpp \
-    dbvalue.cpp \
     mortality_rates.cpp \
     solve.cpp \
     $(liblmi_common_sources)
@@ -328,7 +328,6 @@
     ihs_commfns.cpp \
     ihs_database.cpp \
     ihs_dbdict.cpp \
-    ihs_dbvalue.cpp \
     ihs_funddata.cpp \
     ihs_irc7702.cpp \
     ihs_irc7702a.cpp \
@@ -726,10 +725,10 @@
   $(common_test_objects) \
   data_directory.cpp \
   dbnames.cpp \
+  dbvalue.cpp \
   expm1.cpp \
   global_settings.cpp \
   ihs_dbdict.cpp \
-  ihs_dbvalue.cpp \
   ihs_funddata.cpp \
   miscellany.cpp \
   path_utility.cpp \

Modified: lmi/trunk/dbvalue.cpp
===================================================================
--- lmi/trunk/dbvalue.cpp       2010-05-01 12:29:26 UTC (rev 4883)
+++ lmi/trunk/dbvalue.cpp       2010-05-01 13:14:15 UTC (rev 4884)
@@ -1,6 +1,6 @@
 // Product-database entity.
 //
-// Copyright (C) 1998, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 
Gregory W. Chicares.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 
2008, 2009, 2010 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
@@ -26,38 +26,63 @@
 #   pragma hdrstop
 #endif // __BORLANDC__
 
-#include "ihs_dbvalue.cpp"
-#if 0
-
 #include "dbvalue.hpp"
 
 #include "alert.hpp"
+#include "assert_lmi.hpp"
+#include "dbnames.hpp"
+#include "math_functors.hpp" // greater_of(), lesser_of()
+#include "print_matrix.hpp"
+#include "value_cast.hpp"
+#include "xml_serialize.hpp"
 
-#include <limits>
-#include <stdexcept>
+#include <algorithm>
+#include <functional>
+#include <iterator>          // std::advance()
+#include <limits>            // std::numeric_limits
+#include <numeric>
+#include <ostream>
 
-// TODO ?? This must die.
-namespace deprecated
+static int const ScalarDims[TDBValue::e_number_of_axes] = {1, 1, 1, 1, 1, 1, 
1};
+static int const MaxPossibleElements = std::numeric_limits<int>::max();
+
+std::vector<int> const& TDBValue::maximum_dimensions()
 {
-    template<typename T, typename SIZE_T>
-    void dupmem(T* dest, T const*const value, SIZE_T n)
-    {
-        for(SIZE_T j = 0; j < n; j++)
-            dest[j] = value[j];
-    }
-} // namespace deprecated
+    static int const d[e_number_of_axes] =
+        {e_max_dim_gender
+        ,e_max_dim_class
+        ,e_max_dim_smoking
+        ,e_max_dim_issue_age
+        ,e_max_dim_uw_basis
+        ,e_max_dim_state
+        ,e_max_dim_duration
+        };
+    static std::vector<int> const z(d, d + e_number_of_axes);
+    return z;
+}
 
 //============================================================================
+bool TDBValue::Equivalent(TDBValue const& a, TDBValue const& b)
+{
+    return(a.axis_lengths_ == b.axis_lengths_ && a.data_values_ == 
b.data_values_);
+}
+
+//============================================================================
+bool TDBValue::VariesByState(TDBValue const& z)
+{
+    LMI_ASSERT(5 < z.axis_lengths_.size());
+    return 1 != z.axis_lengths_[5];
+}
+
+//============================================================================
 TDBValue::TDBValue()
-    :key_  (0)
-    ,ndims_(0)
-    ,dims_ (0)
-    ,ndata_(0)
-    ,data_ (0)
+    :key_          (0)
+    ,axis_lengths_ (e_number_of_axes)
 {
 }
 
-//============================================================================
+/// Handy ctor for writing programs to generate '.database' files.
+
 TDBValue::TDBValue
     (int                key
     ,int                ndims
@@ -65,29 +90,52 @@
     ,double const*      data
     ,std::string const& gloss
     )
-    :key_   (key)
-    ,ndims_ (ndims)
-    ,gloss_ (gloss)
+    :key_          (key)
+    ,gloss_        (gloss)
 {
-    dims_ = new int[ndims_];
-    deprecated::dupmem(dims_, dims, ndims_);
-    ndata_ = getndata();
+    axis_lengths_ .assign(dims, dims + ndims);
+    data_values_  .assign(data, data + getndata());
 
-    data_ = new double[ndata_];
-    deprecated::dupmem(data_, data, ndata_);
+    ParanoidCheck();
 }
 
 //============================================================================
+TDBValue::TDBValue
+    (int                        key
+    ,std::vector<int> const&    dims
+    ,std::vector<double> const& data
+    ,std::string const&         gloss
+    )
+    :key_          (key)
+    ,axis_lengths_ (dims)
+    ,data_values_  (data)
+    ,gloss_        (gloss)
+{
+    ParanoidCheck();
+}
+
+/// Handy ctor for scalar data.
+
+TDBValue::TDBValue
+    (int                key
+    ,double             datum
+    ,std::string const& gloss
+    )
+    :key_          (key)
+    ,gloss_        (gloss)
+{
+    axis_lengths_ .assign(ScalarDims, ScalarDims + e_number_of_axes);
+    data_values_  .push_back(datum);
+}
+
+//============================================================================
 TDBValue::TDBValue(TDBValue const& z)
     :obstruct_slicing<TDBValue>()
-    ,key_   (z.key_  )
-    ,ndims_ (z.ndims_)
-    ,ndata_ (z.ndata_)
+    ,key_          (z.key_)
+    ,axis_lengths_ (z.axis_lengths_)
+    ,data_values_  (z.data_values_)
+    ,gloss_        (z.gloss_)
 {
-    dims_ = new int[ndims_];
-    deprecated::dupmem(dims_, z.dims_, ndims_);
-    data_ = new double[ndata_];
-    deprecated::dupmem(data_, z.data_, ndata_);
 }
 
 //============================================================================
@@ -95,15 +143,10 @@
 {
     if(this != &z)
         {
-        key_   = z.key_;
-        ndata_ = z.ndata_;
-        ndims_ = z.ndims_;
-        delete[]dims_;
-        delete[]data_;
-        dims_ = new int[ndims_];
-        deprecated::dupmem(dims_, z.dims_, ndims_);
-        data_ = new double[ndata_];
-        deprecated::dupmem(data_, z.data_, ndata_);
+        key_          = z.key_;
+        axis_lengths_ = z.axis_lengths_;
+        data_values_  = z.data_values_;
+        gloss_        = z.gloss_;
         }
     return *this;
 }
@@ -111,52 +154,344 @@
 //============================================================================
 TDBValue::~TDBValue()
 {
-    delete[]dims_;
-    delete[]data_;
 }
 
 //============================================================================
-int TDBValue::getndata() const
+void TDBValue::ParanoidCheck() const
 {
-    if(0 == ndims_)
+    if
+        (
+            axis_lengths_.end()
+        !=  std::find
+            (axis_lengths_.begin()
+            ,axis_lengths_.end()
+            ,0
+            )
+        )
         {
-        return 0;
+        fatal_error()
+            << "Database item '"
+            << GetDBNames()[key_].ShortName
+            << "' with key "
+            << key_
+            << " has zero in at least one dimension."
+            << LMI_FLUSH
+            ;
         }
 
-    long int n = 1L;
+    LMI_ASSERT(getndata() == static_cast<int>(data_values_.size()));
+    LMI_ASSERT(DB_FIRST <= key_ && key_ < DB_LAST);
+    LMI_ASSERT(e_number_of_axes == axis_lengths_.size());
+}
 
-    for(int j = 0; j < ndims_; j++)
+//============================================================================
+int TDBValue::getndata() const
+{
+    LMI_ASSERT(!axis_lengths_.empty());
+
+    // Calculate number of elements required from lengths of axes.
+    // Use a double for this purpose so that we can detect whether
+    // the required number exceeds the maximum addressable number,
+    // because a double has a wider range than an integer type.
+    double n = std::accumulate
+        (axis_lengths_.begin()
+        ,axis_lengths_.end()
+        ,1.0
+        ,std::multiplies<double>()
+        );
+
+    // Meaningful iff a long int is bigger than an int.
+    if(MaxPossibleElements < n)
         {
-        n *= dims_[j];
+        fatal_error()
+            << "Database item '"
+            << GetDBNames()[key_].ShortName
+            << "' with key "
+            << key_
+            << " contains more than the maximum possible number of elements."
+            << LMI_FLUSH
+            ;
         }
 
-    if(std::numeric_limits<int>::max() < n)
+    if(0 == n)
         {
-        fatal_error() << "Too much data in database." << LMI_FLUSH;
+        fatal_error()
+            << "Database item '"
+            << GetDBNames()[key_].ShortName
+            << "' with key "
+            << key_
+            << " has no data."
+            << LMI_FLUSH
+            ;
         }
+
+    // Because MaxPossibleElements < n, this cast cannot lose information.
     return static_cast<int>(n);
 }
 
 //============================================================================
-double const* TDBValue::operator[](int const* idx) const
+double& TDBValue::operator[](std::vector<int> const& idx)
 {
+    LMI_ASSERT(e_number_of_axes == idx.size());
+
+    if(e_number_of_axes != axis_lengths_.size())
+        {
+        fatal_error()
+            << "Trying to index database with key "
+            << key_
+            << ": "
+            << "e_number_of_axes is " << e_number_of_axes
+            << ", and axis_lengths.size() is " << axis_lengths_.size()
+            << ", but those quantities must be equal."
+            << LMI_FLUSH
+            ;
+        }
+
     int z = 0;
-    for(int j = 0; j < ndims_ - 1; j++)
+    // TODO ?? Can we use an STL algorithm instead?
+    for(unsigned int j = 0; j < axis_lengths_.size(); j++)
         {
-        if(1 != dims_[j])
+        if(1 != axis_lengths_[j])
             {
-            z = z * dims_[j] + idx[j];
+            LMI_ASSERT(idx[j] < axis_lengths_[j]);
+            z = z * axis_lengths_[j] + idx[j];
             }
         }
-    if(ndata_ <= z)
+// TODO ?? erase    z *= axis_lengths_.back();
+    if(static_cast<int>(data_values_.size()) <= z)
         {
-        throw std::runtime_error
-            ("Trying to index database item past end of data."
+        z = 0;
+        fatal_error()
+            << "Trying to index database item with key "
+            << key_
+            << " past end of data."
+            << LMI_FLUSH
+            ;
+        }
+    return data_values_[z];
+}
+
+//============================================================================
+double const* TDBValue::operator[](TDBIndex const& idx) const
+{
+    std::vector<double> index(idx.GetIdx());
+
+    LMI_ASSERT(0 < axis_lengths_.size());
+    int z = 0;
+    // TODO ?? Can we use an STL algorithm instead?
+    for(unsigned int j = 0; j < axis_lengths_.size() - 1; j++)
+        {
+        if(1 != axis_lengths_[j])
+            {
+            LMI_ASSERT(index[j] < axis_lengths_[j]);
+            z = z * axis_lengths_[j] + static_cast<int>(index[j]);
+            }
+        }
+    z *= axis_lengths_.back();
+    if(static_cast<int>(data_values_.size()) <= z)
+        {
+        z = 0;
+        fatal_error()
+            << "Trying to index database item with key "
+            << key_
+            << " past end of data."
+            << LMI_FLUSH
+            ;
+        }
+    return &data_values_[z];
+}
+
+//============================================================================
+void TDBValue::Reshape(std::vector<int> const& dims)
+{
+    // Create a new instance of this class having the same
+    // key but the desired number of axes
+    std::vector<double> new_data
+        (
+        std::accumulate
+            (dims.begin()
+            ,dims.end()
+            ,1
+            ,std::multiplies<int>()
+            )
+        );
+    TDBValue new_object
+        (GetKey()
+        ,dims
+        ,new_data
+        );
+
+    // ET !! std::vector<int> max_dims_used = max(axis_lengths_, dims);
+    // ...and then expunge this comment:
+    // greater length of src or dst along each axis
+    std::vector<int> max_dims_used(e_number_of_axes);
+    std::transform
+        (axis_lengths_.begin()
+        ,axis_lengths_.end()
+        ,dims.begin()
+        ,max_dims_used.begin()
+        ,greater_of<int>()
+        );
+    // TODO ?? Oops--erase above std::transform() call--want only dst axes.
+    max_dims_used = dims;
+
+    // Number of times we'll go through the assignment loop.
+    // TODO ?? prolly should use max_dims_used instead of dims here (they're 
the same).
+    int n_iter = std::accumulate
+        (dims.begin()
+        ,dims.end()
+        ,1
+        ,std::multiplies<int>()
+        );
+
+    // ET !! std::vector<int> dst_max_idx = dims - 1;
+    // ...and then expunge this comment:
+    // max index of dst along each axis
+    std::vector<int> dst_max_idx(dims);
+    std::transform
+        (dst_max_idx.begin()
+        ,dst_max_idx.end()
+        ,dst_max_idx.begin()
+        ,std::bind2nd(std::minus<int>(), 1)
+        );
+    // ET !! std::vector<int> src_max_idx = axis_lengths_ - 1;
+    // ...and then expunge this comment:
+    // max index of src along each axis
+    std::vector<int> src_max_idx(axis_lengths_);
+    std::transform
+        (src_max_idx.begin()
+        ,src_max_idx.end()
+        ,src_max_idx.begin()
+        ,std::bind2nd(std::minus<int>(), 1)
+        );
+
+    // indexes new_object
+    std::vector<int> dst_idx(e_number_of_axes);
+    // indexes '*this'
+    std::vector<int> src_idx(e_number_of_axes);
+
+    std::vector<int> working_idx(e_number_of_axes);
+    for(int j = 0; j < n_iter; j++)
+        {
+        int z = j;
+        std::vector<int>::const_iterator i = max_dims_used.begin();
+        std::vector<int>::iterator w = working_idx.begin();
+        while(i != max_dims_used.end())
+            {
+            LMI_ASSERT(0 != *i);
+            *w = z % *i;
+            z /= *i;
+            i++;
+            w++;
+            }
+        LMI_ASSERT(0 == z);
+
+        // ET !! dst_idx = min(working_idx, dst_max_idx)
+        // ET !! src_idx = min(working_idx, src_max_idx)
+        // ...and then expunge this comment:
+        // limit dst and source indexes to those that actually vary
+        std::transform
+            (working_idx.begin()
+            ,working_idx.end()
+            ,dst_max_idx.begin()
+            ,dst_idx.begin()
+            ,lesser_of<int>()
             );
+        std::transform
+            (working_idx.begin()
+            ,working_idx.end()
+            ,src_max_idx.begin()
+            ,src_idx.begin()
+            ,lesser_of<int>()
+            );
+        new_object[dst_idx] = operator[](src_idx);
         }
-    return &data_[z];
+
+// erase    (*this) = new_object;
+    axis_lengths_ = dims;
+    data_values_ = new_object.data_values_;
 }
 
+//============================================================================
+std::ostream& TDBValue::write(std::ostream& os) const
+{
+    os
+        << '"' << GetDBNames()[key_].LongName << '"'
+        << '\n'
+        << "  name='" << GetDBNames()[key_].ShortName << "'"
+        << " key=" << key_
+        << '\n'
+        ;
+    if(!gloss_.empty())
+        {
+        os << "  gloss: " << gloss_ << '\n';
+        }
+
+    if(1 == getndata())
+        {
+        os << "  scalar";
+        }
+    else
+        {
+        os << "  varies by:";
+        if(1 != axis_lengths_[0]) os <<    " gender[" << axis_lengths_[0] << 
']';
+        if(1 != axis_lengths_[1]) os <<  " uw_class[" << axis_lengths_[1] << 
']';
+        if(1 != axis_lengths_[2]) os <<   " smoking[" << axis_lengths_[2] << 
']';
+        if(1 != axis_lengths_[3]) os << " issue_age[" << axis_lengths_[3] << 
']';
+        if(1 != axis_lengths_[4]) os <<  " uw_basis[" << axis_lengths_[4] << 
']';
+        if(1 != axis_lengths_[5]) os <<     " state[" << axis_lengths_[5] << 
']';
+        if(1 != axis_lengths_[6]) os <<  " duration[" << axis_lengths_[6] << 
']';
+        }
+
+    os << '\n';
+    print_matrix(os, data_values_, axis_lengths_);
+    os << '\n';
+    return os;
+}
+
+//============================================================================
+// TODO ?? Combine this with ParanoidCheck()?
+bool TDBValue::AreAllAxesOK() const
+{
+    bool rc = true;
+    std::vector<int> const& max_dims(maximum_dimensions());
+    LMI_ASSERT(axis_lengths_.size() == max_dims.size());
+    std::vector<int>::const_iterator ai = axis_lengths_.begin();
+    std::vector<int>::const_iterator mi = max_dims.begin();
+
+    while(ai != axis_lengths_.end()) // not duration!
+        {
+        if(*ai != 1 && *ai != *mi && *ai != axis_lengths_.back())
+            {
+            warning()
+                << "Database item '"
+                << GetDBNames()[key_].ShortName
+                << "' with key "
+                << key_
+                << " has invalid length in at least one dimension."
+                << LMI_FLUSH
+                ;
+            rc = false;
+            }
+        ai++;
+        mi++;
+        }
+
+    if(max_dims.back() < axis_lengths_.back())
+            {
+            warning()
+                << "Database item '"
+                << GetDBNames()[key_].ShortName
+                << "' with key "
+                << key_
+                << " has invalid duration."
+                << LMI_FLUSH
+                ;
+            rc = false;
+            }
+    return rc;
+}
+
 int TDBValue::GetKey() const
 {
     return key_;
@@ -164,12 +499,55 @@
 
 int TDBValue::GetNDims() const
 {
-    return ndims_;
+    return axis_lengths_.size();
 }
 
 int TDBValue::GetLength() const
 {
-    return dims_[TDBIndex::MaxIndex];
+    LMI_ASSERT(0 < axis_lengths_.size());
+    return axis_lengths_.back();
 }
-#endif // 0
 
+int TDBValue::GetLength(int axis) const
+{
+    LMI_ASSERT(0 <= axis && axis < static_cast<int>(axis_lengths_.size()));
+    return axis_lengths_[axis];
+}
+
+std::vector<int> const& TDBValue::GetAxisLengths() const
+{
+    return axis_lengths_;
+}
+
+void TDBValue::read(xml::element const& e)
+{
+    std::string short_name;
+    xml_serialize::get_element(e, "key"         , short_name   );
+    key_ = db_key_from_name(short_name);
+    xml_serialize::get_element(e, "axis_lengths", axis_lengths_);
+    xml_serialize::get_element(e, "data_values" , data_values_ );
+    xml_serialize::get_element(e, "gloss"       , gloss_       );
+
+    LMI_ASSERT(getndata() == static_cast<int>(data_values_.size()));
+    LMI_ASSERT
+        (   0 < static_cast<int>(data_values_.size())
+        &&      static_cast<int>(data_values_.size()) < MaxPossibleElements
+        );
+    AreAllAxesOK();
+}
+
+void TDBValue::write(xml::element& e) const
+{
+    LMI_ASSERT(getndata() == static_cast<int>(data_values_.size()));
+    LMI_ASSERT
+        (   0 < static_cast<int>(data_values_.size())
+        &&      static_cast<int>(data_values_.size()) < MaxPossibleElements
+        );
+    AreAllAxesOK();
+
+    xml_serialize::set_element(e, "key"         , db_name_from_key(key_));
+    xml_serialize::set_element(e, "axis_lengths", axis_lengths_);
+    xml_serialize::set_element(e, "data_values" , data_values_ );
+    xml_serialize::set_element(e, "gloss"       , gloss_       );
+}
+

Deleted: lmi/trunk/ihs_dbvalue.cpp
===================================================================
--- lmi/trunk/ihs_dbvalue.cpp   2010-05-01 12:29:26 UTC (rev 4883)
+++ lmi/trunk/ihs_dbvalue.cpp   2010-05-01 13:14:15 UTC (rev 4884)
@@ -1,553 +0,0 @@
-// Product-database entity.
-//
-// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 
2008, 2009, 2010 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 "dbvalue.hpp"
-
-#include "alert.hpp"
-#include "assert_lmi.hpp"
-#include "dbnames.hpp"
-#include "math_functors.hpp" // greater_of(), lesser_of()
-#include "print_matrix.hpp"
-#include "value_cast.hpp"
-#include "xml_serialize.hpp"
-
-#include <algorithm>
-#include <functional>
-#include <iterator>          // std::advance()
-#include <limits>            // std::numeric_limits
-#include <numeric>
-#include <ostream>
-
-static int const ScalarDims[TDBValue::e_number_of_axes] = {1, 1, 1, 1, 1, 1, 
1};
-static int const MaxPossibleElements = std::numeric_limits<int>::max();
-
-std::vector<int> const& TDBValue::maximum_dimensions()
-{
-    static int const d[e_number_of_axes] =
-        {e_max_dim_gender
-        ,e_max_dim_class
-        ,e_max_dim_smoking
-        ,e_max_dim_issue_age
-        ,e_max_dim_uw_basis
-        ,e_max_dim_state
-        ,e_max_dim_duration
-        };
-    static std::vector<int> const z(d, d + e_number_of_axes);
-    return z;
-}
-
-//============================================================================
-bool TDBValue::Equivalent(TDBValue const& a, TDBValue const& b)
-{
-    return(a.axis_lengths_ == b.axis_lengths_ && a.data_values_ == 
b.data_values_);
-}
-
-//============================================================================
-bool TDBValue::VariesByState(TDBValue const& z)
-{
-    LMI_ASSERT(5 < z.axis_lengths_.size());
-    return 1 != z.axis_lengths_[5];
-}
-
-//============================================================================
-TDBValue::TDBValue()
-    :key_          (0)
-    ,axis_lengths_ (e_number_of_axes)
-{
-}
-
-/// Handy ctor for writing programs to generate '.database' files.
-
-TDBValue::TDBValue
-    (int                key
-    ,int                ndims
-    ,int const*         dims
-    ,double const*      data
-    ,std::string const& gloss
-    )
-    :key_          (key)
-    ,gloss_        (gloss)
-{
-    axis_lengths_ .assign(dims, dims + ndims);
-    data_values_  .assign(data, data + getndata());
-
-    ParanoidCheck();
-}
-
-//============================================================================
-TDBValue::TDBValue
-    (int                        key
-    ,std::vector<int> const&    dims
-    ,std::vector<double> const& data
-    ,std::string const&         gloss
-    )
-    :key_          (key)
-    ,axis_lengths_ (dims)
-    ,data_values_  (data)
-    ,gloss_        (gloss)
-{
-    ParanoidCheck();
-}
-
-/// Handy ctor for scalar data.
-
-TDBValue::TDBValue
-    (int                key
-    ,double             datum
-    ,std::string const& gloss
-    )
-    :key_          (key)
-    ,gloss_        (gloss)
-{
-    axis_lengths_ .assign(ScalarDims, ScalarDims + e_number_of_axes);
-    data_values_  .push_back(datum);
-}
-
-//============================================================================
-TDBValue::TDBValue(TDBValue const& z)
-    :obstruct_slicing<TDBValue>()
-    ,key_          (z.key_)
-    ,axis_lengths_ (z.axis_lengths_)
-    ,data_values_  (z.data_values_)
-    ,gloss_        (z.gloss_)
-{
-}
-
-//============================================================================
-TDBValue& TDBValue::operator=(TDBValue const& z)
-{
-    if(this != &z)
-        {
-        key_          = z.key_;
-        axis_lengths_ = z.axis_lengths_;
-        data_values_  = z.data_values_;
-        gloss_        = z.gloss_;
-        }
-    return *this;
-}
-
-//============================================================================
-TDBValue::~TDBValue()
-{
-}
-
-//============================================================================
-void TDBValue::ParanoidCheck() const
-{
-    if
-        (
-            axis_lengths_.end()
-        !=  std::find
-            (axis_lengths_.begin()
-            ,axis_lengths_.end()
-            ,0
-            )
-        )
-        {
-        fatal_error()
-            << "Database item '"
-            << GetDBNames()[key_].ShortName
-            << "' with key "
-            << key_
-            << " has zero in at least one dimension."
-            << LMI_FLUSH
-            ;
-        }
-
-    LMI_ASSERT(getndata() == static_cast<int>(data_values_.size()));
-    LMI_ASSERT(DB_FIRST <= key_ && key_ < DB_LAST);
-    LMI_ASSERT(e_number_of_axes == axis_lengths_.size());
-}
-
-//============================================================================
-int TDBValue::getndata() const
-{
-    LMI_ASSERT(!axis_lengths_.empty());
-
-    // Calculate number of elements required from lengths of axes.
-    // Use a double for this purpose so that we can detect whether
-    // the required number exceeds the maximum addressable number,
-    // because a double has a wider range than an integer type.
-    double n = std::accumulate
-        (axis_lengths_.begin()
-        ,axis_lengths_.end()
-        ,1.0
-        ,std::multiplies<double>()
-        );
-
-    // Meaningful iff a long int is bigger than an int.
-    if(MaxPossibleElements < n)
-        {
-        fatal_error()
-            << "Database item '"
-            << GetDBNames()[key_].ShortName
-            << "' with key "
-            << key_
-            << " contains more than the maximum possible number of elements."
-            << LMI_FLUSH
-            ;
-        }
-
-    if(0 == n)
-        {
-        fatal_error()
-            << "Database item '"
-            << GetDBNames()[key_].ShortName
-            << "' with key "
-            << key_
-            << " has no data."
-            << LMI_FLUSH
-            ;
-        }
-
-    // Because MaxPossibleElements < n, this cast cannot lose information.
-    return static_cast<int>(n);
-}
-
-//============================================================================
-double& TDBValue::operator[](std::vector<int> const& idx)
-{
-    LMI_ASSERT(e_number_of_axes == idx.size());
-
-    if(e_number_of_axes != axis_lengths_.size())
-        {
-        fatal_error()
-            << "Trying to index database with key "
-            << key_
-            << ": "
-            << "e_number_of_axes is " << e_number_of_axes
-            << ", and axis_lengths.size() is " << axis_lengths_.size()
-            << ", but those quantities must be equal."
-            << LMI_FLUSH
-            ;
-        }
-
-    int z = 0;
-    // TODO ?? Can we use an STL algorithm instead?
-    for(unsigned int j = 0; j < axis_lengths_.size(); j++)
-        {
-        if(1 != axis_lengths_[j])
-            {
-            LMI_ASSERT(idx[j] < axis_lengths_[j]);
-            z = z * axis_lengths_[j] + idx[j];
-            }
-        }
-// TODO ?? erase    z *= axis_lengths_.back();
-    if(static_cast<int>(data_values_.size()) <= z)
-        {
-        z = 0;
-        fatal_error()
-            << "Trying to index database item with key "
-            << key_
-            << " past end of data."
-            << LMI_FLUSH
-            ;
-        }
-    return data_values_[z];
-}
-
-//============================================================================
-double const* TDBValue::operator[](TDBIndex const& idx) const
-{
-    std::vector<double> index(idx.GetIdx());
-
-    LMI_ASSERT(0 < axis_lengths_.size());
-    int z = 0;
-    // TODO ?? Can we use an STL algorithm instead?
-    for(unsigned int j = 0; j < axis_lengths_.size() - 1; j++)
-        {
-        if(1 != axis_lengths_[j])
-            {
-            LMI_ASSERT(index[j] < axis_lengths_[j]);
-            z = z * axis_lengths_[j] + static_cast<int>(index[j]);
-            }
-        }
-    z *= axis_lengths_.back();
-    if(static_cast<int>(data_values_.size()) <= z)
-        {
-        z = 0;
-        fatal_error()
-            << "Trying to index database item with key "
-            << key_
-            << " past end of data."
-            << LMI_FLUSH
-            ;
-        }
-    return &data_values_[z];
-}
-
-//============================================================================
-void TDBValue::Reshape(std::vector<int> const& dims)
-{
-    // Create a new instance of this class having the same
-    // key but the desired number of axes
-    std::vector<double> new_data
-        (
-        std::accumulate
-            (dims.begin()
-            ,dims.end()
-            ,1
-            ,std::multiplies<int>()
-            )
-        );
-    TDBValue new_object
-        (GetKey()
-        ,dims
-        ,new_data
-        );
-
-    // ET !! std::vector<int> max_dims_used = max(axis_lengths_, dims);
-    // ...and then expunge this comment:
-    // greater length of src or dst along each axis
-    std::vector<int> max_dims_used(e_number_of_axes);
-    std::transform
-        (axis_lengths_.begin()
-        ,axis_lengths_.end()
-        ,dims.begin()
-        ,max_dims_used.begin()
-        ,greater_of<int>()
-        );
-    // TODO ?? Oops--erase above std::transform() call--want only dst axes.
-    max_dims_used = dims;
-
-    // Number of times we'll go through the assignment loop.
-    // TODO ?? prolly should use max_dims_used instead of dims here (they're 
the same).
-    int n_iter = std::accumulate
-        (dims.begin()
-        ,dims.end()
-        ,1
-        ,std::multiplies<int>()
-        );
-
-    // ET !! std::vector<int> dst_max_idx = dims - 1;
-    // ...and then expunge this comment:
-    // max index of dst along each axis
-    std::vector<int> dst_max_idx(dims);
-    std::transform
-        (dst_max_idx.begin()
-        ,dst_max_idx.end()
-        ,dst_max_idx.begin()
-        ,std::bind2nd(std::minus<int>(), 1)
-        );
-    // ET !! std::vector<int> src_max_idx = axis_lengths_ - 1;
-    // ...and then expunge this comment:
-    // max index of src along each axis
-    std::vector<int> src_max_idx(axis_lengths_);
-    std::transform
-        (src_max_idx.begin()
-        ,src_max_idx.end()
-        ,src_max_idx.begin()
-        ,std::bind2nd(std::minus<int>(), 1)
-        );
-
-    // indexes new_object
-    std::vector<int> dst_idx(e_number_of_axes);
-    // indexes '*this'
-    std::vector<int> src_idx(e_number_of_axes);
-
-    std::vector<int> working_idx(e_number_of_axes);
-    for(int j = 0; j < n_iter; j++)
-        {
-        int z = j;
-        std::vector<int>::const_iterator i = max_dims_used.begin();
-        std::vector<int>::iterator w = working_idx.begin();
-        while(i != max_dims_used.end())
-            {
-            LMI_ASSERT(0 != *i);
-            *w = z % *i;
-            z /= *i;
-            i++;
-            w++;
-            }
-        LMI_ASSERT(0 == z);
-
-        // ET !! dst_idx = min(working_idx, dst_max_idx)
-        // ET !! src_idx = min(working_idx, src_max_idx)
-        // ...and then expunge this comment:
-        // limit dst and source indexes to those that actually vary
-        std::transform
-            (working_idx.begin()
-            ,working_idx.end()
-            ,dst_max_idx.begin()
-            ,dst_idx.begin()
-            ,lesser_of<int>()
-            );
-        std::transform
-            (working_idx.begin()
-            ,working_idx.end()
-            ,src_max_idx.begin()
-            ,src_idx.begin()
-            ,lesser_of<int>()
-            );
-        new_object[dst_idx] = operator[](src_idx);
-        }
-
-// erase    (*this) = new_object;
-    axis_lengths_ = dims;
-    data_values_ = new_object.data_values_;
-}
-
-//============================================================================
-std::ostream& TDBValue::write(std::ostream& os) const
-{
-    os
-        << '"' << GetDBNames()[key_].LongName << '"'
-        << '\n'
-        << "  name='" << GetDBNames()[key_].ShortName << "'"
-        << " key=" << key_
-        << '\n'
-        ;
-    if(!gloss_.empty())
-        {
-        os << "  gloss: " << gloss_ << '\n';
-        }
-
-    if(1 == getndata())
-        {
-        os << "  scalar";
-        }
-    else
-        {
-        os << "  varies by:";
-        if(1 != axis_lengths_[0]) os <<    " gender[" << axis_lengths_[0] << 
']';
-        if(1 != axis_lengths_[1]) os <<  " uw_class[" << axis_lengths_[1] << 
']';
-        if(1 != axis_lengths_[2]) os <<   " smoking[" << axis_lengths_[2] << 
']';
-        if(1 != axis_lengths_[3]) os << " issue_age[" << axis_lengths_[3] << 
']';
-        if(1 != axis_lengths_[4]) os <<  " uw_basis[" << axis_lengths_[4] << 
']';
-        if(1 != axis_lengths_[5]) os <<     " state[" << axis_lengths_[5] << 
']';
-        if(1 != axis_lengths_[6]) os <<  " duration[" << axis_lengths_[6] << 
']';
-        }
-
-    os << '\n';
-    print_matrix(os, data_values_, axis_lengths_);
-    os << '\n';
-    return os;
-}
-
-//============================================================================
-// TODO ?? Combine this with ParanoidCheck()?
-bool TDBValue::AreAllAxesOK() const
-{
-    bool rc = true;
-    std::vector<int> const& max_dims(maximum_dimensions());
-    LMI_ASSERT(axis_lengths_.size() == max_dims.size());
-    std::vector<int>::const_iterator ai = axis_lengths_.begin();
-    std::vector<int>::const_iterator mi = max_dims.begin();
-
-    while(ai != axis_lengths_.end()) // not duration!
-        {
-        if(*ai != 1 && *ai != *mi && *ai != axis_lengths_.back())
-            {
-            warning()
-                << "Database item '"
-                << GetDBNames()[key_].ShortName
-                << "' with key "
-                << key_
-                << " has invalid length in at least one dimension."
-                << LMI_FLUSH
-                ;
-            rc = false;
-            }
-        ai++;
-        mi++;
-        }
-
-    if(max_dims.back() < axis_lengths_.back())
-            {
-            warning()
-                << "Database item '"
-                << GetDBNames()[key_].ShortName
-                << "' with key "
-                << key_
-                << " has invalid duration."
-                << LMI_FLUSH
-                ;
-            rc = false;
-            }
-    return rc;
-}
-
-int TDBValue::GetKey() const
-{
-    return key_;
-}
-
-int TDBValue::GetNDims() const
-{
-    return axis_lengths_.size();
-}
-
-int TDBValue::GetLength() const
-{
-    LMI_ASSERT(0 < axis_lengths_.size());
-    return axis_lengths_.back();
-}
-
-int TDBValue::GetLength(int axis) const
-{
-    LMI_ASSERT(0 <= axis && axis < static_cast<int>(axis_lengths_.size()));
-    return axis_lengths_[axis];
-}
-
-std::vector<int> const& TDBValue::GetAxisLengths() const
-{
-    return axis_lengths_;
-}
-
-void TDBValue::read(xml::element const& e)
-{
-    std::string short_name;
-    xml_serialize::get_element(e, "key"         , short_name   );
-    key_ = db_key_from_name(short_name);
-    xml_serialize::get_element(e, "axis_lengths", axis_lengths_);
-    xml_serialize::get_element(e, "data_values" , data_values_ );
-    xml_serialize::get_element(e, "gloss"       , gloss_       );
-
-    LMI_ASSERT(getndata() == static_cast<int>(data_values_.size()));
-    LMI_ASSERT
-        (   0 < static_cast<int>(data_values_.size())
-        &&      static_cast<int>(data_values_.size()) < MaxPossibleElements
-        );
-    AreAllAxesOK();
-}
-
-void TDBValue::write(xml::element& e) const
-{
-    LMI_ASSERT(getndata() == static_cast<int>(data_values_.size()));
-    LMI_ASSERT
-        (   0 < static_cast<int>(data_values_.size())
-        &&      static_cast<int>(data_values_.size()) < MaxPossibleElements
-        );
-    AreAllAxesOK();
-
-    xml_serialize::set_element(e, "key"         , db_name_from_key(key_));
-    xml_serialize::set_element(e, "axis_lengths", axis_lengths_);
-    xml_serialize::set_element(e, "data_values" , data_values_ );
-    xml_serialize::set_element(e, "gloss"       , gloss_       );
-}
-

Modified: lmi/trunk/objects.make
===================================================================
--- lmi/trunk/objects.make      2010-05-01 12:29:26 UTC (rev 4883)
+++ lmi/trunk/objects.make      2010-05-01 13:14:15 UTC (rev 4884)
@@ -189,6 +189,7 @@
   datum_boolean.o \
   datum_string.o \
   dbnames.o \
+  dbvalue.o \
   death_benefits.o \
   emit_ledger.o \
   expm1.o \
@@ -255,7 +256,6 @@
   basicvalues.o \
   database.o \
   dbdict.o \
-  dbvalue.o \
   mortality_rates.o \
   solve.o \
 
@@ -275,7 +275,6 @@
   ihs_commfns.o \
   ihs_database.o \
   ihs_dbdict.o \
-  ihs_dbvalue.o \
   ihs_funddata.o \
   ihs_irc7702.o \
   ihs_irc7702a.o \
@@ -377,6 +376,7 @@
   datum_base.o \
   datum_string.o \
   dbnames.o \
+  dbvalue.o \
   death_benefits.o \
   expm1.o \
   facets.o \
@@ -386,7 +386,6 @@
   ihs_commfns.o \
   ihs_database.o \
   ihs_dbdict.o \
-  ihs_dbvalue.o \
   ihs_funddata.o \
   ihs_mortal.o \
   input.o \
@@ -772,11 +771,11 @@
   data_directory.o \
   datum_base.o \
   dbnames.o \
+  dbvalue.o \
   expm1.o \
   facets.o \
   global_settings.o \
   ihs_dbdict.o \
-  ihs_dbvalue.o \
   ihs_funddata.o \
   mc_enum.o \
   mc_enum_types.o \





reply via email to

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