00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef _BOOST_UBLAS_TRAITS_
00014 #define _BOOST_UBLAS_TRAITS_
00015
00016 #include <iterator>
00017 #include <complex>
00018 #include <boost/config/no_tr1/cmath.hpp>
00019
00020 #include <boost/numeric/ublas/detail/config.hpp>
00021 #include <boost/numeric/ublas/detail/iterator.hpp>
00022 #include <boost/numeric/ublas/detail/returntype_deduction.hpp>
00023
00024 #include <boost/type_traits.hpp>
00025 #include <complex>
00026 #include <boost/typeof/typeof.hpp>
00027 #include <boost/utility/enable_if.hpp>
00028 #include <boost/type_traits/is_float.hpp>
00029 #include <boost/type_traits/is_integral.hpp>
00030 #include <boost/mpl/and.hpp>
00031
00032
00033 namespace {
00034 template<class T> T boost_numeric_ublas_sqrt (const T& t) {
00035 using namespace std;
00036
00037 return sqrt (t);
00038 }
00039 template<class T> T boost_numeric_ublas_abs (const T& t) {
00040 using namespace std;
00041
00042 return abs (t);
00043 }
00044 }
00045
00046 namespace boost { namespace numeric { namespace ublas {
00047
00048
00049
00050 template<class X, class Y>
00051 struct promote_traits {
00052 typedef type_deduction_detail::base_result_of<X, Y> base_type;
00053 static typename base_type::x_type x;
00054 static typename base_type::y_type y;
00055 static const std::size_t size = sizeof (
00056 type_deduction_detail::test<
00057 typename base_type::x_type
00058 , typename base_type::y_type
00059 >(x + y)
00060 );
00061
00062 static const std::size_t index = (size / sizeof (char)) - 1;
00063 typedef typename mpl::at_c<
00064 typename base_type::types, index>::type id;
00065 typedef typename id::type promote_type;
00066 };
00067
00068 template<typename R, typename I>
00069 typename boost::enable_if<
00070 mpl::and_<
00071 boost::is_float<R>,
00072 boost::is_integral<I>
00073 >,
00074 std::complex<R> >::type inline operator+ (I in1, std::complex<R> const& in2 ) {
00075 return R (in1) + in2;
00076 }
00077
00078 template<typename R, typename I>
00079 typename boost::enable_if<
00080 mpl::and_<
00081 boost::is_float<R>,
00082 boost::is_integral<I>
00083 >,
00084 std::complex<R> >::type inline operator+ (std::complex<R> const& in1, I in2) {
00085 return in1 + R (in2);
00086 }
00087
00088 template<typename R, typename I>
00089 typename boost::enable_if<
00090 mpl::and_<
00091 boost::is_float<R>,
00092 boost::is_integral<I>
00093 >,
00094 std::complex<R> >::type inline operator- (I in1, std::complex<R> const& in2) {
00095 return R (in1) - in2;
00096 }
00097
00098 template<typename R, typename I>
00099 typename boost::enable_if<
00100 mpl::and_<
00101 boost::is_float<R>,
00102 boost::is_integral<I>
00103 >,
00104 std::complex<R> >::type inline operator- (std::complex<R> const& in1, I in2) {
00105 return in1 - R (in2);
00106 }
00107
00108 template<typename R, typename I>
00109 typename boost::enable_if<
00110 mpl::and_<
00111 boost::is_float<R>,
00112 boost::is_integral<I>
00113 >,
00114 std::complex<R> >::type inline operator* (I in1, std::complex<R> const& in2) {
00115 return R (in1) * in2;
00116 }
00117
00118 template<typename R, typename I>
00119 typename boost::enable_if<
00120 mpl::and_<
00121 boost::is_float<R>,
00122 boost::is_integral<I>
00123 >,
00124 std::complex<R> >::type inline operator* (std::complex<R> const& in1, I in2) {
00125 return in1 * R(in2);
00126 }
00127
00128 template<typename R, typename I>
00129 typename boost::enable_if<
00130 mpl::and_<
00131 boost::is_float<R>,
00132 boost::is_integral<I>
00133 >,
00134 std::complex<R> >::type inline operator/ (I in1, std::complex<R> const& in2) {
00135 return R(in1) / in2;
00136 }
00137
00138 template<typename R, typename I>
00139 typename boost::enable_if<
00140 mpl::and_<
00141 boost::is_float<R>,
00142 boost::is_integral<I>
00143 >,
00144 std::complex<R> >::type inline operator/ (std::complex<R> const& in1, I in2) {
00145 return in1 / R (in2);
00146 }
00147
00148
00149
00150
00151 template<class T>
00152 struct type_traits;
00153
00154
00155 template<class T>
00156 struct scalar_traits {
00157 typedef scalar_traits<T> self_type;
00158 typedef T value_type;
00159 typedef const T &const_reference;
00160 typedef T &reference;
00161
00162 typedef T real_type;
00163 typedef real_type precision_type;
00164
00165 static const unsigned plus_complexity = 1;
00166 static const unsigned multiplies_complexity = 1;
00167
00168 static
00169 BOOST_UBLAS_INLINE
00170 real_type real (const_reference t) {
00171 return t;
00172 }
00173 static
00174 BOOST_UBLAS_INLINE
00175 real_type imag (const_reference ) {
00176 return 0;
00177 }
00178 static
00179 BOOST_UBLAS_INLINE
00180 value_type conj (const_reference t) {
00181 return t;
00182 }
00183
00184 static
00185 BOOST_UBLAS_INLINE
00186 real_type type_abs (const_reference t) {
00187 return boost_numeric_ublas_abs (t);
00188 }
00189 static
00190 BOOST_UBLAS_INLINE
00191 value_type type_sqrt (const_reference t) {
00192
00193 return value_type (boost_numeric_ublas_sqrt (t));
00194 }
00195
00196 static
00197 BOOST_UBLAS_INLINE
00198 real_type norm_1 (const_reference t) {
00199 return self_type::type_abs (t);
00200 }
00201 static
00202 BOOST_UBLAS_INLINE
00203 real_type norm_2 (const_reference t) {
00204 return self_type::type_abs (t);
00205 }
00206 static
00207 BOOST_UBLAS_INLINE
00208 real_type norm_inf (const_reference t) {
00209 return self_type::type_abs (t);
00210 }
00211
00212 static
00213 BOOST_UBLAS_INLINE
00214 bool equals (const_reference t1, const_reference t2) {
00215 return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
00216 (std::max) ((std::max) (self_type::norm_inf (t1),
00217 self_type::norm_inf (t2)),
00218 BOOST_UBLAS_TYPE_CHECK_MIN);
00219 }
00220 };
00221
00222
00223 template<class T>
00224 struct type_traits : scalar_traits <T> {
00225 typedef type_traits<T> self_type;
00226 typedef T value_type;
00227 typedef const T &const_reference;
00228 typedef T &reference;
00229
00230 typedef T real_type;
00231 typedef real_type precision_type;
00232 static const unsigned multiplies_complexity = 1;
00233
00234 };
00235
00236
00237 template<>
00238 struct type_traits<float> : scalar_traits<float> {
00239 typedef type_traits<float> self_type;
00240 typedef float value_type;
00241 typedef const value_type &const_reference;
00242 typedef value_type &reference;
00243 typedef value_type real_type;
00244 typedef double precision_type;
00245 };
00246 template<>
00247 struct type_traits<double> : scalar_traits<double> {
00248 typedef type_traits<double> self_type;
00249 typedef double value_type;
00250 typedef const value_type &const_reference;
00251 typedef value_type &reference;
00252 typedef value_type real_type;
00253 typedef long double precision_type;
00254 };
00255 template<>
00256 struct type_traits<long double> : scalar_traits<long double> {
00257 typedef type_traits<long double> self_type;
00258 typedef long double value_type;
00259 typedef const value_type &const_reference;
00260 typedef value_type &reference;
00261 typedef value_type real_type;
00262 typedef value_type precision_type;
00263 };
00264
00265
00266 template<class T>
00267 struct complex_traits {
00268 typedef complex_traits<T> self_type;
00269 typedef T value_type;
00270 typedef const T &const_reference;
00271 typedef T &reference;
00272
00273 typedef typename T::value_type real_type;
00274 typedef real_type precision_type;
00275
00276 static const unsigned plus_complexity = 2;
00277 static const unsigned multiplies_complexity = 6;
00278
00279 static
00280 BOOST_UBLAS_INLINE
00281 real_type real (const_reference t) {
00282 return std::real (t);
00283 }
00284 static
00285 BOOST_UBLAS_INLINE
00286 real_type imag (const_reference t) {
00287 return std::imag (t);
00288 }
00289 static
00290 BOOST_UBLAS_INLINE
00291 value_type conj (const_reference t) {
00292 return std::conj (t);
00293 }
00294
00295 static
00296 BOOST_UBLAS_INLINE
00297 real_type type_abs (const_reference t) {
00298 return abs (t);
00299 }
00300 static
00301 BOOST_UBLAS_INLINE
00302 value_type type_sqrt (const_reference t) {
00303 return sqrt (t);
00304 }
00305
00306 static
00307 BOOST_UBLAS_INLINE
00308 real_type norm_1 (const_reference t) {
00309 return self_type::type_abs (t);
00310
00311
00312
00313 }
00314 static
00315 BOOST_UBLAS_INLINE
00316 real_type norm_2 (const_reference t) {
00317 return self_type::type_abs (t);
00318 }
00319 static
00320 BOOST_UBLAS_INLINE
00321 real_type norm_inf (const_reference t) {
00322 return self_type::type_abs (t);
00323
00324
00325
00326 }
00327
00328 static
00329 BOOST_UBLAS_INLINE
00330 bool equals (const_reference t1, const_reference t2) {
00331 return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
00332 (std::max) ((std::max) (self_type::norm_inf (t1),
00333 self_type::norm_inf (t2)),
00334 BOOST_UBLAS_TYPE_CHECK_MIN);
00335 }
00336 };
00337
00338
00339 template<>
00340 struct type_traits<std::complex<float> > : complex_traits<std::complex<float> >{
00341 typedef type_traits<std::complex<float> > self_type;
00342 typedef std::complex<float> value_type;
00343 typedef const value_type &const_reference;
00344 typedef value_type &reference;
00345 typedef float real_type;
00346 typedef std::complex<double> precision_type;
00347
00348 };
00349 template<>
00350 struct type_traits<std::complex<double> > : complex_traits<std::complex<double> >{
00351 typedef type_traits<std::complex<double> > self_type;
00352 typedef std::complex<double> value_type;
00353 typedef const value_type &const_reference;
00354 typedef value_type &reference;
00355 typedef double real_type;
00356 typedef std::complex<long double> precision_type;
00357 };
00358 template<>
00359 struct type_traits<std::complex<long double> > : complex_traits<std::complex<long double> > {
00360 typedef type_traits<std::complex<long double> > self_type;
00361 typedef std::complex<long double> value_type;
00362 typedef const value_type &const_reference;
00363 typedef value_type &reference;
00364 typedef long double real_type;
00365 typedef value_type precision_type;
00366 };
00367
00368 #ifdef BOOST_UBLAS_USE_INTERVAL
00369
00370 template<>
00371 struct type_traits<boost::numeric::interval<float> > : scalar_traits<boost::numeric::interval<float> > {
00372 typedef type_traits<boost::numeric::interval<float> > self_type;
00373 typedef boost::numeric::interval<float> value_type;
00374 typedef const value_type &const_reference;
00375 typedef value_type &reference;
00376 typedef value_type real_type;
00377 typedef boost::numeric::interval<double> precision_type;
00378
00379 };
00380 template<>
00381 struct type_traits<boost::numeric::interval<double> > : scalar_traits<boost::numeric::interval<double> > {
00382 typedef type_traits<boost::numeric::interval<double> > self_type;
00383 typedef boost::numeric::interval<double> value_type;
00384 typedef const value_type &const_reference;
00385 typedef value_type &reference;
00386 typedef value_type real_type;
00387 typedef boost::numeric::interval<long double> precision_type;
00388 };
00389 template<>
00390 struct type_traits<boost::numeric::interval<long double> > : scalar_traits<boost::numeric::interval<long double> > {
00391 typedef type_traits<boost::numeric::interval<long double> > self_type;
00392 typedef boost::numeric::interval<long double> value_type;
00393 typedef const value_type &const_reference;
00394 typedef value_type &reference;
00395 typedef value_type real_type;
00396 typedef value_type precision_type;
00397 };
00398 #endif
00399
00400
00401
00402
00403 struct unknown_storage_tag {};
00404 struct sparse_proxy_tag: public unknown_storage_tag {};
00405 struct sparse_tag: public sparse_proxy_tag {};
00406 struct packed_proxy_tag: public sparse_proxy_tag {};
00407 struct packed_tag: public packed_proxy_tag {};
00408 struct dense_proxy_tag: public packed_proxy_tag {};
00409 struct dense_tag: public dense_proxy_tag {};
00410
00411 template<class S1, class S2>
00412 struct storage_restrict_traits {
00413 typedef S1 storage_category;
00414 };
00415
00416 template<>
00417 struct storage_restrict_traits<sparse_tag, dense_proxy_tag> {
00418 typedef sparse_proxy_tag storage_category;
00419 };
00420 template<>
00421 struct storage_restrict_traits<sparse_tag, packed_proxy_tag> {
00422 typedef sparse_proxy_tag storage_category;
00423 };
00424 template<>
00425 struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> {
00426 typedef sparse_proxy_tag storage_category;
00427 };
00428
00429 template<>
00430 struct storage_restrict_traits<packed_tag, dense_proxy_tag> {
00431 typedef packed_proxy_tag storage_category;
00432 };
00433 template<>
00434 struct storage_restrict_traits<packed_tag, packed_proxy_tag> {
00435 typedef packed_proxy_tag storage_category;
00436 };
00437 template<>
00438 struct storage_restrict_traits<packed_tag, sparse_proxy_tag> {
00439 typedef sparse_proxy_tag storage_category;
00440 };
00441
00442 template<>
00443 struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> {
00444 typedef sparse_proxy_tag storage_category;
00445 };
00446
00447 template<>
00448 struct storage_restrict_traits<dense_tag, dense_proxy_tag> {
00449 typedef dense_proxy_tag storage_category;
00450 };
00451 template<>
00452 struct storage_restrict_traits<dense_tag, packed_proxy_tag> {
00453 typedef packed_proxy_tag storage_category;
00454 };
00455 template<>
00456 struct storage_restrict_traits<dense_tag, sparse_proxy_tag> {
00457 typedef sparse_proxy_tag storage_category;
00458 };
00459
00460 template<>
00461 struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> {
00462 typedef packed_proxy_tag storage_category;
00463 };
00464 template<>
00465 struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> {
00466 typedef sparse_proxy_tag storage_category;
00467 };
00468
00469
00470
00471
00472 struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {};
00473 struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {};
00474 struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {};
00475
00476
00477 template<class IC>
00478 struct iterator_base_traits {};
00479
00480 template<>
00481 struct iterator_base_traits<std::forward_iterator_tag> {
00482 template<class I, class T>
00483 struct iterator_base {
00484 typedef forward_iterator_base<std::forward_iterator_tag, I, T> type;
00485 };
00486 };
00487
00488 template<>
00489 struct iterator_base_traits<std::bidirectional_iterator_tag> {
00490 template<class I, class T>
00491 struct iterator_base {
00492 typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type;
00493 };
00494 };
00495 template<>
00496 struct iterator_base_traits<sparse_bidirectional_iterator_tag> {
00497 template<class I, class T>
00498 struct iterator_base {
00499 typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type;
00500 };
00501 };
00502
00503 template<>
00504 struct iterator_base_traits<std::random_access_iterator_tag> {
00505 template<class I, class T>
00506 struct iterator_base {
00507 typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type;
00508 };
00509 };
00510 template<>
00511 struct iterator_base_traits<packed_random_access_iterator_tag> {
00512 template<class I, class T>
00513 struct iterator_base {
00514 typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type;
00515 };
00516 };
00517 template<>
00518 struct iterator_base_traits<dense_random_access_iterator_tag> {
00519 template<class I, class T>
00520 struct iterator_base {
00521 typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type;
00522 };
00523 };
00524
00525 template<class I1, class I2>
00526 struct iterator_restrict_traits {
00527 typedef I1 iterator_category;
00528 };
00529
00530 template<>
00531 struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
00532 typedef sparse_bidirectional_iterator_tag iterator_category;
00533 };
00534 template<>
00535 struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> {
00536 typedef sparse_bidirectional_iterator_tag iterator_category;
00537 };
00538
00539 template<>
00540 struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
00541 typedef sparse_bidirectional_iterator_tag iterator_category;
00542 };
00543 template<>
00544 struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> {
00545 typedef sparse_bidirectional_iterator_tag iterator_category;
00546 };
00547
00548 template<>
00549 struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> {
00550 typedef packed_random_access_iterator_tag iterator_category;
00551 };
00552 template<>
00553 struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> {
00554 typedef packed_random_access_iterator_tag iterator_category;
00555 };
00556
00557 template<class I>
00558 BOOST_UBLAS_INLINE
00559 void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) {
00560 it += (std::min) (compare, it_end - it);
00561 }
00562 template<class I>
00563 BOOST_UBLAS_INLINE
00564 void increment (I &it, const I &, typename I::difference_type , sparse_bidirectional_iterator_tag) {
00565 ++ it;
00566 }
00567 template<class I>
00568 BOOST_UBLAS_INLINE
00569 void increment (I &it, const I &it_end, typename I::difference_type compare) {
00570 increment (it, it_end, compare, typename I::iterator_category ());
00571 }
00572
00573 template<class I>
00574 BOOST_UBLAS_INLINE
00575 void increment (I &it, const I &it_end) {
00576 #if BOOST_UBLAS_TYPE_CHECK
00577 I cit (it);
00578 while (cit != it_end) {
00579 BOOST_UBLAS_CHECK (*cit == typename I::value_type(), internal_logic ());
00580 ++ cit;
00581 }
00582 #endif
00583 it = it_end;
00584 }
00585
00586 namespace detail {
00587
00588
00589
00590 template<typename T>
00591 struct has_trivial_constructor : public boost::has_trivial_constructor<T> {};
00592
00593 template<typename T>
00594 struct has_trivial_destructor : public boost::has_trivial_destructor<T> {};
00595
00596 template<typename FLT>
00597 struct has_trivial_constructor<std::complex<FLT> > : public boost::true_type {};
00598
00599 template<typename FLT>
00600 struct has_trivial_destructor<std::complex<FLT> > : public boost::true_type {};
00601
00602 }
00603
00604
00608 template < class E >
00609 struct container_view_traits {
00611 typedef typename E::size_type size_type;
00613 typedef typename E::difference_type difference_type;
00614
00616 typedef typename E::storage_category storage_category;
00617
00619 typedef typename E::value_type value_type;
00621 typedef typename E::const_reference const_reference;
00622
00624 typedef typename E::const_closure_type const_closure_type;
00625 };
00626
00630 template < class E >
00631 struct mutable_container_traits {
00633 typedef typename E::reference reference;
00634
00636 typedef typename E::closure_type closure_type;
00637 };
00638
00642 template < class E >
00643 struct container_traits
00644 : container_view_traits<E>, mutable_container_traits<E> {
00645
00646 };
00647
00648
00652 template < class MATRIX >
00653 struct matrix_view_traits : container_view_traits <MATRIX> {
00654
00656 typedef typename MATRIX::orientation_category orientation_category;
00657
00659 typedef typename MATRIX::const_iterator1 const_iterator1;
00660
00662 typedef typename MATRIX::const_iterator2 const_iterator2;
00663 };
00664
00668 template < class MATRIX >
00669 struct mutable_matrix_traits
00670 : mutable_container_traits <MATRIX> {
00671
00673 typedef typename MATRIX::iterator1 iterator1;
00674
00676 typedef typename MATRIX::iterator2 iterator2;
00677 };
00678
00679
00683 template < class MATRIX >
00684 struct matrix_traits
00685 : matrix_view_traits <MATRIX>, mutable_matrix_traits <MATRIX> {
00686 };
00687
00691 template < class VECTOR >
00692 struct vector_view_traits : container_view_traits <VECTOR> {
00693
00695 typedef typename VECTOR::const_iterator const_iterator;
00696
00698 static
00699 const_iterator begin(const VECTOR & v) {
00700 return v.begin();
00701 }
00703 static
00704 const_iterator end(const VECTOR & v) {
00705 return v.end();
00706 }
00707
00708 };
00709
00713 template < class VECTOR >
00714 struct mutable_vector_traits : mutable_container_traits <VECTOR> {
00716 typedef typename VECTOR::iterator iterator;
00717
00719 static
00720 iterator begin(VECTOR & v) {
00721 return v.begin();
00722 }
00723
00725 static
00726 iterator end(VECTOR & v) {
00727 return v.end();
00728 }
00729 };
00730
00734 template < class VECTOR >
00735 struct vector_traits
00736 : vector_view_traits <VECTOR>, mutable_vector_traits <VECTOR> {
00737 };
00738
00739
00740
00741
00742 }}}
00743
00744 #endif