$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r80645 - in branches/release: boost/numeric/ublas boost/numeric/ublas/operation libs/numeric/ublas libs/numeric/ublas/doc libs/numeric/ublas/test
From: guwi17_at_[hidden]
Date: 2012-09-22 17:57:58
Author: guwi17
Date: 2012-09-22 17:57:57 EDT (Sat, 22 Sep 2012)
New Revision: 80645
URL: http://svn.boost.org/trac/boost/changeset/80645
Log:
merged [80483],[80487],[80586],[80591],[80592],[80599],[80600],[80624],[80625],[80643],[80644] into release:
* fix #4024
* fix #5812
* fix #7296 (hopefully ;-)
* see #7363 (must wait for a full test cycle before closing this task)
Added:
   branches/release/libs/numeric/ublas/test/test_coordinate_matrix_inplace_merge.cpp
      - copied unchanged from r80625, /trunk/libs/numeric/ublas/test/test_coordinate_matrix_inplace_merge.cpp
   branches/release/libs/numeric/ublas/test/test_coordinate_vector_inplace_merge.cpp
      - copied unchanged from r80625, /trunk/libs/numeric/ublas/test/test_coordinate_vector_inplace_merge.cpp
Properties modified: 
   branches/release/boost/numeric/ublas/   (props changed)
   branches/release/boost/numeric/ublas/functional.hpp   (props changed)
   branches/release/libs/numeric/ublas/   (props changed)
   branches/release/libs/numeric/ublas/doc/   (props changed)
Text files modified: 
   branches/release/boost/numeric/ublas/matrix_sparse.hpp       |    56 ++++++++++++++++++++++++++++++++++++++- 
   branches/release/boost/numeric/ublas/operation/size.hpp      |     6 ++--                                    
   branches/release/boost/numeric/ublas/storage.hpp             |     2 -                                       
   branches/release/boost/numeric/ublas/vector_sparse.hpp       |    49 ++++++++++++++++++++++++++++++++++      
   branches/release/libs/numeric/ublas/test/Jamfile.v2          |     7 +++++                                   
   branches/release/libs/numeric/ublas/test/test_triangular.cpp |    47 ++++++++++++++-------------------       
   branches/release/libs/numeric/ublas/test/utils.hpp           |    29 +++++++++++++-------                    
   7 files changed, 151 insertions(+), 45 deletions(-)
Modified: branches/release/boost/numeric/ublas/matrix_sparse.hpp
==============================================================================
--- branches/release/boost/numeric/ublas/matrix_sparse.hpp	(original)
+++ branches/release/boost/numeric/ublas/matrix_sparse.hpp	2012-09-22 17:57:57 EDT (Sat, 22 Sep 2012)
@@ -4391,17 +4391,69 @@
             m1.swap (m2);
         }
 
