00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_UPDATE_INCLUDE
00013 #define MTL_UPDATE_INCLUDE
00014
00015 #include <boost/numeric/mtl/operation/assign_mode.hpp>
00016 #include <boost/numeric/mtl/utility/range_generator.hpp>
00017 #include <boost/numeric/mtl/utility/tag.hpp>
00018 #include <boost/numeric/mtl/utility/ashape.hpp>
00019
00020 namespace mtl { namespace operations {
00021
00022 template <typename Element>
00023 struct update_store
00024 {
00025 template <typename Value>
00026 Element& operator() (Element& x, Value const& y)
00027 {
00028 return x= y;
00029 }
00030
00031
00032 template <typename Value>
00033 Element init(Value const& y)
00034 {
00035 return y;
00036 }
00037 };
00038
00039 template <typename Element>
00040 struct update_plus
00041 {
00042 template <typename Value>
00043 Element& operator() (Element& x, Value const& y)
00044 {
00045 return x+= y;
00046 }
00047
00048
00049 template <typename Value>
00050 Element init(Value const& y)
00051 {
00052 return y;
00053 }
00054 };
00055
00056 template <typename Element>
00057 struct update_minus
00058 {
00059 template <typename Value>
00060 Element& operator() (Element& x, Value const& y)
00061 {
00062 return x-= y;
00063 }
00064
00065
00066 template <typename Value>
00067 Element init(Value const& y)
00068 {
00069 return -y;
00070 }
00071 };
00072
00073 template <typename Element>
00074 struct update_times
00075 {
00076 template <typename Value>
00077 Element& operator() (Element& x, Value const& y)
00078 {
00079 return x*= y;
00080 }
00081
00082
00083 template <typename Value>
00084 Element init(Value const& y)
00085 {
00086 return y;
00087 }
00088 };
00089
00090 template <typename Element, typename MonoidOp>
00091 struct update_adapter
00092 {
00093 template <typename Value>
00094 Element& operator() (Element& x, Value const& y)
00095 {
00096 return x= MonoidOp()(x, y);
00097 }
00098
00099
00100 template <typename Value>
00101 Element init(Value const& y)
00102 {
00103 return y;
00104 }
00105 };
00106
00107
00108 template <typename Inserter, typename SizeType = std::size_t>
00109 struct update_proxy
00110 {
00111 typedef update_proxy self;
00112 typedef typename Inserter::value_type value_type;
00113
00114 explicit update_proxy(Inserter& ins, SizeType row, SizeType col)
00115 : ins(ins), row(row), col(col) {}
00116
00117 struct nonsense {};
00118
00119 template <typename Value>
00120 self& operator<< (Value const& val)
00121 {
00122 return lshift(val, typename ashape::ashape<Value>::type());
00123 }
00124
00125 void f(typename mtl::ashape::ashape<typename Inserter::matrix_type>::type) {}
00126
00127 template <typename Value>
00128 self& operator= (Value const& val)
00129 {
00130 ins.template modify<update_store<value_type> > (row, col, val);
00131 return *this;
00132 }
00133
00134 template <typename Value>
00135 self& operator+= (Value const& val)
00136 {
00137 ins.template modify<update_plus<value_type> > (row, col, val);
00138 return *this;
00139 }
00140
00141 private:
00142
00143 typedef typename Inserter::matrix_type matrix_type;
00144 typedef typename mtl::ashape::ashape<matrix_type>::type matrix_shape;
00145 typedef typename mtl::ashape::ashape<typename matrix_type::value_type>::type value_shape;
00146
00147
00148
00149 template <typename Value>
00150 self& lshift (Value const& val, value_shape)
00151 {
00152 ins.update (row, col, val);
00153 return *this;
00154 }
00155
00156
00157
00158
00159 template <typename MatrixSrc>
00160 self& lshift (const MatrixSrc& src, matrix_shape)
00161 {
00162 namespace traits = mtl::traits;
00163 typename traits::row<MatrixSrc>::type row(src);
00164 typename traits::col<MatrixSrc>::type col(src);
00165 typename traits::const_value<MatrixSrc>::type value(src);
00166
00167 typedef typename traits::range_generator<tag::major, MatrixSrc>::type cursor_type;
00168 typedef typename traits::range_generator<tag::nz, cursor_type>::type icursor_type;
00169
00170 for (cursor_type cursor = begin<tag::major>(src), cend = end<tag::major>(src); cursor != cend; ++cursor)
00171 for (icursor_type icursor = begin<tag::nz>(cursor), icend = end<tag::nz>(cursor); icursor != icend; ++icursor)
00172 ins.update(row(*icursor) + this->row, col(*icursor) + this->col, value(*icursor));
00173
00174 return *this;
00175 }
00176
00177 Inserter& ins;
00178 SizeType row, col;
00179 };
00180
00182 template <typename Assign, typename Value>
00183 struct update_assign_mode {};
00184
00185 template <typename Value>
00186 struct update_assign_mode<assign::assign_sum, Value>
00187 {
00188 typedef update_plus<Value> type;
00189 };
00190
00191 template <typename Value>
00192 struct update_assign_mode<assign::plus_sum, Value>
00193 {
00194 typedef update_plus<Value> type;
00195 };
00196
00197 template <typename Value>
00198 struct update_assign_mode<assign::minus_sum, Value>
00199 {
00200 typedef update_minus<Value> type;
00201 };
00202
00203 }
00204
00205 using operations::update_store;
00206 using operations::update_plus;
00207 using operations::update_minus;
00208 using operations::update_times;
00209
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 #if 0
00232
00233
00234 namespace math {
00235
00236
00237 template <typename Element, typename MonoidOp>
00238 struct identity {};
00239
00240 #if 0
00241 template <typename Element, typename MonoidOp>
00242 struct identity< Element, mtl::operations::update_adapter< Element, MonoidOp > >
00243 : struct identity< Element, MonoidOp >
00244 {};
00245 #endif
00246
00247
00248 template < class T >
00249 struct identity< T, mtl::operations::update_store<T> >
00250 {
00251 static const T value = 0 ;
00252 T operator()() const { return value ; }
00253 } ;
00254
00255 template < class T >
00256 const T identity< T, mtl::operations::update_store< T > >::value ;
00257
00258
00259
00260 template < class T >
00261 struct identity< T, mtl::operations::update_plus<T> >
00262 {
00263 static const T value = 0 ;
00264 T operator()() const { return value ; }
00265 } ;
00266
00267 template < class T >
00268 const T identity< T, mtl::operations::update_plus< T > >::value ;
00269
00270
00271
00272 template < class T >
00273 struct identity< T, mtl::operations::update_mult<T> >
00274 {
00275 static const T value = 1 ;
00276 T operator()() const { return value ; }
00277 } ;
00278
00279 template < class T >
00280 const T identity< T, mtl::operations::update_mult< T > >::value ;
00281
00282 }
00283 #endif
00284
00285 #endif // MTL_UPDATE_INCLUDE