1 // Copyright (c) 2000-2013 2 // Joerg Walter, Mathias Koch. David Bellot 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See 5 // accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 // 8 // The authors gratefully acknowledge the support of 9 // GeNeSys mbH & Co. KG in producing this work. 10 // 11 #ifndef _BOOST_UBLAS_EXPRESSION_TYPE_ 12 #define _BOOST_UBLAS_EXPRESSION_TYPE_ 13 14 #include <boost/numeric/ublas/exception.hpp> 15 #include <boost/numeric/ublas/traits.hpp> 16 #include <boost/numeric/ublas/functional.hpp> 17 18 19 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish 20 // Iterators based on ideas of Jeremy Siek 21 22 namespace boost { namespace numeric { namespace ublas { 23 24 /** \brief Base class for uBLAS statically derived expressions using the the Barton Nackman trick 25 * 26 * This is a NonAssignable class 27 * Directly implement nonassignable - simplifes debugging call trace! 28 * 29 * \tparam E an expression type 30 */ 31 template<class E> 32 class ublas_expression { 33 public: 34 typedef E expression_type; 35 /* E can be an incomplete type - to define the following we would need more template arguments 36 typedef typename E::type_category type_category; 37 typedef typename E::value_type value_type; 38 */ 39 40 protected: ublas_expression()41 ublas_expression () {} ~ublas_expression()42 ~ublas_expression () {} 43 private: 44 const ublas_expression& operator= (const ublas_expression &); 45 }; 46 47 48 /** \brief Base class for Scalar Expression models 49 * 50 * It does not model the Scalar Expression concept but all derived types should. 51 * The class defines a common base type and some common interface for all statically 52 * derived Scalar Expression classes. 53 * 54 * We implement the casts to the statically derived type. 55 * 56 * \tparam E an expression type 57 */ 58 template<class E> 59 class scalar_expression: 60 public ublas_expression<E> { 61 public: 62 typedef E expression_type; 63 typedef scalar_tag type_category; 64 65 BOOST_UBLAS_INLINE operator ()() const66 const expression_type &operator () () const { 67 return *static_cast<const expression_type *> (this); 68 } 69 BOOST_UBLAS_INLINE operator ()()70 expression_type &operator () () { 71 return *static_cast<expression_type *> (this); 72 } 73 }; 74 75 template<class T> 76 class scalar_reference: 77 public scalar_expression<scalar_reference<T> > { 78 79 typedef scalar_reference<T> self_type; 80 public: 81 typedef T value_type; 82 typedef const value_type &const_reference; 83 typedef typename boost::mpl::if_<boost::is_const<T>, 84 const_reference, 85 value_type &>::type reference; 86 typedef const self_type const_closure_type; 87 typedef const_closure_type closure_type; 88 89 // Construction and destruction 90 BOOST_UBLAS_INLINE scalar_reference(reference t)91 explicit scalar_reference (reference t): 92 t_ (t) {} 93 94 // Conversion 95 BOOST_UBLAS_INLINE operator value_type() const96 operator value_type () const { 97 return t_; 98 } 99 100 // Assignment 101 BOOST_UBLAS_INLINE operator =(const scalar_reference & s)102 scalar_reference &operator = (const scalar_reference &s) { 103 t_ = s.t_; 104 return *this; 105 } 106 template<class AE> 107 BOOST_UBLAS_INLINE operator =(const scalar_expression<AE> & ae)108 scalar_reference &operator = (const scalar_expression<AE> &ae) { 109 t_ = ae; 110 return *this; 111 } 112 113 // Closure comparison 114 BOOST_UBLAS_INLINE same_closure(const scalar_reference & sr) const115 bool same_closure (const scalar_reference &sr) const { 116 return &t_ == &sr.t_; 117 } 118 119 private: 120 reference t_; 121 }; 122 123 template<class T> 124 class scalar_value: 125 public scalar_expression<scalar_value<T> > { 126 127 typedef scalar_value<T> self_type; 128 public: 129 typedef T value_type; 130 typedef const value_type &const_reference; 131 typedef typename boost::mpl::if_<boost::is_const<T>, 132 const_reference, 133 value_type &>::type reference; 134 typedef const scalar_reference<const self_type> const_closure_type; 135 typedef scalar_reference<self_type> closure_type; 136 137 // Construction and destruction 138 BOOST_UBLAS_INLINE scalar_value()139 scalar_value (): 140 t_ () {} 141 BOOST_UBLAS_INLINE scalar_value(const value_type & t)142 scalar_value (const value_type &t): 143 t_ (t) {} 144 145 BOOST_UBLAS_INLINE operator value_type() const146 operator value_type () const { 147 return t_; 148 } 149 150 // Assignment 151 BOOST_UBLAS_INLINE operator =(const scalar_value & s)152 scalar_value &operator = (const scalar_value &s) { 153 t_ = s.t_; 154 return *this; 155 } 156 template<class AE> 157 BOOST_UBLAS_INLINE operator =(const scalar_expression<AE> & ae)158 scalar_value &operator = (const scalar_expression<AE> &ae) { 159 t_ = ae; 160 return *this; 161 } 162 163 // Closure comparison 164 BOOST_UBLAS_INLINE same_closure(const scalar_value & sv) const165 bool same_closure (const scalar_value &sv) const { 166 return this == &sv; // self closing on instances value 167 } 168 169 private: 170 value_type t_; 171 }; 172 173 174 /** \brief Base class for Vector Expression models 175 * 176 * it does not model the Vector Expression concept but all derived types should. 177 * The class defines a common base type and some common interface for all 178 * statically derived Vector Expression classes. 179 * We implement the casts to the statically derived type. 180 */ 181 template<class E> 182 class vector_expression: 183 public ublas_expression<E> { 184 public: 185 static const unsigned complexity = 0; 186 typedef E expression_type; 187 typedef vector_tag type_category; 188 /* E can be an incomplete type - to define the following we would need more template arguments 189 typedef typename E::size_type size_type; 190 */ 191 192 BOOST_UBLAS_INLINE operator ()() const193 const expression_type &operator () () const { 194 return *static_cast<const expression_type *> (this); 195 } 196 BOOST_UBLAS_INLINE operator ()()197 expression_type &operator () () { 198 return *static_cast<expression_type *> (this); 199 } 200 201 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 202 private: 203 // projection types 204 typedef vector_range<E> vector_range_type; 205 typedef vector_range<const E> const_vector_range_type; 206 typedef vector_slice<E> vector_slice_type; 207 typedef vector_slice<const E> const_vector_slice_type; 208 // vector_indirect_type will depend on the A template parameter 209 typedef basic_range<> default_range; // required to avoid range/slice name confusion 210 typedef basic_slice<> default_slice; 211 public: 212 BOOST_UBLAS_INLINE operator ()(const default_range & r) const213 const_vector_range_type operator () (const default_range &r) const { 214 return const_vector_range_type (operator () (), r); 215 } 216 BOOST_UBLAS_INLINE operator ()(const default_range & r)217 vector_range_type operator () (const default_range &r) { 218 return vector_range_type (operator () (), r); 219 } 220 BOOST_UBLAS_INLINE operator ()(const default_slice & s) const221 const_vector_slice_type operator () (const default_slice &s) const { 222 return const_vector_slice_type (operator () (), s); 223 } 224 BOOST_UBLAS_INLINE operator ()(const default_slice & s)225 vector_slice_type operator () (const default_slice &s) { 226 return vector_slice_type (operator () (), s); 227 } 228 template<class A> 229 BOOST_UBLAS_INLINE operator ()(const indirect_array<A> & ia) const230 const vector_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia) const { 231 return vector_indirect<const E, indirect_array<A> > (operator () (), ia); 232 } 233 template<class A> 234 BOOST_UBLAS_INLINE operator ()(const indirect_array<A> & ia)235 vector_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia) { 236 return vector_indirect<E, indirect_array<A> > (operator () (), ia); 237 } 238 239 BOOST_UBLAS_INLINE project(const default_range & r) const240 const_vector_range_type project (const default_range &r) const { 241 return const_vector_range_type (operator () (), r); 242 } 243 BOOST_UBLAS_INLINE project(const default_range & r)244 vector_range_type project (const default_range &r) { 245 return vector_range_type (operator () (), r); 246 } 247 BOOST_UBLAS_INLINE project(const default_slice & s) const248 const_vector_slice_type project (const default_slice &s) const { 249 return const_vector_slice_type (operator () (), s); 250 } 251 BOOST_UBLAS_INLINE project(const default_slice & s)252 vector_slice_type project (const default_slice &s) { 253 return vector_slice_type (operator () (), s); 254 } 255 template<class A> 256 BOOST_UBLAS_INLINE project(const indirect_array<A> & ia) const257 const vector_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia) const { 258 return vector_indirect<const E, indirect_array<A> > (operator () (), ia); 259 } 260 template<class A> 261 BOOST_UBLAS_INLINE project(const indirect_array<A> & ia)262 vector_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia) { 263 return vector_indirect<E, indirect_array<A> > (operator () (), ia); 264 } 265 #endif 266 }; 267 268 /** \brief Base class for Vector container models 269 * 270 * it does not model the Vector concept but all derived types should. 271 * The class defines a common base type and some common interface for all 272 * statically derived Vector classes 273 * We implement the casts to the statically derived type. 274 */ 275 template<class C> 276 class vector_container: 277 public vector_expression<C> { 278 public: 279 static const unsigned complexity = 0; 280 typedef C container_type; 281 typedef vector_tag type_category; 282 283 BOOST_UBLAS_INLINE operator ()() const284 const container_type &operator () () const { 285 return *static_cast<const container_type *> (this); 286 } 287 BOOST_UBLAS_INLINE operator ()()288 container_type &operator () () { 289 return *static_cast<container_type *> (this); 290 } 291 292 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 293 using vector_expression<C>::operator (); 294 #endif 295 }; 296 297 298 /** \brief Base class for Matrix Expression models 299 * 300 * it does not model the Matrix Expression concept but all derived types should. 301 * The class defines a common base type and some common interface for all 302 * statically derived Matrix Expression classes 303 * We implement the casts to the statically derived type. 304 */ 305 template<class E> 306 class matrix_expression: 307 public ublas_expression<E> { 308 private: 309 typedef matrix_expression<E> self_type; 310 public: 311 static const unsigned complexity = 0; 312 typedef E expression_type; 313 typedef matrix_tag type_category; 314 /* E can be an incomplete type - to define the following we would need more template arguments 315 typedef typename E::size_type size_type; 316 */ 317 318 BOOST_UBLAS_INLINE operator ()() const319 const expression_type &operator () () const { 320 return *static_cast<const expression_type *> (this); 321 } 322 BOOST_UBLAS_INLINE operator ()()323 expression_type &operator () () { 324 return *static_cast<expression_type *> (this); 325 } 326 327 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 328 private: 329 // projection types 330 typedef vector_range<E> vector_range_type; 331 typedef const vector_range<const E> const_vector_range_type; 332 typedef vector_slice<E> vector_slice_type; 333 typedef const vector_slice<const E> const_vector_slice_type; 334 typedef matrix_row<E> matrix_row_type; 335 typedef const matrix_row<const E> const_matrix_row_type; 336 typedef matrix_column<E> matrix_column_type; 337 typedef const matrix_column<const E> const_matrix_column_type; 338 typedef matrix_range<E> matrix_range_type; 339 typedef const matrix_range<const E> const_matrix_range_type; 340 typedef matrix_slice<E> matrix_slice_type; 341 typedef const matrix_slice<const E> const_matrix_slice_type; 342 // matrix_indirect_type will depend on the A template parameter 343 typedef basic_range<> default_range; // required to avoid range/slice name confusion 344 typedef basic_slice<> default_slice; 345 346 public: 347 BOOST_UBLAS_INLINE operator [](std::size_t i) const348 const_matrix_row_type operator [] (std::size_t i) const { 349 return const_matrix_row_type (operator () (), i); 350 } 351 BOOST_UBLAS_INLINE operator [](std::size_t i)352 matrix_row_type operator [] (std::size_t i) { 353 return matrix_row_type (operator () (), i); 354 } 355 BOOST_UBLAS_INLINE row(std::size_t i) const356 const_matrix_row_type row (std::size_t i) const { 357 return const_matrix_row_type (operator () (), i); 358 } 359 BOOST_UBLAS_INLINE row(std::size_t i)360 matrix_row_type row (std::size_t i) { 361 return matrix_row_type (operator () (), i); 362 } 363 BOOST_UBLAS_INLINE column(std::size_t j) const364 const_matrix_column_type column (std::size_t j) const { 365 return const_matrix_column_type (operator () (), j); 366 } 367 BOOST_UBLAS_INLINE column(std::size_t j)368 matrix_column_type column (std::size_t j) { 369 return matrix_column_type (operator () (), j); 370 } 371 372 BOOST_UBLAS_INLINE operator ()(const default_range & r1,const default_range & r2) const373 const_matrix_range_type operator () (const default_range &r1, const default_range &r2) const { 374 return const_matrix_range_type (operator () (), r1, r2); 375 } 376 BOOST_UBLAS_INLINE operator ()(const default_range & r1,const default_range & r2)377 matrix_range_type operator () (const default_range &r1, const default_range &r2) { 378 return matrix_range_type (operator () (), r1, r2); 379 } 380 BOOST_UBLAS_INLINE operator ()(const default_slice & s1,const default_slice & s2) const381 const_matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) const { 382 return const_matrix_slice_type (operator () (), s1, s2); 383 } 384 BOOST_UBLAS_INLINE operator ()(const default_slice & s1,const default_slice & s2)385 matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) { 386 return matrix_slice_type (operator () (), s1, s2); 387 } 388 template<class A> 389 BOOST_UBLAS_INLINE operator ()(const indirect_array<A> & ia1,const indirect_array<A> & ia2) const390 const matrix_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const { 391 return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2); 392 } 393 template<class A> 394 BOOST_UBLAS_INLINE operator ()(const indirect_array<A> & ia1,const indirect_array<A> & ia2)395 matrix_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) { 396 return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2); 397 } 398 399 BOOST_UBLAS_INLINE project(const default_range & r1,const default_range & r2) const400 const_matrix_range_type project (const default_range &r1, const default_range &r2) const { 401 return const_matrix_range_type (operator () (), r1, r2); 402 } 403 BOOST_UBLAS_INLINE project(const default_range & r1,const default_range & r2)404 matrix_range_type project (const default_range &r1, const default_range &r2) { 405 return matrix_range_type (operator () (), r1, r2); 406 } 407 BOOST_UBLAS_INLINE project(const default_slice & s1,const default_slice & s2) const408 const_matrix_slice_type project (const default_slice &s1, const default_slice &s2) const { 409 return const_matrix_slice_type (operator () (), s1, s2); 410 } 411 BOOST_UBLAS_INLINE project(const default_slice & s1,const default_slice & s2)412 matrix_slice_type project (const default_slice &s1, const default_slice &s2) { 413 return matrix_slice_type (operator () (), s1, s2); 414 } 415 template<class A> 416 BOOST_UBLAS_INLINE project(const indirect_array<A> & ia1,const indirect_array<A> & ia2) const417 const matrix_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const { 418 return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2); 419 } 420 template<class A> 421 BOOST_UBLAS_INLINE project(const indirect_array<A> & ia1,const indirect_array<A> & ia2)422 matrix_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) { 423 return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2); 424 } 425 #endif 426 }; 427 428 #ifdef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 429 struct iterator1_tag {}; 430 struct iterator2_tag {}; 431 432 template<class I> 433 BOOST_UBLAS_INLINE begin(const I & it,iterator1_tag)434 typename I::dual_iterator_type begin (const I &it, iterator1_tag) { 435 return it ().find2 (1, it.index1 (), 0); 436 } 437 template<class I> 438 BOOST_UBLAS_INLINE end(const I & it,iterator1_tag)439 typename I::dual_iterator_type end (const I &it, iterator1_tag) { 440 return it ().find2 (1, it.index1 (), it ().size2 ()); 441 } 442 template<class I> 443 BOOST_UBLAS_INLINE rbegin(const I & it,iterator1_tag)444 typename I::dual_reverse_iterator_type rbegin (const I &it, iterator1_tag) { 445 return typename I::dual_reverse_iterator_type (end (it, iterator1_tag ())); 446 } 447 template<class I> 448 BOOST_UBLAS_INLINE rend(const I & it,iterator1_tag)449 typename I::dual_reverse_iterator_type rend (const I &it, iterator1_tag) { 450 return typename I::dual_reverse_iterator_type (begin (it, iterator1_tag ())); 451 } 452 453 template<class I> 454 BOOST_UBLAS_INLINE begin(const I & it,iterator2_tag)455 typename I::dual_iterator_type begin (const I &it, iterator2_tag) { 456 return it ().find1 (1, 0, it.index2 ()); 457 } 458 template<class I> 459 BOOST_UBLAS_INLINE end(const I & it,iterator2_tag)460 typename I::dual_iterator_type end (const I &it, iterator2_tag) { 461 return it ().find1 (1, it ().size1 (), it.index2 ()); 462 } 463 template<class I> 464 BOOST_UBLAS_INLINE rbegin(const I & it,iterator2_tag)465 typename I::dual_reverse_iterator_type rbegin (const I &it, iterator2_tag) { 466 return typename I::dual_reverse_iterator_type (end (it, iterator2_tag ())); 467 } 468 template<class I> 469 BOOST_UBLAS_INLINE rend(const I & it,iterator2_tag)470 typename I::dual_reverse_iterator_type rend (const I &it, iterator2_tag) { 471 return typename I::dual_reverse_iterator_type (begin (it, iterator2_tag ())); 472 } 473 #endif 474 475 /** \brief Base class for Matrix container models 476 * 477 * it does not model the Matrix concept but all derived types should. 478 * The class defines a common base type and some common interface for all 479 * statically derived Matrix classes 480 * We implement the casts to the statically derived type. 481 */ 482 template<class C> 483 class matrix_container: 484 public matrix_expression<C> { 485 public: 486 static const unsigned complexity = 0; 487 typedef C container_type; 488 typedef matrix_tag type_category; 489 490 BOOST_UBLAS_INLINE operator ()() const491 const container_type &operator () () const { 492 return *static_cast<const container_type *> (this); 493 } 494 BOOST_UBLAS_INLINE operator ()()495 container_type &operator () () { 496 return *static_cast<container_type *> (this); 497 } 498 499 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 500 using matrix_expression<C>::operator (); 501 #endif 502 }; 503 504 }}} 505 506 #endif 507