![]() |
Boost.uBlas 1.49
Linear Algebra in C++: matrices, vectors and numeric algorithms
|
00001 // 00002 // Copyright (c) 2000-2010 00003 // Joerg Walter, Mathias Koch. David Bellot 00004 // 00005 // Distributed under the Boost Software License, Version 1.0. (See 00006 // accompanying file LICENSE_1_0.txt or copy at 00007 // http://www.boost.org/LICENSE_1_0.txt) 00008 // 00009 // The authors gratefully acknowledge the support of 00010 // GeNeSys mbH & Co. KG in producing this work. 00011 // 00012 #ifndef _BOOST_UBLAS_EXPRESSION_TYPE_ 00013 #define _BOOST_UBLAS_EXPRESSION_TYPE_ 00014 00015 #include <boost/numeric/ublas/exception.hpp> 00016 #include <boost/numeric/ublas/traits.hpp> 00017 #include <boost/numeric/ublas/functional.hpp> 00018 00019 00020 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish 00021 // Iterators based on ideas of Jeremy Siek 00022 00023 namespace boost { namespace numeric { namespace ublas { 00024 00032 template<class E> 00033 class ublas_expression { 00034 public: 00035 typedef E expression_type; 00036 /* E can be an incomplete type - to define the following we would need more template arguments 00037 typedef typename E::type_category type_category; 00038 typedef typename E::value_type value_type; 00039 */ 00040 00041 protected: 00042 ublas_expression () {} 00043 ~ublas_expression () {} 00044 private: 00045 const ublas_expression& operator= (const ublas_expression &); 00046 }; 00047 00048 00059 template<class E> 00060 class scalar_expression: 00061 public ublas_expression<E> { 00062 public: 00063 typedef E expression_type; 00064 typedef scalar_tag type_category; 00065 00066 BOOST_UBLAS_INLINE 00067 const expression_type &operator () () const { 00068 return *static_cast<const expression_type *> (this); 00069 } 00070 BOOST_UBLAS_INLINE 00071 expression_type &operator () () { 00072 return *static_cast<expression_type *> (this); 00073 } 00074 }; 00075 00076 template<class T> 00077 class scalar_reference: 00078 public scalar_expression<scalar_reference<T> > { 00079 00080 typedef scalar_reference<T> self_type; 00081 public: 00082 typedef T value_type; 00083 typedef const value_type &const_reference; 00084 typedef typename boost::mpl::if_<boost::is_const<T>, 00085 const_reference, 00086 value_type &>::type reference; 00087 typedef const self_type const_closure_type; 00088 typedef const_closure_type closure_type; 00089 00090 // Construction and destruction 00091 BOOST_UBLAS_INLINE 00092 explicit scalar_reference (reference t): 00093 t_ (t) {} 00094 00095 // Conversion 00096 BOOST_UBLAS_INLINE 00097 operator value_type () const { 00098 return t_; 00099 } 00100 00101 // Assignment 00102 BOOST_UBLAS_INLINE 00103 scalar_reference &operator = (const scalar_reference &s) { 00104 t_ = s.t_; 00105 return *this; 00106 } 00107 template<class AE> 00108 BOOST_UBLAS_INLINE 00109 scalar_reference &operator = (const scalar_expression<AE> &ae) { 00110 t_ = ae; 00111 return *this; 00112 } 00113 00114 // Closure comparison 00115 BOOST_UBLAS_INLINE 00116 bool same_closure (const scalar_reference &sr) const { 00117 return &t_ == &sr.t_; 00118 } 00119 00120 private: 00121 reference t_; 00122 }; 00123 00124 template<class T> 00125 class scalar_value: 00126 public scalar_expression<scalar_value<T> > { 00127 00128 typedef scalar_value<T> self_type; 00129 public: 00130 typedef T value_type; 00131 typedef const value_type &const_reference; 00132 typedef typename boost::mpl::if_<boost::is_const<T>, 00133 const_reference, 00134 value_type &>::type reference; 00135 typedef const scalar_reference<const self_type> const_closure_type; 00136 typedef scalar_reference<self_type> closure_type; 00137 00138 // Construction and destruction 00139 BOOST_UBLAS_INLINE 00140 scalar_value (): 00141 t_ () {} 00142 BOOST_UBLAS_INLINE 00143 scalar_value (const value_type &t): 00144 t_ (t) {} 00145 00146 BOOST_UBLAS_INLINE 00147 operator value_type () const { 00148 return t_; 00149 } 00150 00151 // Assignment 00152 BOOST_UBLAS_INLINE 00153 scalar_value &operator = (const scalar_value &s) { 00154 t_ = s.t_; 00155 return *this; 00156 } 00157 template<class AE> 00158 BOOST_UBLAS_INLINE 00159 scalar_value &operator = (const scalar_expression<AE> &ae) { 00160 t_ = ae; 00161 return *this; 00162 } 00163 00164 // Closure comparison 00165 BOOST_UBLAS_INLINE 00166 bool same_closure (const scalar_value &sv) const { 00167 return this == &sv; // self closing on instances value 00168 } 00169 00170 private: 00171 value_type t_; 00172 }; 00173 00174 00182 template<class E> 00183 class vector_expression: 00184 public ublas_expression<E> { 00185 public: 00186 static const unsigned complexity = 0; 00187 typedef E expression_type; 00188 typedef vector_tag type_category; 00189 /* E can be an incomplete type - to define the following we would need more template arguments 00190 typedef typename E::size_type size_type; 00191 */ 00192 00193 BOOST_UBLAS_INLINE 00194 const expression_type &operator () () const { 00195 return *static_cast<const expression_type *> (this); 00196 } 00197 BOOST_UBLAS_INLINE 00198 expression_type &operator () () { 00199 return *static_cast<expression_type *> (this); 00200 } 00201 00202 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 00203 private: 00204 // projection types 00205 typedef vector_range<E> vector_range_type; 00206 typedef vector_range<const E> const_vector_range_type; 00207 typedef vector_slice<E> vector_slice_type; 00208 typedef vector_slice<const E> const_vector_slice_type; 00209 // vector_indirect_type will depend on the A template parameter 00210 typedef basic_range<> default_range; // required to avoid range/slice name confusion 00211 typedef basic_slice<> default_slice; 00212 public: 00213 BOOST_UBLAS_INLINE 00214 const_vector_range_type operator () (const default_range &r) const { 00215 return const_vector_range_type (operator () (), r); 00216 } 00217 BOOST_UBLAS_INLINE 00218 vector_range_type operator () (const default_range &r) { 00219 return vector_range_type (operator () (), r); 00220 } 00221 BOOST_UBLAS_INLINE 00222 const_vector_slice_type operator () (const default_slice &s) const { 00223 return const_vector_slice_type (operator () (), s); 00224 } 00225 BOOST_UBLAS_INLINE 00226 vector_slice_type operator () (const default_slice &s) { 00227 return vector_slice_type (operator () (), s); 00228 } 00229 template<class A> 00230 BOOST_UBLAS_INLINE 00231 const vector_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia) const { 00232 return vector_indirect<const E, indirect_array<A> > (operator () (), ia); 00233 } 00234 template<class A> 00235 BOOST_UBLAS_INLINE 00236 vector_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia) { 00237 return vector_indirect<E, indirect_array<A> > (operator () (), ia); 00238 } 00239 00240 BOOST_UBLAS_INLINE 00241 const_vector_range_type project (const default_range &r) const { 00242 return const_vector_range_type (operator () (), r); 00243 } 00244 BOOST_UBLAS_INLINE 00245 vector_range_type project (const default_range &r) { 00246 return vector_range_type (operator () (), r); 00247 } 00248 BOOST_UBLAS_INLINE 00249 const_vector_slice_type project (const default_slice &s) const { 00250 return const_vector_slice_type (operator () (), s); 00251 } 00252 BOOST_UBLAS_INLINE 00253 vector_slice_type project (const default_slice &s) { 00254 return vector_slice_type (operator () (), s); 00255 } 00256 template<class A> 00257 BOOST_UBLAS_INLINE 00258 const vector_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia) const { 00259 return vector_indirect<const E, indirect_array<A> > (operator () (), ia); 00260 } 00261 template<class A> 00262 BOOST_UBLAS_INLINE 00263 vector_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia) { 00264 return vector_indirect<E, indirect_array<A> > (operator () (), ia); 00265 } 00266 #endif 00267 }; 00268 00276 template<class C> 00277 class vector_container: 00278 public vector_expression<C> { 00279 public: 00280 static const unsigned complexity = 0; 00281 typedef C container_type; 00282 typedef vector_tag type_category; 00283 00284 BOOST_UBLAS_INLINE 00285 const container_type &operator () () const { 00286 return *static_cast<const container_type *> (this); 00287 } 00288 BOOST_UBLAS_INLINE 00289 container_type &operator () () { 00290 return *static_cast<container_type *> (this); 00291 } 00292 00293 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 00294 using vector_expression<C>::operator (); 00295 #endif 00296 }; 00297 00298 00306 template<class E> 00307 class matrix_expression: 00308 public ublas_expression<E> { 00309 private: 00310 typedef matrix_expression<E> self_type; 00311 public: 00312 static const unsigned complexity = 0; 00313 typedef E expression_type; 00314 typedef matrix_tag type_category; 00315 /* E can be an incomplete type - to define the following we would need more template arguments 00316 typedef typename E::size_type size_type; 00317 */ 00318 00319 BOOST_UBLAS_INLINE 00320 const expression_type &operator () () const { 00321 return *static_cast<const expression_type *> (this); 00322 } 00323 BOOST_UBLAS_INLINE 00324 expression_type &operator () () { 00325 return *static_cast<expression_type *> (this); 00326 } 00327 00328 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 00329 private: 00330 // projection types 00331 typedef vector_range<E> vector_range_type; 00332 typedef const vector_range<const E> const_vector_range_type; 00333 typedef vector_slice<E> vector_slice_type; 00334 typedef const vector_slice<const E> const_vector_slice_type; 00335 typedef matrix_row<E> matrix_row_type; 00336 typedef const matrix_row<const E> const_matrix_row_type; 00337 typedef matrix_column<E> matrix_column_type; 00338 typedef const matrix_column<const E> const_matrix_column_type; 00339 typedef matrix_range<E> matrix_range_type; 00340 typedef const matrix_range<const E> const_matrix_range_type; 00341 typedef matrix_slice<E> matrix_slice_type; 00342 typedef const matrix_slice<const E> const_matrix_slice_type; 00343 // matrix_indirect_type will depend on the A template parameter 00344 typedef basic_range<> default_range; // required to avoid range/slice name confusion 00345 typedef basic_slice<> default_slice; 00346 00347 public: 00348 BOOST_UBLAS_INLINE 00349 const_matrix_row_type operator [] (std::size_t i) const { 00350 return const_matrix_row_type (operator () (), i); 00351 } 00352 BOOST_UBLAS_INLINE 00353 matrix_row_type operator [] (std::size_t i) { 00354 return matrix_row_type (operator () (), i); 00355 } 00356 BOOST_UBLAS_INLINE 00357 const_matrix_row_type row (std::size_t i) const { 00358 return const_matrix_row_type (operator () (), i); 00359 } 00360 BOOST_UBLAS_INLINE 00361 matrix_row_type row (std::size_t i) { 00362 return matrix_row_type (operator () (), i); 00363 } 00364 BOOST_UBLAS_INLINE 00365 const_matrix_column_type column (std::size_t j) const { 00366 return const_matrix_column_type (operator () (), j); 00367 } 00368 BOOST_UBLAS_INLINE 00369 matrix_column_type column (std::size_t j) { 00370 return matrix_column_type (operator () (), j); 00371 } 00372 00373 BOOST_UBLAS_INLINE 00374 const_matrix_range_type operator () (const default_range &r1, const default_range &r2) const { 00375 return const_matrix_range_type (operator () (), r1, r2); 00376 } 00377 BOOST_UBLAS_INLINE 00378 matrix_range_type operator () (const default_range &r1, const default_range &r2) { 00379 return matrix_range_type (operator () (), r1, r2); 00380 } 00381 BOOST_UBLAS_INLINE 00382 const_matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) const { 00383 return const_matrix_slice_type (operator () (), s1, s2); 00384 } 00385 BOOST_UBLAS_INLINE 00386 matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) { 00387 return matrix_slice_type (operator () (), s1, s2); 00388 } 00389 template<class A> 00390 BOOST_UBLAS_INLINE 00391 const matrix_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const { 00392 return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2); 00393 } 00394 template<class A> 00395 BOOST_UBLAS_INLINE 00396 matrix_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) { 00397 return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2); 00398 } 00399 00400 BOOST_UBLAS_INLINE 00401 const_matrix_range_type project (const default_range &r1, const default_range &r2) const { 00402 return const_matrix_range_type (operator () (), r1, r2); 00403 } 00404 BOOST_UBLAS_INLINE 00405 matrix_range_type project (const default_range &r1, const default_range &r2) { 00406 return matrix_range_type (operator () (), r1, r2); 00407 } 00408 BOOST_UBLAS_INLINE 00409 const_matrix_slice_type project (const default_slice &s1, const default_slice &s2) const { 00410 return const_matrix_slice_type (operator () (), s1, s2); 00411 } 00412 BOOST_UBLAS_INLINE 00413 matrix_slice_type project (const default_slice &s1, const default_slice &s2) { 00414 return matrix_slice_type (operator () (), s1, s2); 00415 } 00416 template<class A> 00417 BOOST_UBLAS_INLINE 00418 const matrix_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const { 00419 return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2); 00420 } 00421 template<class A> 00422 BOOST_UBLAS_INLINE 00423 matrix_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) { 00424 return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2); 00425 } 00426 #endif 00427 }; 00428 00429 #ifdef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 00430 struct iterator1_tag {}; 00431 struct iterator2_tag {}; 00432 00433 template<class I> 00434 BOOST_UBLAS_INLINE 00435 typename I::dual_iterator_type begin (const I &it, iterator1_tag) { 00436 return it ().find2 (1, it.index1 (), 0); 00437 } 00438 template<class I> 00439 BOOST_UBLAS_INLINE 00440 typename I::dual_iterator_type end (const I &it, iterator1_tag) { 00441 return it ().find2 (1, it.index1 (), it ().size2 ()); 00442 } 00443 template<class I> 00444 BOOST_UBLAS_INLINE 00445 typename I::dual_reverse_iterator_type rbegin (const I &it, iterator1_tag) { 00446 return typename I::dual_reverse_iterator_type (end (it, iterator1_tag ())); 00447 } 00448 template<class I> 00449 BOOST_UBLAS_INLINE 00450 typename I::dual_reverse_iterator_type rend (const I &it, iterator1_tag) { 00451 return typename I::dual_reverse_iterator_type (begin (it, iterator1_tag ())); 00452 } 00453 00454 template<class I> 00455 BOOST_UBLAS_INLINE 00456 typename I::dual_iterator_type begin (const I &it, iterator2_tag) { 00457 return it ().find1 (1, 0, it.index2 ()); 00458 } 00459 template<class I> 00460 BOOST_UBLAS_INLINE 00461 typename I::dual_iterator_type end (const I &it, iterator2_tag) { 00462 return it ().find1 (1, it ().size1 (), it.index2 ()); 00463 } 00464 template<class I> 00465 BOOST_UBLAS_INLINE 00466 typename I::dual_reverse_iterator_type rbegin (const I &it, iterator2_tag) { 00467 return typename I::dual_reverse_iterator_type (end (it, iterator2_tag ())); 00468 } 00469 template<class I> 00470 BOOST_UBLAS_INLINE 00471 typename I::dual_reverse_iterator_type rend (const I &it, iterator2_tag) { 00472 return typename I::dual_reverse_iterator_type (begin (it, iterator2_tag ())); 00473 } 00474 #endif 00475 00483 template<class C> 00484 class matrix_container: 00485 public matrix_expression<C> { 00486 public: 00487 static const unsigned complexity = 0; 00488 typedef C container_type; 00489 typedef matrix_tag type_category; 00490 00491 BOOST_UBLAS_INLINE 00492 const container_type &operator () () const { 00493 return *static_cast<const container_type *> (this); 00494 } 00495 BOOST_UBLAS_INLINE 00496 container_type &operator () () { 00497 return *static_cast<container_type *> (this); 00498 } 00499 00500 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 00501 using matrix_expression<C>::operator (); 00502 #endif 00503 }; 00504 00505 }}} 00506 00507 #endif