2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // The authors gratefully acknowledge the support of
10 // GeNeSys mbH & Co. KG in producing this work.
13 #ifndef _BOOST_UBLAS_TRAITS_
14 #define _BOOST_UBLAS_TRAITS_
18 #include <boost/config/no_tr1/cmath.hpp>
20 #include <boost/numeric/ublas/detail/config.hpp>
21 #include <boost/numeric/ublas/detail/iterator.hpp>
22 #include <boost/numeric/ublas/detail/returntype_deduction.hpp>
23 #ifdef BOOST_UBLAS_USE_INTERVAL
24 #include <boost/numeric/interval.hpp>
27 #include <boost/type_traits.hpp>
29 #include <boost/typeof/typeof.hpp>
30 #include <boost/utility/enable_if.hpp>
31 #include <boost/type_traits/is_float.hpp>
32 #include <boost/type_traits/is_integral.hpp>
33 #include <boost/type_traits/is_unsigned.hpp>
34 #include <boost/mpl/and.hpp>
36 // anonymous namespace to avoid ADL issues
38 template<class T> T boost_numeric_ublas_sqrt (const T& t) {
40 // we'll find either std::sqrt or else another version via ADL:
45 inline typename boost::disable_if<
46 boost::is_unsigned<T>, T >::type
47 boost_numeric_ublas_abs (const T &t ) {
53 inline typename boost::enable_if<
54 boost::is_unsigned<T>, T >::type
55 boost_numeric_ublas_abs (const T &t ) {
60 namespace boost { namespace numeric { namespace ublas {
63 template<typename R, typename I>
64 typename boost::enable_if<
69 std::complex<R> >::type inline operator+ (I in1, std::complex<R> const& in2 ) {
73 template<typename R, typename I>
74 typename boost::enable_if<
79 std::complex<R> >::type inline operator+ (std::complex<R> const& in1, I in2) {
83 template<typename R, typename I>
84 typename boost::enable_if<
89 std::complex<R> >::type inline operator- (I in1, std::complex<R> const& in2) {
93 template<typename R, typename I>
94 typename boost::enable_if<
99 std::complex<R> >::type inline operator- (std::complex<R> const& in1, I in2) {
100 return in1 - R (in2);
103 template<typename R, typename I>
104 typename boost::enable_if<
107 boost::is_integral<I>
109 std::complex<R> >::type inline operator* (I in1, std::complex<R> const& in2) {
110 return R (in1) * in2;
113 template<typename R, typename I>
114 typename boost::enable_if<
117 boost::is_integral<I>
119 std::complex<R> >::type inline operator* (std::complex<R> const& in1, I in2) {
123 template<typename R, typename I>
124 typename boost::enable_if<
127 boost::is_integral<I>
129 std::complex<R> >::type inline operator/ (I in1, std::complex<R> const& in2) {
133 template<typename R, typename I>
134 typename boost::enable_if<
137 boost::is_integral<I>
139 std::complex<R> >::type inline operator/ (std::complex<R> const& in1, I in2) {
140 return in1 / R (in2);
143 // Use Joel de Guzman's return type deduction
144 // uBLAS assumes a common return type for all binary arithmetic operators
145 template<class X, class Y>
146 struct promote_traits {
147 typedef type_deduction_detail::base_result_of<X, Y> base_type;
148 static typename base_type::x_type x;
149 static typename base_type::y_type y;
150 static const std::size_t size = sizeof (
151 type_deduction_detail::test<
152 typename base_type::x_type
153 , typename base_type::y_type
154 >(x + y) // Use x+y to stand of all the arithmetic actions
157 static const std::size_t index = (size / sizeof (char)) - 1;
158 typedef typename mpl::at_c<
159 typename base_type::types, index>::type id;
160 typedef typename id::type promote_type;
165 // Type traits - generic numeric properties and functions
169 // Define properties for a generic scalar type
171 struct scalar_traits {
172 typedef scalar_traits<T> self_type;
173 typedef T value_type;
174 typedef const T &const_reference;
175 typedef T &reference;
178 typedef real_type precision_type; // we do not know what type has more precision then the real_type
180 static const unsigned plus_complexity = 1;
181 static const unsigned multiplies_complexity = 1;
185 real_type real (const_reference t) {
190 real_type imag (const_reference /*t*/) {
195 value_type conj (const_reference t) {
201 real_type type_abs (const_reference t) {
202 return boost_numeric_ublas_abs (t);
206 value_type type_sqrt (const_reference t) {
207 // force a type conversion back to value_type for intgral types
208 return value_type (boost_numeric_ublas_sqrt (t));
213 real_type norm_1 (const_reference t) {
214 return self_type::type_abs (t);
218 real_type norm_2 (const_reference t) {
219 return self_type::type_abs (t);
223 real_type norm_inf (const_reference t) {
224 return self_type::type_abs (t);
229 bool equals (const_reference t1, const_reference t2) {
230 return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
231 (std::max) ((std::max) (self_type::norm_inf (t1),
232 self_type::norm_inf (t2)),
233 BOOST_UBLAS_TYPE_CHECK_MIN);
237 // Define default type traits, assume T is a scalar type
239 struct type_traits : scalar_traits <T> {
240 typedef type_traits<T> self_type;
241 typedef T value_type;
242 typedef const T &const_reference;
243 typedef T &reference;
246 typedef real_type precision_type;
247 static const unsigned multiplies_complexity = 1;
251 // Define real type traits
253 struct type_traits<float> : scalar_traits<float> {
254 typedef type_traits<float> self_type;
255 typedef float value_type;
256 typedef const value_type &const_reference;
257 typedef value_type &reference;
258 typedef value_type real_type;
259 typedef double precision_type;
262 struct type_traits<double> : scalar_traits<double> {
263 typedef type_traits<double> self_type;
264 typedef double value_type;
265 typedef const value_type &const_reference;
266 typedef value_type &reference;
267 typedef value_type real_type;
268 typedef long double precision_type;
271 struct type_traits<long double> : scalar_traits<long double> {
272 typedef type_traits<long double> self_type;
273 typedef long double value_type;
274 typedef const value_type &const_reference;
275 typedef value_type &reference;
276 typedef value_type real_type;
277 typedef value_type precision_type;
280 // Define properties for a generic complex type
282 struct complex_traits {
283 typedef complex_traits<T> self_type;
284 typedef T value_type;
285 typedef const T &const_reference;
286 typedef T &reference;
288 typedef typename T::value_type real_type;
289 typedef real_type precision_type; // we do not know what type has more precision then the real_type
291 static const unsigned plus_complexity = 2;
292 static const unsigned multiplies_complexity = 6;
296 real_type real (const_reference t) {
297 return std::real (t);
301 real_type imag (const_reference t) {
302 return std::imag (t);
306 value_type conj (const_reference t) {
307 return std::conj (t);
312 real_type type_abs (const_reference t) {
317 value_type type_sqrt (const_reference t) {
323 real_type norm_1 (const_reference t) {
324 return self_type::type_abs (t);
325 // original computation has been replaced because a complex number should behave like a scalar type
326 // return type_traits<real_type>::type_abs (self_type::real (t)) +
327 // type_traits<real_type>::type_abs (self_type::imag (t));
331 real_type norm_2 (const_reference t) {
332 return self_type::type_abs (t);
336 real_type norm_inf (const_reference t) {
337 return self_type::type_abs (t);
338 // original computation has been replaced because a complex number should behave like a scalar type
339 // return (std::max) (type_traits<real_type>::type_abs (self_type::real (t)),
340 // type_traits<real_type>::type_abs (self_type::imag (t)));
345 bool equals (const_reference t1, const_reference t2) {
346 return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
347 (std::max) ((std::max) (self_type::norm_inf (t1),
348 self_type::norm_inf (t2)),
349 BOOST_UBLAS_TYPE_CHECK_MIN);
353 // Define complex type traits
355 struct type_traits<std::complex<float> > : complex_traits<std::complex<float> >{
356 typedef type_traits<std::complex<float> > self_type;
357 typedef std::complex<float> value_type;
358 typedef const value_type &const_reference;
359 typedef value_type &reference;
360 typedef float real_type;
361 typedef std::complex<double> precision_type;
365 struct type_traits<std::complex<double> > : complex_traits<std::complex<double> >{
366 typedef type_traits<std::complex<double> > self_type;
367 typedef std::complex<double> value_type;
368 typedef const value_type &const_reference;
369 typedef value_type &reference;
370 typedef double real_type;
371 typedef std::complex<long double> precision_type;
374 struct type_traits<std::complex<long double> > : complex_traits<std::complex<long double> > {
375 typedef type_traits<std::complex<long double> > self_type;
376 typedef std::complex<long double> value_type;
377 typedef const value_type &const_reference;
378 typedef value_type &reference;
379 typedef long double real_type;
380 typedef value_type precision_type;
383 #ifdef BOOST_UBLAS_USE_INTERVAL
384 // Define scalar interval type traits
386 struct type_traits<boost::numeric::interval<float> > : scalar_traits<boost::numeric::interval<float> > {
387 typedef type_traits<boost::numeric::interval<float> > self_type;
388 typedef boost::numeric::interval<float> value_type;
389 typedef const value_type &const_reference;
390 typedef value_type &reference;
391 typedef value_type real_type;
392 typedef boost::numeric::interval<double> precision_type;
396 struct type_traits<boost::numeric::interval<double> > : scalar_traits<boost::numeric::interval<double> > {
397 typedef type_traits<boost::numeric::interval<double> > self_type;
398 typedef boost::numeric::interval<double> value_type;
399 typedef const value_type &const_reference;
400 typedef value_type &reference;
401 typedef value_type real_type;
402 typedef boost::numeric::interval<long double> precision_type;
405 struct type_traits<boost::numeric::interval<long double> > : scalar_traits<boost::numeric::interval<long double> > {
406 typedef type_traits<boost::numeric::interval<long double> > self_type;
407 typedef boost::numeric::interval<long double> value_type;
408 typedef const value_type &const_reference;
409 typedef value_type &reference;
410 typedef value_type real_type;
411 typedef value_type precision_type;
416 // Storage tags -- hierarchical definition of storage characteristics
418 struct unknown_storage_tag {};
419 struct sparse_proxy_tag: public unknown_storage_tag {};
420 struct sparse_tag: public sparse_proxy_tag {};
421 struct packed_proxy_tag: public sparse_proxy_tag {};
422 struct packed_tag: public packed_proxy_tag {};
423 struct dense_proxy_tag: public packed_proxy_tag {};
424 struct dense_tag: public dense_proxy_tag {};
426 template<class S1, class S2>
427 struct storage_restrict_traits {
428 typedef S1 storage_category;
432 struct storage_restrict_traits<sparse_tag, dense_proxy_tag> {
433 typedef sparse_proxy_tag storage_category;
436 struct storage_restrict_traits<sparse_tag, packed_proxy_tag> {
437 typedef sparse_proxy_tag storage_category;
440 struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> {
441 typedef sparse_proxy_tag storage_category;
445 struct storage_restrict_traits<packed_tag, dense_proxy_tag> {
446 typedef packed_proxy_tag storage_category;
449 struct storage_restrict_traits<packed_tag, packed_proxy_tag> {
450 typedef packed_proxy_tag storage_category;
453 struct storage_restrict_traits<packed_tag, sparse_proxy_tag> {
454 typedef sparse_proxy_tag storage_category;
458 struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> {
459 typedef sparse_proxy_tag storage_category;
463 struct storage_restrict_traits<dense_tag, dense_proxy_tag> {
464 typedef dense_proxy_tag storage_category;
467 struct storage_restrict_traits<dense_tag, packed_proxy_tag> {
468 typedef packed_proxy_tag storage_category;
471 struct storage_restrict_traits<dense_tag, sparse_proxy_tag> {
472 typedef sparse_proxy_tag storage_category;
476 struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> {
477 typedef packed_proxy_tag storage_category;
480 struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> {
481 typedef sparse_proxy_tag storage_category;
485 // Iterator tags -- hierarchical definition of storage characteristics
487 struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {};
488 struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {};
489 struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {};
491 // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-)
493 struct iterator_base_traits {};
496 struct iterator_base_traits<std::forward_iterator_tag> {
497 template<class I, class T>
498 struct iterator_base {
499 typedef forward_iterator_base<std::forward_iterator_tag, I, T> type;
504 struct iterator_base_traits<std::bidirectional_iterator_tag> {
505 template<class I, class T>
506 struct iterator_base {
507 typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type;
511 struct iterator_base_traits<sparse_bidirectional_iterator_tag> {
512 template<class I, class T>
513 struct iterator_base {
514 typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type;
519 struct iterator_base_traits<std::random_access_iterator_tag> {
520 template<class I, class T>
521 struct iterator_base {
522 typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type;
526 struct iterator_base_traits<packed_random_access_iterator_tag> {
527 template<class I, class T>
528 struct iterator_base {
529 typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type;
533 struct iterator_base_traits<dense_random_access_iterator_tag> {
534 template<class I, class T>
535 struct iterator_base {
536 typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type;
540 template<class I1, class I2>
541 struct iterator_restrict_traits {
542 typedef I1 iterator_category;
546 struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
547 typedef sparse_bidirectional_iterator_tag iterator_category;
550 struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> {
551 typedef sparse_bidirectional_iterator_tag iterator_category;
555 struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
556 typedef sparse_bidirectional_iterator_tag iterator_category;
559 struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> {
560 typedef sparse_bidirectional_iterator_tag iterator_category;
564 struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> {
565 typedef packed_random_access_iterator_tag iterator_category;
568 struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> {
569 typedef packed_random_access_iterator_tag iterator_category;
574 void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) {
575 it += (std::min) (compare, it_end - it);
579 void increment (I &it, const I &/* it_end */, typename I::difference_type /* compare */, sparse_bidirectional_iterator_tag) {
584 void increment (I &it, const I &it_end, typename I::difference_type compare) {
585 increment (it, it_end, compare, typename I::iterator_category ());
590 void increment (I &it, const I &it_end) {
591 #if BOOST_UBLAS_TYPE_CHECK
593 while (cit != it_end) {
594 BOOST_UBLAS_CHECK (*cit == typename I::value_type/*zero*/(), internal_logic ());
603 // specialisation which define whether a type has a trivial constructor
604 // or not. This is used by array types.
606 struct has_trivial_constructor : public boost::has_trivial_constructor<T> {};
609 struct has_trivial_destructor : public boost::has_trivial_destructor<T> {};
611 template<typename FLT>
612 struct has_trivial_constructor<std::complex<FLT> > : public has_trivial_constructor<FLT> {};
614 template<typename FLT>
615 struct has_trivial_destructor<std::complex<FLT> > : public has_trivial_destructor<FLT> {};
620 /** \brief Traits class to extract type information from a constant matrix or vector CONTAINER.
624 struct container_view_traits {
626 typedef typename E::size_type size_type;
627 /// type of differences of indices
628 typedef typename E::difference_type difference_type;
630 /// storage category: \c unknown_storage_tag, \c dense_tag, \c packed_tag, ...
631 typedef typename E::storage_category storage_category;
634 typedef typename E::value_type value_type;
635 /// const reference to an element
636 typedef typename E::const_reference const_reference;
638 /// type used in expressions to mark a reference to this class (usually a const container_reference<const E> or the class itself)
639 typedef typename E::const_closure_type const_closure_type;
642 /** \brief Traits class to extract additional type information from a mutable matrix or vector CONTAINER.
646 struct mutable_container_traits {
647 /// reference to an element
648 typedef typename E::reference reference;
650 /// type used in expressions to mark a reference to this class (usually a container_reference<E> or the class itself)
651 typedef typename E::closure_type closure_type;
654 /** \brief Traits class to extract type information from a matrix or vector CONTAINER.
658 struct container_traits
659 : container_view_traits<E>, mutable_container_traits<E> {
664 /** \brief Traits class to extract type information from a constant MATRIX.
667 template < class MATRIX >
668 struct matrix_view_traits : container_view_traits <MATRIX> {
670 /// orientation of the matrix, either \c row_major_tag, \c column_major_tag or \c unknown_orientation_tag
671 typedef typename MATRIX::orientation_category orientation_category;
673 /// row iterator for the matrix
674 typedef typename MATRIX::const_iterator1 const_iterator1;
676 /// column iterator for the matrix
677 typedef typename MATRIX::const_iterator2 const_iterator2;
680 /** \brief Traits class to extract additional type information from a mutable MATRIX.
683 template < class MATRIX >
684 struct mutable_matrix_traits
685 : mutable_container_traits <MATRIX> {
687 /// row iterator for the matrix
688 typedef typename MATRIX::iterator1 iterator1;
690 /// column iterator for the matrix
691 typedef typename MATRIX::iterator2 iterator2;
695 /** \brief Traits class to extract type information from a MATRIX.
698 template < class MATRIX >
700 : matrix_view_traits <MATRIX>, mutable_matrix_traits <MATRIX> {
703 /** \brief Traits class to extract type information from a VECTOR.
706 template < class VECTOR >
707 struct vector_view_traits : container_view_traits <VECTOR> {
709 /// iterator for the VECTOR
710 typedef typename VECTOR::const_iterator const_iterator;
712 /// iterator pointing to the first element
714 const_iterator begin(const VECTOR & v) {
717 /// iterator pointing behind the last element
719 const_iterator end(const VECTOR & v) {
725 /** \brief Traits class to extract type information from a VECTOR.
728 template < class VECTOR >
729 struct mutable_vector_traits : mutable_container_traits <VECTOR> {
730 /// iterator for the VECTOR
731 typedef typename VECTOR::iterator iterator;
733 /// iterator pointing to the first element
735 iterator begin(VECTOR & v) {
739 /// iterator pointing behind the last element
741 iterator end(VECTOR & v) {
746 /** \brief Traits class to extract type information from a VECTOR.
749 template < class VECTOR >
751 : vector_view_traits <VECTOR>, mutable_vector_traits <VECTOR> {
755 // Note: specializations for T[N] and T[M][N] have been moved to traits/c_array.hpp