operation_sparse.hpp 8.0 KB

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