+        // replacement if STL lower bound algorithm for use of inplace_merge
+        array_size_type lower_bound (array_size_type beg, array_size_type end, array_size_type target) const {
+            while (end > beg) {
+                array_size_type mid = (beg + end) / 2;
+                if (((index1_data_[mid] < index1_data_[target]) ||
+                     ((index1_data_[mid] == index1_data_[target]) &&
+                      (index2_data_[mid] < index2_data_[target])))) {
+                    beg = mid + 1;
+                } else {
+                    end = mid;
+                }
+            }
+            return beg;
+        }
+
+        // specialized replacement of STL inplace_merge to avoid compilation
+        // problems with respect to the array_triple iterator
+        void inplace_merge (array_size_type beg, array_size_type mid, array_size_type end) const {
+            array_size_type len_lef = mid - beg;
+            array_size_type len_rig = end - mid;
+
+            if (len_lef == 1 && len_rig == 1) {
+                if ((index1_data_[mid] < index1_data_[beg]) ||
+                    ((index1_data_[mid] == index1_data_[beg]) && (index2_data_[mid] < index2_data_[beg])))
+                    {
+                        std::swap(index1_data_[beg], index1_data_[mid]);
+                        std::swap(index2_data_[beg], index2_data_[mid]);
+                        std::swap(value_data_[beg], value_data_[mid]);
+                    }
+            } else if (len_lef > 0 && len_rig > 0) {
+                array_size_type lef_mid, rig_mid;
+                if (len_lef >= len_rig) {
+                    lef_mid = (beg + mid) / 2;
+                    rig_mid = lower_bound(mid, end, lef_mid);
+                } else {
+                    rig_mid = (mid + end) / 2;
+                    lef_mid = lower_bound(beg, mid, rig_mid);
+                }
+                std::rotate(&index1_data_[0] + lef_mid, &index1_data_[0] + mid, &index1_data_[0] + rig_mid);
+                std::rotate(&index2_data_[0] + lef_mid, &index2_data_[0] + mid, &index2_data_[0] + rig_mid);
+                std::rotate(&value_data_[0] + lef_mid, &value_data_[0] + mid, &value_data_[0] + rig_mid);
+
+                array_size_type new_mid = lef_mid + rig_mid - mid;
+                inplace_merge(beg, lef_mid, new_mid);
+                inplace_merge(new_mid, rig_mid, end);
+            }
+        }
+
         // Sorting and summation of duplicates
         BOOST_UBLAS_INLINE
         void sort () const {
             if (! sorted_ && filled_ > 0) {
                 typedef index_triple_array<index_array_type, index_array_type, value_array_type> array_triple;
                 array_triple ita (filled_, index1_data_, index2_data_, value_data_);
+#ifndef BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT
                 const typename array_triple::iterator iunsorted = ita.begin () + sorted_filled_;
                 // sort new elements and merge
                 std::sort (iunsorted, ita.end ());
-                std::inplace_merge (ita.begin (), iunsorted, ita.end ());
-                
+                inplace_merge(0, sorted_filled_, filled_);
+#else
+                const typename array_triple::iterator iunsorted = ita.begin ();
+                std::sort (iunsorted, ita.end ());
+#endif                
                 // sum duplicates with += and remove
                 array_size_type filled = 0;
                 for (array_size_type i = 1; i < filled_; ++ i) {
Modified: branches/release/boost/numeric/ublas/operation/size.hpp
==============================================================================
--- branches/release/boost/numeric/ublas/operation/size.hpp	(original)
+++ branches/release/boost/numeric/ublas/operation/size.hpp	2012-09-22 17:57:57 EDT (Sat, 22 Sep 2012)
@@ -304,7 +304,7 @@
 BOOST_UBLAS_INLINE
 typename vector_traits<VectorExprT>::size_type size(vector_expression<VectorExprT> const& ve)
 {
-    return detail::size_by_dim_impl<Dim, vector_tag>::template apply(ve);
+    return detail::size_by_dim_impl<Dim, vector_tag>::apply(ve);
 }
 
 
@@ -321,7 +321,7 @@
 BOOST_UBLAS_INLINE
 typename matrix_traits<MatrixExprT>::size_type size(matrix_expression<MatrixExprT> const& me)
 {
-    return detail::size_by_dim_impl<Dim, matrix_tag>::template apply(me);
+    return detail::size_by_dim_impl<Dim, matrix_tag>::apply(me);
 }
 
 
@@ -341,7 +341,7 @@
     detail::matrix_size_type<MatrixExprT>
 >::type size(matrix_expression<MatrixExprT> const& me)
 {
-    return detail::size_by_tag_impl<TagT, matrix_tag, typename matrix_traits<MatrixExprT>::orientation_category>::template apply(me);
+    return detail::size_by_tag_impl<TagT, matrix_tag, typename matrix_traits<MatrixExprT>::orientation_category>::apply(me);
 }
 
 }}} // Namespace boost::numeric::ublas
Modified: branches/release/boost/numeric/ublas/storage.hpp
==============================================================================
--- branches/release/boost/numeric/ublas/storage.hpp	(original)
+++ branches/release/boost/numeric/ublas/storage.hpp	2012-09-22 17:57:57 EDT (Sat, 22 Sep 2012)
@@ -1564,7 +1564,6 @@
 
     template <class V>
     class index_pair :
