2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // The authors gratefully acknowledge the support of
10 // GeNeSys mbH & Co. KG in producing this work.
13 #ifndef _BOOST_UBLAS_OPERATION_SPARSE_
14 #define _BOOST_UBLAS_OPERATION_SPARSE_
16 #include <boost/numeric/ublas/traits.hpp>
18 // These scaled additions were borrowed from MTL unashamedly.
19 // But Alexei Novakov had a lot of ideas to improve these. Thanks.
21 namespace boost
{ namespace numeric
{ namespace ublas
{
23 template<class M
, class E1
, class E2
, class TRI
>
26 sparse_prod (const matrix_expression
<E1
> &e1
,
27 const matrix_expression
<E2
> &e2
,
30 typedef M matrix_type
;
31 typedef TRI triangular_restriction
;
32 typedef const E1 expression1_type
;
33 typedef const E2 expression2_type
;
34 typedef typename
M::size_type size_type
;
35 typedef typename
M::value_type value_type
;
37 // ISSUE why is there a dense vector here?
38 vector
<value_type
> temporary (e2 ().size2 ());
40 typename
expression1_type::const_iterator1
it1 (e1 ().begin1 ());
41 typename
expression1_type::const_iterator1
it1_end (e1 ().end1 ());
42 while (it1
!= it1_end
) {
43 size_type
jb (temporary
.size ());
45 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
46 typename
expression1_type::const_iterator2
it2 (it1
.begin ());
47 typename
expression1_type::const_iterator2
it2_end (it1
.end ());
49 typename
expression1_type::const_iterator2
it2 (boost::numeric::ublas::begin (it1
, iterator1_tag ()));
50 typename
expression1_type::const_iterator2
it2_end (boost::numeric::ublas::end (it1
, iterator1_tag ()));
52 while (it2
!= it2_end
) {
53 // temporary.plus_assign (*it2 * row (e2 (), it2.index2 ()));
54 matrix_row
<expression2_type
> mr (e2 (), it2
.index2 ());
55 typename matrix_row
<expression2_type
>::const_iterator
itr (mr
.begin ());
56 typename matrix_row
<expression2_type
>::const_iterator
itr_end (mr
.end ());
57 while (itr
!= itr_end
) {
58 size_type
j (itr
.index ());
59 temporary (j
) += *it2
* *itr
;
60 jb
= (std::min
) (jb
, j
);
61 je
= (std::max
) (je
, j
);
66 for (size_type j
= jb
; j
< je
+ 1; ++ j
) {
67 if (temporary (j
) != value_type
/*zero*/()) {
68 // FIXME we'll need to extend the container interface!
69 // m.push_back (it1.index1 (), j, temporary (j));
70 // FIXME What to do with adaptors?
71 // m.insert (it1.index1 (), j, temporary (j));
72 if (triangular_restriction::other (it1
.index1 (), j
))
73 m (it1
.index1 (), j
) = temporary (j
);
74 temporary (j
) = value_type
/*zero*/();
82 template<class M
, class E1
, class E2
, class TRI
>
85 sparse_prod (const matrix_expression
<E1
> &e1
,
86 const matrix_expression
<E2
> &e2
,
89 typedef M matrix_type
;
90 typedef TRI triangular_restriction
;
91 typedef const E1 expression1_type
;
92 typedef const E2 expression2_type
;
93 typedef typename
M::size_type size_type
;
94 typedef typename
M::value_type value_type
;
96 // ISSUE why is there a dense vector here?
97 vector
<value_type
> temporary (e1 ().size1 ());
99 typename
expression2_type::const_iterator2
it2 (e2 ().begin2 ());
100 typename
expression2_type::const_iterator2
it2_end (e2 ().end2 ());
101 while (it2
!= it2_end
) {
102 size_type
ib (temporary
.size ());
104 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
105 typename
expression2_type::const_iterator1
it1 (it2
.begin ());
106 typename
expression2_type::const_iterator1
it1_end (it2
.end ());
108 typename
expression2_type::const_iterator1
it1 (boost::numeric::ublas::begin (it2
, iterator2_tag ()));
109 typename
expression2_type::const_iterator1
it1_end (boost::numeric::ublas::end (it2
, iterator2_tag ()));
111 while (it1
!= it1_end
) {
112 // column (m, it2.index2 ()).plus_assign (*it1 * column (e1 (), it1.index1 ()));
113 matrix_column
<expression1_type
> mc (e1 (), it1
.index1 ());
114 typename matrix_column
<expression1_type
>::const_iterator
itc (mc
.begin ());
115 typename matrix_column
<expression1_type
>::const_iterator
itc_end (mc
.end ());
116 while (itc
!= itc_end
) {
117 size_type
i (itc
.index ());
118 temporary (i
) += *it1
* *itc
;
119 ib
= (std::min
) (ib
, i
);
120 ie
= (std::max
) (ie
, i
);
125 for (size_type i
= ib
; i
< ie
+ 1; ++ i
) {
126 if (temporary (i
) != value_type
/*zero*/()) {
127 // FIXME we'll need to extend the container interface!
128 // m.push_back (i, it2.index2 (), temporary (i));
129 // FIXME What to do with adaptors?
130 // m.insert (i, it2.index2 (), temporary (i));
131 if (triangular_restriction::other (i
, it2
.index2 ()))
132 m (i
, it2
.index2 ()) = temporary (i
);
133 temporary (i
) = value_type
/*zero*/();
142 template<class M
, class E1
, class E2
, class TRI
>
145 sparse_prod (const matrix_expression
<E1
> &e1
,
146 const matrix_expression
<E2
> &e2
,
147 M
&m
, TRI
, bool init
= true) {
148 typedef typename
M::value_type value_type
;
149 typedef TRI triangular_restriction
;
150 typedef typename
M::orientation_category orientation_category
;
153 m
.assign (zero_matrix
<value_type
> (e1 ().size1 (), e2 ().size2 ()));
154 return sparse_prod (e1
, e2
, m
, triangular_restriction (), orientation_category ());
156 template<class M
, class E1
, class E2
, class TRI
>
159 sparse_prod (const matrix_expression
<E1
> &e1
,
160 const matrix_expression
<E2
> &e2
,
162 typedef M matrix_type
;
163 typedef TRI triangular_restriction
;
165 matrix_type
m (e1 ().size1 (), e2 ().size2 ());
166 // FIXME needed for c_matrix?!
167 // return sparse_prod (e1, e2, m, triangular_restriction (), false);
168 return sparse_prod (e1
, e2
, m
, triangular_restriction (), true);
170 template<class M
, class E1
, class E2
>
173 sparse_prod (const matrix_expression
<E1
> &e1
,
174 const matrix_expression
<E2
> &e2
,
175 M
&m
, bool init
= true) {
176 typedef typename
M::value_type value_type
;
177 typedef typename
M::orientation_category orientation_category
;
180 m
.assign (zero_matrix
<value_type
> (e1 ().size1 (), e2 ().size2 ()));
181 return sparse_prod (e1
, e2
, m
, full (), orientation_category ());
183 template<class M
, class E1
, class E2
>
186 sparse_prod (const matrix_expression
<E1
> &e1
,
187 const matrix_expression
<E2
> &e2
) {
188 typedef M matrix_type
;
190 matrix_type
m (e1 ().size1 (), e2 ().size2 ());
191 // FIXME needed for c_matrix?!
192 // return sparse_prod (e1, e2, m, full (), false);
193 return sparse_prod (e1
, e2
, m
, full (), true);