00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_COPY_INCLUDE
00013 #define MTL_COPY_INCLUDE
00014
00015 #include <boost/numeric/mtl/mtl_fwd.hpp>
00016 #include <boost/numeric/mtl/detail/index.hpp>
00017 #include <boost/numeric/mtl/utility/tag.hpp>
00018 #include <boost/numeric/mtl/utility/exception.hpp>
00019 #include <boost/numeric/mtl/utility/range_generator.hpp>
00020 #include <boost/numeric/mtl/utility/ashape.hpp>
00021 #include <boost/numeric/mtl/matrix/inserter.hpp>
00022 #include <boost/numeric/mtl/operation/set_to_zero.hpp>
00023 #include <boost/numeric/mtl/operation/update.hpp>
00024 #include <boost/numeric/mtl/operation/print.hpp>
00025 #include <boost/numeric/mtl/operation/crop.hpp>
00026
00027 #include <boost/static_assert.hpp>
00028 #include <boost/type_traits.hpp>
00029 #include <iostream>
00030
00031 namespace mtl {
00032
00033 namespace detail {
00034
00035
00036
00037 template <typename MatrixDest>
00038 inline void zero_with_sparse_src(MatrixDest& dest, tag::sparse)
00039 {
00040 set_to_zero(dest);
00041 }
00042
00043 template <typename MatrixDest>
00044 inline void zero_with_sparse_src(MatrixDest& dest, tag::universe) {}
00045
00046
00047 template <typename Updater> struct copy_inserter_size {};
00048
00049
00050 template <typename Value>
00051 struct copy_inserter_size< operations::update_store<Value> >
00052 {
00053 template <typename MatrixSrc, typename MatrixDest>
00054 static inline int apply(const MatrixSrc& src, const MatrixDest& dest)
00055 {
00056 return int(src.nnz() * 1.2 / dest.dim1());
00057 }
00058 };
00059
00060 struct sum_of_sizes
00061 {
00062 template <typename MatrixSrc, typename MatrixDest>
00063 static inline int apply(const MatrixSrc& src, const MatrixDest& dest)
00064 { return int((src.nnz() + dest.nnz()) * 1.2 / dest.dim1()); }
00065 };
00066
00067
00068 template <typename Value> struct copy_inserter_size< operations::update_plus<Value> > : sum_of_sizes {};
00069 template <typename Value> struct copy_inserter_size< operations::update_minus<Value> > : sum_of_sizes {};
00070
00071 }
00072
00073
00074 template <typename Updater, typename MatrixSrc, typename MatrixDest>
00075 inline void gen_matrix_copy(const MatrixSrc& src, MatrixDest& dest, bool with_reset)
00076 {
00077 MTL_THROW_IF(num_rows(src) != num_rows(dest) || num_cols(src) != num_cols(dest), incompatible_size());
00078
00079 if (with_reset)
00080 detail::zero_with_sparse_src(dest, typename traits::category<MatrixSrc>::type());
00081
00082 typename traits::row<MatrixSrc>::type row(src);
00083 typename traits::col<MatrixSrc>::type col(src);
00084 typename traits::const_value<MatrixSrc>::type value(src);
00085 typedef typename traits::range_generator<tag::major, MatrixSrc>::type cursor_type;
00086
00087
00088 matrix::inserter<MatrixDest, Updater> ins(dest, detail::copy_inserter_size<Updater>::apply(src, dest));
00089 for (cursor_type cursor = begin<tag::major>(src), cend = end<tag::major>(src);
00090 cursor != cend; ++cursor) {
00091
00092
00093 typedef typename traits::range_generator<tag::nz, cursor_type>::type icursor_type;
00094 for (icursor_type icursor = begin<tag::nz>(cursor), icend = end<tag::nz>(cursor);
00095 icursor != icend; ++icursor) {
00096
00097 ins(row(*icursor), col(*icursor)) << value(*icursor); }
00098 }
00099 }
00100
00102 template <typename MatrixSrc, typename MatrixDest>
00103 inline void matrix_copy(const MatrixSrc& src, MatrixDest& dest)
00104 {
00105 gen_matrix_copy< operations::update_store<typename MatrixDest::value_type> >(src, dest, true);
00106 }
00107
00108
00110 template <typename MatrixSrc, typename MatrixDest>
00111 inline void matrix_copy_plus(const MatrixSrc& src, MatrixDest& dest)
00112 {
00113 gen_matrix_copy< operations::update_plus<typename MatrixDest::value_type> >(src, dest, false);
00114 }
00115
00117 template <typename MatrixSrc, typename MatrixDest>
00118 inline void matrix_copy_minus(const MatrixSrc& src, MatrixDest& dest)
00119 {
00120 gen_matrix_copy< operations::update_minus<typename MatrixDest::value_type> >(src, dest, false);
00121 }
00122
00124 template <typename MatrixSrc, typename MatrixDest>
00125 inline void matrix_copy_ele_times(const MatrixSrc& src, MatrixDest& dest)
00126 {
00127 MTL_THROW_IF(num_rows(src) != num_rows(dest) || num_cols(src) != num_cols(dest), incompatible_size());
00128
00129 typename traits::row<MatrixDest>::type row(dest);
00130 typename traits::col<MatrixDest>::type col(dest);
00131 typename traits::value<MatrixDest>::type value(dest);
00132 typedef typename traits::range_generator<tag::major, MatrixDest>::type cursor_type;
00133 typedef typename traits::range_generator<tag::nz, cursor_type>::type icursor_type;
00134
00135 for (cursor_type cursor = begin<tag::major>(dest), cend = end<tag::major>(dest); cursor != cend; ++cursor)
00136 for (icursor_type icursor = begin<tag::nz>(cursor), icend = end<tag::nz>(cursor); icursor != icend; ++icursor)
00137 value(*icursor, value(*icursor) * src[row(*icursor)][col(*icursor)]);
00138 #if 0 // copy would result in a*0 = a and 0*b = b!!!!
00139 gen_matrix_copy< operations::update_times<typename MatrixDest::value_type> >(src, dest, false);
00140 #endif
00141 crop(dest);
00142 }
00143
00144
00145 template <typename MatrixSrc, typename MatrixDest>
00146 inline void copy(const MatrixSrc& src, tag::matrix, MatrixDest& dest, tag::matrix)
00147
00148 {
00149 return matrix_copy(src, dest);
00150 }
00151
00152
00153
00154 template <typename Updater, typename VectorSrc, typename VectorDest>
00155 inline void gen_vector_copy(const VectorSrc& src, VectorDest& dest, bool with_reset)
00156 {
00157
00158
00159
00160 BOOST_STATIC_ASSERT((boost::is_same<typename ashape::ashape<VectorSrc>::type,
00161 typename ashape::ashape<VectorDest>::type>::value));
00162
00163 MTL_THROW_IF(size(src) != size(dest), incompatible_size());
00164
00165 if (with_reset)
00166 detail::zero_with_sparse_src(dest, typename traits::category<VectorSrc>::type());
00167
00168 typename traits::index<VectorSrc>::type index(src);
00169 typename traits::const_value<VectorSrc>::type value(src);
00170
00171 typedef typename traits::range_generator<tag::nz, VectorSrc>::type cursor_type;
00172 for (cursor_type cursor = begin<tag::nz>(src), cend = end<tag::nz>(src);
00173 cursor != cend; ++cursor)
00174 Updater()(dest[index(*cursor)], value(*cursor));
00175 }
00176
00178 template <typename VectorSrc, typename VectorDest>
00179 inline void vector_copy(const VectorSrc& src, VectorDest& dest)
00180 {
00181 gen_vector_copy< operations::update_store<typename VectorDest::value_type> >(src, dest, true);
00182 }
00183
00184
00186 template <typename VectorSrc, typename VectorDest>
00187 inline void vector_copy_plus(const VectorSrc& src, VectorDest& dest)
00188 {
00189 gen_vector_copy< operations::update_plus<typename VectorDest::value_type> >(src, dest, false);
00190 }
00191
00193 template <typename VectorSrc, typename VectorDest>
00194 inline void vector_copy_minus(const VectorSrc& src, VectorDest& dest)
00195 {
00196 gen_vector_copy< operations::update_minus<typename VectorDest::value_type> >(src, dest, false);
00197 }
00198
00199
00200
00201 template <typename VectorSrc, typename VectorDest>
00202 inline void copy(const VectorSrc& src, tag::vector, VectorDest& dest, tag::vector)
00203 {
00204 return vector_copy(src, dest);
00205 }
00206
00207
00208 template <typename CollSrc, typename CollDest>
00209 inline void copy(const CollSrc& src, CollDest& dest)
00210 {
00211 return copy(src, traits::category<CollSrc>::type(), dest, traits::category<CollDest>::type());
00212 }
00213
00214
00215 }
00216
00217 #endif // MTL_COPY_INCLUDE