1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
//
// Copyright (c) 2000-2002
// Joerg Walter, Mathias Koch
//
// 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)
//
// The authors gratefully acknowledge the support of
// GeNeSys mbH & Co. KG in producing this work.
//
#ifndef _BOOST_UBLAS_OPERATION_SPARSE_
#define _BOOST_UBLAS_OPERATION_SPARSE_
#include <boost/numeric/ublas/traits.hpp>
// These scaled additions were borrowed from MTL unashamedly.
// But Alexei Novakov had a lot of ideas to improve these. Thanks.
namespace boost { namespace numeric { namespace ublas {
template<class M, class E1, class E2, class TRI>
BOOST_UBLAS_INLINE
M &
sparse_prod (const matrix_expression<E1> &e1,
const matrix_expression<E2> &e2,
M &m, TRI,
row_major_tag) {
typedef M matrix_type;
typedef TRI triangular_restriction;
typedef const E1 expression1_type;
typedef const E2 expression2_type;
typedef typename M::size_type size_type;
typedef typename M::value_type value_type;
// ISSUE why is there a dense vector here?
vector<value_type> temporary (e2 ().size2 ());
temporary.clear ();
typename expression1_type::const_iterator1 it1 (e1 ().begin1 ());
typename expression1_type::const_iterator1 it1_end (e1 ().end1 ());
while (it1 != it1_end) {
size_type jb (temporary.size ());
size_type je (0);
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
typename expression1_type::const_iterator2 it2 (it1.begin ());
typename expression1_type::const_iterator2 it2_end (it1.end ());
#else
typename expression1_type::const_iterator2 it2 (boost::numeric::ublas::begin (it1, iterator1_tag ()));
typename expression1_type::const_iterator2 it2_end (boost::numeric::ublas::end (it1, iterator1_tag ()));
#endif
while (it2 != it2_end) {
// temporary.plus_assign (*it2 * row (e2 (), it2.index2 ()));
matrix_row<expression2_type> mr (e2 (), it2.index2 ());
typename matrix_row<expression2_type>::const_iterator itr (mr.begin ());
typename matrix_row<expression2_type>::const_iterator itr_end (mr.end ());
while (itr != itr_end) {
size_type j (itr.index ());
temporary (j) += *it2 * *itr;
jb = (std::min) (jb, j);
je = (std::max) (je, j);
++ itr;
}
++ it2;
}
for (size_type j = jb; j < je + 1; ++ j) {
if (temporary (j) != value_type/*zero*/()) {
// FIXME we'll need to extend the container interface!
// m.push_back (it1.index1 (), j, temporary (j));
// FIXME What to do with adaptors?
// m.insert (it1.index1 (), j, temporary (j));
if (triangular_restriction::other (it1.index1 (), j))
m (it1.index1 (), j) = temporary (j);
temporary (j) = value_type/*zero*/();
}
}
++ it1;
}
return m;
}
template<class M, class E1, class E2, class TRI>
BOOST_UBLAS_INLINE
M &
sparse_prod (const matrix_expression<E1> &e1,
const matrix_expression<E2> &e2,
M &m, TRI,
column_major_tag) {
typedef M matrix_type;
typedef TRI triangular_restriction;
typedef const E1 expression1_type;
typedef const E2 expression2_type;
typedef typename M::size_type size_type;
typedef typename M::value_type value_type;
// ISSUE why is there a dense vector here?
vector<value_type> temporary (e1 ().size1 ());
temporary.clear ();
typename expression2_type::const_iterator2 it2 (e2 ().begin2 ());
typename expression2_type::const_iterator2 it2_end (e2 ().end2 ());
while (it2 != it2_end) {
size_type ib (temporary.size ());
size_type ie (0);
#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
typename expression2_type::const_iterator1 it1 (it2.begin ());
typename expression2_type::const_iterator1 it1_end (it2.end ());
#else
typename expression2_type::const_iterator1 it1 (boost::numeric::ublas::begin (it2, iterator2_tag ()));
typename expression2_type::const_iterator1 it1_end (boost::numeric::ublas::end (it2, iterator2_tag ()));
#endif
while (it1 != it1_end) {
// column (m, it2.index2 ()).plus_assign (*it1 * column (e1 (), it1.index1 ()));
matrix_column<expression1_type> mc (e1 (), it1.index1 ());
typename matrix_column<expression1_type>::const_iterator itc (mc.begin ());
typename matrix_column<expression1_type>::const_iterator itc_end (mc.end ());
while (itc != itc_end) {
size_type i (itc.index ());
temporary (i) += *it1 * *itc;
ib = (std::min) (ib, i);
ie = (std::max) (ie, i);
++ itc;
}
++ it1;
}
for (size_type i = ib; i < ie + 1; ++ i) {
if (temporary (i) != value_type/*zero*/()) {
// FIXME we'll need to extend the container interface!
// m.push_back (i, it2.index2 (), temporary (i));
// FIXME What to do with adaptors?
// m.insert (i, it2.index2 (), temporary (i));
if (triangular_restriction::other (i, it2.index2 ()))
m (i, it2.index2 ()) = temporary (i);
temporary (i) = value_type/*zero*/();
}
}
++ it2;
}
return m;
}
// Dispatcher
template<class M, class E1, class E2, class TRI>
BOOST_UBLAS_INLINE
M &
sparse_prod (const matrix_expression<E1> &e1,
const matrix_expression<E2> &e2,
M &m, TRI, bool init = true) {
typedef typename M::value_type value_type;
typedef TRI triangular_restriction;
typedef typename M::orientation_category orientation_category;
if (init)
m.assign (zero_matrix<value_type> (e1 ().size1 (), e2 ().size2 ()));
return sparse_prod (e1, e2, m, triangular_restriction (), orientation_category ());
}
template<class M, class E1, class E2, class TRI>
BOOST_UBLAS_INLINE
M
sparse_prod (const matrix_expression<E1> &e1,
const matrix_expression<E2> &e2,
TRI) {
typedef M matrix_type;
typedef TRI triangular_restriction;
matrix_type m (e1 ().size1 (), e2 ().size2 ());
// FIXME needed for c_matrix?!
// return sparse_prod (e1, e2, m, triangular_restriction (), false);
return sparse_prod (e1, e2, m, triangular_restriction (), true);
}
template<class M, class E1, class E2>
BOOST_UBLAS_INLINE
M &
sparse_prod (const matrix_expression<E1> &e1,
const matrix_expression<E2> &e2,
M &m, bool init = true) {
typedef typename M::value_type value_type;
typedef typename M::orientation_category orientation_category;
if (init)
m.assign (zero_matrix<value_type> (e1 ().size1 (), e2 ().size2 ()));
return sparse_prod (e1, e2, m, full (), orientation_category ());
}
template<class M, class E1, class E2>
BOOST_UBLAS_INLINE
M
sparse_prod (const matrix_expression<E1> &e1,
const matrix_expression<E2> &e2) {
typedef M matrix_type;
matrix_type m (e1 ().size1 (), e2 ().size2 ());
// FIXME needed for c_matrix?!
// return sparse_prod (e1, e2, m, full (), false);
return sparse_prod (e1, e2, m, full (), true);
}
}}}
#endif
|