Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r67022 - in sandbox/numeric_bindings: boost/numeric/bindings/detail boost/numeric/bindings/traits/detail libs/numeric/bindings/lapack/test
From: thomas.klimpel_at_[hidden]
Date: 2010-12-05 12:30:29


Author: klimpel
Date: 2010-12-05 12:30:25 EST (Sun, 05 Dec 2010)
New Revision: 67022
URL: http://svn.boost.org/trac/boost/changeset/67022

Log:
Polished interleave functionality for complex vectors a bit, such that the usage is simplified and no reinterpret_casts are needed by the code using this new functionality.
Added:
   sandbox/numeric_bindings/boost/numeric/bindings/detail/complex_utils.hpp (contents, props changed)
Text files modified:
   sandbox/numeric_bindings/boost/numeric/bindings/traits/detail/utils.hpp | 95 ----------------------------------------
   sandbox/numeric_bindings/libs/numeric/bindings/lapack/test/hseqr.cpp | 18 ++----
   sandbox/numeric_bindings/libs/numeric/bindings/lapack/test/ublas_gees.cpp | 10 +--
   3 files changed, 10 insertions(+), 113 deletions(-)

Added: sandbox/numeric_bindings/boost/numeric/bindings/detail/complex_utils.hpp
==============================================================================
--- (empty file)
+++ sandbox/numeric_bindings/boost/numeric/bindings/detail/complex_utils.hpp 2010-12-05 12:30:25 EST (Sun, 05 Dec 2010)
@@ -0,0 +1,178 @@
+//
+// Copyright (c) 2003 Kresimir Fresl
+// Copyright (c) 2010 Thomas Klimpel
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_NUMERIC_BINDINGS_DETAIL_COMPLEX_UTILS_HPP
+#define BOOST_NUMERIC_BINDINGS_DETAIL_COMPLEX_UTILS_HPP
+
+#include <iterator>
+#include <boost/numeric/bindings/begin.hpp>
+#include <boost/numeric/bindings/end.hpp>
+#include <boost/numeric/bindings/is_complex.hpp>
+#include <boost/numeric/bindings/remove_imaginary.hpp>
+#include <boost/numeric/bindings/value_type.hpp>
+#include <boost/numeric/bindings/vector_view.hpp>
+#include <boost/utility/enable_if.hpp>
+
+namespace boost {
+namespace numeric {
+namespace bindings {
+
+namespace detail {
+
+#ifdef BOOST_NUMERIC_BINDINGS_BY_THE_BOOK
+template <typename It>
+void inshuffle(It it, std::size_t n) {
+ if (n==0) return;
+ for (std::size_t i = 0; 2*i < n; ++i) {
+ std::size_t k = 2*i + 1;
+ while (2*k <= n) k *= 2;
+ typename std::iterator_traits<It>::value_type tmp = it[n+i];
+ it[n+i] = it[k-1];
+ while (k % 2 == 0) {
+ it[k-1] = it[(k/2)-1];
+ k /= 2;
+ }
+ it[k-1] = tmp;
+ }
+ std::size_t kmin = 1;
+ while (2*kmin <= n) kmin *= 2;
+ for (std::size_t i = 0; 4*i+1 < n; ++i) {
+ std::size_t k = 2*i + 1;
+ while (2*k <= n) k *= 2;
+ std::size_t k1 = 2*(i+1) + 1;
+ while (2*k1 <= n) k1 *= 2;
+ if (k > k1) {
+ if (k1 < kmin) {
+ kmin = k1;
+ inshuffle(it+n, i+1);
+ }
+ else
+ inshuffle(it+n+1, i);
+ }
+ }
+ return inshuffle(it+n+(n%2), n/2);
+}
+#else
+template <typename It>
+void inshuffle(It it, std::size_t n) {
+ while (n > 0) {
+ std::size_t kmin = 1;
+ while (kmin <= n)
+ kmin *= 2;
+ {
+ std::size_t kk = kmin/2;
+ It itn = it + n;
+ for (std::size_t i = 0, s = (n+1)/2; i < s; ++i) {
+ std::size_t k = (2*i+1)*kk;
+ while (k > n) {
+ k /= 2;
+ kk /= 2;
+ }
+ // apply the cyclic permutation
+ typename std::iterator_traits<It>::value_type tmp = itn[i];
+ itn[i] = it[k-1];
+ while (k % 2 == 0) {
+ it[k-1] = it[(k/2)-1];
+ k /= 2;
+ }
+ it[k-1] = tmp;
+ }
+ }
+ // the optimized computation of k fails for n=2,
+ // so skip the 'normalization' loop when possible
+ if (n > 3) {
+ std::size_t kk = kmin/4;
+ for (std::size_t i = 1; 4*i < n+3; ++i) {
+ std::size_t k = (2*i+1)*kk;
+ if (k > n) {
+ kk /= 2;
+ if (k < kmin) {
+ kmin = k;
+ // if kmin is updated, do an in-shuffle
+ inshuffle(it+n, i);
+ }
+ else
+ // otherwise do an out-shuffle
+ inshuffle(it+n+1, i-1);
+ }
+ }
+ }
+ // implement the tail recursion as an iteration
+ it += n+(n%2);
+ n /= 2;
+ }
+}
+#endif
+
+// Reorders a real array followed by an imaginary array to a true complex array
+// where real and imaginary part of each number directly follow each other.
+template <typename VectorW>
+typename boost::enable_if< is_complex< typename bindings::value_type< VectorW >::type >, void >::type
+interlace (VectorW& w) {
+ typedef typename bindings::value_type< VectorW >::type value_type;
+ typedef typename bindings::remove_imaginary< value_type >::type real_type;
+ value_type* pw = bindings::begin_value(w);
+ std::ptrdiff_t n = bindings::end_value(w) - pw;
+ if (n < 2) return;
+ inshuffle(reinterpret_cast<real_type*> (pw)+1, n-1);
+}
+
+namespace result_of {
+
+template< typename VectorW >
+struct real_part_view {
+ typedef typename bindings::result_of::vector_view< typename
+ bindings::remove_imaginary< typename
+ bindings::value_type< VectorW >::type
+ >::type >::type type;
+};
+
+template< typename VectorW >
+struct imag_part_view {
+ typedef typename bindings::result_of::vector_view< typename
+ bindings::remove_imaginary< typename
+ bindings::value_type< VectorW >::type
+ >::type >::type type;
+};
+
+} // namespace result_of
+
+// Creates a real vector_view to the first half of the complex array,
+// which is intended to be filled by the real part
+template <typename VectorW>
+typename boost::enable_if< is_complex< typename bindings::value_type< VectorW >::type >,
+ typename result_of::real_part_view< VectorW >::type const >::type
+real_part_view (VectorW& w) {
+ typedef typename bindings::value_type< VectorW >::type value_type;
+ typedef typename bindings::remove_imaginary< value_type >::type real_type;
+ value_type* pw = bindings::begin_value(w);
+ std::ptrdiff_t n = bindings::end_value(w) - pw;
+ return bindings::vector_view(reinterpret_cast<real_type*> (pw), n);
+}
+
+// Creates a real vector_view to the second half of the complex array,
+// which is intended to be filled by the imaginary part
+template <typename VectorW>
+typename boost::enable_if< is_complex< typename bindings::value_type< VectorW >::type >,
+ typename result_of::imag_part_view< VectorW >::type const >::type
+imag_part_view (VectorW& w) {
+ typedef typename bindings::value_type< VectorW >::type value_type;
+ typedef typename bindings::remove_imaginary< value_type >::type real_type;
+ value_type* pw = bindings::begin_value(w);
+ std::ptrdiff_t n = bindings::end_value(w) - pw;
+ return bindings::vector_view(reinterpret_cast<real_type*> (pw)+n, n);
+}
+
+} // namespace detail
+
+} // namespace bindings
+} // namespace numeric
+} // namespace boost
+
+#endif