-        private boost::noncopyable,
         public container_reference<V> {
 
         typedef index_pair<V> self_type;
@@ -1734,7 +1733,6 @@
 
     template <class M>
     class index_triple :
-        private boost::noncopyable,
         public container_reference<M> {
 
         typedef index_triple<M> self_type;
Modified: branches/release/boost/numeric/ublas/vector_sparse.hpp
==============================================================================
--- branches/release/boost/numeric/ublas/vector_sparse.hpp	(original)
+++ branches/release/boost/numeric/ublas/vector_sparse.hpp	2012-09-22 17:57:57 EDT (Sat, 22 Sep 2012)
@@ -1801,16 +1801,63 @@
             v1.swap (v2);
         }
 
+        // replacement if STL lower bound algorithm for use of inplace_merge
+        size_type lower_bound (size_type beg, size_type end, size_type target) const {
+            while (end > beg) {
+                size_type mid = (beg + end) / 2;
+                if (index_data_[mid] < index_data_[target]) {
+                    beg = mid + 1;
+                } else {
+                    end = mid;
+                }
+            }
+            return beg;
+        }
+
+        // specialized replacement of STL inplace_merge to avoid compilation
+        // problems with respect to the array_triple iterator
+        void inplace_merge (size_type beg, size_type mid, size_type end) const {
+            size_type len_lef = mid - beg;
+            size_type len_rig = end - mid;
+
+            if (len_lef == 1 && len_rig == 1) {
+                if (index_data_[mid] < index_data_[beg]) {
+                    std::swap(index_data_[beg], index_data_[mid]);
+                    std::swap(value_data_[beg], value_data_[mid]);
+                }
+            } else if (len_lef > 0 && len_rig > 0) {
+                size_type lef_mid, rig_mid;
+                if (len_lef >= len_rig) {
+                    lef_mid = (beg + mid) / 2;
+                    rig_mid = lower_bound(mid, end, lef_mid);
+                } else {
+                    rig_mid = (mid + end) / 2;
+                    lef_mid = lower_bound(beg, mid, rig_mid);
+                }
+                std::rotate(&index_data_[0] + lef_mid, &index_data_[0] + mid, &index_data_[0] + rig_mid);
+                std::rotate(&value_data_[0] + lef_mid, &value_data_[0] + mid, &value_data_[0] + rig_mid);
+
+                size_type new_mid = lef_mid + rig_mid - mid;
+                inplace_merge(beg, lef_mid, new_mid);
+                inplace_merge(new_mid, rig_mid, end);
+            }
+        }
+
         // Sorting and summation of duplicates
         BOOST_UBLAS_INLINE
         void sort () const {
             if (! sorted_ && filled_ > 0) {
                 typedef index_pair_array<index_array_type, value_array_type> array_pair;
                 array_pair ipa (filled_, index_data_, value_data_);
+#ifndef BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT
                 const typename array_pair::iterator iunsorted = ipa.begin () + sorted_filled_;
                 // sort new elements and merge
                 std::sort (iunsorted, ipa.end ());
-                std::inplace_merge (ipa.begin (), iunsorted, ipa.end ());
+                inplace_merge(0, sorted_filled_, filled_);
+#else
+                const typename array_pair::iterator iunsorted = ipa.begin ();
+                std::sort (iunsorted, ipa.end ());
+#endif
 
                 // sum duplicates with += and remove
                 size_type filled = 0;
Modified: branches/release/libs/numeric/ublas/test/Jamfile.v2
==============================================================================
--- branches/release/libs/numeric/ublas/test/Jamfile.v2	(original)
+++ branches/release/libs/numeric/ublas/test/Jamfile.v2	2012-09-22 17:57:57 EDT (Sat, 22 Sep 2012)
@@ -157,6 +157,9 @@
           [ run test_assignment.cpp
           ]
           [ run test_triangular.cpp
+        :
+        :
+        : <library>/boost/timer//boost_timer
           ]
           [ run test_ticket7296.cpp
           ]
@@ -181,4 +184,8 @@
         : test_inplace_solve_mvov
         :
       ]
+      [ run test_coordinate_vector_inplace_merge.cpp 
+      ]
+      [ run test_coordinate_matrix_inplace_merge.cpp 
+      ]
     ;
Modified: branches/release/libs/numeric/ublas/test/test_triangular.cpp
==============================================================================
--- branches/release/libs/numeric/ublas/test/test_triangular.cpp	(original)
+++ branches/release/libs/numeric/ublas/test/test_triangular.cpp	2012-09-22 17:57:57 EDT (Sat, 22 Sep 2012)
@@ -6,6 +6,7 @@
 #include <boost/numeric/ublas/triangular.hpp>
 #include <boost/numeric/ublas/io.hpp>
 
+#include <boost/timer/timer.hpp>
 
 #include <sys/times.h>
 #include <sys/time.h>
@@ -33,7 +34,7 @@
 
 
 int main() {
-  const int n=10000;
+  const int n=7000;
 #if 1
   ublas::compressed_matrix<double, ublas::row_major>     mat_row_upp(n, n);
   ublas::compressed_matrix<double, ublas::column_major>  mat_col_upp(n, n);
@@ -76,62 +77,54 @@
 
   std::cerr << "Starting..." << std::endl;
   {
-    clock_t start = clock();
+    boost::timer::auto_cpu_timer t(std::cerr, "col_low x: %t sec CPU, %w sec real\n");
     ublas::vector<double>  x(b);
     ublas::inplace_solve(mat_col_low,  x, ublas::lower_tag());
-    std::cerr << "Col_low x: " << clock()-start << std::endl;
     std::cerr << "delta: " << diff(mat_col_low, x, b) << "\n";
   }
   {
-    clock_t start = clock();
+    boost::timer::auto_cpu_timer t(std::cerr, "row_low x: %t sec CPU, %w sec real\n");
     ublas::vector<double>  x(b);
     ublas::inplace_solve(mat_row_low, x, ublas::lower_tag());
-    std::cerr << "Row_low x: " << clock()-start << std::endl;
     std::cerr << "delta: " << diff(mat_row_low, x, b) << "\n";
   }
 
   {
-    clock_t start = clock();
+    boost::timer::auto_cpu_timer t(std::cerr, "col_upp x: %t sec CPU, %w sec real\n");
     ublas::vector<double>  x(b);
     ublas::inplace_solve(mat_col_upp,  x, ublas::upper_tag());
-    std::cerr << "col_upp x: " << clock()-start << std::endl;
     std::cerr << "delta: " << diff(mat_col_upp, x, b) << "\n";
   }
   {
-    clock_t start = clock();
+    boost::timer::auto_cpu_timer t(std::cerr, "row_upp x: %t sec CPU, %w sec real\n");
     ublas::vector<double>  x(b);
     ublas::inplace_solve(mat_row_upp, x, ublas::upper_tag());
-    std::cerr << "row_upp x: " << clock()-start << std::endl;
     std::cerr << "delta: " << diff(mat_row_upp, x, b) << "\n";
   }
 
-//   {
-//     clock_t start = clock();
-//     ublas::vector<double>  x(b);
-//     ublas::inplace_solve(x, mat_col_low, ublas::lower_tag());
-//     std::cerr << "x col_low: " << clock()-start << std::endl;
-//     std::cerr << "delta: " << diff(x, mat_col_low, b) << "\n";
-//   }
   {
-    clock_t start = clock();
+    boost::timer::auto_cpu_timer t(std::cerr, "x col_low: %t sec CPU, %w sec real\n");
+    ublas::vector<double>  x(b);
+    ublas::inplace_solve(x, mat_col_low, ublas::lower_tag());
+    std::cerr << "delta: " << diff(x, mat_col_low, b) << "\n";
+  }
+  {
+    boost::timer::auto_cpu_timer t(std::cerr, "x row_low: %t sec CPU, %w sec real\n");
     ublas::vector<double>  x(b);
     ublas::inplace_solve(x, mat_row_low, ublas::lower_tag());
-    std::cerr << "x row_low: " << clock()-start << std::endl;
     std::cerr << "delta: " << diff(x, mat_row_low, b) << "\n";
   }
 
-//   {
-//     clock_t start = clock();
-//     ublas::vector<double>  x(b);
-//     ublas::inplace_solve(x, mat_col_upp, ublas::upper_tag());
-//     std::cerr << "x col_upp: " << clock()-start << std::endl;
-//     std::cerr << "delta: " << diff(x, mat_col_upp, b) << "\n";
-//   }
   {
-    clock_t start = clock();
+    boost::timer::auto_cpu_timer t(std::cerr, "x col_upp: %t sec CPU, %w sec real\n");
+    ublas::vector<double>  x(b);
+    ublas::inplace_solve(x, mat_col_upp, ublas::upper_tag());
+    std::cerr << "delta: " << diff(x, mat_col_upp, b) << "\n";
+  }
+  {
+    boost::timer::auto_cpu_timer t(std::cerr, "x row_upp: %t sec CPU, %w sec real\n");
     ublas::vector<double>  x(b);
     ublas::inplace_solve(x, mat_row_upp, ublas::upper_tag());
-    std::cerr << "x row_upp: " << clock()-start << std::endl;
     std::cerr << "delta: " << diff(x, mat_row_upp, b) << "\n";
   }
 
Modified: branches/release/libs/numeric/ublas/test/utils.hpp
==============================================================================
--- branches/release/libs/numeric/ublas/test/utils.hpp	(original)
+++ branches/release/libs/numeric/ublas/test/utils.hpp	2012-09-22 17:57:57 EDT (Sat, 22 Sep 2012)
@@ -54,6 +54,9 @@
 
 #include <boost/numeric/ublas/detail/config.hpp>
 #include <boost/numeric/ublas/traits.hpp>
+
+#include <boost/math/special_functions/fpclassify.hpp> // isnan, isinf
+
 #include <cmath>
 #include <complex>
 #include <cstddef>
@@ -63,13 +66,17 @@
 
 namespace boost { namespace numeric { namespace ublas { namespace test { namespace detail { namespace /*<unnamed>*/ {
 
+  using ::std::abs;
+  using ::std::max;
+
 /// Check if the given complex number is a NaN.
+// read the comments in fpclassify as well
 template <typename T>
 BOOST_UBLAS_INLINE
-bool isnan(::std::complex<T> const& z)
+bool (isnan)(::std::complex<T> const& z)
 {
         // According to IEEE, NaN is different even by itself
-	return (z != z) || ::std::isnan(z.real()) || ::std::isnan(z.imag());
+  return (z != z) || (boost::math::isnan)(z.real()) || (boost::math::isnan)(z.imag());
 }
 
 /// Check if two (real) numbers are close each other (wrt a given tolerance).
@@ -80,12 +87,12 @@
         typedef typename promote_traits<typename promote_traits<T1,T2>::promote_type,
                                                                         T3>::promote_type real_type;
 
-    if (::std::isnan(x) || ::std::isnan(y))
+    if ((boost::math::isnan)(x) || (boost::math::isnan)(y))
     {
         // According to IEEE, NaN is different even by itself
         return false;
     }
-    return ::std::abs(x-y) <= (::std::max(static_cast<real_type>(::std::abs(x)), static_cast<real_type>(::std::abs(y)))*tol);
+    return abs(x-y) <= (max(static_cast<real_type>(abs(x)), static_cast<real_type>(abs(y)))*tol);
 }
 
 /// Check if two complex numbers are close each other (wrt a given tolerance).
@@ -96,14 +103,15 @@
         typedef typename promote_traits<typename promote_traits<T1,T2>::promote_type,
                                                                         T3>::promote_type real_type;
 
-    if (isnan(x) || isnan(y))
+    if ((isnan)(x) || (isnan)(y))
     {
         // According to IEEE, NaN is different even by itself
         return false;
     }
         ::std::complex<real_type> xx(x);
         ::std::complex<real_type> yy(y);
-    return ::std::abs(xx-yy) <= (::std::max(::std::abs(xx), ::std::abs(yy))*tol);
+
+    return abs(xx-yy) <= (max(abs(xx), abs(yy))*tol);
 }
 
 /// Check if two (real) numbers are close each other (wrt a given tolerance).
@@ -114,12 +122,12 @@
         typedef typename promote_traits<typename promote_traits<T1,T2>::promote_type,
                                                                         T3>::promote_type real_type;
 
-    if (::std::isnan(x) || ::std::isnan(y))
+    if ((boost::math::isnan)(x) || (boost::math::isnan)(y))
     {
         // According to IEEE, NaN is different even by itself
         return false;
     }
-    return ::std::abs(x-y)/::std::abs(y) <= tol;
+    return abs(x-y)/abs(y) <= tol;
 }
 
 /// Check if two complex numbers are close each other (wrt a given tolerance).
@@ -130,14 +138,15 @@
         typedef typename promote_traits<typename promote_traits<T1,T2>::promote_type,
                                                                         T3>::promote_type real_type;
 
-    if (isnan(x) || isnan(y))
+    if ((isnan)(x) || (isnan)(y))
     {
         // According to IEEE, NaN is different even by itself
         return false;
     }
         ::std::complex<real_type> xx(x);
         ::std::complex<real_type> yy(y);
-    return ::std::abs(xx-yy)/::std::abs(yy) <= tol;
+
+    return abs(xx-yy)/abs(yy) <= tol;
 }
 
 }}}}}} // Namespace boost::numeric::ublas::test::detail::<unnamed>