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

[mdds] 15/62: Imported Upstream version 0.5.3



This is an automated email from the git hooks/post-receive script.

rene pushed a commit to branch master
in repository mdds.

commit d3bd0aedf9420bda9692787b5e116201fdb7a49a
Author: Rene Engelhard <rene@debian.org>
Date:   Thu Apr 21 14:50:47 2016 +0200

    Imported Upstream version 0.5.3
---
 Makefile.in                                        |  25 +-
 NEWS                                               |   9 +
 configure                                          |  32 +-
 include/mdds/mixed_type_matrix.hpp                 |  10 +-
 include/mdds/mixed_type_matrix_def.inl             |  25 +-
 include/mdds/mixed_type_matrix_storage.hpp         | 765 +++------------------
 .../mixed_type_matrix_storage_filled_linear.inl    | 701 +++++++++++++++++++
 ...xed_type_matrix_storage_filled_nested_array.inl | 374 ++++++++++
 include/mdds/mixed_type_matrix_storage_sparse.inl  | 376 ++++++++++
 include/mdds/rectangle_set.hpp                     | 246 +------
 .../{rectangle_set.hpp => rectangle_set_def.inl}   | 225 +-----
 misc/mdds.spec.in                                  |   4 +-
 src/array_creation_perf_test.cpp                   |  81 +++
 src/mixed_type_matrix_test.cpp                     |  83 ++-
 src/test_global.hpp                                |   1 +
 15 files changed, 1798 insertions(+), 1159 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index de4c975..9a98933 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -18,18 +18,25 @@ EXECS= \
 	rectangle_set_test
 
 HEADERS= \
-	$(INCDIR)/mdds/node.hpp \
-	$(INCDIR)/mdds/quad_node.hpp \
-	$(INCDIR)/mdds/global.hpp \
-	$(INCDIR)/mdds/flat_segment_tree.hpp \
 	$(INCDIR)/mdds/flat_segment_tree_def.inl \
-	$(INCDIR)/mdds/point_quad_tree.hpp \
-	$(INCDIR)/mdds/segment_tree.hpp \
-	$(INCDIR)/mdds/mixed_type_matrix.hpp \
+	$(INCDIR)/mdds/flat_segment_tree.hpp \
+	$(INCDIR)/mdds/flat_segment_tree_itr.hpp \
+	$(INCDIR)/mdds/global.hpp \
+	$(INCDIR)/mdds/hash_container/map.hpp \
 	$(INCDIR)/mdds/mixed_type_matrix_def.inl \
-	$(INCDIR)/mdds/mixed_type_matrix_storage.hpp \
+	$(INCDIR)/mdds/mixed_type_matrix_element.hpp \
 	$(INCDIR)/mdds/mixed_type_matrix_flag_storage.hpp \
-	$(INCDIR)/mdds/rectangle_set.hpp
+	$(INCDIR)/mdds/mixed_type_matrix.hpp \
+	$(INCDIR)/mdds/mixed_type_matrix_storage_filled_linear.inl \
+	$(INCDIR)/mdds/mixed_type_matrix_storage_filled_nested_array.inl \
+	$(INCDIR)/mdds/mixed_type_matrix_storage.hpp \
+	$(INCDIR)/mdds/mixed_type_matrix_storage_sparse.inl \
+	$(INCDIR)/mdds/node.hpp \
+	$(INCDIR)/mdds/point_quad_tree.hpp \
+	$(INCDIR)/mdds/quad_node.hpp \
+	$(INCDIR)/mdds/rectangle_set_def.inl \
+	$(INCDIR)/mdds/rectangle_set.hpp \
+	$(INCDIR)/mdds/segment_tree.hpp
 
 DEPENDS= \
 	$(HEADERS)
diff --git a/NEWS b/NEWS
index d200527..7f9a224 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,12 @@
+mdds 0.5.3
+
+* mixed_type_matrix
+
+  * re-implemented the filled storage for better performance, with two 
+    separate implementations for zero and emtpy matrix types.  The 
+    newer implementation should improve object creation time 
+    considerably.
+
 mdds 0.5.2
 
 * flat_segment_tree
diff --git a/configure b/configure
index 1352ca1..680db6a 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for mdds 0.5.2.
+# Generated by GNU Autoconf 2.68 for mdds 0.5.3.
 #
 # Report bugs to <kohei.yoshida@gmail.com>.
 #
@@ -559,8 +559,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='mdds'
 PACKAGE_TARNAME='mdds'
-PACKAGE_VERSION='0.5.2'
-PACKAGE_STRING='mdds 0.5.2'
+PACKAGE_VERSION='0.5.3'
+PACKAGE_STRING='mdds 0.5.3'
 PACKAGE_BUGREPORT='kohei.yoshida@gmail.com'
 PACKAGE_URL=''
 