Modified: sandbox/numeric_bindings/boost/numeric/bindings/traits/detail/utils.hpp
==============================================================================
--- sandbox/numeric_bindings/boost/numeric/bindings/traits/detail/utils.hpp (original)
+++ sandbox/numeric_bindings/boost/numeric/bindings/traits/detail/utils.hpp 2010-12-05 12:30:25 EST (Sun, 05 Dec 2010)
@@ -1,7 +1,6 @@
 /*
  *
  * Copyright (c) Kresimir Fresl 2003
- * Copyright (c) 2010 Thomas Klimpel
  *
  * Distributed under the Boost Software License, Version 1.0.
  * (See accompanying file LICENSE_1_0.txt or copy at
@@ -47,100 +46,6 @@
 #endif
     }
 
-#ifdef BOOST_NUMERIC_BINDINGS_BY_THE_BOOK
- template <typename It>
- void inshuffle(It it, std::size_t n) {
- if (n==0) return;
- for (std::size_t i = 0; 2*i < n; ++i) {
- std::size_t k = 2*i + 1;
- while (2*k <= n) k *= 2;
- typename std::iterator_traits<It>::value_type tmp = it[n+i];
- it[n+i] = it[k-1];
- while (k % 2 == 0) {
- it[k-1] = it[(k/2)-1];
- k /= 2;
- }
- it[k-1] = tmp;
- }
- std::size_t kmin = 1;
- while (2*kmin <= n) kmin *= 2;
- for (std::size_t i = 0; 4*i+1 < n; ++i) {
- std::size_t k = 2*i + 1;
- while (2*k <= n) k *= 2;
- std::size_t k1 = 2*(i+1) + 1;
- while (2*k1 <= n) k1 *= 2;
- if (k > k1) {
- if (k1 < kmin) {
- kmin = k1;
- inshuffle(it+n, i+1);
- }
- else
- inshuffle(it+n+1, i);
- }
- }
- return inshuffle(it+n+(n%2), n/2);
- }
-#else
- template <typename It>
- void inshuffle(It it, std::size_t n) {
- while (n > 0) {
- std::size_t kmin = 1;
- while (kmin <= n)
- kmin *= 2;
- {
- std::size_t kk = kmin/2;
- It itn = it + n;
- for (std::size_t i = 0, s = (n+1)/2; i < s; ++i) {
- std::size_t k = (2*i+1)*kk;
- while (k > n) {
- k /= 2;
- kk /= 2;
- }
- // apply the cyclic permutation
- typename std::iterator_traits<It>::value_type tmp = itn[i];
- itn[i] = it[k-1];
- while (k % 2 == 0) {
- it[k-1] = it[(k/2)-1];
- k /= 2;
- }
- it[k-1] = tmp;
- }
- }
- // the optimized computation of k fails for n=2,
- // so skip the 'normalization' loop when possible
- if (n > 3) {
- std::size_t kk = kmin/4;
- for (std::size_t i = 1; 4*i < n+3; ++i) {
- std::size_t k = (2*i+1)*kk;
- if (k > n) {
- kk /= 2;
- if (k < kmin) {
- kmin = k;
- // if kmin is updated, do an in-shuffle
- inshuffle(it+n, i);
- }
- else
- // otherwise do an out-shuffle
- inshuffle(it+n+1, i-1);
- }
- }
- }
- // implement the tail recursion as an iteration
- it += n+(n%2);
- n /= 2;
- }
- }
-#endif
-
- // real & imaginary arrays => complex array
- template <typename CIt>
- void interlace (CIt c, std::ptrdiff_t n) {
- typedef typename std::iterator_traits<CIt>::value_type cmplx_t;
- typedef typename type_traits<cmplx_t>::real_type real_t;
- if (n < 2) return;
- inshuffle(reinterpret_cast<real_t*> (&*c)+1, n-1);
- }
-
     // converts real/complex to std::ptrdiff_t
     inline std::ptrdiff_t to_int (float f) { return static_cast<std::ptrdiff_t> (f); }
     inline std::ptrdiff_t to_int (double d) { return static_cast<std::ptrdiff_t> (d); }

Modified: sandbox/numeric_bindings/libs/numeric/bindings/lapack/test/hseqr.cpp
==============================================================================
--- sandbox/numeric_bindings/libs/numeric/bindings/lapack/test/hseqr.cpp (original)
+++ sandbox/numeric_bindings/libs/numeric/bindings/lapack/test/hseqr.cpp 2010-12-05 12:30:25 EST (Sun, 05 Dec 2010)
@@ -8,7 +8,7 @@
 #include <boost/numeric/ublas/io.hpp>
 #include <boost/numeric/bindings/ublas/matrix.hpp>
 #include <boost/numeric/bindings/ublas/vector.hpp>
-#include <boost/numeric/bindings/traits/detail/utils.hpp>
+#include <boost/numeric/bindings/detail/complex_utils.hpp>
 #include <boost/numeric/bindings/vector_view.hpp>
 #include <boost/numeric/bindings/lapack/computational/hseqr.hpp>
 #include <boost/numeric/bindings/lapack/computational/trevc.hpp>
@@ -49,12 +49,10 @@
     cout << "\nHSEQR for only eigenvalues." << endl;
     ublas::matrix<double, ublas::column_major> Z_dummy(1,1);
     lapack::hseqr('E', 'N', 1, n, H,
- bindings::vector_view(reinterpret_cast<double*>(
- &*bindings::begin_value(values)), bindings::size(values)),
- bindings::vector_view(reinterpret_cast<double*>(
- &*bindings::begin_value(values))+bindings::size(values), bindings::size(values)),
+ bindings::detail::real_part_view(values),
+ bindings::detail::imag_part_view(values),
         Z_dummy);
- bindings::traits::detail::interlace(bindings::begin_value(values), bindings::size(values));
+ bindings::detail::interlace(values);
     cout << "\nH:\n" << H << endl;
     cout << "\nvalues: " << values << endl;
 
@@ -62,12 +60,10 @@
     Hessenberg(H);
     cout << "H:\n" << H << endl;
     lapack::hseqr('S', 'I', 1, n, H,
- bindings::vector_view(reinterpret_cast<double*>(
- &*bindings::begin_value(values)), bindings::size(values)),
- bindings::vector_view(reinterpret_cast<double*>(
- &*bindings::begin_value(values))+bindings::size(values), bindings::size(values)),
+ bindings::detail::real_part_view(values),
+ bindings::detail::imag_part_view(values),
         Z);
- bindings::traits::detail::interlace(bindings::begin_value(values), bindings::size(values));
+ bindings::detail::interlace(values);
     cout << "\nH: " << H << endl;
     cout << "\nvalues: " << values << endl;
     cout << "\nZ: " << Z << endl;

Modified: sandbox/numeric_bindings/libs/numeric/bindings/lapack/test/ublas_gees.cpp
==============================================================================
--- sandbox/numeric_bindings/libs/numeric/bindings/lapack/test/ublas_gees.cpp (original)
+++ sandbox/numeric_bindings/libs/numeric/bindings/lapack/test/ublas_gees.cpp 2010-12-05 12:30:25 EST (Sun, 05 Dec 2010)
@@ -16,6 +16,7 @@
 #include <boost/numeric/bindings/lapack/driver/gees.hpp>
 #include <boost/numeric/bindings/detail/array.hpp>
 #include <boost/numeric/bindings/vector_view.hpp>
+#include <boost/numeric/bindings/detail/complex_utils.hpp>
 #include <boost/numeric/ublas/io.hpp>
 #include <boost/type_traits/is_complex.hpp>
 #include <boost/mpl/if.hpp>
@@ -26,7 +27,6 @@
 
 namespace ublas = boost::numeric::ublas;
 namespace lapack = boost::numeric::bindings::lapack;
-namespace traits = boost::numeric::bindings::traits;
 namespace bindings = boost::numeric::bindings;
 
 struct apply_real {
@@ -35,14 +35,10 @@
   static inline std::ptrdiff_t gees( const char jobvs, const char sort,
         external_fp select, MatrixA& a, fortran_int_t& sdim, VectorW& w,
         MatrixVS& vs, Workspace work ) {
- typedef typename bindings::value_type< MatrixA >::type value_type;
     fortran_int_t info = lapack::gees( jobvs, sort, select, a, sdim,
- bindings::vector_view(reinterpret_cast<value_type*>(
- &*bindings::begin_value(w)), bindings::size(w)),
- bindings::vector_view(reinterpret_cast<value_type*>(
- &*bindings::begin_value(w))+bindings::size(w), bindings::size(w)),
+ bindings::detail::real_part_view(w), bindings::detail::imag_part_view(w),
       vs, work );
- traits::detail::interlace(bindings::begin_value(w), bindings::size(w));
+ bindings::detail::interlace(w);
     return info;
   }
 };


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk