1 //
2 //  Copyright (c) 2000-2002
3 //  Joerg Walter, Mathias Koch
4 //
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)
8 //
9 //  The authors gratefully acknowledge the support of
10 //  GeNeSys mbH & Co. KG in producing this work.
11 //
12 
13 #ifndef _BOOST_UBLAS_TRAITS_
14 #define _BOOST_UBLAS_TRAITS_
15 
16 #include <iterator>
17 #include <complex>
18 #include <boost/config/no_tr1/cmath.hpp>
19 
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>
25 #endif
26 
27 #include <boost/type_traits.hpp>
28 #include <complex>
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>
35 #include <boost/mpl/if.hpp>
36 #include <boost/typeof/typeof.hpp>
37 
38 
39 // anonymous namespace to avoid ADL issues
40 namespace {
41   template<class T>
42     typename boost::mpl::if_c<boost::is_integral<T>::value,
43                               double,
44                               T>::type
boost_numeric_ublas_sqrt(const T & t)45   boost_numeric_ublas_sqrt (const T& t) {
46     using namespace std;
47     // we'll find either std::sqrt or else another version via ADL:
48     return sqrt (t);
49   }
50 
51 template<typename T>
52 inline typename boost::disable_if<
53     boost::is_unsigned<T>, T >::type
boost_numeric_ublas_abs(const T & t)54     boost_numeric_ublas_abs (const T &t ) {
55         using namespace std;
56         // force a type conversion back to T for char and short types
57         return static_cast<T>(abs( t ));
58     }
59 
60 template<typename T>
61 inline typename boost::enable_if<
62     boost::is_unsigned<T>, T >::type
boost_numeric_ublas_abs(const T & t)63     boost_numeric_ublas_abs (const T &t ) {
64         return t;
65     }
66 }
67 
68 namespace boost { namespace numeric { namespace ublas {
69 
70 
71     template<typename R, typename I>
72     typename boost::enable_if<
73       mpl::and_<
74         boost::is_float<R>,
75         boost::is_integral<I>
76         >,
operator +(I in1,std::complex<R> const & in2)77       std::complex<R> >::type inline operator+ (I in1, std::complex<R> const& in2 ) {
78       return R (in1) + in2;
79     }
80 
81     template<typename R, typename I>
82     typename boost::enable_if<
83       mpl::and_<
84         boost::is_float<R>,
85         boost::is_integral<I>
86         >,
operator +(std::complex<R> const & in1,I in2)87       std::complex<R> >::type inline operator+ (std::complex<R> const& in1, I in2) {
88       return in1 + R (in2);
89     }
90 
91     template<typename R, typename I>
92     typename boost::enable_if<
93       mpl::and_<
94         boost::is_float<R>,
95         boost::is_integral<I>
96         >,
operator -(I in1,std::complex<R> const & in2)97       std::complex<R> >::type inline operator- (I in1, std::complex<R> const& in2) {
98       return R (in1) - in2;
99     }
100 
101     template<typename R, typename I>
102     typename boost::enable_if<
103       mpl::and_<
104         boost::is_float<R>,
105         boost::is_integral<I>
106         >,
operator -(std::complex<R> const & in1,I in2)107       std::complex<R> >::type inline operator- (std::complex<R> const& in1, I in2) {
108       return in1 - R (in2);
109     }
110 
111     template<typename R, typename I>
112     typename boost::enable_if<
113       mpl::and_<
114         boost::is_float<R>,
115         boost::is_integral<I>
116         >,
operator *(I in1,std::complex<R> const & in2)117       std::complex<R> >::type inline operator* (I in1, std::complex<R> const& in2) {
118       return R (in1) * in2;
119     }
120 
121     template<typename R, typename I>
122     typename boost::enable_if<
123       mpl::and_<
124         boost::is_float<R>,
125         boost::is_integral<I>
126         >,
operator *(std::complex<R> const & in1,I in2)127       std::complex<R> >::type inline operator* (std::complex<R> const& in1, I in2) {
128       return in1 * R(in2);
129     }
130 
131     template<typename R, typename I>
132     typename boost::enable_if<
133       mpl::and_<
134         boost::is_float<R>,
135         boost::is_integral<I>
136         >,
operator /(I in1,std::complex<R> const & in2)137       std::complex<R> >::type inline operator/ (I in1, std::complex<R> const& in2) {
138       return R(in1) / in2;
139     }
140 
141     template<typename R, typename I>
142     typename boost::enable_if<
143       mpl::and_<
144         boost::is_float<R>,
145         boost::is_integral<I>
146         >,
operator /(std::complex<R> const & in1,I in2)147       std::complex<R> >::type inline operator/ (std::complex<R> const& in1, I in2) {
148       return in1 / R (in2);
149     }
150 
151     // uBLAS assumes a common return type for all binary arithmetic operators
152     template<class X, class Y>
153     struct promote_traits {
154         typedef BOOST_TYPEOF_TPL(X() + Y()) promote_type;
155     };
156 
157 
158 
159     // Type traits - generic numeric properties and functions
160     template<class T>
161     struct type_traits;
162 
163     // Define properties for a generic scalar type
164     template<class T>
165     struct scalar_traits {
166         typedef scalar_traits<T> self_type;
167         typedef T value_type;
168         typedef const T &const_reference;
169         typedef T &reference;
170 
171         typedef T real_type;
172         typedef real_type precision_type;       // we do not know what type has more precision then the real_type
173 
174         static const unsigned plus_complexity = 1;
175         static const unsigned multiplies_complexity = 1;
176 
177         static
178         BOOST_UBLAS_INLINE
realboost::numeric::ublas::scalar_traits179         real_type real (const_reference t) {
180                 return t;
181         }
182         static
183         BOOST_UBLAS_INLINE
imagboost::numeric::ublas::scalar_traits184         real_type imag (const_reference /*t*/) {
185                 return 0;
186         }
187         static
188         BOOST_UBLAS_INLINE
conjboost::numeric::ublas::scalar_traits189         value_type conj (const_reference t) {
190                 return t;
191         }
192 
193         static
194         BOOST_UBLAS_INLINE
type_absboost::numeric::ublas::scalar_traits195         real_type type_abs (const_reference t) {
196             return boost_numeric_ublas_abs (t);
197         }
198         static
199         BOOST_UBLAS_INLINE
type_sqrtboost::numeric::ublas::scalar_traits200         value_type type_sqrt (const_reference t) {
201             // force a type conversion back to value_type for intgral types
202             return value_type (boost_numeric_ublas_sqrt (t));
203         }
204 
205         static
206         BOOST_UBLAS_INLINE
norm_1boost::numeric::ublas::scalar_traits207         real_type norm_1 (const_reference t) {
208             return self_type::type_abs (t);
209         }
210         static
211         BOOST_UBLAS_INLINE
norm_2boost::numeric::ublas::scalar_traits212         real_type norm_2 (const_reference t) {
213             return self_type::type_abs (t);
214         }
215         static
216         BOOST_UBLAS_INLINE
norm_infboost::numeric::ublas::scalar_traits217         real_type norm_inf (const_reference t) {
218             return self_type::type_abs (t);
219         }
220 
221         static
222         BOOST_UBLAS_INLINE
equalsboost::numeric::ublas::scalar_traits223         bool equals (const_reference t1, const_reference t2) {
224             return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
225                    (std::max) ((std::max) (self_type::norm_inf (t1),
226                                        self_type::norm_inf (t2)),
227                              BOOST_UBLAS_TYPE_CHECK_MIN);
228         }
229     };
230 
231     // Define default type traits, assume T is a scalar type
232     template<class T>
233     struct type_traits : scalar_traits <T> {
234         typedef type_traits<T> self_type;
235         typedef T value_type;
236         typedef const T &const_reference;
237         typedef T &reference;
238 
239         typedef T real_type;
240         typedef real_type precision_type;
241         static const unsigned multiplies_complexity = 1;
242 
243     };
244 
245     // Define real type traits
246     template<>
247     struct type_traits<float> : scalar_traits<float> {
248         typedef type_traits<float> self_type;
249         typedef float value_type;
250         typedef const value_type &const_reference;
251         typedef value_type &reference;
252         typedef value_type real_type;
253         typedef double precision_type;
254     };
255     template<>
256     struct type_traits<double> : scalar_traits<double> {
257         typedef type_traits<double> self_type;
258         typedef double value_type;
259         typedef const value_type &const_reference;
260         typedef value_type &reference;
261         typedef value_type real_type;
262         typedef long double precision_type;
263     };
264     template<>
265     struct type_traits<long double>  : scalar_traits<long double> {
266         typedef type_traits<long double> self_type;
267         typedef long double value_type;
268         typedef const value_type &const_reference;
269         typedef value_type &reference;
270         typedef value_type real_type;
271         typedef value_type precision_type;
272     };
273 
274     // Define properties for a generic complex type
275     template<class T>
276     struct complex_traits {
277         typedef complex_traits<T> self_type;
278         typedef T value_type;
279         typedef const T &const_reference;
280         typedef T &reference;
281 
282         typedef typename T::value_type real_type;
283         typedef real_type precision_type;       // we do not know what type has more precision then the real_type
284 
285         static const unsigned plus_complexity = 2;
286         static const unsigned multiplies_complexity = 6;
287 
288         static
289         BOOST_UBLAS_INLINE
realboost::numeric::ublas::complex_traits290         real_type real (const_reference t) {
291                 return std::real (t);
292         }
293         static
294         BOOST_UBLAS_INLINE
imagboost::numeric::ublas::complex_traits295         real_type imag (const_reference t) {
296                 return std::imag (t);
297         }
298         static
299         BOOST_UBLAS_INLINE
conjboost::numeric::ublas::complex_traits300         value_type conj (const_reference t) {
301                 return std::conj (t);
302         }
303 
304         static
305         BOOST_UBLAS_INLINE
type_absboost::numeric::ublas::complex_traits306         real_type type_abs (const_reference t) {
307                 return abs (t);
308         }
309         static
310         BOOST_UBLAS_INLINE
type_sqrtboost::numeric::ublas::complex_traits311         value_type type_sqrt (const_reference t) {
312                 return sqrt (t);
313         }
314 
315         static
316         BOOST_UBLAS_INLINE
norm_1boost::numeric::ublas::complex_traits317         real_type norm_1 (const_reference t) {
318             return self_type::type_abs (t);
319             // original computation has been replaced because a complex number should behave like a scalar type
320             // return type_traits<real_type>::type_abs (self_type::real (t)) +
321             //       type_traits<real_type>::type_abs (self_type::imag (t));
322         }
323         static
324         BOOST_UBLAS_INLINE
norm_2boost::numeric::ublas::complex_traits325         real_type norm_2 (const_reference t) {
326             return self_type::type_abs (t);
327         }
328         static
329         BOOST_UBLAS_INLINE
norm_infboost::numeric::ublas::complex_traits330         real_type norm_inf (const_reference t) {
331             return self_type::type_abs (t);
332             // original computation has been replaced because a complex number should behave like a scalar type
333             // return (std::max) (type_traits<real_type>::type_abs (self_type::real (t)),
334             //                 type_traits<real_type>::type_abs (self_type::imag (t)));
335         }
336 
337         static
338         BOOST_UBLAS_INLINE
equalsboost::numeric::ublas::complex_traits339         bool equals (const_reference t1, const_reference t2) {
340             return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
341                    (std::max) ((std::max) (self_type::norm_inf (t1),
342                                        self_type::norm_inf (t2)),
343                              BOOST_UBLAS_TYPE_CHECK_MIN);
344         }
345     };
346 
347     // Define complex type traits
348     template<>
349     struct type_traits<std::complex<float> > : complex_traits<std::complex<float> >{
350         typedef type_traits<std::complex<float> > self_type;
351         typedef std::complex<float> value_type;
352         typedef const value_type &const_reference;
353         typedef value_type &reference;
354         typedef float real_type;
355         typedef std::complex<double> precision_type;
356 
357     };
358     template<>
359     struct type_traits<std::complex<double> > : complex_traits<std::complex<double> >{
360         typedef type_traits<std::complex<double> > self_type;
361         typedef std::complex<double> value_type;
362         typedef const value_type &const_reference;
363         typedef value_type &reference;
364         typedef double real_type;
365         typedef std::complex<long double> precision_type;
366     };
367     template<>
368     struct type_traits<std::complex<long double> > : complex_traits<std::complex<long double> > {
369         typedef type_traits<std::complex<long double> > self_type;
370         typedef std::complex<long double> value_type;
371         typedef const value_type &const_reference;
372         typedef value_type &reference;
373         typedef long double real_type;
374         typedef value_type precision_type;
375     };
376 
377 #ifdef BOOST_UBLAS_USE_INTERVAL
378     // Define scalar interval type traits
379     template<>
380     struct type_traits<boost::numeric::interval<float> > : scalar_traits<boost::numeric::interval<float> > {
381         typedef type_traits<boost::numeric::interval<float> > self_type;
382         typedef boost::numeric::interval<float> value_type;
383         typedef const value_type &const_reference;
384         typedef value_type &reference;
385         typedef value_type real_type;
386         typedef boost::numeric::interval<double> precision_type;
387 
388     };
389     template<>
390     struct type_traits<boost::numeric::interval<double> > : scalar_traits<boost::numeric::interval<double> > {
391         typedef type_traits<boost::numeric::interval<double> > self_type;
392         typedef boost::numeric::interval<double> value_type;
393         typedef const value_type &const_reference;
394         typedef value_type &reference;
395         typedef value_type real_type;
396         typedef boost::numeric::interval<long double> precision_type;
397     };
398     template<>
399     struct type_traits<boost::numeric::interval<long double> > : scalar_traits<boost::numeric::interval<long double> > {
400         typedef type_traits<boost::numeric::interval<long double> > self_type;
401         typedef boost::numeric::interval<long double> value_type;
402         typedef const value_type &const_reference;
403         typedef value_type &reference;
404         typedef value_type real_type;
405         typedef value_type precision_type;
406     };
407 #endif
408 
409 
410     // Storage tags -- hierarchical definition of storage characteristics
411 
412     struct unknown_storage_tag {};
413     struct sparse_proxy_tag: public unknown_storage_tag {};
414     struct sparse_tag: public sparse_proxy_tag {};
415     struct packed_proxy_tag: public sparse_proxy_tag {};
416     struct packed_tag: public packed_proxy_tag {};
417     struct dense_proxy_tag: public packed_proxy_tag {};
418     struct dense_tag: public dense_proxy_tag {};
419 
420     template<class S1, class S2>
421     struct storage_restrict_traits {
422         typedef S1 storage_category;
423     };
424 
425     template<>
426     struct storage_restrict_traits<sparse_tag, dense_proxy_tag> {
427         typedef sparse_proxy_tag storage_category;
428     };
429     template<>
430     struct storage_restrict_traits<sparse_tag, packed_proxy_tag> {
431         typedef sparse_proxy_tag storage_category;
432     };
433     template<>
434     struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> {
435         typedef sparse_proxy_tag storage_category;
436     };
437 
438     template<>
439     struct storage_restrict_traits<packed_tag, dense_proxy_tag> {
440         typedef packed_proxy_tag storage_category;
441     };
442     template<>
443     struct storage_restrict_traits<packed_tag, packed_proxy_tag> {
444         typedef packed_proxy_tag storage_category;
445     };
446     template<>
447     struct storage_restrict_traits<packed_tag, sparse_proxy_tag> {
448         typedef sparse_proxy_tag storage_category;
449     };
450 
451     template<>
452     struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> {
453         typedef sparse_proxy_tag storage_category;
454     };
455 
456     template<>
457     struct storage_restrict_traits<dense_tag, dense_proxy_tag> {
458         typedef dense_proxy_tag storage_category;
459     };
460     template<>
461     struct storage_restrict_traits<dense_tag, packed_proxy_tag> {
462         typedef packed_proxy_tag storage_category;
463     };
464     template<>
465     struct storage_restrict_traits<dense_tag, sparse_proxy_tag> {
466         typedef sparse_proxy_tag storage_category;
467     };
468 
469     template<>
470     struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> {
471         typedef packed_proxy_tag storage_category;
472     };
473     template<>
474     struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> {
475         typedef sparse_proxy_tag storage_category;
476     };
477 
478 
479     // Iterator tags -- hierarchical definition of storage characteristics
480 
481     struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {};
482     struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {};
483     struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {};
484 
485     // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-)
486     template<class IC>
487     struct iterator_base_traits {};
488 
489     template<>
490     struct iterator_base_traits<std::forward_iterator_tag> {
491         template<class I, class T>
492         struct iterator_base {
493             typedef forward_iterator_base<std::forward_iterator_tag, I, T> type;
494         };
495     };
496 
497     template<>
498     struct iterator_base_traits<std::bidirectional_iterator_tag> {
499         template<class I, class T>
500         struct iterator_base {
501             typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type;
502         };
503     };
504     template<>
505     struct iterator_base_traits<sparse_bidirectional_iterator_tag> {
506         template<class I, class T>
507         struct iterator_base {
508             typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type;
509         };
510     };
511 
512     template<>
513     struct iterator_base_traits<std::random_access_iterator_tag> {
514         template<class I, class T>
515         struct iterator_base {
516             typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type;
517         };
518     };
519     template<>
520     struct iterator_base_traits<packed_random_access_iterator_tag> {
521         template<class I, class T>
522         struct iterator_base {
523             typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type;
524         };
525     };
526     template<>
527     struct iterator_base_traits<dense_random_access_iterator_tag> {
528         template<class I, class T>
529         struct iterator_base {
530             typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type;
531         };
532     };
533 
534     template<class I1, class I2>
535     struct iterator_restrict_traits {
536         typedef I1 iterator_category;
537     };
538 
539     template<>
540     struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
541         typedef sparse_bidirectional_iterator_tag iterator_category;
542     };
543     template<>
544     struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> {
545         typedef sparse_bidirectional_iterator_tag iterator_category;
546     };
547 
548     template<>
549     struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
550         typedef sparse_bidirectional_iterator_tag iterator_category;
551     };
552     template<>
553     struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> {
554         typedef sparse_bidirectional_iterator_tag iterator_category;
555     };
556 
557     template<>
558     struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> {
559         typedef packed_random_access_iterator_tag iterator_category;
560     };
561     template<>
562     struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> {
563         typedef packed_random_access_iterator_tag iterator_category;
564     };
565 
566     template<class I>
567     BOOST_UBLAS_INLINE
increment(I & it,const I & it_end,typename I::difference_type compare,packed_random_access_iterator_tag)568     void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) {
569         it += (std::min) (compare, it_end - it);
570     }
571     template<class I>
572     BOOST_UBLAS_INLINE
increment(I & it,const I &,typename I::difference_type,sparse_bidirectional_iterator_tag)573     void increment (I &it, const I &/* it_end */, typename I::difference_type /* compare */, sparse_bidirectional_iterator_tag) {
574         ++ it;
575     }
576     template<class I>
577     BOOST_UBLAS_INLINE
increment(I & it,const I & it_end,typename I::difference_type compare)578     void increment (I &it, const I &it_end, typename I::difference_type compare) {
579         increment (it, it_end, compare, typename I::iterator_category ());
580     }
581 
582     template<class I>
583     BOOST_UBLAS_INLINE
increment(I & it,const I & it_end)584     void increment (I &it, const I &it_end) {
585 #if BOOST_UBLAS_TYPE_CHECK
586         I cit (it);
587         while (cit != it_end) {
588             BOOST_UBLAS_CHECK (*cit == typename I::value_type/*zero*/(), internal_logic ());
589             ++ cit;
590         }
591 #endif
592         it = it_end;
593     }
594 
595     namespace detail {
596 
597         // specialisation which define whether a type has a trivial constructor
598         // or not. This is used by array types.
599         template<typename T>
600         struct has_trivial_constructor : public boost::has_trivial_constructor<T> {};
601 
602         template<typename T>
603         struct has_trivial_destructor : public boost::has_trivial_destructor<T> {};
604 
605         template<typename FLT>
606         struct has_trivial_constructor<std::complex<FLT> > : public has_trivial_constructor<FLT> {};
607 
608         template<typename FLT>
609         struct has_trivial_destructor<std::complex<FLT> > : public has_trivial_destructor<FLT> {};
610 
611     }
612 
613 
614     /**  \brief Traits class to extract type information from a constant matrix or vector CONTAINER.
615      *
616      */
617     template < class E >
618     struct container_view_traits {
619         /// type of indices
620         typedef typename E::size_type             size_type;
621         /// type of differences of indices
622         typedef typename E::difference_type       difference_type;
623 
624         /// storage category: \c unknown_storage_tag, \c dense_tag, \c packed_tag, ...
625         typedef typename E::storage_category      storage_category;
626 
627         /// type of elements
628         typedef typename E::value_type            value_type;
629         /// const reference to an element
630         typedef typename E::const_reference       const_reference;
631 
632         /// type used in expressions to mark a reference to this class (usually a const container_reference<const E> or the class itself)
633         typedef typename E::const_closure_type    const_closure_type;
634     };
635 
636     /**  \brief Traits class to extract additional type information from a mutable matrix or vector CONTAINER.
637      *
638      */
639     template < class E >
640     struct mutable_container_traits {
641         /// reference to an element
642         typedef typename E::reference             reference;
643 
644         /// type used in expressions to mark a reference to this class (usually a container_reference<E> or the class itself)
645         typedef typename E::closure_type          closure_type;
646     };
647 
648     /**  \brief Traits class to extract type information from a matrix or vector CONTAINER.
649      *
650      */
651     template < class E >
652     struct container_traits
653         : container_view_traits<E>, mutable_container_traits<E> {
654 
655     };
656 
657 
658     /**  \brief Traits class to extract type information from a constant MATRIX.
659      *
660      */
661     template < class MATRIX >
662     struct matrix_view_traits : container_view_traits <MATRIX> {
663 
664         /// orientation of the matrix, either \c row_major_tag, \c column_major_tag or \c unknown_orientation_tag
665         typedef typename MATRIX::orientation_category  orientation_category;
666 
667         /// row iterator for the matrix
668         typedef typename MATRIX::const_iterator1  const_iterator1;
669 
670         /// column iterator for the matrix
671         typedef typename MATRIX::const_iterator2  const_iterator2;
672     };
673 
674     /**  \brief Traits class to extract additional type information from a mutable MATRIX.
675      *
676      */
677     template < class MATRIX >
678     struct mutable_matrix_traits
679         : mutable_container_traits <MATRIX> {
680 
681         /// row iterator for the matrix
682         typedef typename MATRIX::iterator1  iterator1;
683 
684         /// column iterator for the matrix
685         typedef typename MATRIX::iterator2  iterator2;
686     };
687 
688 
689     /**  \brief Traits class to extract type information from a MATRIX.
690      *
691      */
692     template < class MATRIX >
693     struct matrix_traits
694         : matrix_view_traits <MATRIX>, mutable_matrix_traits <MATRIX> {
695     };
696 
697     /**  \brief Traits class to extract type information from a VECTOR.
698      *
699      */
700     template < class VECTOR >
701     struct vector_view_traits : container_view_traits <VECTOR> {
702 
703         /// iterator for the VECTOR
704         typedef typename VECTOR::const_iterator  const_iterator;
705 
706         /// iterator pointing to the first element
707         static
beginboost::numeric::ublas::vector_view_traits708         const_iterator begin(const VECTOR & v) {
709             return v.begin();
710         }
711         /// iterator pointing behind the last element
712         static
endboost::numeric::ublas::vector_view_traits713         const_iterator end(const VECTOR & v) {
714             return v.end();
715         }
716 
717     };
718 
719     /**  \brief Traits class to extract type information from a VECTOR.
720      *
721      */
722     template < class VECTOR >
723     struct mutable_vector_traits : mutable_container_traits <VECTOR> {
724         /// iterator for the VECTOR
725         typedef typename VECTOR::iterator  iterator;
726 
727         /// iterator pointing to the first element
728         static
beginboost::numeric::ublas::mutable_vector_traits729         iterator begin(VECTOR & v) {
730             return v.begin();
731         }
732 
733         /// iterator pointing behind the last element
734         static
endboost::numeric::ublas::mutable_vector_traits735         iterator end(VECTOR & v) {
736             return v.end();
737         }
738     };
739 
740     /**  \brief Traits class to extract type information from a VECTOR.
741      *
742      */
743     template < class VECTOR >
744     struct vector_traits
745         : vector_view_traits <VECTOR>, mutable_vector_traits <VECTOR> {
746     };
747 
748 
749     // Note: specializations for T[N] and T[M][N] have been moved to traits/c_array.hpp
750 
751 }}}
752 
753 #endif
754