[Top][All Lists]
[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 \
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lmi-commits] [4884] Merge two TUs, as if by renaming 'ihs_dbvalue.cpp' to 'dbvalue.cpp',
Greg Chicares <=