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