@@ -1160,7 +1160,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures mdds 0.5.2 to adapt to many kinds of systems.
+\`configure' configures mdds 0.5.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1221,7 +1221,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of mdds 0.5.2:";;
+     short | recursive ) echo "Configuration of mdds 0.5.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1305,7 +1305,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-mdds configure 0.5.2
+mdds configure 0.5.3
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -1322,7 +1322,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by mdds $as_me 0.5.2, which was
+It was created by mdds $as_me 0.5.3, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -1671,7 +1671,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
-VERSION=0.5.2
+VERSION=0.5.3
 
 
 PACKAGE_TARNAME=mdds
@@ -2268,7 +2268,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by mdds $as_me 0.5.2, which was
+This file was extended by mdds $as_me 0.5.3, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -2321,7 +2321,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-mdds config.status 0.5.2
+mdds config.status 0.5.3
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
@@ -3437,7 +3437,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by mdds $as_me 0.5.2, which was
+This file was extended by mdds $as_me 0.5.3, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -3490,7 +3490,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-mdds config.status 0.5.2
+mdds config.status 0.5.3
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
@@ -4607,7 +4607,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by mdds $as_me 0.5.2, which was
+This file was extended by mdds $as_me 0.5.3, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -4660,7 +4660,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-mdds config.status 0.5.2
+mdds config.status 0.5.3
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
@@ -5778,7 +5778,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by mdds $as_me 0.5.2, which was
+This file was extended by mdds $as_me 0.5.3, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -5831,7 +5831,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-mdds config.status 0.5.2
+mdds config.status 0.5.3
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
diff --git a/include/mdds/mixed_type_matrix.hpp b/include/mdds/mixed_type_matrix.hpp
index 758baff..4487b7f 100644
--- a/include/mdds/mixed_type_matrix.hpp
+++ b/include/mdds/mixed_type_matrix.hpp
@@ -81,7 +81,8 @@ private:
 
 public:
     typedef ::mdds::flag_storage<flag_type, size_pair_type, size_pair_type_hash> flag_storage;
-    typedef ::mdds::storage_filled<mixed_type_matrix> filled_storage_type;
+    typedef ::mdds::storage_filled_linear<mixed_type_matrix> filled_storage_type;
+    typedef ::mdds::storage_filled_linear_zero<mixed_type_matrix> filled_storage_zero_type;
     typedef ::mdds::storage_sparse<mixed_type_matrix> sparse_storage_type;
 
     typedef typename storage_base::const_iterator const_iterator;
@@ -220,6 +221,13 @@ public:
 #endif
 
 private:
+    /**
+     * Storage classes have no vtable; the concrete class type must be
+     * specified when deleting the instance.
+     */
+    void delete_storage();
+
+private:
     storage_base* mp_storage;
 };
 
diff --git a/include/mdds/mixed_type_matrix_def.inl b/include/mdds/mixed_type_matrix_def.inl
index 9d9cf54..264c039 100644
--- a/include/mdds/mixed_type_matrix_def.inl
+++ b/include/mdds/mixed_type_matrix_def.inl
@@ -34,7 +34,7 @@ mixed_type_matrix<_String,_Flag>::create_storage(size_t rows, size_t cols, matri
     switch (density)
     {
         case matrix_density_filled_zero:
-            return new filled_storage_type(rows, cols, matrix_init_element_zero);
+            return new filled_storage_zero_type(rows, cols, matrix_init_element_zero);
         case matrix_density_filled_empty:
             return new filled_storage_type(rows, cols, matrix_init_element_empty);
         case matrix_density_sparse_zero:
@@ -77,7 +77,7 @@ mixed_type_matrix<_String,_Flag>::mixed_type_matrix(const mixed_type_matrix& r)
 template<typename _String, typename _Flag>
 mixed_type_matrix<_String,_Flag>::~mixed_type_matrix()
 {
-    delete mp_storage;
+    delete_storage();
 }
 
 template<typename _String, typename _Flag>
@@ -102,7 +102,7 @@ mixed_type_matrix<_String,_Flag>::operator= (const mixed_type_matrix& r)
         // self assignment.
         return *this;
 
-    delete mp_storage;
+    delete_storage();
     mp_storage = r.mp_storage->clone();
     return *this;
 }
@@ -299,4 +299,23 @@ void mixed_type_matrix<_String,_Flag>::dump_flags() const
 }
 #endif
 
+template<typename _String, typename _Flag>
+void mixed_type_matrix<_String,_Flag>::delete_storage()
+{
+    switch (mp_storage->get_storage_type())
+    {
+        case matrix_storage_filled:
+            delete static_cast<filled_storage_type*>(mp_storage);
+        break;
+        case matrix_storage_filled_zero:
+            delete static_cast<filled_storage_zero_type*>(mp_storage);
+        break;
+        case matrix_storage_sparse:
+            delete static_cast<sparse_storage_type*>(mp_storage);
+        break;
+        default:
+            assert(!"unknown storage type!");
+    }
+}
+
 }
diff --git a/include/mdds/mixed_type_matrix_storage.hpp b/include/mdds/mixed_type_matrix_storage.hpp
index 2f95bf9..91456df 100644
--- a/include/mdds/mixed_type_matrix_storage.hpp
+++ b/include/mdds/mixed_type_matrix_storage.hpp
@@ -32,12 +32,14 @@
 
 #include <boost/ptr_container/ptr_vector.hpp>
 #include <boost/ptr_container/ptr_map.hpp>
+#include <boost/pool/object_pool.hpp>
 
 namespace mdds {
 
 enum matrix_storage_t
 {
     matrix_storage_filled,
+    matrix_storage_filled_zero,
     matrix_storage_sparse
 };
 
@@ -84,22 +86,6 @@ public:
         m_row_itr(r.m_row_itr),
         m_row_itr_end(r.m_row_itr_end) {}
 
-    /**
-     * Set the current iterator position to the end position.
-     */
-    void set_to_end()
-    {
-        if (empty())
-            return;
-
-        m_rows_itr = m_rows_itr_end;
-        typename store_type::rows_type::const_iterator itr = m_rows_itr_end;
-        --itr; // Move to the last row.
-
-        // They both need to be at the end position of the last row.
-        m_row_itr = m_row_itr_end = m_rows_wrap(itr).end();
-    }
-
     bool operator== (const const_itr_access& r) const
     {
         if (&m_db != &r.m_db)
@@ -126,12 +112,6 @@ public:
 
     bool empty() const { return m_db.get_rows().begin() == m_rows_itr_end; }
 
-    void update_row_itr()
-    {
-        m_row_itr = m_rows_wrap(m_rows_itr).begin();
-        m_row_itr_end = m_rows_wrap(m_rows_itr).end();
-    }
-
     const element& get() const { return m_wrap(m_row_itr); }
 
     bool inc()
@@ -186,6 +166,30 @@ public:
         return true;
     }
 
+    /**
+     * Set the current iterator position to the end position.
+     */
+    void set_to_end()
+    {
+        if (empty())
+            return;
+
+        m_rows_itr = m_rows_itr_end;
+        typename store_type::rows_type::const_iterator itr = m_rows_itr_end;
+        --itr; // Move to the last row.
+
+        // They both need to be at the end position of the last row.
+        m_row_itr = m_row_itr_end = m_rows_wrap(itr).end();
+    }
+
+private:
+
+    void update_row_itr()
+    {
+        m_row_itr = m_rows_wrap(m_rows_itr).begin();
+        m_row_itr_end = m_rows_wrap(m_rows_itr).end();
+    }
+
 private:
     const store_type& m_db;
     typename store_type::rows_type::const_iterator m_rows_itr;
@@ -205,12 +209,15 @@ public:
     typedef typename _MatrixType::element               element;
     typedef typename _MatrixType::flag_storage          flag_storage;
     typedef typename _MatrixType::string_type           string_type;
-    typedef typename _MatrixType::filled_storage_type   filled_storage_type;
-    typedef typename _MatrixType::sparse_storage_type   sparse_storage_type;
+
+    typedef typename _MatrixType::filled_storage_type filled_storage_type;
+    typedef typename _MatrixType::filled_storage_zero_type filled_storage_zero_type;
+    typedef typename _MatrixType::sparse_storage_type sparse_storage_type;
 
     class const_iterator
     {
         typedef typename filled_storage_type::const_itr_access filled_access_type;
+        typedef typename filled_storage_zero_type::const_itr_access filled_zero_access_type;
         typedef typename sparse_storage_type::const_itr_access sparse_access_type;
     public:
         // iterator traits
@@ -235,6 +242,9 @@ public:
                     case matrix_storage_filled:
                         get_filled_itr()->set_to_end();
                     break;
+                    case matrix_storage_filled_zero:
+                        get_filled_zero_itr()->set_to_end();
+                    break;
                     case matrix_storage_sparse:
                         get_sparse_itr()->set_to_end();
                     break;
@@ -256,6 +266,9 @@ public:
                 case matrix_storage_filled:
                     m_const_itr_access = new filled_access_type(*r.get_filled_itr());
                 break;
+                case matrix_storage_filled_zero:
+                    m_const_itr_access = new filled_zero_access_type(*r.get_filled_zero_itr());
+                break;
                 case matrix_storage_sparse:
                     m_const_itr_access = new sparse_access_type(*r.get_sparse_itr());
                 break;
@@ -271,6 +284,9 @@ public:
                 case matrix_storage_filled:
                     delete get_filled_itr();
                 break;
+                case matrix_storage_filled_zero:
+                    delete get_filled_zero_itr();
+                break;
                 case matrix_storage_sparse:
                     delete get_sparse_itr();
                 break;
@@ -302,6 +318,8 @@ public:
             {
                 case matrix_storage_filled:
                     return get_filled_itr()->get();
+                case matrix_storage_filled_zero:
+                    return get_filled_zero_itr()->get();
                 case matrix_storage_sparse:
                     return get_sparse_itr()->get();
                 default:
@@ -316,6 +334,8 @@ public:
             {
                 case matrix_storage_filled:
                     return &get_filled_itr()->get();
+                case matrix_storage_filled_zero:
+                    return &get_filled_zero_itr()->get();
                 case matrix_storage_sparse:
                     return &get_sparse_itr()->get();
                 default:
@@ -332,6 +352,9 @@ public:
                 case matrix_storage_filled:
                     has_next = get_filled_itr()->inc();
                 break;
+                case matrix_storage_filled_zero:
+                    has_next = get_filled_zero_itr()->inc();
+                break;
                 case matrix_storage_sparse:
                     has_next = get_sparse_itr()->inc();
                 break;
@@ -349,6 +372,9 @@ public:
                 case matrix_storage_filled:
                     has_next = get_filled_itr()->dec();
                 break;
+                case matrix_storage_filled_zero:
+                    has_next = get_filled_zero_itr()->dec();
+                break;
                 case matrix_storage_sparse:
                     has_next = get_sparse_itr()->dec();
                 break;
@@ -375,6 +401,8 @@ public:
             {
                 case matrix_storage_filled:
                     return *get_filled_itr() == *r.get_filled_itr();
+                case matrix_storage_filled_zero:
+                    return *get_filled_zero_itr() == *r.get_filled_zero_itr();
                 case matrix_storage_sparse:
                     return *get_sparse_itr() == *r.get_sparse_itr();
                 default:
@@ -389,6 +417,7 @@ public:
         }
 
     private:
+
         filled_access_type* get_filled_itr()
         {
             return static_cast<filled_access_type*>(m_const_itr_access);
@@ -399,6 +428,16 @@ public:
             return static_cast<const filled_access_type*>(m_const_itr_access);
         }
 
+        filled_zero_access_type* get_filled_zero_itr()
+        {
+            return static_cast<filled_zero_access_type*>(m_const_itr_access);
+        }
+
+        const filled_zero_access_type* get_filled_zero_itr() const
+        {
+            return static_cast<const filled_zero_access_type*>(m_const_itr_access);
+        }
+
         sparse_access_type* get_sparse_itr()
         {
             return static_cast<sparse_access_type*>(m_const_itr_access);
@@ -430,12 +469,11 @@ public:
 
     matrix_storage_t get_storage_type() const { return m_store_type; }
 
-    /** 
-     * the destructor must remain virtual because the derived classes have 
-     * different sizes.  TODO: Figure out a way to remove the virtual-ness 
-     * without leaking memory. 
-     */ 
-    virtual ~storage_base() {}
+    /**
+     * When deleting the storage object, the caller must explicitly specify
+     * the concrete class or else memory will leak.
+     */
+    ~storage_base() {}
 
     const_iterator begin() const
     {
@@ -447,6 +485,12 @@ public:
                 return const_iterator(p, m_store_type);
             }
             break;
+            case matrix_storage_filled_zero:
+            {
+                void* p = static_cast<const filled_storage_zero_type*>(this)->get_const_itr_access();
+                return const_iterator(p, m_store_type);
+            }
+            break;
             case matrix_storage_sparse:
             {
                 void* p = static_cast<const sparse_storage_type*>(this)->get_const_itr_access();
@@ -469,6 +513,12 @@ public:
                 return const_iterator(p, m_store_type, true);
             }
             break;
+            case matrix_storage_filled_zero:
+            {
+                void* p = static_cast<const filled_storage_zero_type*>(this)->get_const_itr_access();
+                return const_iterator(p, m_store_type, true);
+            }
+            break;
             case matrix_storage_sparse:
             {
                 void* p = static_cast<const sparse_storage_type*>(this)->get_const_itr_access();
@@ -487,6 +537,8 @@ public:
         {
             case matrix_storage_filled:
                 return static_cast<filled_storage_type*>(this)->get_element(row, col);
+            case matrix_storage_filled_zero:
+                return static_cast<filled_storage_zero_type*>(this)->get_element(row, col);
             case matrix_storage_sparse:
                 return static_cast<sparse_storage_type*>(this)->get_element(row, col);
             default:
@@ -501,6 +553,8 @@ public:
         {
             case matrix_storage_filled:
                 return static_cast<const filled_storage_type*>(this)->get_type(row, col);
+            case matrix_storage_filled_zero:
+                return static_cast<const filled_storage_zero_type*>(this)->get_type(row, col);
             case matrix_storage_sparse:
                 return static_cast<const sparse_storage_type*>(this)->get_type(row, col);
             default:
@@ -515,6 +569,8 @@ public:
         {
             case matrix_storage_filled:
                 return static_cast<const filled_storage_type*>(this)->get_numeric(row, col);
+            case matrix_storage_filled_zero:
+                return static_cast<const filled_storage_zero_type*>(this)->get_numeric(row, col);
             case matrix_storage_sparse:
                 return static_cast<const sparse_storage_type*>(this)->get_numeric(row, col);
             default:
@@ -529,6 +585,8 @@ public:
         {
             case matrix_storage_filled:
                 return static_cast<const filled_storage_type*>(this)->get_string(row, col);
+            case matrix_storage_filled_zero:
+                return static_cast<const filled_storage_zero_type*>(this)->get_string(row, col);
             case matrix_storage_sparse:
                 return static_cast<const sparse_storage_type*>(this)->get_string(row, col);
             default:
@@ -543,6 +601,8 @@ public:
         {
             case matrix_storage_filled:
                 return static_cast<const filled_storage_type*>(this)->get_boolean(row, col);
+            case matrix_storage_filled_zero:
+                return static_cast<const filled_storage_zero_type*>(this)->get_boolean(row, col);
             case matrix_storage_sparse:
                 return static_cast<const sparse_storage_type*>(this)->get_boolean(row, col);
             default:
@@ -557,6 +617,8 @@ public:
         {
             case matrix_storage_filled:
                 return static_cast<const filled_storage_type*>(this)->rows();
+            case matrix_storage_filled_zero:
+                return static_cast<const filled_storage_zero_type*>(this)->rows();
             case matrix_storage_sparse:
                 return static_cast<const sparse_storage_type*>(this)->rows();
             default:
@@ -571,6 +633,8 @@ public:
         {
             case matrix_storage_filled:
                 return static_cast<const filled_storage_type*>(this)->cols();
+            case matrix_storage_filled_zero:
+                return static_cast<const filled_storage_zero_type*>(this)->cols();
             case matrix_storage_sparse:
                 return static_cast<const sparse_storage_type*>(this)->cols();
             default:
@@ -586,6 +650,9 @@ public:
             case matrix_storage_filled:
                 static_cast<filled_storage_type*>(this)->transpose();
             break;
+            case matrix_storage_filled_zero:
+                static_cast<filled_storage_zero_type*>(this)->transpose();
+            break;
             case matrix_storage_sparse:
                 static_cast<sparse_storage_type*>(this)->transpose();
             break;
@@ -601,6 +668,9 @@ public:
             case matrix_storage_filled:
                 static_cast<filled_storage_type*>(this)->resize(row, col);
             break;
+            case matrix_storage_filled_zero:
+                static_cast<filled_storage_zero_type*>(this)->resize(row, col);
+            break;
             case matrix_storage_sparse:
                 static_cast<sparse_storage_type*>(this)->resize(row, col);
             break;
@@ -616,6 +686,9 @@ public:
             case matrix_storage_filled:
                 static_cast<filled_storage_type*>(this)->clear();
             break;
+            case matrix_storage_filled_zero:
+                static_cast<filled_storage_zero_type*>(this)->clear();
+            break;
             case matrix_storage_sparse:
                 static_cast<sparse_storage_type*>(this)->clear();
             break;
@@ -630,6 +703,8 @@ public:
         {
             case matrix_storage_filled:
                 return static_cast<filled_storage_type*>(this)->numeric();
+            case matrix_storage_filled_zero:
+                return static_cast<filled_storage_zero_type*>(this)->numeric();
             case matrix_storage_sparse:
                 return static_cast<sparse_storage_type*>(this)->numeric();
             default:
@@ -644,6 +719,8 @@ public:
         {
             case matrix_storage_filled:
                 return static_cast<const filled_storage_type*>(this)->empty();
+            case matrix_storage_filled_zero:
+                return static_cast<const filled_storage_zero_type*>(this)->empty();
             case matrix_storage_sparse:
                 return static_cast<const sparse_storage_type*>(this)->empty();
             default:
@@ -658,6 +735,8 @@ public:
         {
             case matrix_storage_filled:
                 return static_cast<const filled_storage_type*>(this)->clone();
+            case matrix_storage_filled_zero:
+                return static_cast<const filled_storage_zero_type*>(this)->clone();
             case matrix_storage_sparse:
                 return static_cast<const sparse_storage_type*>(this)->clone();
             default:
@@ -677,628 +756,10 @@ private:
     flag_storage            m_flags;
 };
 
-/**
- * This storage creates instance for every single element, even for the
- * empty elements. 
- */
-template<typename _MatrixType>
-class storage_filled : public ::mdds::storage_base<_MatrixType>
-{
-    typedef _MatrixType matrix_type;
-    typedef typename matrix_type::string_type   string_type;
-
-public:
-    typedef typename matrix_type::element element;
-    typedef ::boost::ptr_vector<element>  row_type;
-    typedef ::boost::ptr_vector<row_type> rows_type;
-
-    struct elem_wrap
-    {
-        const element& operator() (const typename row_type::const_iterator& itr) const 
-        { 
-            return *itr; 
-        }
-    };
-    struct rows_wrap
-    {
-        const row_type& operator() (const typename rows_type::const_iterator& itr) const
-        { 
-            return *itr;
-        }
-    };
-    typedef ::mdds::const_itr_access<storage_filled, elem_wrap, rows_wrap> const_itr_access;
-
-    storage_filled(size_t _rows, size_t _cols, matrix_init_element_t init_type) :
-        storage_base<matrix_type>(matrix_storage_filled, init_type),
-        m_numeric(false),
-        m_valid(false)
-    {
-        m_rows.reserve(_rows);
-        for (size_t i = 0; i < _rows; ++i)
-        {
-            m_rows.push_back(new row_type);
-            init_row(m_rows.back(), _cols);
-        }
-    }
-
-    storage_filled(const storage_filled& r) :
-        storage_base<matrix_type>(r),
-        m_rows(r.m_rows),
-        m_numeric(r.m_numeric),
-        m_valid(r.m_valid) {}
-
-    virtual ~storage_filled() {}
-
-    const_itr_access* get_const_itr_access() const
-    {
-        return new const_itr_access(*this);
-    }
-
-    element& get_element(size_t row, size_t col)
-    {
-        m_valid = false;
-        return m_rows.at(row).at(col);
-    }
-
-    matrix_element_t get_type(size_t row, size_t col) const
-    {
-        return m_rows.at(row).at(col).m_type;
-    }
-
-    double get_numeric(size_t row, size_t col) const
-    {
-        const element& elem = m_rows.at(row).at(col);
-        switch (elem.m_type)
-        {
-            case element_numeric:
-                return elem.m_numeric;
-            case element_boolean:
-                return static_cast<double>(elem.m_boolean);
-            case element_empty:
-            default:
-                ;
-        }
-        return 0.0;
-    }
-
-    const string_type* get_string(size_t row, size_t col) const
-    {
-        const element& elem = m_rows.at(row).at(col);
-        if (elem.m_type != element_string)
-            throw matrix_storage_error("element type is not string.");
-
-        return elem.mp_string;
-    }
-
-    bool get_boolean(size_t row, size_t col) const
-    {
-        const element& elem = m_rows.at(row).at(col);
-        if (elem.m_type != element_boolean)
-            throw matrix_storage_error("element type is not boolean.");
-
-        return elem.m_boolean;
-    }
-
-    size_t rows() const
-    {
-        return m_rows.size();
-    }
-
-    size_t cols() const
-    {
-        return m_rows.empty() ? 0 : m_rows[0].size();
-    }
-
-    void transpose()
-    {
-        rows_type trans_mx;
-        size_t row_size = rows(), col_size = cols();
-        trans_mx.reserve(col_size);
-        for (size_t col = 0; col < col_size; ++col)
-        {
-            trans_mx.push_back(new row_type);
-            row_type& trans_row = trans_mx.back();
-            trans_row.reserve(row_size);
-            for (size_t row = 0; row < row_size; ++row)
-                trans_row.push_back(new element(m_rows[row][col]));
-        }
-        m_rows.swap(trans_mx);
-    }
-
-    void resize(size_t row, size_t col)
-    {
-        m_valid = false;
-        if (!row || !col)
-        {
-            // Empty the matrix.
-            clear();
-            return;
-        }
-
-        size_t cur_rows = rows(), cur_cols = cols();
-
-        if (!cur_rows || !cur_cols)
-        {
-            // current matrix is empty.
-            rows_type new_rows;
-            new_rows.reserve(row);
-            for (size_t i = 0; i < row; ++i)
-            {
-                new_rows.push_back(new row_type);
-                init_row(new_rows.back(), col);
-            }
-            m_rows.swap(new_rows);
-            return;
-        }
-
-        if (row > cur_rows)
-        {
-            // Insert extra rows...
-            size_t new_row_count = row - cur_rows;
-            m_rows.reserve(row);
-            for (size_t i = 0; i < new_row_count; ++i)
-            {
-                m_rows.push_back(new row_type);
-                init_row(m_rows.back(), col);
-            }
-
-            resize_rows(cur_rows-1, cur_cols, col);
-        }
-        else if (cur_rows > row)
-        {
-            // Remove rows to new size.
-            m_rows.resize(row);
-            resize_rows(row-1, cur_cols, col);
-        }
-        else
-        {
-            assert(cur_rows == row);
-            resize_rows(cur_rows-1, cur_cols, col);
-        }
-    }
-
-    void clear()
-    {
-        m_rows.clear();
-        m_valid = true;
-        m_numeric = false;
-    }
-
-    bool numeric()
-    {
-        if (m_valid)
-            return m_numeric;
-
-        typename rows_type::const_iterator itr_row = m_rows.begin(), itr_row_end = m_rows.end();
-        for (; itr_row != itr_row_end; ++itr_row)
-        {
-            typename row_type::const_iterator itr_col = itr_row->begin(), itr_col_end = itr_row->end();
-            for (; itr_col != itr_col_end; ++itr_col)
-            {
-                matrix_element_t elem_type = itr_col->m_type;
-                if (elem_type != element_numeric && elem_type != element_boolean)
-                {
-                    m_numeric = false;
-                    m_valid = true;
-                    return m_numeric;
-                }
-            }
-        }
-
-        m_numeric = true;
-        m_valid = true;
-        return m_numeric;
-    }
-
-    bool empty() const
-    {
-        return m_rows.empty();
-    }
-
-    ::mdds::storage_base<matrix_type>* clone() const
-    {
-        return new storage_filled(*this);
-    }
-
-    const rows_type& get_rows() const { return m_rows; }
-
-private:
-
-    /**
-     * Resize rows to a new column size, from row 0 up to specified upper 
-     * row. 
-     */
-    void resize_rows(size_t upper_row, size_t cur_cols, size_t new_cols)
-    {
-        for (size_t i = 0; i <= upper_row; ++i)
-        {
-            // Resize pre-existing rows to new column size.
-            if (new_cols > cur_cols)
-            {
-                size_t new_col_count = new_cols - cur_cols;
-                for (size_t j = 0; j < new_col_count; ++j)
-                    insert_new_elem(m_rows[i]);
-            }
-            else if (new_cols < cur_cols)
-                m_rows[i].resize(new_cols);
-        }
-    }
-
-    void init_row(row_type& row, size_t col_size)
-    {
-        row.reserve(col_size);
-        for (size_t j = 0; j < col_size; ++j)
-            insert_new_elem(row);
-    }
-
-    void insert_new_elem(row_type& row)
-    {
-        matrix_init_element_t init_type = storage_base<matrix_type>::get_init_type();
-        switch (init_type)
-        {
-            case matrix_init_element_zero:
-                row.push_back(new element(static_cast<double>(0.0)));
-            break;
-            case matrix_init_element_empty:
-                row.push_back(new element);
-            break;
-            default:
-                throw matrix_storage_error("unknown init type.");
-        }
-    }
-
-private:
-    rows_type m_rows;
-    bool m_numeric:1;
-    bool m_valid:1;
-};
-
-/**
- * This storage stores only non-empty elements. 
- */
-template<typename _MatrixType>
-class storage_sparse : public storage_base<_MatrixType>
-{
-    typedef _MatrixType matrix_type;
-
-    typedef typename matrix_type::string_type  string_type;
-
-public:
-    typedef typename matrix_type::element      element;
-    typedef ::boost::ptr_map<size_t, element>  row_type;
-    typedef ::boost::ptr_map<size_t, row_type> rows_type;
-    struct elem_wrap
-    {
-        const element& operator() (const typename row_type::const_iterator& itr) const
-        {
-            return *itr->second;
-        }
-    };
-    struct rows_wrap
-    {
-        const row_type& operator() (const typename rows_type::const_iterator& itr) const
-        {
-            return *itr->second;
-        }
-    };
-    typedef ::mdds::const_itr_access<storage_sparse, elem_wrap, rows_wrap> const_itr_access;
-
-    storage_sparse(size_t _rows, size_t _cols, matrix_init_element_t init_type) : 
-        storage_base<matrix_type>(matrix_storage_sparse, init_type),
-        m_row_size(_rows), m_col_size(_cols),
-        m_numeric(_rows && _cols), m_valid(true)
-    {
-        switch (storage_base<matrix_type>::get_init_type())
-        {
-            case matrix_init_element_zero:
-                m_empty_elem.m_type = element_numeric;
-                m_empty_elem.m_numeric = 0.0;
-            break;
-            default:
-                m_empty_elem.m_type = element_empty;
-                m_numeric = false;
-        }
-    }
-
-    storage_sparse(const storage_sparse& r) :
-        storage_base<matrix_type>(r),
-        m_rows(r.m_rows), 
-        m_empty_elem(r.m_empty_elem), 
-        m_row_size(r.m_row_size), 
-        m_col_size(r.m_col_size) {}
-
-    virtual ~storage_sparse() {}
-
-    const_itr_access* get_const_itr_access() const { return new const_itr_access(*this); }
-
-    element & get_element(size_t row, size_t col)
-    {
-        if (row >= m_row_size || col >= m_col_size)
-            throw matrix_storage_error("specified element is out-of-bound.");
-
-        m_valid = false;
-
-        typename rows_type::iterator itr = m_rows.find(row);
-        if (itr == m_rows.end())
-        {
-            // Insert a brand-new row.
-            ::std::pair<typename rows_type::iterator, bool> r = m_rows.insert(row, new row_type);
-            if (!r.second)
-                throw matrix_storage_error("failed to insert a new row instance into storage_sparse.");
-            itr = r.first;
-        }
-
-        row_type& row_store = *itr->second;
-        typename row_type::iterator itr_elem = row_store.find(col);
-        if (itr_elem == row_store.end())
-        {
-            // Insert a new element at this column position.
-            ::std::pair<typename row_type::iterator, bool> r = row_store.insert(col, new element);
-            if (!r.second)
-                throw matrix_storage_error("failed to insert a new element instance.");
-            itr_elem = r.first;
-        }
-        return *itr_elem->second;
-    }
-
-    matrix_element_t get_type(size_t row, size_t col) const
-    {
-        typename rows_type::const_iterator itr = m_rows.find(row);
-        if (itr == m_rows.end())
-            return m_empty_elem.m_type;
-
-        const row_type& row_store = *itr->second;
-        typename row_type::const_iterator itr_elem = row_store.find(col);
-        if (itr_elem == row_store.end())
-            return m_empty_elem.m_type;
-
-        return itr_elem->second->m_type;
-    }
-
-    double get_numeric(size_t row, size_t col) const
-    {
-        const element& elem = get_non_empty_element(row, col);
-        switch (elem.m_type)
-        {
-            case element_numeric:
-                return elem.m_numeric;
-            case element_boolean:
-                return static_cast<double>(elem.m_boolean);
-            case element_empty:
-            default:
-                ;
-        }
-        return 0.0;
-    }
-
-    const string_type* get_string(size_t row, size_t col) const
-    {
-        matrix_element_t elem_type = get_type(row, col);
-        if (elem_type != element_string)
-            throw matrix_storage_error("element type is not string.");
-
-        return get_non_empty_element(row, col).mp_string;
-    }
-
-    bool get_boolean(size_t row, size_t col) const
-    {
-        matrix_element_t elem_type = get_type(row, col);
-        if (elem_type != element_boolean)
-            throw matrix_storage_error("element type is not string.");
-
-        return get_non_empty_element(row, col).m_boolean;
-    }
-
-    size_t rows() const
-    {
-        return m_row_size;
-    }
-
-    size_t cols() const
-    {
-        return m_col_size;
-    }
-
-    typedef ::std::pair<size_t, size_t> elem_pos_type;
-
-    struct elem_pos_sorter : public ::std::binary_function<elem_pos_type, elem_pos_type, bool>
-    {
-        bool operator() (const elem_pos_type& left, const elem_pos_type& right) const
-        {
-            if (left.first != right.first)
-                return left.first < right.first;
-            return left.second < right.second;
-        }
-    };
-
-    void transpose()
-    {
-        using namespace std;
-
-        rows_type trans;
-
-        // First, pick up the positions of all non-empty elements.
-        vector<elem_pos_type> filled_elems;
-        {
-            typename rows_type::const_iterator itr_row = m_rows.begin(), itr_row_end = m_rows.end();
-            for (; itr_row != itr_row_end; ++itr_row)
-            {
-                size_t row_idx = itr_row->first;
-                const row_type& row = *itr_row->second;
-                typename row_type::const_iterator itr_col = row.begin(), itr_col_end = row.end();
-                for (; itr_col != itr_col_end; ++itr_col)
-                {
-                    // Be sure to swap the row and column indices.
-                    filled_elems.push_back(elem_pos_type(itr_col->first, row_idx));
-                }
-            }
-        }
-        // Sort by row index first, then by column index.
-        sort(filled_elems.begin(), filled_elems.end(), elem_pos_sorter());
-
-        // Iterate through the non-empty element positions and perform 
-        // transposition.
-        typename vector<elem_pos_type>::const_iterator 
-            itr_pos = filled_elems.begin(), itr_pos_end = filled_elems.end();
-        while (itr_pos != itr_pos_end)
-        {
-            // First item of the new row.
-            size_t row_idx = itr_pos->first;
-            size_t col_idx = itr_pos->second;
-            pair<typename rows_type::iterator, bool> r = trans.insert(row_idx, new row_type);
-            if (!r.second)
-                throw matrix_storage_error("failed to insert a new row instance during transposition.");
-
-            typename rows_type::iterator itr_row = r.first;
-            row_type& row = *itr_row->second;
-            pair<typename row_type::iterator, bool> r2 = 
-                row.insert(col_idx, new element(m_rows[col_idx][row_idx]));
-            if (!r2.second)
-                throw matrix_storage_error("afiled to insert a new element instance during transposition.");
-
-            // Keep iterating until we get a different row index.
-            for (++itr_pos; itr_pos != itr_pos_end && itr_pos->first == row_idx; ++itr_pos)
-            {
-                col_idx = itr_pos->second;
-                r2 = row.insert(col_idx, new element(m_rows[col_idx][row_idx]));
-                if (!r2.second)
-                    throw matrix_storage_error("afiled to insert a new element instance during transposition.");
-            }
-        }
-
-        m_rows.swap(trans);
-        ::std::swap(m_row_size, m_col_size);
-    }
-
-    void resize(size_t row, size_t col)
-    {
-        m_valid = false;
-
-        if (!row || !col)
-        {
-            clear();
-            return;
-        }
-
-        // Resizing a sparse matrix need to modify the data only when 
-        // shrinking.
-
-        if (m_row_size > row)
-        {
-            // Remove all rows where the row index is greater than or 
-            // equal to 'row'.
-            typename rows_type::iterator itr = m_rows.lower_bound(row);
-            m_rows.erase(itr, m_rows.end());
-        }
-
-        if (m_col_size > col)
-        {
-            typename rows_type::iterator itr = m_rows.begin(), itr_end = m_rows.end();
-            for (; itr != itr_end; ++itr)
-            {
-                // Now, remove all columns where the column index is 
-                // greater than or equal to 'col'.
-                row_type& row_container = *itr->second;
-                typename row_type::iterator itr_elem = row_container.lower_bound(col);
-                row_container.erase(itr_elem, row_container.end());
-            }
-        }
-
-        m_row_size = row;
-        m_col_size = col;
-    }
-
-    void clear()
-    {
-        m_rows.clear();
-        m_row_size = 0;
-        m_col_size = 0;
-        m_valid = true;
-        m_numeric = false;
-    }
-
-    bool numeric()
-    {
-        using namespace std;
-
-        if (m_valid)
-            return m_numeric;
-
-        size_t non_empty_count = 0;
-        typename rows_type::const_iterator itr_row = m_rows.begin(), itr_row_end = m_rows.end();
-        for (; itr_row != itr_row_end; ++itr_row)
-        {
-            const row_type& row = *itr_row->second;
-            non_empty_count += row.size();
-            assert(row.size() <= m_col_size);
-            typename row_type::const_iterator itr_col = row.begin(), itr_col_end = row.end();
-            for (; itr_col != itr_col_end; ++itr_col)
-            {
-                const element& elem = *itr_col->second;
-                if (elem.m_type != element_numeric && elem.m_type != element_boolean)
-                {
-                    m_valid = true;
-                    m_numeric = false;
-                    return m_numeric;
-                }
-            }
-        }
-
-        // All non-empty elements are numeric.
-
-        matrix_init_element_t init_type = storage_base<matrix_type>::get_init_type();
-        if (init_type == matrix_init_element_zero)
-            m_numeric = true;
-        else
-        {    
-            size_t total_elem_count = m_row_size * m_col_size;
-            assert(non_empty_count <= total_elem_count);
-            m_numeric = total_elem_count == non_empty_count;
-        }
-
-        m_valid = true;
-        return m_numeric;
-    }
-
-    bool empty() const
-    {
-        // If one of row and column sizes are zero, the other size must be
-        // zero, and vise versa.
-        assert((!m_row_size && !m_col_size) || (m_row_size && m_col_size));
-
-        return m_row_size == 0 || m_col_size == 0;
-    }
-
-    storage_base<matrix_type>* clone() const
-    {
-        return new storage_sparse(*this);
-    }
-
-    const rows_type& get_rows() const { return m_rows; }
-
-private:
-    const element& get_non_empty_element(size_t row, size_t col) const
-    {
-        typename rows_type::const_iterator itr = m_rows.find(row);
-        if (itr == m_rows.end())
-            return m_empty_elem;
-
-        const row_type& row_store = *itr->second;
-        typename row_type::const_iterator itr_elem = row_store.find(col);
-        if (itr_elem == row_store.end())
-            return m_empty_elem;
-        return *itr_elem->second;
-    }
-
-private:
-    rows_type   m_rows;
-    element     m_empty_elem;
-    size_t      m_row_size;
-    size_t      m_col_size;
-    bool        m_numeric:1;
-    bool        m_valid:1;
-};
-
 }
 
+#include "mixed_type_matrix_storage_filled_nested_array.inl"
+#include "mixed_type_matrix_storage_filled_linear.inl"
+#include "mixed_type_matrix_storage_sparse.inl"
+
 #endif
diff --git a/include/mdds/mixed_type_matrix_storage_filled_linear.inl b/include/mdds/mixed_type_matrix_storage_filled_linear.inl
new file mode 100644
index 0000000..bd400ec
--- /dev/null
+++ b/include/mdds/mixed_type_matrix_storage_filled_linear.inl
@@ -0,0 +1,701 @@
+/*************************************************************************
+ *
+ * Copyright (c) 2011 Kohei Yoshida
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ ************************************************************************/
+
+namespace mdds {
+
+/**
+ * Iterator wrapper for storage whose data provides standard iterators.
+ */
+template<typename _StoreType, typename _ItrWrap>
+class const_itr_access_linear
+{
+    typedef _StoreType store_type;
+    typedef _ItrWrap itr_wrap_type;
+public:
+    typedef typename store_type::element element;
+
+    const_itr_access_linear(const store_type& db) : 
+        m_db(db), 
+        m_itr(db.get_array().begin()),
+        m_itr_end(db.get_array().end()) {}
+
+    const_itr_access_linear(const const_itr_access_linear& r) :
+        m_db(r.m_db),
+        m_itr(r.m_itr),
+        m_itr_end(r.m_itr_end) {}
+
+    bool operator== (const const_itr_access_linear& r) const
+    {
+        if (&m_db != &r.m_db)
+            // different storage instances.
+            return false;
+
+        return m_itr == r.m_itr;
+    }
+
+    bool empty() const { return m_db.get_array().begin() == m_itr_end; }
+
+    const element& get() const
+    {
+        assert(m_itr != m_itr_end);
+        return m_itr_wrap(m_itr);
+    }
+
+    bool inc()
+    {
+        if (m_itr == m_itr_end)
+            return false;
+
+        ++m_itr;
+        return m_itr != m_itr_end;
+    }
+
+    bool dec()
+    {
+        if (m_itr == m_db.get_array().begin())
+            // already on the first element.
+            return false;
+
+        --m_itr;
+        return true;
+    }
+
+    /**
+     * Set the current iterator position to the end position.
+     */
+    void set_to_end()
+    {
+        if (empty())
+            return;
+
+        m_itr = m_itr_end;
+    }
+private:
+    const store_type& m_db;
+    itr_wrap_type m_itr_wrap;
+    typename store_type::array_type::const_iterator m_itr;
+    typename store_type::array_type::const_iterator m_itr_end;
+};
+
+/**
+ * Iterator access wrapper whose storage type is a C-style array with no
+ * standard iterators.
+ */
+template<typename _StoreType>
+class const_itr_access_array
+{
+    typedef _StoreType store_type;
+public:
+    typedef typename store_type::element element;
+
+    const_itr_access_array(const store_type& db) : 
+        m_db(db), 
+        m_array(db.get_array()),
+        m_size(db.rows()*db.cols()),
+        m_pos(0) {}
+
+    const_itr_access_array(const const_itr_access_array& r) :
+        m_db(r.m_db),
+        m_array(r.m_array),
+        m_size(r.m_size),
+        m_pos(r.m_pos) {}
+
+    bool operator== (const const_itr_access_array& r) const
+    {
+        if (&m_db != &r.m_db)
+            // different storage instances.
+            return false;
+
+        return m_array == r.m_array && m_size == r.m_size && m_pos == r.m_pos;
+    }
+
+    bool empty() const { return m_db.empty(); }
+
+    const element& get() const
+    {
+        return m_array[m_pos];
+    }
+
+    bool inc()
+    {
+        if (m_pos == m_size)
+            return false;
+
+        ++m_pos;
+        return m_pos != m_size;
+    }
+
+    bool dec()
+    {
+        if (m_pos == 0)
+            // already on the first element.
+            return false;
+
+        --m_pos;
+        return true;
+    }
+
+    /**
+     * Set the current iterator position to the end position.
+     */
+    void set_to_end()
+    {
+        if (empty())
+            return;
+
+        m_pos = m_size;
+    }
+private:
+    const store_type& m_db;
+    const typename store_type::element* m_array;
+    const size_t m_size;
+    size_t m_pos;
+};
+
+/**
+ * This storage creates instance for every single element, even for the
+ * empty elements. 
+ */
+template<typename _MatrixType>
+class storage_filled_linear : public ::mdds::storage_base<_MatrixType>
+{
+    typedef _MatrixType matrix_type;
+    typedef typename matrix_type::string_type string_type;
+
+public:
+    typedef typename matrix_type::element element;
+    typedef ::std::vector<element*> array_type;
+    struct itr_wrap
+    {
+        const element& operator() (const typename array_type::const_iterator& itr) const
+        {
+            return *(*itr);
+        }
+    };
+    typedef const_itr_access_linear<storage_filled_linear, itr_wrap> const_itr_access;
+
+    storage_filled_linear(size_t _rows, size_t _cols, matrix_init_element_t init_type) :
+        storage_base<matrix_type>(matrix_storage_filled, init_type),
+        m_element_pool(new ::boost::object_pool<element>),
+        m_rows(_rows),
+        m_cols(_cols),
+        m_numeric(false),
+        m_valid(false)
+    {
+        if (init_type == matrix_init_element_zero)
+            m_init_elem.set_numeric(0.0);
+
+        size_t n = m_rows * m_cols;
+        m_array.resize(n, &m_init_elem);
+    }
+
+    storage_filled_linear(const storage_filled_linear& r) :
+        storage_base<matrix_type>(r),
+        m_element_pool(new ::boost::object_pool<element>),
+        m_init_elem(r.m_init_elem),
+        m_rows(r.m_rows),
+        m_cols(r.m_cols),
+        m_numeric(r.m_numeric),
+        m_valid(r.m_valid)
+    {
+        size_t n = r.m_array.size();
+        if (!n)
+            return;
+
+        // Populate the array with initial values first.
+        m_array.resize(n, &m_init_elem);
+
+        for (size_t i = 0; i < n; ++i)
+        {
+            const element* p = r.m_array[i];
+            if (p != &r.m_init_elem)
+                // non-default value.  Duplicate the element instance.
+                m_array[i] = m_element_pool->construct(*p);
+        }
+    }
+
+    ~storage_filled_linear()
+    {
+        delete m_element_pool;
+    }
+
+    const_itr_access* get_const_itr_access() const
+    {
+        return new const_itr_access(*this);
+    }
+
+    element& get_element(size_t row, size_t col)
+    {
+        m_valid = false;
+        size_t pos = get_pos(row, col);
+        if (m_array.at(pos) == &m_init_elem)
+        {
+            // Initial element.  Instantiate a new element to take its place.
+            matrix_init_element_t init_type = storage_base<matrix_type>::get_init_type();
+            switch (init_type)
+            {
+                case matrix_init_element_zero:
+                    m_array[pos] = m_element_pool->construct(static_cast<double>(0.0));
+                break;
+                case matrix_init_element_empty:
+                    m_array[pos] = m_element_pool->construct();
+                break;
+                default:
+                    throw matrix_storage_error("unknown init type.");
+            }
+        }
+        return *m_array[pos];
+    }
+
+    matrix_element_t get_type(size_t row, size_t col) const
+    {
+        return m_array.at(get_pos(row, col))->m_type;
+    }
+
+    double get_numeric(size_t row, size_t col) const
+    {
+        const element& elem = *m_array.at(get_pos(row, col));
+        switch (elem.m_type)
+        {
+            case element_numeric:
+                return elem.m_numeric;
+            case element_boolean:
+                return static_cast<double>(elem.m_boolean);
+            case element_empty:
+            default:
+                ;
+        }
+        return 0.0;
+    }
+
+    const string_type* get_string(size_t row, size_t col) const
+    {
+        const element& elem = *m_array.at(get_pos(row, col));
+        if (elem.m_type != element_string)
+            throw matrix_storage_error("element type is not string.");
+
+        return elem.mp_string;
+    }
+
+    bool get_boolean(size_t row, size_t col) const
+    {
+        const element& elem = *m_array.at(get_pos(row, col));
+        if (elem.m_type != element_boolean)
+            throw matrix_storage_error("element type is not boolean.");
+
+        return elem.m_boolean;
+    }
+
+    size_t rows() const
+    {
+        return m_rows;
+    }
+
+    size_t cols() const
+    {
+        return m_cols;
+    }
+
+    void transpose()
+    {
+        array_type trans_array(m_array.size(), &m_init_elem);
+        for (size_t i = 0; i < m_rows; ++i)
+            for (size_t j = 0; j < m_cols; ++j)
+                trans_array[m_rows*j+i] = m_array[get_pos(i,j)];
+
+        m_array.swap(trans_array);
+        ::std::swap(m_rows, m_cols);
+    }
+
+    void resize(size_t row, size_t col)
+    {
+        m_valid = false;
+        if (!row || !col)
+        {
+            // Empty the matrix.
+            clear();
+            m_rows = row;
+            m_cols = col;
+            return;
+        }
+
+        size_t new_size = row * col;
+        if (m_array.empty())
+        {
+            // Current matrix is empty.
+            m_array.resize(new_size, &m_init_elem);
+            m_rows = row;
+            m_cols = col;
+            return;
+        }
+
+        array_type new_array(new_size, &m_init_elem);
+        size_t min_rows = ::std::min(row, m_rows);
+        size_t min_cols = ::std::min(col, m_cols);
+        for (size_t i = 0; i < min_rows; ++i)
+        {
+            for (size_t j = 0; j < min_cols; ++j)
+                new_array[col*i+j] = m_array[get_pos(i, j)];
+        }
+
+        if (row < m_rows)
+        {
+            // Delete all element instances that are in the rows being stripped off.
+            for (size_t i = row; i < m_rows; ++i)
+            {
+                for (size_t j = 0; j < m_cols; ++j)
+                {
+                    element* p = m_array[get_pos(i, j)];
+                    if (p != &m_init_elem)
+                        m_element_pool->destroy(p);
+                }
+            }
+        }
+
+        if (col < m_cols)
+        {
+            // Delete all elements in the columns that are being stripped off.
+            for (size_t i = 0; i < min_rows; ++i)
+            {
+                for (size_t j = col; j < m_cols; ++j)
+                {
+                    element* p = m_array[get_pos(i, j)];
+                    if (p != &m_init_elem)
+                        m_element_pool->destroy(p);
+                }
+            }
+        }
+
+        m_array.swap(new_array);
+        m_rows = row;
+        m_cols = col;
+    }
+
+    void clear()
+    {
+        delete m_element_pool;
+        m_element_pool = new ::boost::object_pool<element>;
+        m_array.clear();
+        m_valid = true;
+        m_numeric = false;
+    }
+
+    bool numeric()
+    {
+        if (m_valid)
+            return m_numeric;
+
+        typename array_type::const_iterator itr = m_array.begin(), itr_end = m_array.end();
+        for (; itr != itr_end; ++itr)
+        {
+            const element* p = *itr;
+            matrix_element_t elem_type = p->m_type;
+            if (elem_type != element_numeric && elem_type != element_boolean)
+            {
+                m_numeric = false;
+                m_valid = true;
+                return m_numeric;
+            }
+        }
+
+        m_numeric = true;
+        m_valid = true;
+        return m_numeric;
+    }
+
+    bool empty() const
+    {
+        return m_array.empty();
+    }
+
+    ::mdds::storage_base<matrix_type>* clone() const
+    {
+        return new storage_filled_linear(*this);
+    }
+
+    const array_type& get_array() const { return m_array; }
+
+private:
+
+    /**
+     * Get an array position of the data referenced by the row and column 
+     * indices.  The array consists of multiple rows, the content of row 0 
+     * followded by the content of row 1, and so on.  <b>Note that no 
+     * boundary check is performed in this method.</b> 
+     *  
+     * @param row 0-based row index.
+     * @param col 0-based column index.
+     * @return position in the data array. 
+     */
+    size_t get_pos(size_t row, size_t col) const
+    {
+        return m_cols * row + col;
+    }
+
+private:
+    ::boost::object_pool<element>* m_element_pool;
+    array_type m_array;
+    element m_init_elem;
+    size_t m_rows;
+    size_t m_cols;
+    bool m_numeric:1;
+    bool m_valid:1;
+};
+
+/**
+ * All elements are filled with unique numeric element instances, with their
+ * initial values being zero.
+ */
+template<typename _MatrixType>
+class storage_filled_linear_zero : public ::mdds::storage_base<_MatrixType>
+{
+    typedef _MatrixType matrix_type;
+    typedef typename matrix_type::string_type string_type;
+
+public:
+    typedef typename matrix_type::element element;
+    typedef ::std::vector<element> array_type;
+    struct itr_wrap
+    {
+        const element& operator() (const typename array_type::const_iterator& itr) const
+        {
+            return *itr;
+        }
+    };
+    typedef const_itr_access_linear<storage_filled_linear_zero, itr_wrap> const_itr_access;
+
+    storage_filled_linear_zero(size_t _rows, size_t _cols, matrix_init_element_t init_type) :
+        storage_base<matrix_type>(matrix_storage_filled_zero, init_type),
+        m_rows(_rows),
+        m_cols(_cols),
+        m_numeric(false),
+        m_valid(false)
+    {
+        assert(init_type == matrix_init_element_zero);
+
+        size_t n = m_rows * m_cols;
+        if (!n)
+            return;
+
+        m_array.resize(n, element(0.0));
+    }
+
+    storage_filled_linear_zero(const storage_filled_linear_zero& r) :
+        storage_base<matrix_type>(r),
+        m_array(r.m_array),
+        m_rows(r.m_rows),
+        m_cols(r.m_cols),
+        m_numeric(r.m_numeric),
+        m_valid(r.m_valid) {}
+
+    ~storage_filled_linear_zero() {}
+
+    const_itr_access* get_const_itr_access() const
+    {
+        return new const_itr_access(*this);
+    }
+
+    element& get_element(size_t row, size_t col)
+    {
+        m_valid = false;
+        return m_array[get_pos(row,col)];
+    }
+
+    matrix_element_t get_type(size_t row, size_t col) const
+    {
+        return m_array[get_pos(row,col)].m_type;
+    }
+
+    double get_numeric(size_t row, size_t col) const
+    {
+        const element& elem = m_array[get_pos(row,col)];
+        switch (elem.m_type)
+        {
+            case element_numeric:
+                return elem.m_numeric;
+            case element_boolean:
+                return static_cast<double>(elem.m_boolean);
+            case element_empty:
+            default:
+                ;
+        }
+        return 0.0;
+    }
+
+    const string_type* get_string(size_t row, size_t col) const
+    {
+        const element& elem = m_array[get_pos(row,col)];
+        if (elem.m_type != element_string)
+            throw matrix_storage_error("element type is not string.");
+
+        return elem.mp_string;
+    }
+
+    bool get_boolean(size_t row, size_t col) const
+    {
+        const element& elem = m_array[get_pos(row,col)];
+        if (elem.m_type != element_boolean)
+            throw matrix_storage_error("element type is not boolean.");
+
+        return elem.m_boolean;
+    }
+
+    size_t rows() const
+    {
+        return m_rows;
+    }
+
+    size_t cols() const
+    {
+        return m_cols;
+    }
+
+    void transpose()
+    {
+        if (!m_rows || !m_cols)
+            // empty matrix - nothing to do.
+            return;
+
+        array_type trans_array(m_rows*m_cols, element(0.0));
+        for (size_t i = 0; i < m_rows; ++i)
+            for (size_t j = 0; j < m_cols; ++j)
+                trans_array[m_rows*j+i] = m_array[get_pos(i,j)];
+
+        m_array.swap(trans_array);
+        ::std::swap(m_rows, m_cols);
+    }
+
+    void resize(size_t row, size_t col)
+    {
+        m_valid = false;
+        if (!row || !col)
+        {
+            // Empty the matrix.
+            clear();
+            m_rows = row;
+            m_cols = col;
+            return;
+        }
+
+        size_t new_size = row * col;
+        if (empty())
+        {
+            // Current matrix is empty.
+            m_array.resize(new_size, element(0.0));
+            m_rows = row;
+            m_cols = col;
+            return;
+        }
+
+        array_type new_array(new_size, element(0.0));
+        size_t min_rows = ::std::min(row, m_rows);
+        size_t min_cols = ::std::min(col, m_cols);
+        for (size_t i = 0; i < min_rows; ++i)
+        {
+            for (size_t j = 0; j < min_cols; ++j)
+                new_array[col*i+j] = m_array[get_pos(i, j)];
+        }
+
+        m_array.swap(new_array);
+        m_rows = row;
+        m_cols = col;
+    }
+
+    void clear()
+    {
+        m_array.clear();
+        m_valid = true;
+        m_numeric = false;
+    }
+
+    bool numeric()
+    {
+        if (m_valid)
+            return m_numeric;
+
+        size_t n = m_array.size();
+        if (!n)
+        {
+            // empty matrix is never considered numeric.
+            m_numeric = false;
+            return m_numeric;
+        }
+
+        for (size_t i = 0; i < n; ++i)
+        {
+            matrix_element_t elem_type = m_array[i].m_type;
+            if (elem_type != element_numeric && elem_type != element_boolean)
+            {
+                m_numeric = false;
+                m_valid = true;
+                return m_numeric;
+            }
+        }
+
+        m_numeric = true;
+        m_valid = true;
+        return m_numeric;
+    }
+
+    bool empty() const
+    {
+        return m_array.empty();    
+    }
+
+    ::mdds::storage_base<matrix_type>* clone() const
+    {
+        return new storage_filled_linear_zero(*this);
+    }
+
+    const array_type& get_array() const { return m_array; }
+
+private:
+
+    /**
+     * Get an array position of the data referenced by the row and column 
+     * indices.  The array consists of multiple rows, the content of row 0 
+     * followded by the content of row 1, and so on.  <b>Note that no 
+     * boundary check is performed in this method.</b> 
+     *  
+     * @param row 0-based row index.
+     * @param col 0-based column index.
+     * @return position in the data array. 
+     */
+    size_t get_pos(size_t row, size_t col) const
+    {
+        return m_cols * row + col;
+    }
+
+private:
+    array_type m_array;
+    size_t m_rows;
+    size_t m_cols;
+    bool m_numeric:1;
+    bool m_valid:1;
+};
+
+}
diff --git a/include/mdds/mixed_type_matrix_storage_filled_nested_array.inl b/include/mdds/mixed_type_matrix_storage_filled_nested_array.inl
new file mode 100644
index 0000000..acb8662
--- /dev/null
+++ b/include/mdds/mixed_type_matrix_storage_filled_nested_array.inl
@@ -0,0 +1,374 @@
+/*************************************************************************
+ *
+ * Copyright (c) 2011 Kohei Yoshida
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ ************************************************************************/
+
+namespace mdds {
+
+/**
+ * This storage creates instance for every single element, even for the
+ * empty elements. 
+ */
+template<typename _MatrixType>
+class storage_filled_nested_array : public ::mdds::storage_base<_MatrixType>
+{
+    typedef _MatrixType matrix_type;
+    typedef typename matrix_type::string_type string_type;
+
+public:
+    typedef typename matrix_type::element element;
+    typedef ::std::vector<element*> row_type;
+    typedef ::std::vector<row_type*> rows_type;
+
+    struct elem_wrap
+    {
+        const element& operator() (const typename row_type::const_iterator& itr) const 
+        { 
+            return *(*itr); 
+        }
+    };
+    struct rows_wrap
+    {
+        const row_type& operator() (const typename rows_type::const_iterator& itr) const
+        { 
+            return *(*itr);
+        }
+    };
+    typedef ::mdds::const_itr_access<storage_filled_nested_array, elem_wrap, rows_wrap> const_itr_access;
+
+    storage_filled_nested_array(size_t _rows, size_t _cols, matrix_init_element_t init_type) :
+        storage_base<matrix_type>(matrix_storage_filled, init_type),
+        m_row_pool(new ::boost::object_pool<row_type>),
+        m_element_pool(new ::boost::object_pool<element>),
+        m_numeric(false),
+        m_valid(false)
+    {
+        if (init_type == matrix_init_element_zero)
+            m_init_elem.set_numeric(0.0);
+
+        m_rows.reserve(_rows);
+        for (size_t i = 0; i < _rows; ++i)
+            m_rows.push_back(m_row_pool->construct(_cols, &m_init_elem));
+    }
+
+    storage_filled_nested_array(const storage_filled_nested_array& r) :
+        storage_base<matrix_type>(r),
+        m_row_pool(new ::boost::object_pool<row_type>),
+        m_element_pool(new ::boost::object_pool<element>),
+        m_init_elem(r.m_init_elem),
+        m_numeric(r.m_numeric),
+        m_valid(r.m_valid)
+    {
+        size_t n = r.m_rows.size();
+        m_rows.reserve(n);
+        for (size_t i = 0; i < n; ++i)
+        {
+            const row_type& row_other = *r.m_rows[i];
+            size_t col_size = row_other.size();
+            m_rows.push_back(m_row_pool->construct(col_size, &m_init_elem));
+            row_type& row = *m_rows.back();
+            for (size_t j = 0; j < col_size; ++j)
+            {
+                if (row_other[j] != &r.m_init_elem)
+                    row[j] = m_element_pool->construct(*row_other[j]);
+            }
+        }
+    }
+
+    virtual ~storage_filled_nested_array()
+    {
+        delete m_row_pool;
+        delete m_element_pool;
+    }
+
+    const_itr_access* get_const_itr_access() const
+    {
+        return new const_itr_access(*this);
+    }
+
+    element& get_element(size_t row, size_t col)
+    {
+        m_valid = false;
+        if (m_rows.at(row)->at(col) == &m_init_elem)
+        {
+            // Initial element.  Instantiate a new element to take its place.
+            matrix_init_element_t init_type = storage_base<matrix_type>::get_init_type();
+            switch (init_type)
+            {
+                case matrix_init_element_zero:
+                    (*m_rows[row])[col] = m_element_pool->construct(static_cast<double>(0.0));
+                break;
+                case matrix_init_element_empty:
+                    (*m_rows[row])[col] = m_element_pool->construct();
+                break;
+                default:
+                    throw matrix_storage_error("unknown init type.");
+            }
+        }
+        return *(*m_rows[row])[col];
+    }
+
+    matrix_element_t get_type(size_t row, size_t col) const
+    {
+        return m_rows.at(row)->at(col)->m_type;
+    }
+
+    double get_numeric(size_t row, size_t col) const
+    {
+        const element& elem = *m_rows.at(row)->at(col);
+        switch (elem.m_type)
+        {
+            case element_numeric:
+                return elem.m_numeric;
+            case element_boolean:
+                return static_cast<double>(elem.m_boolean);
+            case element_empty:
+            default:
+                ;
+        }
+        return 0.0;
+    }
+
+    const string_type* get_string(size_t row, size_t col) const
+    {
+        const element& elem = *m_rows.at(row)->at(col);
+        if (elem.m_type != element_string)
+            throw matrix_storage_error("element type is not string.");
+
+        return elem.mp_string;
+    }
+
+    bool get_boolean(size_t row, size_t col) const
+    {
+        const element& elem = *m_rows.at(row)->at(col);
+        if (elem.m_type != element_boolean)
+            throw matrix_storage_error("element type is not boolean.");
+
+        return elem.m_boolean;
+    }
+
+    size_t rows() const
+    {
+        return m_rows.size();
+    }
+
+    size_t cols() const
+    {
+        return m_rows.empty() ? 0 : m_rows[0]->size();
+    }
+
+    void transpose()
+    {
+        rows_type trans_mx;
+        size_t row_size = rows(), col_size = cols();
+        trans_mx.reserve(col_size);
+        for (size_t col = 0; col < col_size; ++col)
+        {
+            trans_mx.push_back(m_row_pool->construct());
+            row_type& trans_row = *trans_mx.back();
+            trans_row.reserve(row_size);
+            for (size_t row = 0; row < row_size; ++row)
+                trans_row.push_back((*m_rows[row])[col]);
+        }
+        m_rows.swap(trans_mx);
+
+        // Delete the row instances in the old container.
+        delete_rows(trans_mx, 0);
+    }
+
+    void resize(size_t row, size_t col)
+    {
+        m_valid = false;
+        if (!row || !col)
+        {
+            // Empty the matrix.
+            clear();
+            return;
+        }
+
+        size_t cur_rows = rows(), cur_cols = cols();
+
+        if (!cur_rows || !cur_cols)
+        {
+            // current matrix is empty.
+            rows_type new_rows;
+            new_rows.reserve(row);
+            for (size_t i = 0; i < row; ++i)
+                new_rows.push_back(m_row_pool->construct(col, &m_init_elem));
+
+            m_rows.swap(new_rows);
+            return;
+        }
+
+        if (row > cur_rows)
+        {
+            // Insert extra rows...
+            size_t new_row_count = row - cur_rows;
+            m_rows.reserve(row);
+            for (size_t i = 0; i < new_row_count; ++i)
+                m_rows.push_back(m_row_pool->construct(col, &m_init_elem));
+
+            resize_rows(cur_rows-1, cur_cols, col);
+        }
+        else if (cur_rows > row)
+        {
+            // Remove rows to new size.  Delete the row instances that are to
+            // be stripped off.
+            delete_rows(m_rows, row);
+            m_rows.resize(row);
+            resize_rows(row-1, cur_cols, col);
+        }
+        else
+        {
+            assert(cur_rows == row);
+            resize_rows(cur_rows-1, cur_cols, col);
+        }
+    }
+
+    void clear()
+    {
+        delete m_row_pool;
+        delete m_element_pool;
+        m_row_pool = new ::boost::object_pool<row_type>;
+        m_element_pool = new ::boost::object_pool<element>;
+        m_rows.clear();
+        m_valid = true;
+        m_numeric = false;
+    }
+
+    bool numeric()
+    {
+        if (m_valid)
+            return m_numeric;
+
+        typename rows_type::const_iterator itr_row = m_rows.begin(), itr_row_end = m_rows.end();
+        for (; itr_row != itr_row_end; ++itr_row)
+        {
+            typename row_type::const_iterator itr_col = (*itr_row)->begin(), itr_col_end = (*itr_row)->end();
+            for (; itr_col != itr_col_end; ++itr_col)
+            {
+                const element* p = *itr_col;
+                matrix_element_t elem_type = p->m_type;
+                if (elem_type != element_numeric && elem_type != element_boolean)
+                {
+                    m_numeric = false;
+                    m_valid = true;
+                    return m_numeric;
+                }
+            }
+        }
+
+        m_numeric = true;
+        m_valid = true;
+        return m_numeric;
+    }
+
+    bool empty() const
+    {
+        return m_rows.empty();
+    }
+
+    ::mdds::storage_base<matrix_type>* clone() const
+    {
+        return new storage_filled_nested_array(*this);
+    }
+
+    const rows_type& get_rows() const { return m_rows; }
+
+private:
+
+    /**
+     * Resize rows to a new column size, from row 0 up to specified upper 
+     * row. 
+     */
+    void resize_rows(size_t upper_row, size_t cur_cols, size_t new_cols)
+    {
+        for (size_t i = 0; i <= upper_row; ++i)
+        {
+            // Resize pre-existing rows to new column size.
+            if (new_cols > cur_cols)
+            {
+                size_t new_col_count = new_cols - cur_cols;
+                for (size_t j = 0; j < new_col_count; ++j)
+                    append_new_elem(*m_rows[i]);
+            }
+            else if (new_cols < cur_cols)
+            {
+                // Delete the instances being cast out.
+                delete_elems_from_row(*m_rows[i], new_cols);
+                m_rows[i]->resize(new_cols);
+            }
+        }
+    }
+
+    void delete_rows(rows_type& row_array, size_t first_row)
+    {
+        typename rows_type::iterator itr = row_array.begin(), itr_end = row_array.end();
+        ::std::advance(itr, first_row);
+        for (; itr != itr_end; ++itr)
+        {
+            row_type* p = *itr;
+            m_row_pool->destroy(p);
+        }
+    }
+
+    void delete_elems_from_row(row_type& row, size_t new_cols)
+    {
+        typename row_type::iterator itr = row.begin(), itr_end = row.end();
+        ::std::advance(itr, new_cols);
+        for (; itr != itr_end; ++itr)
+        {
+            element* p = *itr;
+            if (p != &m_init_elem)
+                m_element_pool->destroy(p);
+        }
+    }
+
+    void append_new_elem(row_type& row)
+    {
+        matrix_init_element_t init_type = storage_base<matrix_type>::get_init_type();
+        switch (init_type)
+        {
+            case matrix_init_element_zero:
+                row.push_back(m_element_pool->construct(static_cast<double>(0.0)));
+            break;
+            case matrix_init_element_empty:
+                row.push_back(m_element_pool->construct());
+            break;
+            default:
+                throw matrix_storage_error("unknown init type.");
+        }
+    }
+
+private:
+    ::boost::object_pool<row_type>* m_row_pool;
+    ::boost::object_pool<element>* m_element_pool;
+    rows_type m_rows;
+    element m_init_elem;
+    bool m_numeric:1;
+    bool m_valid:1;
+};
+
+}
diff --git a/include/mdds/mixed_type_matrix_storage_sparse.inl b/include/mdds/mixed_type_matrix_storage_sparse.inl
new file mode 100644
index 0000000..cc30906
--- /dev/null
+++ b/include/mdds/mixed_type_matrix_storage_sparse.inl
@@ -0,0 +1,376 @@
+/*************************************************************************
+ *
+ * Copyright (c) 2011 Kohei Yoshida
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ ************************************************************************/
+
+namespace mdds {
+
+/**
+ * This storage stores only non-empty elements. 
+ */
+template<typename _MatrixType>
+class storage_sparse : public storage_base<_MatrixType>
+{
+    typedef _MatrixType matrix_type;
+
+    typedef typename matrix_type::string_type  string_type;
+
+public:
+    typedef typename matrix_type::element      element;
+    typedef ::boost::ptr_map<size_t, element>  row_type;
+    typedef ::boost::ptr_map<size_t, row_type> rows_type;
+    struct elem_wrap
+    {
+        const element& operator() (const typename row_type::const_iterator& itr) const
+        {
+            return *itr->second;
+        }
+    };
+    struct rows_wrap
+    {
+        const row_type& operator() (const typename rows_type::const_iterator& itr) const
+        {
+            return *itr->second;
+        }
+    };
+    typedef ::mdds::const_itr_access<storage_sparse, elem_wrap, rows_wrap> const_itr_access;
+
+    storage_sparse(size_t _rows, size_t _cols, matrix_init_element_t init_type) : 
+        storage_base<matrix_type>(matrix_storage_sparse, init_type),
+        m_row_size(_rows), m_col_size(_cols),
+        m_numeric(_rows && _cols), m_valid(true)
+    {
+        switch (storage_base<matrix_type>::get_init_type())
+        {
+            case matrix_init_element_zero:
+                m_empty_elem.m_type = element_numeric;
+                m_empty_elem.m_numeric = 0.0;
+            break;
+            default:
+                m_empty_elem.m_type = element_empty;
+                m_numeric = false;
+        }
+    }
+
+    storage_sparse(const storage_sparse& r) :
+        storage_base<matrix_type>(r),
+        m_rows(r.m_rows), 
+        m_empty_elem(r.m_empty_elem), 
+        m_row_size(r.m_row_size), 
+        m_col_size(r.m_col_size) {}
+
+    ~storage_sparse() {}
+
+    const_itr_access* get_const_itr_access() const { return new const_itr_access(*this); }
+
+    element & get_element(size_t row, size_t col)
+    {
+        if (row >= m_row_size || col >= m_col_size)
+            throw matrix_storage_error("specified element is out-of-bound.");
+
+        m_valid = false;
+
+        typename rows_type::iterator itr = m_rows.find(row);
+        if (itr == m_rows.end())
+        {
+            // Insert a brand-new row.
+            ::std::pair<typename rows_type::iterator, bool> r = m_rows.insert(row, new row_type);
+            if (!r.second)
+                throw matrix_storage_error("failed to insert a new row instance into storage_sparse.");
+            itr = r.first;
+        }
+
+        row_type& row_store = *itr->second;
+        typename row_type::iterator itr_elem = row_store.find(col);
+        if (itr_elem == row_store.end())
+        {
+            // Insert a new element at this column position.
+            ::std::pair<typename row_type::iterator, bool> r = row_store.insert(col, new element);
+            if (!r.second)
+                throw matrix_storage_error("failed to insert a new element instance.");
+            itr_elem = r.first;
+        }
+        return *itr_elem->second;
+    }
+
+    matrix_element_t get_type(size_t row, size_t col) const
+    {
+        typename rows_type::const_iterator itr = m_rows.find(row);
+        if (itr == m_rows.end())
+            return m_empty_elem.m_type;
+
+        const row_type& row_store = *itr->second;
+        typename row_type::const_iterator itr_elem = row_store.find(col);
+        if (itr_elem == row_store.end())
+            return m_empty_elem.m_type;
+
+        return itr_elem->second->m_type;
+    }
+
+    double get_numeric(size_t row, size_t col) const
+    {
+        const element& elem = get_non_empty_element(row, col);
+        switch (elem.m_type)
+        {
+            case element_numeric:
+                return elem.m_numeric;
+            case element_boolean:
+                return static_cast<double>(elem.m_boolean);
+            case element_empty:
+            default:
+                ;
+        }
+        return 0.0;
+    }
+
+    const string_type* get_string(size_t row, size_t col) const
+    {
+        matrix_element_t elem_type = get_type(row, col);
+        if (elem_type != element_string)
+            throw matrix_storage_error("element type is not string.");
+
+        return get_non_empty_element(row, col).mp_string;
+    }
+
+    bool get_boolean(size_t row, size_t col) const
+    {
+        matrix_element_t elem_type = get_type(row, col);
+        if (elem_type != element_boolean)
+            throw matrix_storage_error("element type is not string.");
+
+        return get_non_empty_element(row, col).m_boolean;
+    }
+
+    size_t rows() const
+    {
+        return m_row_size;
+    }
+
+    size_t cols() const
+    {
+        return m_col_size;
+    }
+
+    typedef ::std::pair<size_t, size_t> elem_pos_type;
+
+    struct elem_pos_sorter : public ::std::binary_function<elem_pos_type, elem_pos_type, bool>
+    {
+        bool operator() (const elem_pos_type& left, const elem_pos_type& right) const
+        {
+            if (left.first != right.first)
+                return left.first < right.first;
+            return left.second < right.second;
+        }
+    };
+
+    void transpose()
+    {
+        using namespace std;
+
+        rows_type trans;
+
+        // First, pick up the positions of all non-empty elements.
+        vector<elem_pos_type> filled_elems;
+        {
+            typename rows_type::const_iterator itr_row = m_rows.begin(), itr_row_end = m_rows.end();
+            for (; itr_row != itr_row_end; ++itr_row)
+            {
+                size_t row_idx = itr_row->first;
+                const row_type& row = *itr_row->second;
+                typename row_type::const_iterator itr_col = row.begin(), itr_col_end = row.end();
+                for (; itr_col != itr_col_end; ++itr_col)
+                {
+                    // Be sure to swap the row and column indices.
+                    filled_elems.push_back(elem_pos_type(itr_col->first, row_idx));
+                }
+            }
+        }
+        // Sort by row index first, then by column index.
+        sort(filled_elems.begin(), filled_elems.end(), elem_pos_sorter());
+
+        // Iterate through the non-empty element positions and perform 
+        // transposition.
+        typename vector<elem_pos_type>::const_iterator 
+            itr_pos = filled_elems.begin(), itr_pos_end = filled_elems.end();
+        while (itr_pos != itr_pos_end)
+        {
+            // First item of the new row.
+            size_t row_idx = itr_pos->first;
+            size_t col_idx = itr_pos->second;
+            pair<typename rows_type::iterator, bool> r = trans.insert(row_idx, new row_type);
+            if (!r.second)
+                throw matrix_storage_error("failed to insert a new row instance during transposition.");
+
+            typename rows_type::iterator itr_row = r.first;
+            row_type& row = *itr_row->second;
+            pair<typename row_type::iterator, bool> r2 = 
+                row.insert(col_idx, new element(m_rows[col_idx][row_idx]));
+            if (!r2.second)
+                throw matrix_storage_error("afiled to insert a new element instance during transposition.");
+
+            // Keep iterating until we get a different row index.
+            for (++itr_pos; itr_pos != itr_pos_end && itr_pos->first == row_idx; ++itr_pos)
+            {
+                col_idx = itr_pos->second;
+                r2 = row.insert(col_idx, new element(m_rows[col_idx][row_idx]));
+                if (!r2.second)
+                    throw matrix_storage_error("afiled to insert a new element instance during transposition.");
+            }
+        }
+
+        m_rows.swap(trans);
+        ::std::swap(m_row_size, m_col_size);
+    }
+
+    void resize(size_t row, size_t col)
+    {
+        m_valid = false;
+
+        if (!row || !col)
+        {
+            clear();
+            return;
+        }
+
+        // Resizing a sparse matrix need to modify the data only when 
+        // shrinking.
+
+        if (m_row_size > row)
+        {
+            // Remove all rows where the row index is greater than or 
+            // equal to 'row'.
+            typename rows_type::iterator itr = m_rows.lower_bound(row);
+            m_rows.erase(itr, m_rows.end());
+        }
+
+        if (m_col_size > col)
+        {
+            typename rows_type::iterator itr = m_rows.begin(), itr_end = m_rows.end();
+            for (; itr != itr_end; ++itr)
+            {
+                // Now, remove all columns where the column index is 
+                // greater than or equal to 'col'.
+                row_type& row_container = *itr->second;
+                typename row_type::iterator itr_elem = row_container.lower_bound(col);
+                row_container.erase(itr_elem, row_container.end());
+            }
+        }
+
+        m_row_size = row;
+        m_col_size = col;
+    }
+
+    void clear()
+    {
+        m_rows.clear();
+        m_row_size = 0;
+        m_col_size = 0;
+        m_valid = true;
+        m_numeric = false;
+    }
+
+    bool numeric()
+    {
+        using namespace std;
+
+        if (m_valid)
+            return m_numeric;
+
+        size_t non_empty_count = 0;
+        typename rows_type::const_iterator itr_row = m_rows.begin(), itr_row_end = m_rows.end();
+        for (; itr_row != itr_row_end; ++itr_row)
+        {
+            const row_type& row = *itr_row->second;
+            non_empty_count += row.size();
+            assert(row.size() <= m_col_size);
+            typename row_type::const_iterator itr_col = row.begin(), itr_col_end = row.end();
+            for (; itr_col != itr_col_end; ++itr_col)
+            {
+                const element& elem = *itr_col->second;
+                if (elem.m_type != element_numeric && elem.m_type != element_boolean)
+                {
+                    m_valid = true;
+                    m_numeric = false;
+                    return m_numeric;
+                }
+            }
+        }
+
+        // All non-empty elements are numeric.
+
+        matrix_init_element_t init_type = storage_base<matrix_type>::get_init_type();
+        if (init_type == matrix_init_element_zero)
+            m_numeric = true;
+        else
+        {    
+            size_t total_elem_count = m_row_size * m_col_size;
+            assert(non_empty_count <= total_elem_count);
+            m_numeric = total_elem_count == non_empty_count;
+        }
+
+        m_valid = true;
+        return m_numeric;
+    }
+
+    bool empty() const
+    {
+        // If one of row and column sizes are zero, the other size must be
+        // zero, and vise versa.
+        assert((!m_row_size && !m_col_size) || (m_row_size && m_col_size));
+
+        return m_row_size == 0 || m_col_size == 0;
+    }
+
+    storage_base<matrix_type>* clone() const
+    {
+        return new storage_sparse(*this);
+    }
+
+    const rows_type& get_rows() const { return m_rows; }
+
+private:
+    const element& get_non_empty_element(size_t row, size_t col) const
+    {
+        typename rows_type::const_iterator itr = m_rows.find(row);
+        if (itr == m_rows.end())
+            return m_empty_elem;
+
+        const row_type& row_store = *itr->second;
+        typename row_type::const_iterator itr_elem = row_store.find(col);
+        if (itr_elem == row_store.end())
+            return m_empty_elem;
+        return *itr_elem->second;
+    }
+
+private:
+    rows_type   m_rows;
+    element     m_empty_elem;
+    size_t      m_row_size;
+    size_t      m_col_size;
+    bool        m_numeric:1;
+    bool        m_valid:1;
+};
+
+}
diff --git a/include/mdds/rectangle_set.hpp b/include/mdds/rectangle_set.hpp
index 5cfd99e..82269a3 100644
--- a/include/mdds/rectangle_set.hpp
+++ b/include/mdds/rectangle_set.hpp
@@ -1,6 +1,6 @@
 /*************************************************************************
  *
- * Copyright (c) 2010 Kohei Yoshida
+ * Copyright (c) 2010, 2011 Kohei Yoshida
  * 
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -248,250 +248,8 @@ private:
     dataset_type m_dataset;
 };
 
-template<typename _Key, typename _Data>
-rectangle_set<_Key,_Data>::rectangle_set()
-{
-}
-
-template<typename _Key, typename _Data>
-rectangle_set<_Key,_Data>::rectangle_set(const rectangle_set& r) :
-    m_inner_map(r.m_inner_map),
-    m_dataset(r.m_dataset)
-{
-    build_outer_segment_tree();
 }
 
-template<typename _Key, typename _Data>
-rectangle_set<_Key,_Data>::~rectangle_set()
-{
-}
-
-template<typename _Key, typename _Data>
-rectangle_set<_Key,_Data>& rectangle_set<_Key,_Data>::operator= (const rectangle_set& r)
-{
-    clear(); // Don't forget to clear the internal state beforehands.
-
-    m_inner_map = r.m_inner_map;
-    m_dataset = r.m_dataset;
-    build_outer_segment_tree();
-    return *this;
-}
-
-template<typename _Key, typename _Data>
-bool rectangle_set<_Key,_Data>::operator== (const rectangle_set& r) const
-{
-    if (m_dataset.size() != r.m_dataset.size())
-        return false;
-
-    typename dataset_type::const_iterator itr = m_dataset.begin(), itr_end = m_dataset.end();
-    for (; itr != itr_end; ++itr)
-    {
-        typename dataset_type::const_iterator itr_rhs = r.m_dataset.find(itr->first);
-        if (itr_rhs == r.m_dataset.end())
-            return false;
-
-        if (itr->second != itr_rhs->second)
-            return false;
-    }
-
-    return true;
-}
-
-template<typename _Key, typename _Data>
-bool rectangle_set<_Key,_Data>::insert(key_type x1, key_type y1, key_type x2, key_type y2, data_type* data)
-{
-    // Make sure this is not a duplicate.
-    if (m_dataset.find(data) != m_dataset.end())
-        return false;
-
-    // Check if interval x1 - x2 is already stored.
-    interval_type outer_interval = interval_type(x1, x2);
-    typename inner_segment_map_type::iterator itr = m_inner_map.find(outer_interval);
-    if (itr == m_inner_map.end())
-    {
-        // this interval has not yet been stored.  Create a new inner segment 
-        // tree instance for this interval.
-        ::std::pair<typename inner_segment_map_type::iterator, bool> r =
-            m_inner_map.insert(outer_interval, new inner_type);
-        if (!r.second)
-            throw general_error("inner segment tree insertion failed.");
-
-        itr = r.first;
-
-        // Register the pointer to this inner segment tree instance with the 
-        // outer segment tree.
-        if (!m_outer_segments.insert(x1, x2, itr->second))
-            // This should never fail if my logic is correct.
-            throw general_error("failed to insert an inner segment tree pointer into the outer segment tree.");
-    }
-
-    inner_type* inner_tree = itr->second;
-    inner_tree->insert(y1, y2, data);
-    m_dataset.insert(typename dataset_type::value_type(data, rectangle(x1, y1, x2, y2)));
-
-    return true;
-}
-
-template<typename _Key, typename _Data>
-bool rectangle_set<_Key,_Data>::search(key_type x, key_type y, search_result_type& result)
-{
-    typename outer_type::search_result_type inner_trees;
-    if (!m_outer_segments.is_tree_valid())
-        m_outer_segments.build_tree();
-
-    if (!m_outer_segments.search(x, inner_trees))
-        return false;
-
-    typename outer_type::search_result_type::iterator itr_tree = inner_trees.begin(), itr_tree_end = inner_trees.end();
-    for (; itr_tree != itr_tree_end; ++itr_tree)
-    {
-        inner_type* inner_tree = *itr_tree;
-        if (!inner_tree->is_tree_valid())
-            inner_tree->build_tree();
-
-        // Search all relevant inner trees and aggregate results.
-        if (!inner_tree->search(y, result))
-            return false;
-    }
-    return true;
-}
-
-template<typename _Key, typename _Data>
-typename rectangle_set<_Key,_Data>::search_result
-rectangle_set<_Key,_Data>::search(key_type x, key_type y)
-{
-    search_result result;
-    typename outer_type::search_result_type inner_trees;
-    if (!m_outer_segments.is_tree_valid())
-        m_outer_segments.build_tree();
-
-    if (!m_outer_segments.search(x, inner_trees))
-        return result;
-
-    typename outer_type::search_result_type::iterator itr_tree = inner_trees.begin(), itr_tree_end = inner_trees.end();
-    for (; itr_tree != itr_tree_end; ++itr_tree)
-    {
-        inner_type* inner_tree = *itr_tree;
-        if (!inner_tree->is_tree_valid())
-            inner_tree->build_tree();
-
-        // Search all relevant inner trees and aggregate results.
-        inner_tree->search(y, result);
-    }
-    return result;
-}
-
-template<typename _Key, typename _Data>
-void rectangle_set<_Key,_Data>::remove(data_type* data)
-{
-    typename dataset_type::iterator itr_data = m_dataset.find(data);
-    if (itr_data == m_dataset.end())
-        // The data is not stored in this data structure.
-        return;
-
-    const rectangle& rect = itr_data->second;
-
-    // Find the corresponding inner segment tree for this outer interval.
-    interval_type outer(rect.x1, rect.x2);
-    typename inner_segment_map_type::iterator itr_seg = m_inner_map.find(outer);
-    if (itr_seg == m_inner_map.end())
-        throw general_error("inconsistent internal state: failed to find an internal segment tree for an existing interval.");
-
-    // Remove data from the inner segment tree.
-    inner_type* inner_tree = itr_seg->second;
-    inner_tree->remove(data);
-    if (inner_tree->empty())
-    {
-        // This inner tree is now empty.  Erase it.
-        m_outer_segments.remove(inner_tree);
-        m_inner_map.erase(itr_seg);
-    }
-
-    // Remove it from the data set as well.
-    m_dataset.erase(data);
-}
-
-template<typename _Key, typename _Data>
-void rectangle_set<_Key,_Data>::clear()
-{
-    m_outer_segments.clear();
-    m_inner_map.clear();
-    m_dataset.clear();
-}
-
-template<typename _Key, typename _Data>
-size_t rectangle_set<_Key,_Data>::size() const
-{
-    return m_dataset.size();
-}
-
-template<typename _Key, typename _Data>
-bool rectangle_set<_Key,_Data>::empty() const
-{
-    return m_dataset.empty();
-}
-
-template<typename _Key, typename _Data>
-void rectangle_set<_Key,_Data>::build_outer_segment_tree()
-{
-    // Re-construct the outer segment tree from the authoritative inner tree 
-    // map.
-    typename inner_segment_map_type::iterator itr = m_inner_map.begin(), itr_end = m_inner_map.end();
-    for (; itr != itr_end; ++itr)
-    {
-        const interval_type& interval = itr->first;
-        inner_type* tree = itr->second;
-        m_outer_segments.insert(interval.first, interval.second, tree);
-    }
-}
-
-#ifdef UNIT_TEST
-template<typename _Key, typename _Data>
-void rectangle_set<_Key,_Data>::dump_rectangles() const
-{
-    using namespace std;
-    cout << "dump rectangles ------------------------------------------------" << endl;
-    if (m_dataset.empty())
-    {
-        cout << "No rectangles in the data set." << endl;
-        return;
-    }
-
-    typename dataset_type::const_iterator itr = m_dataset.begin(), itr_end = m_dataset.end();
-    for (; itr != itr_end; ++itr)
-    {
-        const rectangle& rect = itr->second;
-        cout << itr->first->name << ": (x1,y1,x2,y2) = "
-            << "(" << rect.x1 << "," << rect.y1 << "," << rect.x2 << "," << rect.y2 << ")" 
-            << endl;
-    }
-}
-
-template<typename _Key, typename _Data>
-bool rectangle_set<_Key,_Data>::verify_rectangles(const dataset_type& expected) const
-{
-    if (m_dataset.size() != expected.size())
-        // Data sizes differ.
-        return false;
-
-    typename dataset_type::const_iterator itr_data = m_dataset.begin(), itr_data_end = m_dataset.end();
-    for (; itr_data != itr_data_end; ++itr_data)
-    {
-        const data_type* data = itr_data->first;
-        typename dataset_type::const_iterator itr_test = expected.find(data);
-        if (itr_test == expected.end())
-            // Pointer in one container but not in the other.
-            return false;
-
-        if (itr_data->second != itr_test->second)
-            // Rectangle positions and/or sizes differ.
-            return false;
-    }
-
-    return true;
-}
-#endif
-
-}
+#include "rectangle_set_def.inl"
 
 #endif
diff --git a/include/mdds/rectangle_set.hpp b/include/mdds/rectangle_set_def.inl
similarity index 56%
copy from include/mdds/rectangle_set.hpp
copy to include/mdds/rectangle_set_def.inl
index 5cfd99e..a2f40e1 100644
--- a/include/mdds/rectangle_set.hpp
+++ b/include/mdds/rectangle_set_def.inl
@@ -1,6 +1,6 @@
 /*************************************************************************
  *
- * Copyright (c) 2010 Kohei Yoshida
+ * Copyright (c) 2011 Kohei Yoshida
  * 
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -25,230 +25,9 @@
  *
  ************************************************************************/
 
-#ifndef __MDDS_RECTANGLE_SET_HPP__
-#define __MDDS_RECTANGLE_SET_HPP__
-
-#include "segment_tree.hpp"
-#include "global.hpp"
-#include "hash_container/map.hpp"
-
-#include <vector>
-#include <boost/ptr_container/ptr_map.hpp>
-
 namespace mdds {
 
 template<typename _Key, typename _Data>
-class rectangle_set
-{
-public:
-    typedef _Key    key_type;
-    typedef _Data   data_type;
-
-#ifdef UNIT_TEST
-public:
-#else
-private:
-#endif
-    struct rectangle
-    {
-        key_type x1;
-        key_type y1;
-        key_type x2;
-        key_type y2;
-
-        rectangle(key_type _x1, key_type _y1, key_type _x2, key_type _y2) :
-            x1(_x1), y1(_y1), x2(_x2), y2(_y2) {}
-
-        rectangle(const rectangle& r) :
-            x1(r.x1), y1(r.y1), x2(r.x2), y2(r.y2) {}
-
-        rectangle& operator= (const rectangle& r)
-        {
-            x1 = r.x1;
-            y1 = r.y1;
-            x2 = r.x2;
-            y2 = r.y2;
-            return *this;
-        }
-
-        bool operator== (const rectangle& r) const
-        {
-            return x1 == r.x1 && y1 == r.y1 && x2 == r.x2 && y2 == r.y2;
-        }
-
-        bool operator!= (const rectangle& r) const
-        {
-            return !operator==(r);
-        }
-    };
-    typedef _mdds_unordered_map_type<data_type*, rectangle>    dataset_type;
-private:
-    typedef segment_tree<key_type, data_type>   inner_type;
-    typedef segment_tree<key_type, inner_type>  outer_type;
-
-    typedef ::std::pair<key_type, key_type>             interval_type;
-    typedef ::boost::ptr_map<interval_type, inner_type> inner_segment_map_type;
-
-public:
-    typedef typename inner_type::search_result_type search_result_type;
-
-    /** 
-     * Most of the implementation of search_result and its iterator is in 
-     * segment_tree since the iteration logic is identical & depends on the
-     * segment_tree internals. 
-     */
-    class search_result : public inner_type::search_result_base
-    {
-    public:
-        typedef typename inner_type::search_result_base::res_chains_type res_chains_type;
-        typedef typename inner_type::search_result_base::res_chains_ptr res_chains_ptr;
-        typedef typename inner_type::data_chain_type data_chain_type;
-
-    public:
-
-        class iterator : public inner_type::iterator_base
-        {
-            friend class rectangle_set<_Key,_Data>::search_result;
-        private:
-            iterator(const res_chains_ptr& p) : inner_type::iterator_base(p) {}
-        public:
-            iterator() : inner_type::iterator_base() {}
-        };
-
-        search_result() : inner_type::search_result_base() {}
-        search_result(const search_result& r) : inner_type::search_result_base(r) {}
-
-        typename search_result::iterator begin()
-        {
-            typename search_result::iterator itr(
-                inner_type::search_result_base::get_res_chains());
-            itr.move_to_front();
-            return itr;
-        }
-
-        typename search_result::iterator end()
-        {
-            typename search_result::iterator itr(
-                inner_type::search_result_base::get_res_chains());
-            itr.move_to_end();
-            return itr;
-        }
-    };
-
-    rectangle_set();
-    rectangle_set(const rectangle_set& r);
-    ~rectangle_set();
-
-    rectangle_set& operator= (const rectangle_set& r);
-
-    /** 
-     * Equality between two instances of rectangle_set is evaluated based on 
-     * the stored rectangle instances; their pointer values and geometries.
-     */
-    bool operator== (const rectangle_set& r) const;
-
-    bool operator!= (const rectangle_set& r) const { return !operator==(r); }
-
-    /** 
-     * Insert a new rectangle (and data associated with it) into the set. 
-     * Note that insertion of duplicate data instance is not allowed.  A data 
-     * is considered a duplicate if its pointer value is identical to one of 
-     * the data instances already stored within.  Also note that <i>the end
-     * point of a rectangle is non-inclusive; a rectangle of (x1,y1) - (x2,y2) 
-     * means that the rectangle spans x1 <= x < x2 and y1 <= y < y2.</i> 
-     *  
-     * @param x1 lower x coordinate of the rectangle.  Inclusive.
-     * @param y1 lower y coordinate of the rectangle.  Inclusive.
-     * @param x2 upper x coordinate of the rectangle.  Non-inclusive.
-     * @param y2 upper y coordinate of the rectangle.  Non-inclusive.
-     * @param data pointer to data instance associated with this rectangle. 
-     *             <i>Note that the caller is responsible for managing the
-     *             life cycle of the data instance</i>.
-     * 
-     * @return true if a rectangle successfully inserted, false otherwise.
-     */
-    bool insert(key_type x1, key_type y1, key_type x2, key_type y2, data_type* data);
-
-    /** 
-     * Search and collect all rectangles that contains a given point.
-     *  
-     * @param x x coordinate of a query point.
-     * @param y y coordinate of a query point.
-     * @param result array of pointers to rectangle instances.
-     * 
-     * @return true if the search is successful, false otherwise.
-     */
-    bool search(key_type x, key_type y, search_result_type& result);
-
-    /** 
-     * Search and collect all rectangles containing a given point.
-     *  
-     * @param x x coordinate of a query point.
-     * @param y y coordinate of a query point. 
-     * 
-     * @return object containing the result of the search, which can be 
-     *         accessed via iterator.
-     */
-    search_result search(key_type x, key_type y);
-
-    /** 
-     * Remove a rectangle instance pointed to by a given pointer.
-     *
-     * @param data pointer that points to the rectangle instance you wish to 
-     *             remove from the set.
-     */
-    void remove(data_type* data);
-
-    /** 
-     * Clear all rectangles stored in the set.
-     */
-    void clear();
-
-    /** 
-     * Return the number of rectangles currently stored in the set.
-     * 
-     * @return number of stored rectangles.
-     */
-    size_t size() const;
-
-    /** 
-     * Check whether or not the set is empty.
-     * 
-     * @return true if the set is empty, false otherwise.
-     */
-    bool empty() const;
-
-private:
-    void build_outer_segment_tree();
-
-#ifdef UNIT_TEST
-public:
-    void dump_rectangles() const;
-    bool verify_rectangles(const dataset_type& expected) const;
-#endif
-
-private:
-
-    /** 
-     * This data member stores pointers to the inner segment tree instances 
-     * associated with outer intervals.  Used to speed up searches.
-     */
-    outer_type m_outer_segments;
-
-    /**
-     * This data member owns the inner segment_tree instances.
-     */
-    inner_segment_map_type m_inner_map;
-
-    /** 
-     * Used to keep track of currently stored data instances, to prevent 
-     * insertion of duplicates.  Duplicates are defined as data objects having 
-     * identical pointer value. 
-     */
-    dataset_type m_dataset;
-};
-
-template<typename _Key, typename _Data>
 rectangle_set<_Key,_Data>::rectangle_set()
 {
 }
@@ -493,5 +272,3 @@ bool rectangle_set<_Key,_Data>::verify_rectangles(const dataset_type& expected)
 #endif
 
 }
-
-#endif
diff --git a/misc/mdds.spec.in b/misc/mdds.spec.in
index 31e5dd3..2b461f2 100644
--- a/misc/mdds.spec.in
+++ b/misc/mdds.spec.in
@@ -41,7 +41,7 @@ Authors:
 %setup -q -n %{name}_%{version}
 
 %build
-%configure --docdir=%buildroot%{_docdir}
+%configure --docdir=%{_docdir}
 
 %check
 #make check
@@ -54,7 +54,7 @@ rm -rf %buildroot
 
 %files devel
 %defattr(-,root,root)
-%doc %buildroot%{_docdir}
+%doc %{_docdir}
 %{_includedir}/%{name}
 
 %changelog
diff --git a/src/array_creation_perf_test.cpp b/src/array_creation_perf_test.cpp
new file mode 100644
index 0000000..359c8f5
--- /dev/null
+++ b/src/array_creation_perf_test.cpp
@@ -0,0 +1,81 @@
+
+#include <vector>
+#include <boost/pool/object_pool.hpp>
+#include <iostream>
+
+#include <stdio.h>
+#include <string>
+#include <sys/time.h>
+
+namespace {
+
+class StackPrinter
+{
+public:
+    explicit StackPrinter(const char* msg) :
+        msMsg(msg)
+    {
+        fprintf(stdout, "%s: --begin\n", msMsg.c_str());
+        mfStartTime = getTime();
+    }
+
+    ~StackPrinter()
+    {
+        double fEndTime = getTime();
+        fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime));
+    }
+
+    void printTime(int line) const
+    {
+        double fEndTime = getTime();
+        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime));
+    }
+
+private:
+    double getTime() const
+    {
+        timeval tv;
+        gettimeofday(&tv, NULL);
+        return tv.tv_sec + tv.tv_usec / 1000000.0;
+    }
+
+    ::std::string msMsg;
+    double mfStartTime;
+};
+
+}
+
+using namespace std;
+using ::boost::object_pool;
+
+struct element
+{
+    double number;
+    element() : number(0.0) {}
+    element(double num) : number(num) {}
+};
+
+int main()
+{
+    size_t n = 100000000;
+    {
+        StackPrinter __stack_printer__("::main object pool with vector");
+        object_pool<element> elem_pool;
+        vector<element*> vec;
+        vec.reserve(n);
+        for (size_t i = 0; i < n; ++i)
+            vec.push_back(elem_pool.construct());
+
+        cout << "size of vector: " << vec.size() << endl;
+    }
+
+    {
+        StackPrinter __stack_printer__("::main array new");
+        element* parray = new element[n];
+        for (size_t i = 0; i < n; ++i)
+            parray[i].number = 1.0;
+        cout << "size of array: " << sizeof(parray) / sizeof(element) << endl;
+        delete[] parray;
+    }
+    return 0;
+}
diff --git a/src/mixed_type_matrix_test.cpp b/src/mixed_type_matrix_test.cpp
index 9e4a1ea..6fb046c 100644
--- a/src/mixed_type_matrix_test.cpp
+++ b/src/mixed_type_matrix_test.cpp
@@ -25,8 +25,8 @@
  *
  ************************************************************************/
 
-#include "mdds/mixed_type_matrix.hpp"
 #include "test_global.hpp"
+#include "mdds/mixed_type_matrix.hpp"
 
 #include <sstream>
 #include <cassert>
@@ -263,11 +263,16 @@ void mtm_test_resize(matrix_density_t density)
     assert(mxsize.first == 6);
     assert(mxsize.second == 4);
     mx.resize(6, 6);
+    mx.set_boolean(5, 5, true);
     mx.dump();
     mxsize = mx.size();
     assert(mxsize.first == 6);
     assert(mxsize.second == 6);
     mx.resize(3, 6);
+    mx.set_numeric(2, 2, 4.2);
+    mx.set_numeric(2, 3, 3.2);
+    mx.set_numeric(2, 4, 2.2);
+    mx.set_numeric(2, 5, 1.2);
     mx.dump();
     mxsize = mx.size();
     assert(mxsize.first == 3);
@@ -690,15 +695,16 @@ void traverse_itr_access(typename _StoreType::const_itr_access& itr_access)
     assert(i == 0);
 }
 
+template<typename _FilledStoreType>
 void mtm_test_iterator_access_filled(size_t rows, size_t cols)
 {
     StackPrinter __stack_printer__("::mtm_test_iterator_access_filled");
-    typedef storage_filled<mx_type> store_type;
+    typedef _FilledStoreType store_type;
 
     store_type store(rows, cols, matrix_init_element_zero);
     {
         cout << "rows: " << rows << "  cols: " << cols << endl;
-        store_type::const_itr_access* itr_access = store.get_const_itr_access();
+        typename store_type::const_itr_access* itr_access = store.get_const_itr_access();
         traverse_itr_access<store_type>(*itr_access);
         delete itr_access;
     }
@@ -839,6 +845,48 @@ void mtm_test_const_iterator()
     assert(itr == itr_end); // not found.
 }
 
+/**
+ * Measure the performance of object instantiation for filled storage.
+ */
+void mtm_perf_test_filled_storage_creation()
+{
+    StackPrinter __stack_printer__("::mtm_perf_test_filled_storage_creation");
+    cout << "measuring performance on matrix object creation." << endl;
+    size_t rowsize = 1000;
+    size_t obj_count = 30000;
+    cout << "row size: " << rowsize << "  object count: " << obj_count << endl;
+    for (size_t colsize = 1; colsize <= 3; ++colsize)
+    {
+        StackPrinter __stack_printer2__("::mtm_perf_test_filled_storage_creation::group");
+        cout << "column size: " << colsize << endl;
+        for (size_t i = 0; i < obj_count; ++i)
+            mx_type mx(rowsize, colsize, matrix_density_filled_zero);
+    }
+}
+
+void mtm_perf_test_filled_storage_set_numeric()
+{
+    StackPrinter __stack_printer__("::mtm_perf_test_filled_storage_set_numeric");
+    cout << "measuring performance on matrix object creation and populating it with numeric data." << endl;
+    size_t rowsize = 1000;
+    size_t obj_count = 30000;
+    cout << "row size: " << rowsize << "  object count: " << obj_count << endl;
+    for (size_t colsize = 1; colsize <= 3; ++colsize)
+    {
+        StackPrinter __stack_printer2__("::mtm_perf_test_filled_storage_set_numeric::group");
+        cout << "column size: " << colsize << endl;
+        for (size_t i = 0; i < obj_count; ++i)
+        {
+            mx_type mx(rowsize, colsize, matrix_density_filled_zero);
+            for (size_t row = 0; row < rowsize; ++row)
+            {
+                for (size_t col = 0; col < colsize; ++col)
+                    mx.set_numeric(row, col, 1.0);
+            }
+        }
+    }
+}
+
 int main(int argc, char** argv)
 {
     cmd_options opt;
@@ -861,16 +909,35 @@ int main(int argc, char** argv)
     
         run_tests_on_all_density_types(mtm_test_flag_storage);
     
-        mtm_test_iterator_access_filled(1, 1);
-        mtm_test_iterator_access_filled(3, 1);
-        mtm_test_iterator_access_filled(1, 3);
-        mtm_test_iterator_access_filled(3, 3);
-        mtm_test_iterator_access_filled(0, 0);
+        mtm_test_iterator_access_filled<storage_filled_nested_array<mx_type> >(1, 1);
+        mtm_test_iterator_access_filled<storage_filled_nested_array<mx_type> >(3, 1);
+        mtm_test_iterator_access_filled<storage_filled_nested_array<mx_type> >(1, 3);
+        mtm_test_iterator_access_filled<storage_filled_nested_array<mx_type> >(3, 3);
+        mtm_test_iterator_access_filled<storage_filled_nested_array<mx_type> >(0, 0);
+
+        mtm_test_iterator_access_filled<storage_filled_linear<mx_type> >(1, 1);
+        mtm_test_iterator_access_filled<storage_filled_linear<mx_type> >(3, 1);
+        mtm_test_iterator_access_filled<storage_filled_linear<mx_type> >(1, 3);
+        mtm_test_iterator_access_filled<storage_filled_linear<mx_type> >(3, 3);
+        mtm_test_iterator_access_filled<storage_filled_linear<mx_type> >(0, 0);
+
+        mtm_test_iterator_access_filled<storage_filled_linear_zero<mx_type> >(1, 1);
+        mtm_test_iterator_access_filled<storage_filled_linear_zero<mx_type> >(3, 1);
+        mtm_test_iterator_access_filled<storage_filled_linear_zero<mx_type> >(1, 3);
+        mtm_test_iterator_access_filled<storage_filled_linear_zero<mx_type> >(3, 3);
+        mtm_test_iterator_access_filled<storage_filled_linear_zero<mx_type> >(0, 0);
     
         mtm_test_iterator_access_sparse();
     
         mtm_test_const_iterator();
     }
+
+    if (opt.test_perf)
+    {
+        mtm_perf_test_filled_storage_creation();
+        mtm_perf_test_filled_storage_set_numeric();
+    }
+
     cout << "Test finished successfully!" << endl;
     return EXIT_SUCCESS;
 }
diff --git a/src/test_global.hpp b/src/test_global.hpp
index acf03c8..f734465 100644
--- a/src/test_global.hpp
+++ b/src/test_global.hpp
@@ -33,6 +33,7 @@
 #ifdef _WIN32
 #include <windows.h>
 #undef max
+#undef min
 #else
 #include <sys/time.h>
 #endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-openoffice/mdds.git


Reply to: