os/ossrv/ossrv_pub/boost_apis/boost/numeric/ublas/traits.hpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 //
     2 //  Copyright (c) 2000-2002
     3 //  Joerg Walter, Mathias Koch
     4 //
     5 //  Permission to use, copy, modify, distribute and sell this software
     6 //  and its documentation for any purpose is hereby granted without fee,
     7 //  provided that the above copyright notice appear in all copies and
     8 //  that both that copyright notice and this permission notice appear
     9 //  in supporting documentation.  The authors make no representations
    10 //  about the suitability of this software for any purpose.
    11 //  It is provided "as is" without express or implied warranty.
    12 //
    13 //  The authors gratefully acknowledge the support of
    14 //  GeNeSys mbH & Co. KG in producing this work.
    15 //
    16 
    17 #ifndef _BOOST_UBLAS_TRAITS_
    18 #define _BOOST_UBLAS_TRAITS_
    19 
    20 #include <iterator>
    21 #include <complex>
    22 #include <cmath>
    23 
    24 #include <boost/numeric/ublas/detail/config.hpp>
    25 #include <boost/numeric/ublas/detail/iterator.hpp>
    26 #include <boost/numeric/ublas/detail/returntype_deduction.hpp>
    27 
    28 
    29 namespace boost { namespace numeric { namespace ublas {
    30 
    31     // Use Joel de Guzman's return type deduction
    32     // uBLAS assumes a common return type for all binary arithmetic operators
    33     template<class X, class Y>
    34     struct promote_traits {
    35         typedef type_deduction_detail::base_result_of<X, Y> base_type;
    36         static typename base_type::x_type x;
    37         static typename base_type::y_type y;
    38         static const std::size_t size = sizeof (
    39                 type_deduction_detail::test<
    40                     typename base_type::x_type
    41                   , typename base_type::y_type
    42                 >(x + y)     // Use x+y to stand of all the arithmetic actions
    43             );
    44 
    45         static const std::size_t index = (size / sizeof (char)) - 1;
    46         typedef typename mpl::at_c<
    47             typename base_type::types, index>::type id;
    48         typedef typename id::type promote_type;
    49     };
    50 
    51 
    52         // Type traits - generic numeric properties and functions
    53     template<class T>
    54     struct type_traits;
    55         
    56     // Define properties for a generic scalar type
    57     template<class T>
    58     struct scalar_traits {
    59         typedef scalar_traits<T> self_type;
    60         typedef T value_type;
    61         typedef const T &const_reference;
    62         typedef T &reference;
    63 
    64         typedef T real_type;
    65         typedef real_type precision_type;       // we do not know what type has more precision then the real_type
    66 
    67         static const unsigned plus_complexity = 1;
    68         static const unsigned multiplies_complexity = 1;
    69 
    70         static
    71         BOOST_UBLAS_INLINE
    72         real_type real (const_reference t) {
    73                 return t;
    74         }
    75         static
    76         BOOST_UBLAS_INLINE
    77         real_type imag (const_reference /*t*/) {
    78                 return 0;
    79         }
    80         static
    81         BOOST_UBLAS_INLINE
    82         value_type conj (const_reference t) {
    83                 return t;
    84         }
    85 
    86         static
    87         BOOST_UBLAS_INLINE
    88         real_type type_abs (const_reference t) {
    89             return std::abs (t);    // must use explict std:: as bultin types are not in std namespace
    90         }
    91         static
    92         BOOST_UBLAS_INLINE
    93         value_type type_sqrt (const_reference t) {
    94                // force a type conversion back to value_type for intgral types
    95             return value_type (std::sqrt (t));   // must use explict std:: as bultin types are not in std namespace
    96         }
    97 
    98         static
    99         BOOST_UBLAS_INLINE
   100         real_type norm_1 (const_reference t) {
   101             return self_type::type_abs (t);
   102         }
   103         static
   104         BOOST_UBLAS_INLINE
   105         real_type norm_2 (const_reference t) {
   106             return self_type::type_abs (t);
   107         }
   108         static
   109         BOOST_UBLAS_INLINE
   110         real_type norm_inf (const_reference t) {
   111             return self_type::type_abs (t);
   112         }
   113 
   114         static
   115         BOOST_UBLAS_INLINE
   116         bool equals (const_reference t1, const_reference t2) {
   117             return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
   118                    (std::max) ((std::max) (self_type::norm_inf (t1),
   119                                        self_type::norm_inf (t2)),
   120                              BOOST_UBLAS_TYPE_CHECK_MIN);
   121         }
   122     };
   123 
   124     // Define default type traits, assume T is a scalar type
   125     template<class T>
   126     struct type_traits : scalar_traits <T> {
   127         typedef type_traits<T> self_type;
   128         typedef T value_type;
   129         typedef const T &const_reference;
   130         typedef T &reference;
   131 
   132         typedef T real_type;
   133         typedef real_type precision_type;
   134         static const unsigned multiplies_complexity = 1;
   135 
   136     };
   137 
   138     // Define real type traits
   139     template<>
   140     struct type_traits<float> : scalar_traits<float> {
   141         typedef type_traits<float> self_type;
   142         typedef float value_type;
   143         typedef const value_type &const_reference;
   144         typedef value_type &reference;
   145         typedef value_type real_type;
   146         typedef double precision_type;
   147     };
   148     template<>
   149     struct type_traits<double> : scalar_traits<double> {
   150         typedef type_traits<double> self_type;
   151         typedef double value_type;
   152         typedef const value_type &const_reference;
   153         typedef value_type &reference;
   154         typedef value_type real_type;
   155         typedef long double precision_type;
   156     };
   157     template<>
   158     struct type_traits<long double>  : scalar_traits<long double> {
   159         typedef type_traits<long double> self_type;
   160         typedef long double value_type;
   161         typedef const value_type &const_reference;
   162         typedef value_type &reference;
   163         typedef value_type real_type;
   164         typedef value_type precision_type;
   165     };
   166 
   167     // Define properties for a generic complex type
   168     template<class T>
   169     struct complex_traits {
   170         typedef complex_traits<T> self_type;
   171         typedef T value_type;
   172         typedef const T &const_reference;
   173         typedef T &reference;
   174 
   175         typedef typename T::value_type real_type;
   176         typedef real_type precision_type;       // we do not know what type has more precision then the real_type
   177 
   178         static const unsigned plus_complexity = 2;
   179         static const unsigned multiplies_complexity = 6;
   180 
   181         static
   182         BOOST_UBLAS_INLINE
   183         real_type real (const_reference t) {
   184                 return std::real (t);
   185         }
   186         static
   187         BOOST_UBLAS_INLINE
   188         real_type imag (const_reference t) {
   189                 return std::imag (t);
   190         }
   191         static
   192         BOOST_UBLAS_INLINE
   193         value_type conj (const_reference t) {
   194                 return std::conj (t);
   195         }
   196 
   197         static
   198         BOOST_UBLAS_INLINE
   199         real_type type_abs (const_reference t) {
   200                 return abs (t);
   201         }
   202         static
   203         BOOST_UBLAS_INLINE
   204         value_type type_sqrt (const_reference t) {
   205                 return sqrt (t);
   206         }
   207 
   208         static
   209         BOOST_UBLAS_INLINE
   210         real_type norm_1 (const_reference t) {
   211             return type_traits<real_type>::type_abs (self_type::real (t)) +
   212                    type_traits<real_type>::type_abs (self_type::imag (t));
   213         }
   214         static
   215         BOOST_UBLAS_INLINE
   216         real_type norm_2 (const_reference t) {
   217             return self_type::type_abs (t);
   218         }
   219         static
   220         BOOST_UBLAS_INLINE
   221         real_type norm_inf (const_reference t) {
   222             return (std::max) (type_traits<real_type>::type_abs (self_type::real (t)),
   223                              type_traits<real_type>::type_abs (self_type::imag (t)));
   224         }
   225 
   226         static
   227         BOOST_UBLAS_INLINE
   228         bool equals (const_reference t1, const_reference t2) {
   229             return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
   230                    (std::max) ((std::max) (self_type::norm_inf (t1),
   231                                        self_type::norm_inf (t2)),
   232                              BOOST_UBLAS_TYPE_CHECK_MIN);
   233         }
   234     };
   235     
   236     // Define complex type traits
   237     template<>
   238     struct type_traits<std::complex<float> > : complex_traits<std::complex<float> >{
   239         typedef type_traits<std::complex<float> > self_type;
   240         typedef std::complex<float> value_type;
   241         typedef const value_type &const_reference;
   242         typedef value_type &reference;
   243         typedef float real_type;
   244         typedef std::complex<double> precision_type;
   245 
   246     };
   247     template<>
   248     struct type_traits<std::complex<double> > : complex_traits<std::complex<double> >{
   249         typedef type_traits<std::complex<double> > self_type;
   250         typedef std::complex<double> value_type;
   251         typedef const value_type &const_reference;
   252         typedef value_type &reference;
   253         typedef double real_type;
   254         typedef std::complex<long double> precision_type;
   255     };
   256     template<>
   257     struct type_traits<std::complex<long double> > : complex_traits<std::complex<long double> > {
   258         typedef type_traits<std::complex<long double> > self_type;
   259         typedef std::complex<long double> value_type;
   260         typedef const value_type &const_reference;
   261         typedef value_type &reference;
   262         typedef long double real_type;
   263         typedef value_type precision_type;
   264     };
   265 
   266 #ifdef BOOST_UBLAS_USE_INTERVAL
   267     // Define properties for a generic scalar interval type
   268     template<class T>
   269     struct scalar_interval_type_traits : scalar_type_traits<T> {
   270         typedef scalar_interval_type_traits<T> self_type;
   271         typedef boost::numeric::interval<float> value_type;
   272         typedef const value_type &const_reference;
   273         typedef value_type &reference;
   274         typedef value_type real_type;
   275         typedef real_type precision_type;       // we do not know what type has more precision then the real_type
   276 
   277         static const unsigned plus_complexity = 1;
   278         static const unsigned multiplies_complexity = 1;
   279 
   280         static
   281         BOOST_UBLAS_INLINE
   282         real_type type_abs (const_reference t) {
   283             return abs (t);
   284         }
   285         static
   286         BOOST_UBLAS_INLINE
   287         value_type type_sqrt (const_reference t) {
   288             return sqrt (t);
   289         }
   290 
   291         static
   292         BOOST_UBLAS_INLINE
   293         real_type norm_1 (const_reference t) {
   294             return self_type::type_abs (t);
   295         }
   296         static
   297         BOOST_UBLAS_INLINE
   298         real_type norm_2 (const_reference t) {
   299             return self_type::type_abs (t);
   300         }
   301         static
   302         BOOST_UBLAS_INLINE
   303         real_type norm_inf (const_reference t) {
   304             return self_type::type_abs (t);
   305         }
   306 
   307         static
   308         BOOST_UBLAS_INLINE
   309         bool equals (const_reference t1, const_reference t2) {
   310             return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
   311                    (std::max) ((std::max) (self_type::norm_inf (t1),
   312                                        self_type::norm_inf (t2)),
   313                              BOOST_UBLAS_TYPE_CHECK_MIN);
   314         }
   315     };
   316 
   317     // Define scalar interval type traits
   318     template<>
   319     struct type_traits<boost::numeric::interval<float> > : scalar_interval_type_traits<boost::numeric::interval<float> > {
   320         typedef type_traits<boost::numeric::interval<float> > self_type;
   321         typedef boost::numeric::interval<float> value_type;
   322         typedef const value_type &const_reference;
   323         typedef value_type &reference;
   324         typedef value_type real_type;
   325         typedef boost::numeric::interval<double> precision_type;
   326 
   327     };
   328     template<>
   329     struct type_traits<boost::numeric::interval<double> > : scalar_interval_type_traits<boost::numeric::interval<double> > {
   330         typedef type_traits<boost::numeric::interval<double> > self_type;
   331         typedef boost::numeric::interval<double> value_type;
   332         typedef const value_type &const_reference;
   333         typedef value_type &reference;
   334         typedef value_type real_type;
   335         typedef boost::numeric::interval<long double> precision_type;
   336     };
   337     template<>
   338     struct type_traits<boost::numeric::interval<long double> > : scalar_interval_type_traits<boost::numeric::interval<long double> > {
   339         typedef type_traits<boost::numeric::interval<long double> > self_type;
   340         typedef boost::numeric::interval<long double> value_type;
   341         typedef const value_type &const_reference;
   342         typedef value_type &reference;
   343         typedef value_type real_type;
   344         typedef value_type precision_type;
   345     };
   346 
   347 #endif
   348 
   349 
   350     // Storage tags -- hierarchical definition of storage characteristics
   351 
   352     struct unknown_storage_tag {};
   353     struct sparse_proxy_tag: public unknown_storage_tag {};
   354     struct sparse_tag: public sparse_proxy_tag {};
   355     struct packed_proxy_tag: public sparse_proxy_tag {};
   356     struct packed_tag: public packed_proxy_tag {};
   357     struct dense_proxy_tag: public packed_proxy_tag {};
   358     struct dense_tag: public dense_proxy_tag {};
   359 
   360     template<class S1, class S2>
   361     struct storage_restrict_traits {
   362         typedef S1 storage_category;
   363     };
   364 
   365     template<>
   366     struct storage_restrict_traits<sparse_tag, dense_proxy_tag> {
   367         typedef sparse_proxy_tag storage_category;
   368     };
   369     template<>
   370     struct storage_restrict_traits<sparse_tag, packed_proxy_tag> {
   371         typedef sparse_proxy_tag storage_category;
   372     };
   373     template<>
   374     struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> {
   375         typedef sparse_proxy_tag storage_category;
   376     };
   377 
   378     template<>
   379     struct storage_restrict_traits<packed_tag, dense_proxy_tag> {
   380         typedef packed_proxy_tag storage_category;
   381     };
   382     template<>
   383     struct storage_restrict_traits<packed_tag, packed_proxy_tag> {
   384         typedef packed_proxy_tag storage_category;
   385     };
   386     template<>
   387     struct storage_restrict_traits<packed_tag, sparse_proxy_tag> {
   388         typedef sparse_proxy_tag storage_category;
   389     };
   390 
   391     template<>
   392     struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> {
   393         typedef sparse_proxy_tag storage_category;
   394     };
   395 
   396     template<>
   397     struct storage_restrict_traits<dense_tag, dense_proxy_tag> {
   398         typedef dense_proxy_tag storage_category;
   399     };
   400     template<>
   401     struct storage_restrict_traits<dense_tag, packed_proxy_tag> {
   402         typedef packed_proxy_tag storage_category;
   403     };
   404     template<>
   405     struct storage_restrict_traits<dense_tag, sparse_proxy_tag> {
   406         typedef sparse_proxy_tag storage_category;
   407     };
   408 
   409     template<>
   410     struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> {
   411         typedef packed_proxy_tag storage_category;
   412     };
   413     template<>
   414     struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> {
   415         typedef sparse_proxy_tag storage_category;
   416     };
   417 
   418 
   419     // Iterator tags -- hierarchical definition of storage characteristics
   420 
   421     struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {};
   422     struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {};
   423     struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {};
   424 
   425     // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-)
   426     template<class IC>
   427     struct iterator_base_traits {};
   428 
   429     template<>
   430     struct iterator_base_traits<std::forward_iterator_tag> {
   431         template<class I, class T>
   432         struct iterator_base {
   433             typedef forward_iterator_base<std::forward_iterator_tag, I, T> type;
   434         };
   435     };
   436 
   437     template<>
   438     struct iterator_base_traits<std::bidirectional_iterator_tag> {
   439         template<class I, class T>
   440         struct iterator_base {
   441             typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type;
   442         };
   443     };
   444     template<>
   445     struct iterator_base_traits<sparse_bidirectional_iterator_tag> {
   446         template<class I, class T>
   447         struct iterator_base {
   448             typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type;
   449         };
   450     };
   451 
   452     template<>
   453     struct iterator_base_traits<std::random_access_iterator_tag> {
   454         template<class I, class T>
   455         struct iterator_base {
   456             typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type;
   457         };
   458     };
   459     template<>
   460     struct iterator_base_traits<packed_random_access_iterator_tag> {
   461         template<class I, class T>
   462         struct iterator_base {
   463             typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type;
   464         };
   465     };
   466     template<>
   467     struct iterator_base_traits<dense_random_access_iterator_tag> {
   468         template<class I, class T>
   469         struct iterator_base {
   470             typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type;
   471         };
   472     };
   473 
   474     template<class I1, class I2>
   475     struct iterator_restrict_traits {
   476         typedef I1 iterator_category;
   477     };
   478 
   479     template<>
   480     struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
   481         typedef sparse_bidirectional_iterator_tag iterator_category;
   482     };
   483     template<>
   484     struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> {
   485         typedef sparse_bidirectional_iterator_tag iterator_category;
   486     };
   487 
   488     template<>
   489     struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
   490         typedef sparse_bidirectional_iterator_tag iterator_category;
   491     };
   492     template<>
   493     struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> {
   494         typedef sparse_bidirectional_iterator_tag iterator_category;
   495     };
   496 
   497     template<>
   498     struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> {
   499         typedef packed_random_access_iterator_tag iterator_category;
   500     };
   501     template<>
   502     struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> {
   503         typedef packed_random_access_iterator_tag iterator_category;
   504     };
   505 
   506     template<class I>
   507     BOOST_UBLAS_INLINE
   508     void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) {
   509         it += (std::min) (compare, it_end - it);
   510     }
   511     template<class I>
   512     BOOST_UBLAS_INLINE
   513     void increment (I &it, const I &/* it_end */, typename I::difference_type /* compare */, sparse_bidirectional_iterator_tag) {
   514         ++ it;
   515     }
   516     template<class I>
   517     BOOST_UBLAS_INLINE
   518     void increment (I &it, const I &it_end, typename I::difference_type compare) {
   519         increment (it, it_end, compare, typename I::iterator_category ());
   520     }
   521 
   522     template<class I>
   523     BOOST_UBLAS_INLINE
   524     void increment (I &it, const I &it_end) {
   525 #if BOOST_UBLAS_TYPE_CHECK
   526         I cit (it);
   527         while (cit != it_end) {
   528             BOOST_UBLAS_CHECK (*cit == typename I::value_type/*zero*/(), internal_logic ());
   529             ++ cit;
   530         }
   531 #endif
   532         it = it_end;
   533     }
   534 
   535 }}}
   536 
   537 #endif