Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:05

0001 //
0002 //  Copyright (c) 2000-2009
0003 //  Joerg Walter, Mathias Koch, Gunter Winkler
0004 //
0005 //  Distributed under the Boost Software License, Version 1.0. (See
0006 //  accompanying file LICENSE_1_0.txt or copy at
0007 //  http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 //  The authors gratefully acknowledge the support of
0010 //  GeNeSys mbH & Co. KG in producing this work.
0011 //
0012 
0013 #ifndef _BOOST_UBLAS_FUNCTIONAL_
0014 #define _BOOST_UBLAS_FUNCTIONAL_
0015 
0016 #include <functional>
0017 
0018 #include <boost/core/ignore_unused.hpp>
0019 
0020 #include <boost/numeric/ublas/traits.hpp>
0021 #ifdef BOOST_UBLAS_USE_DUFF_DEVICE
0022 #include <boost/numeric/ublas/detail/duff.hpp>
0023 #endif
0024 #ifdef BOOST_UBLAS_USE_SIMD
0025 #include <boost/numeric/ublas/detail/raw.hpp>
0026 #else
0027 namespace boost { namespace numeric { namespace ublas { namespace raw {
0028 }}}}
0029 #endif
0030 #ifdef BOOST_UBLAS_HAVE_BINDINGS
0031 #include <boost/numeric/bindings/traits/std_vector.hpp>
0032 #include <boost/numeric/bindings/traits/ublas_vector.hpp>
0033 #include <boost/numeric/bindings/traits/ublas_matrix.hpp>
0034 #include <boost/numeric/bindings/atlas/cblas.hpp>
0035 #endif
0036 
0037 #include <boost/numeric/ublas/detail/definitions.hpp>
0038 
0039 
0040 
0041 namespace boost { namespace numeric { namespace ublas {
0042 
0043     // Scalar functors
0044 
0045     // Unary
0046     template<class T>
0047     struct scalar_unary_functor {
0048         typedef T value_type;
0049         typedef typename type_traits<T>::const_reference argument_type;
0050         typedef typename type_traits<T>::value_type result_type;
0051     };
0052 
0053     template<class T>
0054     struct scalar_identity:
0055         public scalar_unary_functor<T> {
0056         typedef typename scalar_unary_functor<T>::argument_type argument_type;
0057         typedef typename scalar_unary_functor<T>::result_type result_type;
0058 
0059         static BOOST_UBLAS_INLINE
0060         result_type apply (argument_type t) {
0061             return t;
0062         }
0063     };
0064     template<class T>
0065     struct scalar_negate:
0066         public scalar_unary_functor<T> {
0067         typedef typename scalar_unary_functor<T>::argument_type argument_type;
0068         typedef typename scalar_unary_functor<T>::result_type result_type;
0069 
0070         static BOOST_UBLAS_INLINE
0071         result_type apply (argument_type t) {
0072             return - t;
0073         }
0074     };
0075     template<class T>
0076     struct scalar_conj:
0077         public scalar_unary_functor<T> {
0078         typedef typename scalar_unary_functor<T>::value_type value_type;
0079         typedef typename scalar_unary_functor<T>::argument_type argument_type;
0080         typedef typename scalar_unary_functor<T>::result_type result_type;
0081 
0082         static BOOST_UBLAS_INLINE
0083         result_type apply (argument_type t) {
0084             return type_traits<value_type>::conj (t);
0085         }
0086     };
0087 
0088     // Unary returning real
0089     template<class T>
0090     struct scalar_real_unary_functor {
0091         typedef T value_type;
0092         typedef typename type_traits<T>::const_reference argument_type;
0093         typedef typename type_traits<T>::real_type result_type;
0094     };
0095 
0096     template<class T>
0097     struct scalar_real:
0098         public scalar_real_unary_functor<T> {
0099         typedef typename scalar_real_unary_functor<T>::value_type value_type;
0100         typedef typename scalar_real_unary_functor<T>::argument_type argument_type;
0101         typedef typename scalar_real_unary_functor<T>::result_type result_type;
0102 
0103         static BOOST_UBLAS_INLINE
0104         result_type apply (argument_type t) {
0105             return type_traits<value_type>::real (t);
0106         }
0107     };
0108     template<class T>
0109     struct scalar_imag:
0110         public scalar_real_unary_functor<T> {
0111         typedef typename scalar_real_unary_functor<T>::value_type value_type;
0112         typedef typename scalar_real_unary_functor<T>::argument_type argument_type;
0113         typedef typename scalar_real_unary_functor<T>::result_type result_type;
0114 
0115         static BOOST_UBLAS_INLINE
0116         result_type apply (argument_type t) {
0117             return type_traits<value_type>::imag (t);
0118         }
0119     };
0120 
0121     // Binary
0122     template<class T1, class T2>
0123     struct scalar_binary_functor {
0124         typedef typename type_traits<T1>::const_reference argument1_type;
0125         typedef typename type_traits<T2>::const_reference argument2_type;
0126         typedef typename promote_traits<T1, T2>::promote_type result_type;
0127     };
0128 
0129     template<class T1, class T2>
0130     struct scalar_plus:
0131         public scalar_binary_functor<T1, T2> {
0132         typedef typename scalar_binary_functor<T1, T2>::argument1_type argument1_type;
0133         typedef typename scalar_binary_functor<T1, T2>::argument2_type argument2_type;
0134         typedef typename scalar_binary_functor<T1, T2>::result_type result_type;
0135 
0136         static BOOST_UBLAS_INLINE
0137         result_type apply (argument1_type t1, argument2_type t2) {
0138             return t1 + t2;
0139         }
0140     };
0141     template<class T1, class T2>
0142     struct scalar_minus:
0143         public scalar_binary_functor<T1, T2> {
0144         typedef typename scalar_binary_functor<T1, T2>::argument1_type argument1_type;
0145         typedef typename scalar_binary_functor<T1, T2>::argument2_type argument2_type;
0146         typedef typename scalar_binary_functor<T1, T2>::result_type result_type;
0147 
0148         static BOOST_UBLAS_INLINE
0149         result_type apply (argument1_type t1, argument2_type t2) {
0150             return t1 - t2;
0151         }
0152     };
0153     template<class T1, class T2>
0154     struct scalar_multiplies:
0155         public scalar_binary_functor<T1, T2> {
0156         typedef typename scalar_binary_functor<T1, T2>::argument1_type argument1_type;
0157         typedef typename scalar_binary_functor<T1, T2>::argument2_type argument2_type;
0158         typedef typename scalar_binary_functor<T1, T2>::result_type result_type;
0159 
0160         static BOOST_UBLAS_INLINE
0161         result_type apply (argument1_type t1, argument2_type t2) {
0162             return t1 * t2;
0163         }
0164     };
0165     template<class T1, class T2>
0166     struct scalar_divides:
0167         public scalar_binary_functor<T1, T2> {
0168         typedef typename scalar_binary_functor<T1, T2>::argument1_type argument1_type;
0169         typedef typename scalar_binary_functor<T1, T2>::argument2_type argument2_type;
0170         typedef typename scalar_binary_functor<T1, T2>::result_type result_type;
0171 
0172         static BOOST_UBLAS_INLINE
0173         result_type apply (argument1_type t1, argument2_type t2) {
0174             return t1 / t2;
0175         }
0176     };
0177 
0178     template<class T1, class T2>
0179     struct scalar_binary_assign_functor {
0180         // ISSUE Remove reference to avoid reference to reference problems
0181         typedef typename type_traits<typename boost::remove_reference<T1>::type>::reference argument1_type;
0182         typedef typename type_traits<T2>::const_reference argument2_type;
0183     };
0184 
0185     struct assign_tag {};
0186     struct computed_assign_tag {};
0187 
0188     template<class T1, class T2>
0189     struct scalar_assign:
0190         public scalar_binary_assign_functor<T1, T2> {
0191         typedef typename scalar_binary_assign_functor<T1, T2>::argument1_type argument1_type;
0192         typedef typename scalar_binary_assign_functor<T1, T2>::argument2_type argument2_type;
0193 #if BOOST_WORKAROUND( __IBMCPP__, <=600 )
0194         static const bool computed ;
0195 #else
0196         static const bool computed = false ;
0197 #endif
0198 
0199         static BOOST_UBLAS_INLINE
0200         void apply (argument1_type t1, argument2_type t2) {
0201             t1 = t2;
0202         }
0203 
0204         template<class U1, class U2>
0205         struct rebind {
0206             typedef scalar_assign<U1, U2> other;
0207         };
0208     };
0209 
0210 #if BOOST_WORKAROUND( __IBMCPP__, <=600 )
0211     template<class T1, class T2>
0212     const bool scalar_assign<T1,T2>::computed = false;
0213 #endif
0214 
0215     template<class T1, class T2>
0216     struct scalar_plus_assign:
0217         public scalar_binary_assign_functor<T1, T2> {
0218         typedef typename scalar_binary_assign_functor<T1, T2>::argument1_type argument1_type;
0219         typedef typename scalar_binary_assign_functor<T1, T2>::argument2_type argument2_type;
0220 #if BOOST_WORKAROUND( __IBMCPP__, <=600 )
0221         static const bool computed ;
0222 #else
0223         static const bool computed = true ;
0224 #endif
0225 
0226         static BOOST_UBLAS_INLINE
0227         void apply (argument1_type t1, argument2_type t2) {
0228             t1 += t2;
0229         }
0230 
0231         template<class U1, class U2>
0232         struct rebind {
0233             typedef scalar_plus_assign<U1, U2> other;
0234         };
0235     };
0236 
0237 #if BOOST_WORKAROUND( __IBMCPP__, <=600 )
0238     template<class T1, class T2>
0239     const bool scalar_plus_assign<T1,T2>::computed = true;
0240 #endif
0241 
0242     template<class T1, class T2>
0243     struct scalar_minus_assign:
0244         public scalar_binary_assign_functor<T1, T2> {
0245         typedef typename scalar_binary_assign_functor<T1, T2>::argument1_type argument1_type;
0246         typedef typename scalar_binary_assign_functor<T1, T2>::argument2_type argument2_type;
0247 #if BOOST_WORKAROUND( __IBMCPP__, <=600 )
0248         static const bool computed ;
0249 #else
0250         static const bool computed = true ;
0251 #endif
0252 
0253         static BOOST_UBLAS_INLINE
0254         void apply (argument1_type t1, argument2_type t2) {
0255             t1 -= t2;
0256         }
0257 
0258         template<class U1, class U2>
0259         struct rebind {
0260             typedef scalar_minus_assign<U1, U2> other;
0261         };
0262     };
0263 
0264 #if BOOST_WORKAROUND( __IBMCPP__, <=600 )
0265     template<class T1, class T2>
0266     const bool scalar_minus_assign<T1,T2>::computed = true;
0267 #endif
0268 
0269     template<class T1, class T2>
0270     struct scalar_multiplies_assign:
0271         public scalar_binary_assign_functor<T1, T2> {
0272         typedef typename scalar_binary_assign_functor<T1, T2>::argument1_type argument1_type;
0273         typedef typename scalar_binary_assign_functor<T1, T2>::argument2_type argument2_type;
0274         static const bool computed = true;
0275 
0276         static BOOST_UBLAS_INLINE
0277         void apply (argument1_type t1, argument2_type t2) {
0278             t1 *= t2;
0279         }
0280 
0281         template<class U1, class U2>
0282         struct rebind {
0283             typedef scalar_multiplies_assign<U1, U2> other;
0284         };
0285     };
0286     template<class T1, class T2>
0287     struct scalar_divides_assign:
0288         public scalar_binary_assign_functor<T1, T2> {
0289         typedef typename scalar_binary_assign_functor<T1, T2>::argument1_type argument1_type;
0290         typedef typename scalar_binary_assign_functor<T1, T2>::argument2_type argument2_type;
0291         static const bool computed ;
0292 
0293         static BOOST_UBLAS_INLINE
0294         void apply (argument1_type t1, argument2_type t2) {
0295             t1 /= t2;
0296         }
0297 
0298         template<class U1, class U2>
0299         struct rebind {
0300             typedef scalar_divides_assign<U1, U2> other;
0301         };
0302     };
0303     template<class T1, class T2>
0304     const bool scalar_divides_assign<T1,T2>::computed = true;
0305 
0306     template<class T1, class T2>
0307     struct scalar_binary_swap_functor {
0308         typedef typename type_traits<typename boost::remove_reference<T1>::type>::reference argument1_type;
0309         typedef typename type_traits<typename boost::remove_reference<T2>::type>::reference argument2_type;
0310     };
0311 
0312     template<class T1, class T2>
0313     struct scalar_swap:
0314         public scalar_binary_swap_functor<T1, T2> {
0315         typedef typename scalar_binary_swap_functor<T1, T2>::argument1_type argument1_type;
0316         typedef typename scalar_binary_swap_functor<T1, T2>::argument2_type argument2_type;
0317 
0318         static BOOST_UBLAS_INLINE
0319         void apply (argument1_type t1, argument2_type t2) {
0320             std::swap (t1, t2);
0321         }
0322 
0323         template<class U1, class U2>
0324         struct rebind {
0325             typedef scalar_swap<U1, U2> other;
0326         };
0327     };
0328 
0329     // Vector functors
0330 
0331     // Unary returning scalar
0332     template<class V>
0333     struct vector_scalar_unary_functor {
0334         typedef typename V::value_type value_type;
0335         typedef typename V::value_type result_type;
0336     };
0337 
0338     template<class V>
0339     struct vector_sum: 
0340         public vector_scalar_unary_functor<V> {
0341         typedef typename vector_scalar_unary_functor<V>::value_type value_type;
0342         typedef typename vector_scalar_unary_functor<V>::result_type result_type;
0343 
0344         template<class E>
0345         static BOOST_UBLAS_INLINE
0346         result_type apply (const vector_expression<E> &e) { 
0347             result_type t = result_type (0);
0348             typedef typename E::size_type vector_size_type;
0349             vector_size_type size (e ().size ());
0350             for (vector_size_type i = 0; i < size; ++ i)
0351                 t += e () (i);
0352             return t;
0353         }
0354         // Dense case
0355         template<class D, class I>
0356         static BOOST_UBLAS_INLINE
0357         result_type apply (D size, I it) { 
0358             result_type t = result_type (0);
0359             while (-- size >= 0)
0360                 t += *it, ++ it;
0361             return t; 
0362         }
0363         // Sparse case
0364         template<class I>
0365         static BOOST_UBLAS_INLINE
0366         result_type apply (I it, const I &it_end) {
0367             result_type t = result_type (0);
0368             while (it != it_end) 
0369                 t += *it, ++ it;
0370             return t; 
0371         }
0372     };
0373 
0374     // Unary returning real scalar 
0375     template<class V>
0376     struct vector_scalar_real_unary_functor {
0377         typedef typename V::value_type value_type;
0378         typedef typename type_traits<value_type>::real_type real_type;
0379         typedef real_type result_type;
0380     };
0381 
0382     template<class V>
0383     struct vector_norm_1:
0384         public vector_scalar_real_unary_functor<V> {
0385         typedef typename vector_scalar_real_unary_functor<V>::value_type value_type;
0386         typedef typename vector_scalar_real_unary_functor<V>::real_type real_type;
0387         typedef typename vector_scalar_real_unary_functor<V>::result_type result_type;
0388 
0389         template<class E>
0390         static BOOST_UBLAS_INLINE
0391         result_type apply (const vector_expression<E> &e) {
0392             real_type t = real_type ();
0393             typedef typename E::size_type vector_size_type;
0394             vector_size_type size (e ().size ());
0395             for (vector_size_type i = 0; i < size; ++ i) {
0396                 real_type u (type_traits<value_type>::type_abs (e () (i)));
0397                 t += u;
0398             }
0399             return t;
0400         }
0401         // Dense case
0402         template<class D, class I>
0403         static BOOST_UBLAS_INLINE
0404         result_type apply (D size, I it) {
0405             real_type t = real_type ();
0406             while (-- size >= 0) {
0407                 real_type u (type_traits<value_type>::norm_1 (*it));
0408                 t += u;
0409                 ++ it;
0410             }
0411             return t;
0412         }
0413         // Sparse case
0414         template<class I>
0415         static BOOST_UBLAS_INLINE
0416         result_type apply (I it, const I &it_end) {
0417             real_type t = real_type ();
0418             while (it != it_end) {
0419                 real_type u (type_traits<value_type>::norm_1 (*it));
0420                 t += u;
0421                 ++ it;
0422             }
0423             return t;
0424         }
0425     };
0426     template<class V>
0427     struct vector_norm_2:
0428         public vector_scalar_real_unary_functor<V> {
0429         typedef typename vector_scalar_real_unary_functor<V>::value_type value_type;
0430         typedef typename vector_scalar_real_unary_functor<V>::real_type real_type;
0431         typedef typename vector_scalar_real_unary_functor<V>::result_type result_type;
0432 
0433         template<class E>
0434         static BOOST_UBLAS_INLINE
0435         result_type apply (const vector_expression<E> &e) {
0436             typedef typename E::size_type vector_size_type;
0437             vector_size_type size (e ().size ());
0438 #ifndef BOOST_UBLAS_SCALED_NORM
0439             real_type t = real_type ();
0440             for (vector_size_type i = 0; i < size; ++ i) {
0441                 real_type u (type_traits<value_type>::norm_2 (e () (i)));
0442                 t +=  u * u;
0443             }
0444             return static_cast<result_type>(type_traits<real_type>::type_sqrt (t));
0445 #else
0446             real_type scale = real_type ();
0447             real_type sum_squares (1);
0448             for (vector_size_type i = 0; i < size; ++ i) {
0449                 real_type u (type_traits<value_type>::norm_2 (e () (i)));
0450                 if ( real_type () /* zero */ == u ) continue;
0451                 if (scale < u) {
0452                     real_type v (scale / u);
0453                     sum_squares = sum_squares * v * v + real_type (1);
0454                     scale = u;
0455                 } else {
0456                     real_type v (u / scale);
0457                     sum_squares += v * v;
0458                 }
0459             }
0460             return static_cast<result_type>(scale * type_traits<real_type>::type_sqrt (sum_squares));
0461 #endif
0462         }
0463         // Dense case
0464         template<class D, class I>
0465         static BOOST_UBLAS_INLINE
0466         result_type apply (D size, I it) {
0467 #ifndef BOOST_UBLAS_SCALED_NORM
0468             real_type t = real_type ();
0469             while (-- size >= 0) {
0470                 real_type u (type_traits<value_type>::norm_2 (*it));
0471                 t +=  u * u;
0472                 ++ it;
0473             }
0474             return static_cast<result_type>(type_traits<real_type>::type_sqrt (t));
0475 #else
0476             real_type scale = real_type ();
0477             real_type sum_squares (1);
0478             while (-- size >= 0) {
0479                 real_type u (type_traits<value_type>::norm_2 (*it));
0480                 if (scale < u) {
0481                     real_type v (scale / u);
0482                     sum_squares = sum_squares * v * v + real_type (1);
0483                     scale = u;
0484                 } else {
0485                     real_type v (u / scale);
0486                     sum_squares += v * v;
0487                 }
0488                 ++ it;
0489             }
0490             return static_cast<result_type>(scale * type_traits<real_type>::type_sqrt (sum_squares));
0491 #endif
0492         }
0493         // Sparse case
0494         template<class I>
0495         static BOOST_UBLAS_INLINE
0496         result_type apply (I it, const I &it_end) {
0497 #ifndef BOOST_UBLAS_SCALED_NORM
0498             real_type t = real_type ();
0499             while (it != it_end) {
0500                 real_type u (type_traits<value_type>::norm_2 (*it));
0501                 t +=  u * u;
0502                 ++ it;
0503             }
0504             return static_cast<result_type>(type_traits<real_type>::type_sqrt (t));
0505 #else
0506             real_type scale = real_type ();
0507             real_type sum_squares (1);
0508             while (it != it_end) {
0509                 real_type u (type_traits<value_type>::norm_2 (*it));
0510                 if (scale < u) {
0511                     real_type v (scale / u);
0512                     sum_squares = sum_squares * v * v + real_type (1);
0513                     scale = u;
0514                 } else {
0515                     real_type v (u / scale);
0516                     sum_squares += v * v;
0517                 }
0518                 ++ it;
0519             }
0520             return static_cast<result_type>(scale * type_traits<real_type>::type_sqrt (sum_squares));
0521 #endif
0522         }
0523     };
0524 
0525     template<class V>
0526     struct vector_norm_2_square :
0527         public vector_scalar_real_unary_functor<V> {
0528         typedef typename vector_scalar_real_unary_functor<V>::value_type value_type;
0529         typedef typename vector_scalar_real_unary_functor<V>::real_type real_type;
0530         typedef typename vector_scalar_real_unary_functor<V>::result_type result_type;
0531 
0532         template<class E>
0533         static BOOST_UBLAS_INLINE
0534         result_type apply (const vector_expression<E> &e) {
0535             real_type t = real_type ();
0536             typedef typename E::size_type vector_size_type;
0537             vector_size_type size (e ().size ());
0538             for (vector_size_type i = 0; i < size; ++ i) {
0539                 real_type u (type_traits<value_type>::norm_2 (e () (i)));
0540                 t +=  u * u;
0541             }
0542             return t;
0543         }
0544         // Dense case
0545         template<class D, class I>
0546         static BOOST_UBLAS_INLINE
0547         result_type apply (D size, I it) {
0548             real_type t = real_type ();
0549             while (-- size >= 0) {
0550                 real_type u (type_traits<value_type>::norm_2 (*it));
0551                 t +=  u * u;
0552                 ++ it;
0553             }
0554             return t;
0555         }
0556         // Sparse case
0557         template<class I>
0558         static BOOST_UBLAS_INLINE
0559         result_type apply (I it, const I &it_end) {
0560             real_type t = real_type ();
0561             while (it != it_end) {
0562                 real_type u (type_traits<value_type>::norm_2 (*it));
0563                 t +=  u * u;
0564                 ++ it;
0565             }
0566             return t;
0567         }
0568     };
0569 
0570     template<class V>
0571     struct vector_norm_inf:
0572         public vector_scalar_real_unary_functor<V> {
0573         typedef typename vector_scalar_real_unary_functor<V>::value_type value_type;
0574         typedef typename vector_scalar_real_unary_functor<V>::real_type real_type;
0575         typedef typename vector_scalar_real_unary_functor<V>::result_type result_type;
0576 
0577         template<class E>
0578         static BOOST_UBLAS_INLINE
0579         result_type apply (const vector_expression<E> &e) {
0580             real_type t = real_type ();
0581             typedef typename E::size_type vector_size_type;
0582             vector_size_type size (e ().size ());
0583             for (vector_size_type i = 0; i < size; ++ i) {
0584                 real_type u (type_traits<value_type>::norm_inf (e () (i)));
0585                 if (u > t)
0586                     t = u;
0587             }
0588             return t;
0589         }
0590         // Dense case
0591         template<class D, class I>
0592         static BOOST_UBLAS_INLINE
0593         result_type apply (D size, I it) {
0594             real_type t = real_type ();
0595             while (-- size >= 0) {
0596                 real_type u (type_traits<value_type>::norm_inf (*it));
0597                 if (u > t)
0598                     t = u;
0599                 ++ it;
0600             }
0601             return t;
0602         }
0603         // Sparse case
0604         template<class I>
0605         static BOOST_UBLAS_INLINE
0606         result_type apply (I it, const I &it_end) { 
0607             real_type t = real_type ();
0608             while (it != it_end) {
0609                 real_type u (type_traits<value_type>::norm_inf (*it));
0610                 if (u > t) 
0611                     t = u;
0612                 ++ it;
0613             }
0614             return t; 
0615         }
0616     };
0617 
0618     // Unary returning index
0619     template<class V>
0620     struct vector_scalar_index_unary_functor {
0621         typedef typename V::value_type value_type;
0622         typedef typename type_traits<value_type>::real_type real_type;
0623         typedef typename V::size_type result_type;
0624     };
0625 
0626     template<class V>
0627     struct vector_index_norm_inf:
0628         public vector_scalar_index_unary_functor<V> {
0629         typedef typename vector_scalar_index_unary_functor<V>::value_type value_type;
0630         typedef typename vector_scalar_index_unary_functor<V>::real_type real_type;
0631         typedef typename vector_scalar_index_unary_functor<V>::result_type result_type;
0632 
0633         template<class E>
0634         static BOOST_UBLAS_INLINE
0635         result_type apply (const vector_expression<E> &e) {
0636             // ISSUE For CBLAS compatibility return 0 index in empty case
0637             result_type i_norm_inf (0);
0638             real_type t = real_type ();
0639             typedef typename E::size_type vector_size_type;
0640             vector_size_type size (e ().size ());
0641             for (vector_size_type i = 0; i < size; ++ i) {
0642                 real_type u (type_traits<value_type>::norm_inf (e () (i)));
0643                 if (u > t) {
0644                     i_norm_inf = i;
0645                     t = u;
0646                 }
0647             }
0648             return i_norm_inf;
0649         }
0650         // Dense case
0651         template<class D, class I>
0652         static BOOST_UBLAS_INLINE
0653         result_type apply (D size, I it) {
0654             // ISSUE For CBLAS compatibility return 0 index in empty case
0655             result_type i_norm_inf (0);
0656             real_type t = real_type ();
0657             while (-- size >= 0) {
0658                 real_type u (type_traits<value_type>::norm_inf (*it));
0659                 if (u > t) {
0660                     i_norm_inf = it.index ();
0661                     t = u;
0662                 }
0663                 ++ it;
0664             }
0665             return i_norm_inf;
0666         }
0667         // Sparse case
0668         template<class I>
0669         static BOOST_UBLAS_INLINE
0670         result_type apply (I it, const I &it_end) {
0671             // ISSUE For CBLAS compatibility return 0 index in empty case
0672             result_type i_norm_inf (0);
0673             real_type t = real_type ();
0674             while (it != it_end) {
0675                 real_type u (type_traits<value_type>::norm_inf (*it));
0676                 if (u > t) {
0677                     i_norm_inf = it.index ();
0678                     t = u;
0679                 }
0680                 ++ it;
0681             }
0682             return i_norm_inf;
0683         }
0684     };
0685 
0686     // Binary returning scalar
0687     template<class V1, class V2, class TV>
0688     struct vector_scalar_binary_functor {
0689         typedef TV value_type;
0690         typedef TV result_type;
0691     };
0692 
0693     template<class V1, class V2, class TV>
0694     struct vector_inner_prod:
0695         public vector_scalar_binary_functor<V1, V2, TV> {
0696         typedef typename vector_scalar_binary_functor<V1, V2, TV>::value_type value_type;
0697         typedef typename vector_scalar_binary_functor<V1, V2, TV>::result_type result_type;
0698 
0699         template<class C1, class C2>
0700         static BOOST_UBLAS_INLINE
0701         result_type apply (const vector_container<C1> &c1,
0702                            const vector_container<C2> &c2) {
0703 #ifdef BOOST_UBLAS_USE_SIMD
0704             using namespace raw;
0705             typedef typename C1::size_type vector_size_type;
0706             vector_size_type size (BOOST_UBLAS_SAME (c1 ().size (), c2 ().size ()));
0707             const typename V1::value_type *data1 = data_const (c1 ());
0708             const typename V1::value_type *data2 = data_const (c2 ());
0709             vector_size_type s1 = stride (c1 ());
0710             vector_size_type s2 = stride (c2 ());
0711             result_type t = result_type (0);
0712             if (s1 == 1 && s2 == 1) {
0713                 for (vector_size_type i = 0; i < size; ++ i)
0714                     t += data1 [i] * data2 [i];
0715             } else if (s2 == 1) {
0716                 for (vector_size_type i = 0, i1 = 0; i < size; ++ i, i1 += s1)
0717                     t += data1 [i1] * data2 [i];
0718             } else if (s1 == 1) {
0719                 for (vector_size_type i = 0, i2 = 0; i < size; ++ i, i2 += s2)
0720                     t += data1 [i] * data2 [i2];
0721             } else {
0722                 for (vector_size_type i = 0, i1 = 0, i2 = 0; i < size; ++ i, i1 += s1, i2 += s2)
0723                     t += data1 [i1] * data2 [i2];
0724             }
0725             return t;
0726 #elif defined(BOOST_UBLAS_HAVE_BINDINGS)
0727             return boost::numeric::bindings::atlas::dot (c1 (), c2 ());
0728 #else
0729             return apply (static_cast<const vector_expression<C1> > (c1), static_cast<const vector_expression<C2> > (c2));
0730 #endif
0731         }
0732         template<class E1, class E2>
0733         static BOOST_UBLAS_INLINE
0734         result_type apply (const vector_expression<E1> &e1,
0735                            const vector_expression<E2> &e2) {
0736             typedef typename E1::size_type vector_size_type;
0737             vector_size_type size (BOOST_UBLAS_SAME (e1 ().size (), e2 ().size ()));
0738             result_type t = result_type (0);
0739 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0740             for (vector_size_type i = 0; i < size; ++ i)
0741                 t += e1 () (i) * e2 () (i);
0742 #else
0743             vector_size_type i (0);
0744             DD (size, 4, r, (t += e1 () (i) * e2 () (i), ++ i));
0745 #endif
0746             return t;
0747         }
0748         // Dense case
0749         template<class D, class I1, class I2>
0750         static BOOST_UBLAS_INLINE
0751         result_type apply (D size, I1 it1, I2 it2) {
0752             result_type t = result_type (0);
0753 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0754             while (-- size >= 0)
0755                 t += *it1 * *it2, ++ it1, ++ it2;
0756 #else
0757             DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2));
0758 #endif
0759             return t;
0760         }
0761         // Packed case
0762         template<class I1, class I2>
0763         static BOOST_UBLAS_INLINE
0764         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) {
0765             result_type t = result_type (0);
0766             typedef typename I1::difference_type vector_difference_type;
0767             vector_difference_type it1_size (it1_end - it1);
0768             vector_difference_type it2_size (it2_end - it2);
0769             vector_difference_type diff (0);
0770             if (it1_size > 0 && it2_size > 0)
0771                 diff = it2.index () - it1.index ();
0772             if (diff != 0) {
0773                 vector_difference_type size = (std::min) (diff, it1_size);
0774                 if (size > 0) {
0775                     it1 += size;
0776                     it1_size -= size;
0777                     diff -= size;
0778                 }
0779                 size = (std::min) (- diff, it2_size);
0780                 if (size > 0) {
0781                     it2 += size;
0782                     it2_size -= size;
0783                     diff += size;
0784                 }
0785             }
0786             vector_difference_type size ((std::min) (it1_size, it2_size));
0787             while (-- size >= 0)
0788                 t += *it1 * *it2, ++ it1, ++ it2;
0789             return t;
0790         }
0791         // Sparse case
0792         template<class I1, class I2>
0793         static BOOST_UBLAS_INLINE
0794         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) {
0795             result_type t = result_type (0);
0796             if (it1 != it1_end && it2 != it2_end) {
0797                 for (;;) {
0798                     if (it1.index () == it2.index ()) {
0799                         t += *it1 * *it2, ++ it1, ++ it2;
0800                         if (it1 == it1_end || it2 == it2_end)
0801                             break;
0802                     } else if (it1.index () < it2.index ()) {
0803                         increment (it1, it1_end, it2.index () - it1.index ());
0804                         if (it1 == it1_end)
0805                             break;
0806                     } else if (it1.index () > it2.index ()) {
0807                         increment (it2, it2_end, it1.index () - it2.index ());
0808                         if (it2 == it2_end)
0809                             break;
0810                     }
0811                 }
0812             }
0813             return t;
0814         }
0815     };
0816 
0817     // Matrix functors
0818 
0819     // Binary returning vector
0820     template<class M1, class M2, class TV>
0821     struct matrix_vector_binary_functor {
0822         typedef typename M1::size_type size_type;
0823         typedef typename M1::difference_type difference_type;
0824         typedef TV value_type;
0825         typedef TV result_type;
0826     };
0827 
0828     template<class M1, class M2, class TV>
0829     struct matrix_vector_prod1:
0830         public matrix_vector_binary_functor<M1, M2, TV> {
0831         typedef typename matrix_vector_binary_functor<M1, M2, TV>::size_type size_type;
0832         typedef typename matrix_vector_binary_functor<M1, M2, TV>::difference_type difference_type;
0833         typedef typename matrix_vector_binary_functor<M1, M2, TV>::value_type value_type;
0834         typedef typename matrix_vector_binary_functor<M1, M2, TV>::result_type result_type;
0835 
0836         template<class C1, class C2>
0837         static BOOST_UBLAS_INLINE
0838         result_type apply (const matrix_container<C1> &c1,
0839                            const vector_container<C2> &c2,
0840                            size_type i) {
0841 #ifdef BOOST_UBLAS_USE_SIMD
0842             using namespace raw;
0843             size_type size = BOOST_UBLAS_SAME (c1 ().size2 (), c2 ().size ());
0844             const typename M1::value_type *data1 = data_const (c1 ()) + i * stride1 (c1 ());
0845             const typename M2::value_type *data2 = data_const (c2 ());
0846             size_type s1 = stride2 (c1 ());
0847             size_type s2 = stride (c2 ());
0848             result_type t = result_type (0);
0849             if (s1 == 1 && s2 == 1) {
0850                 for (size_type j = 0; j < size; ++ j)
0851                     t += data1 [j] * data2 [j];
0852             } else if (s2 == 1) {
0853                 for (size_type j = 0, j1 = 0; j < size; ++ j, j1 += s1)
0854                     t += data1 [j1] * data2 [j];
0855             } else if (s1 == 1) {
0856                 for (size_type j = 0, j2 = 0; j < size; ++ j, j2 += s2)
0857                     t += data1 [j] * data2 [j2];
0858             } else {
0859                 for (size_type j = 0, j1 = 0, j2 = 0; j < size; ++ j, j1 += s1, j2 += s2)
0860                     t += data1 [j1] * data2 [j2];
0861             }
0862             return t;
0863 #elif defined(BOOST_UBLAS_HAVE_BINDINGS)
0864             return boost::numeric::bindings::atlas::dot (c1 ().row (i), c2 ());
0865 #else
0866             return apply (static_cast<const matrix_expression<C1> > (c1), static_cast<const vector_expression<C2> > (c2, i));
0867 #endif
0868         }
0869         template<class E1, class E2>
0870         static BOOST_UBLAS_INLINE
0871         result_type apply (const matrix_expression<E1> &e1,
0872                            const vector_expression<E2> &e2,
0873                            size_type i) {
0874             size_type size = BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size ());
0875             result_type t = result_type (0);
0876 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0877             for (size_type j = 0; j < size; ++ j)
0878                 t += e1 () (i, j) * e2 () (j);
0879 #else
0880             size_type j (0);
0881             DD (size, 4, r, (t += e1 () (i, j) * e2 () (j), ++ j));
0882 #endif
0883             return t;
0884         }
0885         // Dense case
0886         template<class I1, class I2>
0887         static BOOST_UBLAS_INLINE
0888         result_type apply (difference_type size, I1 it1, I2 it2) {
0889             result_type t = result_type (0);
0890 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0891             while (-- size >= 0)
0892                 t += *it1 * *it2, ++ it1, ++ it2;
0893 #else
0894             DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2));
0895 #endif
0896             return t;
0897         }
0898         // Packed case
0899         template<class I1, class I2>
0900         static BOOST_UBLAS_INLINE
0901         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) {
0902             result_type t = result_type (0);
0903             difference_type it1_size (it1_end - it1);
0904             difference_type it2_size (it2_end - it2);
0905             difference_type diff (0);
0906             if (it1_size > 0 && it2_size > 0)
0907                 diff = it2.index () - it1.index2 ();
0908             if (diff != 0) {
0909                 difference_type size = (std::min) (diff, it1_size);
0910                 if (size > 0) {
0911                     it1 += size;
0912                     it1_size -= size;
0913                     diff -= size;
0914                 }
0915                 size = (std::min) (- diff, it2_size);
0916                 if (size > 0) {
0917                     it2 += size;
0918                     it2_size -= size;
0919                     diff += size;
0920                 }
0921             }
0922             difference_type size ((std::min) (it1_size, it2_size));
0923             while (-- size >= 0)
0924                 t += *it1 * *it2, ++ it1, ++ it2;
0925             return t;
0926         }
0927         // Sparse case
0928         template<class I1, class I2>
0929         static BOOST_UBLAS_INLINE
0930         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end,
0931                            sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag) {
0932             result_type t = result_type (0);
0933             if (it1 != it1_end && it2 != it2_end) {
0934                 size_type it1_index = it1.index2 (), it2_index = it2.index ();
0935                 for (;;) {
0936                     difference_type compare = it1_index - it2_index;
0937                     if (compare == 0) {
0938                         t += *it1 * *it2, ++ it1, ++ it2;
0939                         if (it1 != it1_end && it2 != it2_end) {
0940                             it1_index = it1.index2 ();
0941                             it2_index = it2.index ();
0942                         } else
0943                             break;
0944                     } else if (compare < 0) {
0945                         increment (it1, it1_end, - compare);
0946                         if (it1 != it1_end)
0947                             it1_index = it1.index2 ();
0948                         else
0949                             break;
0950                     } else if (compare > 0) {
0951                         increment (it2, it2_end, compare);
0952                         if (it2 != it2_end)
0953                             it2_index = it2.index ();
0954                         else
0955                             break;
0956                     }
0957                 }
0958             }
0959             return t;
0960         }
0961         // Sparse packed case
0962         template<class I1, class I2>
0963         static BOOST_UBLAS_INLINE
0964         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &/* it2_end */,
0965                            sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag) {
0966             result_type t = result_type (0);
0967             while (it1 != it1_end) {
0968                 t += *it1 * it2 () (it1.index2 ());
0969                 ++ it1;
0970             }
0971             return t;
0972         }
0973         // Packed sparse case
0974         template<class I1, class I2>
0975         static BOOST_UBLAS_INLINE
0976         result_type apply (I1 it1, const I1 &/* it1_end */, I2 it2, const I2 &it2_end,
0977                            packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag) {
0978             result_type t = result_type (0);
0979             while (it2 != it2_end) {
0980                 t += it1 () (it1.index1 (), it2.index ()) * *it2;
0981                 ++ it2;
0982             }
0983             return t;
0984         }
0985         // Another dispatcher
0986         template<class I1, class I2>
0987         static BOOST_UBLAS_INLINE
0988         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end,
0989                            sparse_bidirectional_iterator_tag) {
0990             typedef typename I1::iterator_category iterator1_category;
0991             typedef typename I2::iterator_category iterator2_category;
0992             return apply (it1, it1_end, it2, it2_end, iterator1_category (), iterator2_category ());
0993         }
0994     };
0995 
0996     template<class M1, class M2, class TV>
0997     struct matrix_vector_prod2:
0998         public matrix_vector_binary_functor<M1, M2, TV> {
0999         typedef typename matrix_vector_binary_functor<M1, M2, TV>::size_type size_type;
1000         typedef typename matrix_vector_binary_functor<M1, M2, TV>::difference_type difference_type;
1001         typedef typename matrix_vector_binary_functor<M1, M2, TV>::value_type value_type;
1002         typedef typename matrix_vector_binary_functor<M1, M2, TV>::result_type result_type;
1003 
1004         template<class C1, class C2>
1005         static BOOST_UBLAS_INLINE
1006         result_type apply (const vector_container<C1> &c1,
1007                            const matrix_container<C2> &c2,
1008                            size_type i) {
1009 #ifdef BOOST_UBLAS_USE_SIMD
1010             using namespace raw;
1011             size_type size = BOOST_UBLAS_SAME (c1 ().size (), c2 ().size1 ());
1012             const typename M1::value_type *data1 = data_const (c1 ());
1013             const typename M2::value_type *data2 = data_const (c2 ()) + i * stride2 (c2 ());
1014             size_type s1 = stride (c1 ());
1015             size_type s2 = stride1 (c2 ());
1016             result_type t = result_type (0);
1017             if (s1 == 1 && s2 == 1) {
1018                 for (size_type j = 0; j < size; ++ j)
1019                     t += data1 [j] * data2 [j];
1020             } else if (s2 == 1) {
1021                 for (size_type j = 0, j1 = 0; j < size; ++ j, j1 += s1)
1022                     t += data1 [j1] * data2 [j];
1023             } else if (s1 == 1) {
1024                 for (size_type j = 0, j2 = 0; j < size; ++ j, j2 += s2)
1025                     t += data1 [j] * data2 [j2];
1026             } else {
1027                 for (size_type j = 0, j1 = 0, j2 = 0; j < size; ++ j, j1 += s1, j2 += s2)
1028                     t += data1 [j1] * data2 [j2];
1029             }
1030             return t;
1031 #elif defined(BOOST_UBLAS_HAVE_BINDINGS)
1032             return boost::numeric::bindings::atlas::dot (c1 (), c2 ().column (i));
1033 #else
1034             return apply (static_cast<const vector_expression<C1> > (c1), static_cast<const matrix_expression<C2> > (c2, i));
1035 #endif
1036         }
1037         template<class E1, class E2>
1038         static BOOST_UBLAS_INLINE
1039         result_type apply (const vector_expression<E1> &e1,
1040                            const matrix_expression<E2> &e2,
1041                            size_type i) {
1042             size_type size = BOOST_UBLAS_SAME (e1 ().size (), e2 ().size1 ());
1043             result_type t = result_type (0);
1044 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
1045             for (size_type j = 0; j < size; ++ j)
1046                 t += e1 () (j) * e2 () (j, i);
1047 #else
1048             size_type j (0);
1049             DD (size, 4, r, (t += e1 () (j) * e2 () (j, i), ++ j));
1050 #endif
1051             return t;
1052         }
1053         // Dense case
1054         template<class I1, class I2>
1055         static BOOST_UBLAS_INLINE
1056         result_type apply (difference_type size, I1 it1, I2 it2) {
1057             result_type t = result_type (0);
1058 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
1059             while (-- size >= 0)
1060                 t += *it1 * *it2, ++ it1, ++ it2;
1061 #else
1062             DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2));
1063 #endif
1064             return t;
1065         }
1066         // Packed case
1067         template<class I1, class I2>
1068         static BOOST_UBLAS_INLINE
1069         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) {
1070             result_type t = result_type (0);
1071             difference_type it1_size (it1_end - it1);
1072             difference_type it2_size (it2_end - it2);
1073             difference_type diff (0);
1074             if (it1_size > 0 && it2_size > 0)
1075                 diff = it2.index1 () - it1.index ();
1076             if (diff != 0) {
1077                 difference_type size = (std::min) (diff, it1_size);
1078                 if (size > 0) {
1079                     it1 += size;
1080                     it1_size -= size;
1081                     diff -= size;
1082                 }
1083                 size = (std::min) (- diff, it2_size);
1084                 if (size > 0) {
1085                     it2 += size;
1086                     it2_size -= size;
1087                     diff += size;
1088                 }
1089             }
1090             difference_type size ((std::min) (it1_size, it2_size));
1091             while (-- size >= 0)
1092                 t += *it1 * *it2, ++ it1, ++ it2;
1093             return t;
1094         }
1095         // Sparse case
1096         template<class I1, class I2>
1097         static BOOST_UBLAS_INLINE
1098         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end,
1099                            sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag) {
1100             result_type t = result_type (0);
1101             if (it1 != it1_end && it2 != it2_end) {
1102                 size_type it1_index = it1.index (), it2_index = it2.index1 ();
1103                 for (;;) {
1104                     difference_type compare = it1_index - it2_index;
1105                     if (compare == 0) {
1106                         t += *it1 * *it2, ++ it1, ++ it2;
1107                         if (it1 != it1_end && it2 != it2_end) {
1108                             it1_index = it1.index ();
1109                             it2_index = it2.index1 ();
1110                         } else
1111                             break;
1112                     } else if (compare < 0) {
1113                         increment (it1, it1_end, - compare);
1114                         if (it1 != it1_end)
1115                             it1_index = it1.index ();
1116                         else
1117                             break;
1118                     } else if (compare > 0) {
1119                         increment (it2, it2_end, compare);
1120                         if (it2 != it2_end)
1121                             it2_index = it2.index1 ();
1122                         else
1123                             break;
1124                     }
1125                 }
1126             }
1127             return t;
1128         }
1129         // Packed sparse case
1130         template<class I1, class I2>
1131         static BOOST_UBLAS_INLINE
1132         result_type apply (I1 it1, const I1 &/* it1_end */, I2 it2, const I2 &it2_end,
1133                            packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag) {
1134             result_type t = result_type (0);
1135             while (it2 != it2_end) {
1136                 t += it1 () (it2.index1 ()) * *it2;
1137                 ++ it2;
1138             }
1139             return t;
1140         }
1141         // Sparse packed case
1142         template<class I1, class I2>
1143         static BOOST_UBLAS_INLINE
1144         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &/* it2_end */,
1145                            sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag) {
1146             result_type t = result_type (0);
1147             while (it1 != it1_end) {
1148                 t += *it1 * it2 () (it1.index (), it2.index2 ());
1149                 ++ it1;
1150             }
1151             return t;
1152         }
1153         // Another dispatcher
1154         template<class I1, class I2>
1155         static BOOST_UBLAS_INLINE
1156         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end,
1157                            sparse_bidirectional_iterator_tag) {
1158             typedef typename I1::iterator_category iterator1_category;
1159             typedef typename I2::iterator_category iterator2_category;
1160             return apply (it1, it1_end, it2, it2_end, iterator1_category (), iterator2_category ());
1161         }
1162     };
1163 
1164     // Binary returning matrix
1165     template<class M1, class M2, class TV>
1166     struct matrix_matrix_binary_functor {
1167         typedef typename M1::size_type size_type;
1168         typedef typename M1::difference_type difference_type;
1169         typedef TV value_type;
1170         typedef TV result_type;
1171     };
1172 
1173     template<class M1, class M2, class TV>
1174     struct matrix_matrix_prod:
1175         public matrix_matrix_binary_functor<M1, M2, TV> {
1176         typedef typename matrix_matrix_binary_functor<M1, M2, TV>::size_type size_type;
1177         typedef typename matrix_matrix_binary_functor<M1, M2, TV>::difference_type difference_type;
1178         typedef typename matrix_matrix_binary_functor<M1, M2, TV>::value_type value_type;
1179         typedef typename matrix_matrix_binary_functor<M1, M2, TV>::result_type result_type;
1180 
1181         template<class C1, class C2>
1182         static BOOST_UBLAS_INLINE
1183         result_type apply (const matrix_container<C1> &c1,
1184                            const matrix_container<C2> &c2,
1185                            size_type i, size_type j) {
1186 #ifdef BOOST_UBLAS_USE_SIMD
1187             using namespace raw;
1188             size_type size = BOOST_UBLAS_SAME (c1 ().size2 (), c2 ().sizc1 ());
1189             const typename M1::value_type *data1 = data_const (c1 ()) + i * stride1 (c1 ());
1190             const typename M2::value_type *data2 = data_const (c2 ()) + j * stride2 (c2 ());
1191             size_type s1 = stride2 (c1 ());
1192             size_type s2 = stride1 (c2 ());
1193             result_type t = result_type (0);
1194             if (s1 == 1 && s2 == 1) {
1195                 for (size_type k = 0; k < size; ++ k)
1196                     t += data1 [k] * data2 [k];
1197             } else if (s2 == 1) {
1198                 for (size_type k = 0, k1 = 0; k < size; ++ k, k1 += s1)
1199                     t += data1 [k1] * data2 [k];
1200             } else if (s1 == 1) {
1201                 for (size_type k = 0, k2 = 0; k < size; ++ k, k2 += s2)
1202                     t += data1 [k] * data2 [k2];
1203             } else {
1204                 for (size_type k = 0, k1 = 0, k2 = 0; k < size; ++ k, k1 += s1, k2 += s2)
1205                     t += data1 [k1] * data2 [k2];
1206             }
1207             return t;
1208 #elif defined(BOOST_UBLAS_HAVE_BINDINGS)
1209             return boost::numeric::bindings::atlas::dot (c1 ().row (i), c2 ().column (j));
1210 #else
1211             boost::ignore_unused(j);
1212             return apply (static_cast<const matrix_expression<C1> > (c1), static_cast<const matrix_expression<C2> > (c2, i));
1213 #endif
1214         }
1215         template<class E1, class E2>
1216         static BOOST_UBLAS_INLINE
1217         result_type apply (const matrix_expression<E1> &e1,
1218                            const matrix_expression<E2> &e2,
1219                            size_type i, size_type j) {
1220             size_type size = BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size1 ());
1221             result_type t = result_type (0);
1222 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
1223             for (size_type k = 0; k < size; ++ k)
1224                 t += e1 () (i, k) * e2 () (k, j);
1225 #else
1226             size_type k (0);
1227             DD (size, 4, r, (t += e1 () (i, k) * e2 () (k, j), ++ k));
1228 #endif
1229             return t;
1230         }
1231         // Dense case
1232         template<class I1, class I2>
1233         static BOOST_UBLAS_INLINE
1234         result_type apply (difference_type size, I1 it1, I2 it2) {
1235             result_type t = result_type (0);
1236 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
1237             while (-- size >= 0)
1238                 t += *it1 * *it2, ++ it1, ++ it2;
1239 #else
1240             DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2));
1241 #endif
1242             return t;
1243         }
1244         // Packed case
1245         template<class I1, class I2>
1246         static BOOST_UBLAS_INLINE
1247         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, packed_random_access_iterator_tag) {
1248             result_type t = result_type (0);
1249             difference_type it1_size (it1_end - it1);
1250             difference_type it2_size (it2_end - it2);
1251             difference_type diff (0);
1252             if (it1_size > 0 && it2_size > 0)
1253                 diff = it2.index1 () - it1.index2 ();
1254             if (diff != 0) {
1255                 difference_type size = (std::min) (diff, it1_size);
1256                 if (size > 0) {
1257                     it1 += size;
1258                     it1_size -= size;
1259                     diff -= size;
1260                 }
1261                 size = (std::min) (- diff, it2_size);
1262                 if (size > 0) {
1263                     it2 += size;
1264                     it2_size -= size;
1265                     diff += size;
1266                 }
1267             }
1268             difference_type size ((std::min) (it1_size, it2_size));
1269             while (-- size >= 0)
1270                 t += *it1 * *it2, ++ it1, ++ it2;
1271             return t;
1272         }
1273         // Sparse case
1274         template<class I1, class I2>
1275         static BOOST_UBLAS_INLINE
1276         result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) {
1277             result_type t = result_type (0);
1278             if (it1 != it1_end && it2 != it2_end) {
1279                 size_type it1_index = it1.index2 (), it2_index = it2.index1 ();
1280                 for (;;) {
1281                     difference_type compare = difference_type (it1_index - it2_index);
1282                     if (compare == 0) {
1283                         t += *it1 * *it2, ++ it1, ++ it2;
1284                         if (it1 != it1_end && it2 != it2_end) {
1285                             it1_index = it1.index2 ();
1286                             it2_index = it2.index1 ();
1287                         } else
1288                             break;
1289                     } else if (compare < 0) {
1290                         increment (it1, it1_end, - compare);
1291                         if (it1 != it1_end)
1292                             it1_index = it1.index2 ();
1293                         else
1294                             break;
1295                     } else if (compare > 0) {
1296                         increment (it2, it2_end, compare);
1297                         if (it2 != it2_end)
1298                             it2_index = it2.index1 ();
1299                         else
1300                             break;
1301                     }
1302                 }
1303             }
1304             return t;
1305         }
1306     };
1307 
1308     // Unary returning scalar norm
1309     template<class M>
1310     struct matrix_scalar_real_unary_functor {
1311         typedef typename M::value_type value_type;
1312         typedef typename type_traits<value_type>::real_type real_type;
1313         typedef real_type result_type;
1314     };
1315 
1316     template<class M>
1317     struct matrix_norm_1:
1318         public matrix_scalar_real_unary_functor<M> {
1319         typedef typename matrix_scalar_real_unary_functor<M>::value_type value_type;
1320         typedef typename matrix_scalar_real_unary_functor<M>::real_type real_type;
1321         typedef typename matrix_scalar_real_unary_functor<M>::result_type result_type;
1322 
1323         template<class E>
1324         static BOOST_UBLAS_INLINE
1325         result_type apply (const matrix_expression<E> &e) {
1326             real_type t = real_type ();
1327             typedef typename E::size_type matrix_size_type;
1328             matrix_size_type size2 (e ().size2 ());
1329             for (matrix_size_type j = 0; j < size2; ++ j) {
1330                 real_type u = real_type ();
1331                 matrix_size_type size1 (e ().size1 ());
1332                 for (matrix_size_type i = 0; i < size1; ++ i) {
1333                     real_type v (type_traits<value_type>::norm_1 (e () (i, j)));
1334                     u += v;
1335                 }
1336                 if (u > t)
1337                     t = u;
1338             }
1339             return t; 
1340         }
1341     };
1342 
1343     template<class M>
1344     struct matrix_norm_frobenius:
1345         public matrix_scalar_real_unary_functor<M> {
1346         typedef typename matrix_scalar_real_unary_functor<M>::value_type value_type;
1347         typedef typename matrix_scalar_real_unary_functor<M>::real_type real_type;
1348         typedef typename matrix_scalar_real_unary_functor<M>::result_type result_type;
1349 
1350         template<class E>
1351         static BOOST_UBLAS_INLINE
1352         result_type apply (const matrix_expression<E> &e) { 
1353             real_type t = real_type ();
1354             typedef typename E::size_type matrix_size_type;
1355             matrix_size_type size1 (e ().size1 ());
1356             for (matrix_size_type i = 0; i < size1; ++ i) {
1357                 matrix_size_type size2 (e ().size2 ());
1358                 for (matrix_size_type j = 0; j < size2; ++ j) {
1359                     real_type u (type_traits<value_type>::norm_2 (e () (i, j)));
1360                     t +=  u * u;
1361                 }
1362             }
1363             return type_traits<real_type>::type_sqrt (t); 
1364         }
1365     };
1366 
1367     template<class M>
1368     struct matrix_norm_inf: 
1369         public matrix_scalar_real_unary_functor<M> {
1370         typedef typename matrix_scalar_real_unary_functor<M>::value_type value_type;
1371         typedef typename matrix_scalar_real_unary_functor<M>::real_type real_type;
1372         typedef typename matrix_scalar_real_unary_functor<M>::result_type result_type;
1373 
1374         template<class E>
1375         static BOOST_UBLAS_INLINE
1376         result_type apply (const matrix_expression<E> &e) {
1377             real_type t = real_type ();
1378             typedef typename E::size_type matrix_size_type;
1379             matrix_size_type size1 (e ().size1 ());
1380             for (matrix_size_type i = 0; i < size1; ++ i) {
1381                 real_type u = real_type ();
1382                 matrix_size_type size2 (e ().size2 ());
1383                 for (matrix_size_type j = 0; j < size2; ++ j) {
1384                     real_type v (type_traits<value_type>::norm_inf (e () (i, j)));
1385                     u += v;
1386                 }
1387                 if (u > t) 
1388                     t = u;  
1389             }
1390             return t; 
1391         }
1392     };
1393 
1394     // forward declaration
1395     template <class Z, class D> struct basic_column_major;
1396 
1397     // This functor defines storage layout and it's properties
1398     // matrix (i,j) -> storage [i * size_i + j]
1399     template <class Z, class D>
1400     struct basic_row_major {
1401         typedef Z size_type;
1402         typedef D difference_type;
1403         typedef row_major_tag orientation_category;
1404         typedef basic_column_major<Z,D> transposed_layout;
1405 
1406         static
1407         BOOST_UBLAS_INLINE
1408         size_type storage_size (size_type size_i, size_type size_j) {
1409             // Guard against size_type overflow
1410             BOOST_UBLAS_CHECK (size_j == 0 || size_i <= (std::numeric_limits<size_type>::max) () / size_j, bad_size ());
1411             return size_i * size_j;
1412         }
1413 
1414         // Indexing conversion to storage element
1415         static
1416         BOOST_UBLAS_INLINE
1417         size_type element (size_type i, size_type size_i, size_type j, size_type size_j) {
1418             BOOST_UBLAS_CHECK (i < size_i, bad_index ());
1419             BOOST_UBLAS_CHECK (j < size_j, bad_index ());
1420             detail::ignore_unused_variable_warning(size_i);
1421             // Guard against size_type overflow
1422             BOOST_UBLAS_CHECK (i <= ((std::numeric_limits<size_type>::max) () - j) / size_j, bad_index ());
1423             return i * size_j + j;
1424         }
1425         static
1426         BOOST_UBLAS_INLINE
1427         size_type address (size_type i, size_type size_i, size_type j, size_type size_j) {
1428             BOOST_UBLAS_CHECK (i <= size_i, bad_index ());
1429             BOOST_UBLAS_CHECK (j <= size_j, bad_index ());
1430             // Guard against size_type overflow - address may be size_j past end of storage
1431             BOOST_UBLAS_CHECK (size_j == 0 || i <= ((std::numeric_limits<size_type>::max) () - j) / size_j, bad_index ());
1432             detail::ignore_unused_variable_warning(size_i);
1433             return i * size_j + j;
1434         }
1435 
1436         // Storage element to index conversion
1437         static
1438         BOOST_UBLAS_INLINE
1439         difference_type distance_i (difference_type k, size_type /* size_i */, size_type size_j) {
1440             return size_j != 0 ? k / size_j : 0;
1441         }
1442         static
1443         BOOST_UBLAS_INLINE
1444         difference_type distance_j (difference_type k, size_type /* size_i */, size_type /* size_j */) {
1445             return k;
1446         }
1447         static
1448         BOOST_UBLAS_INLINE
1449         size_type index_i (difference_type k, size_type /* size_i */, size_type size_j) {
1450             return size_j != 0 ? k / size_j : 0;
1451         }
1452         static
1453         BOOST_UBLAS_INLINE
1454         size_type index_j (difference_type k, size_type /* size_i */, size_type size_j) {
1455             return size_j != 0 ? k % size_j : 0;
1456         }
1457         static
1458         BOOST_UBLAS_INLINE
1459         bool fast_i () {
1460             return false;
1461         }
1462         static
1463         BOOST_UBLAS_INLINE
1464         bool fast_j () {
1465             return true;
1466         }
1467 
1468         // Iterating storage elements
1469         template<class I>
1470         static
1471         BOOST_UBLAS_INLINE
1472         void increment_i (I &it, size_type /* size_i */, size_type size_j) {
1473             it += size_j;
1474         }
1475         template<class I>
1476         static
1477         BOOST_UBLAS_INLINE
1478         void increment_i (I &it, difference_type n, size_type /* size_i */, size_type size_j) {
1479             it += n * size_j;
1480         }
1481         template<class I>
1482         static
1483         BOOST_UBLAS_INLINE
1484         void decrement_i (I &it, size_type /* size_i */, size_type size_j) {
1485             it -= size_j;
1486         }
1487         template<class I>
1488         static
1489         BOOST_UBLAS_INLINE
1490         void decrement_i (I &it, difference_type n, size_type /* size_i */, size_type size_j) {
1491             it -= n * size_j;
1492         }
1493         template<class I>
1494         static
1495         BOOST_UBLAS_INLINE
1496         void increment_j (I &it, size_type /* size_i */, size_type /* size_j */) {
1497             ++ it;
1498         }
1499         template<class I>
1500         static
1501         BOOST_UBLAS_INLINE
1502         void increment_j (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) {
1503             it += n;
1504         }
1505         template<class I>
1506         static
1507         BOOST_UBLAS_INLINE
1508         void decrement_j (I &it, size_type /* size_i */, size_type /* size_j */) {
1509             -- it;
1510         }
1511         template<class I>
1512         static
1513         BOOST_UBLAS_INLINE
1514         void decrement_j (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) {
1515             it -= n;
1516         }
1517 
1518         // Triangular access
1519         static
1520         BOOST_UBLAS_INLINE
1521         size_type triangular_size (size_type size_i, size_type size_j) {
1522             size_type size = (std::max) (size_i, size_j);
1523             // Guard against size_type overflow - simplified
1524             BOOST_UBLAS_CHECK (size == 0 || size / 2 < (std::numeric_limits<size_type>::max) () / size /* +1/2 */, bad_size ());
1525             return ((size + 1) * size) / 2;
1526         }
1527         static
1528         BOOST_UBLAS_INLINE
1529         size_type lower_element (size_type i, size_type size_i, size_type j, size_type size_j) {
1530             BOOST_UBLAS_CHECK (i < size_i, bad_index ());
1531             BOOST_UBLAS_CHECK (j < size_j, bad_index ());
1532             BOOST_UBLAS_CHECK (i >= j, bad_index ());
1533             detail::ignore_unused_variable_warning(size_i);
1534             detail::ignore_unused_variable_warning(size_j);
1535             // FIXME size_type overflow
1536             // sigma_i (i + 1) = (i + 1) * i / 2
1537             // i = 0 1 2 3, sigma = 0 1 3 6
1538             return ((i + 1) * i) / 2 + j;
1539         }
1540         static
1541         BOOST_UBLAS_INLINE
1542         size_type upper_element (size_type i, size_type size_i, size_type j, size_type size_j) {
1543             BOOST_UBLAS_CHECK (i < size_i, bad_index ());
1544             BOOST_UBLAS_CHECK (j < size_j, bad_index ());
1545             BOOST_UBLAS_CHECK (i <= j, bad_index ());
1546             // FIXME size_type overflow
1547             // sigma_i (size - i) = size * i - i * (i - 1) / 2
1548             // i = 0 1 2 3, sigma = 0 4 7 9
1549             return (i * (2 * (std::max) (size_i, size_j) - i + 1)) / 2 + j - i;
1550         }
1551 
1552         // Major and minor indices
1553         static
1554         BOOST_UBLAS_INLINE
1555         size_type index_M (size_type index1, size_type /* index2 */) {
1556             return index1;
1557         }
1558         static
1559         BOOST_UBLAS_INLINE
1560         size_type index_m (size_type /* index1 */, size_type index2) {
1561             return index2;
1562         }
1563         static
1564         BOOST_UBLAS_INLINE
1565         size_type size_M (size_type size_i, size_type /* size_j */) {
1566             return size_i;
1567         }
1568         static
1569         BOOST_UBLAS_INLINE
1570         size_type size_m (size_type /* size_i */, size_type size_j) {
1571             return size_j;
1572         }
1573     };
1574 
1575     // This functor defines storage layout and it's properties
1576     // matrix (i,j) -> storage [i + j * size_i]
1577     template <class Z, class D>
1578     struct basic_column_major {
1579         typedef Z size_type;
1580         typedef D difference_type;
1581         typedef column_major_tag orientation_category;
1582         typedef basic_row_major<Z,D> transposed_layout;
1583 
1584         static
1585         BOOST_UBLAS_INLINE
1586         size_type storage_size (size_type size_i, size_type size_j) {
1587             // Guard against size_type overflow
1588             BOOST_UBLAS_CHECK (size_i == 0 || size_j <= (std::numeric_limits<size_type>::max) () / size_i, bad_size ());
1589             return size_i * size_j;
1590         }
1591 
1592         // Indexing conversion to storage element
1593         static
1594         BOOST_UBLAS_INLINE
1595         size_type element (size_type i, size_type size_i, size_type j, size_type size_j) {
1596             BOOST_UBLAS_CHECK (i < size_i, bad_index ());
1597             BOOST_UBLAS_CHECK (j < size_j, bad_index ());
1598             detail::ignore_unused_variable_warning(size_j);
1599             // Guard against size_type overflow
1600             BOOST_UBLAS_CHECK (j <= ((std::numeric_limits<size_type>::max) () - i) / size_i, bad_index ());
1601             return i + j * size_i;
1602         }
1603         static
1604         BOOST_UBLAS_INLINE
1605         size_type address (size_type i, size_type size_i, size_type j, size_type size_j) {
1606             BOOST_UBLAS_CHECK (i <= size_i, bad_index ());
1607             BOOST_UBLAS_CHECK (j <= size_j, bad_index ());
1608             detail::ignore_unused_variable_warning(size_j);
1609             // Guard against size_type overflow - address may be size_i past end of storage
1610             BOOST_UBLAS_CHECK (size_i == 0 || j <= ((std::numeric_limits<size_type>::max) () - i) / size_i, bad_index ());
1611             return i + j * size_i;
1612         }
1613 
1614         // Storage element to index conversion
1615         static
1616         BOOST_UBLAS_INLINE
1617         difference_type distance_i (difference_type k, size_type /* size_i */, size_type /* size_j */) {
1618             return k;
1619         }
1620         static
1621         BOOST_UBLAS_INLINE
1622         difference_type distance_j (difference_type k, size_type size_i, size_type /* size_j */) {
1623             return size_i != 0 ? k / size_i : 0;
1624         }
1625         static
1626         BOOST_UBLAS_INLINE
1627         size_type index_i (difference_type k, size_type size_i, size_type /* size_j */) {
1628             return size_i != 0 ? k % size_i : 0;
1629         }
1630         static
1631         BOOST_UBLAS_INLINE
1632         size_type index_j (difference_type k, size_type size_i, size_type /* size_j */) {
1633             return size_i != 0 ? k / size_i : 0;
1634         }
1635         static
1636         BOOST_UBLAS_INLINE
1637         bool fast_i () {
1638             return true;
1639         }
1640         static
1641         BOOST_UBLAS_INLINE
1642         bool fast_j () {
1643             return false;
1644         }
1645 
1646         // Iterating
1647         template<class I>
1648         static
1649         BOOST_UBLAS_INLINE
1650         void increment_i (I &it, size_type /* size_i */, size_type /* size_j */) {
1651             ++ it;
1652         }
1653         template<class I>
1654         static
1655         BOOST_UBLAS_INLINE
1656         void increment_i (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) {
1657             it += n;
1658         }
1659         template<class I>
1660         static
1661         BOOST_UBLAS_INLINE
1662         void decrement_i (I &it, size_type /* size_i */, size_type /* size_j */) {
1663             -- it;
1664         }
1665         template<class I>
1666         static
1667         BOOST_UBLAS_INLINE
1668         void decrement_i (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) {
1669             it -= n;
1670         }
1671         template<class I>
1672         static
1673         BOOST_UBLAS_INLINE
1674         void increment_j (I &it, size_type size_i, size_type /* size_j */) {
1675             it += size_i;
1676         }
1677         template<class I>
1678         static
1679         BOOST_UBLAS_INLINE
1680         void increment_j (I &it, difference_type n, size_type size_i, size_type /* size_j */) {
1681             it += n * size_i;
1682         }
1683         template<class I>
1684         static
1685         BOOST_UBLAS_INLINE
1686         void decrement_j (I &it, size_type size_i, size_type /* size_j */) {
1687             it -= size_i;
1688         }
1689         template<class I>
1690         static
1691         BOOST_UBLAS_INLINE
1692         void decrement_j (I &it, difference_type n, size_type size_i, size_type /* size_j */) {
1693             it -= n* size_i;
1694         }
1695 
1696         // Triangular access
1697         static
1698         BOOST_UBLAS_INLINE
1699         size_type triangular_size (size_type size_i, size_type size_j) {
1700             size_type size = (std::max) (size_i, size_j);
1701             // Guard against size_type overflow - simplified
1702             BOOST_UBLAS_CHECK (size == 0 || size / 2 < (std::numeric_limits<size_type>::max) () / size /* +1/2 */, bad_size ());
1703             return ((size + 1) * size) / 2;
1704         }
1705         static
1706         BOOST_UBLAS_INLINE
1707         size_type lower_element (size_type i, size_type size_i, size_type j, size_type size_j) {
1708             BOOST_UBLAS_CHECK (i < size_i, bad_index ());
1709             BOOST_UBLAS_CHECK (j < size_j, bad_index ());
1710             BOOST_UBLAS_CHECK (i >= j, bad_index ());
1711             // FIXME size_type overflow
1712             // sigma_j (size - j) = size * j - j * (j - 1) / 2
1713             // j = 0 1 2 3, sigma = 0 4 7 9
1714             return i - j + (j * (2 * (std::max) (size_i, size_j) - j + 1)) / 2;
1715         }
1716         static
1717         BOOST_UBLAS_INLINE
1718         size_type upper_element (size_type i, size_type size_i, size_type j, size_type size_j) {
1719             BOOST_UBLAS_CHECK (i < size_i, bad_index ());
1720             BOOST_UBLAS_CHECK (j < size_j, bad_index ());
1721             BOOST_UBLAS_CHECK (i <= j, bad_index ());
1722             boost::ignore_unused(size_i, size_j);
1723             // FIXME size_type overflow
1724             // sigma_j (j + 1) = (j + 1) * j / 2
1725             // j = 0 1 2 3, sigma = 0 1 3 6
1726             return i + ((j + 1) * j) / 2;
1727         }
1728 
1729         // Major and minor indices
1730         static
1731         BOOST_UBLAS_INLINE
1732         size_type index_M (size_type /* index1 */, size_type index2) {
1733             return index2;
1734         }
1735         static
1736         BOOST_UBLAS_INLINE
1737         size_type index_m (size_type index1, size_type /* index2 */) {
1738             return index1;
1739         }
1740         static
1741         BOOST_UBLAS_INLINE
1742         size_type size_M (size_type /* size_i */, size_type size_j) {
1743             return size_j;
1744         }
1745         static
1746         BOOST_UBLAS_INLINE
1747         size_type size_m (size_type size_i, size_type /* size_j */) {
1748             return size_i;
1749         }
1750     };
1751 
1752 
1753     template <class Z>
1754     struct basic_full {
1755         typedef Z size_type;
1756 
1757         template<class L>
1758         static
1759         BOOST_UBLAS_INLINE
1760         size_type packed_size (L, size_type size_i, size_type size_j) {
1761             return L::storage_size (size_i, size_j);
1762         }
1763 
1764         static
1765         BOOST_UBLAS_INLINE
1766         bool zero (size_type /* i */, size_type /* j */) {
1767             return false;
1768         }
1769         static
1770         BOOST_UBLAS_INLINE
1771         bool one (size_type /* i */, size_type /* j */) {
1772             return false;
1773         }
1774         static
1775         BOOST_UBLAS_INLINE
1776         bool other (size_type /* i */, size_type /* j */) {
1777             return true;
1778         }
1779         // FIXME: this should not be used at all
1780         static
1781         BOOST_UBLAS_INLINE
1782         size_type restrict1 (size_type i, size_type /* j */) {
1783             return i;
1784         }
1785         static
1786         BOOST_UBLAS_INLINE
1787         size_type restrict2 (size_type /* i */, size_type j) {
1788             return j;
1789         }
1790         static
1791         BOOST_UBLAS_INLINE
1792         size_type mutable_restrict1 (size_type i, size_type /* j */) {
1793             return i;
1794         }
1795         static
1796         BOOST_UBLAS_INLINE
1797         size_type mutable_restrict2 (size_type /* i */, size_type j) {
1798             return j;
1799         }
1800     };
1801 
1802     namespace detail {
1803         template < class L >
1804         struct transposed_structure {
1805             typedef typename L::size_type size_type;
1806 
1807             template<class LAYOUT>
1808             static
1809             BOOST_UBLAS_INLINE
1810             size_type packed_size (LAYOUT l, size_type size_i, size_type size_j) {
1811                 return L::packed_size(l, size_j, size_i);
1812             }
1813 
1814             static
1815             BOOST_UBLAS_INLINE
1816             bool zero (size_type i, size_type j) {
1817                 return L::zero(j, i);
1818             }
1819             static
1820             BOOST_UBLAS_INLINE
1821             bool one (size_type i, size_type j) {
1822                 return L::one(j, i);
1823             }
1824             static
1825             BOOST_UBLAS_INLINE
1826             bool other (size_type i, size_type j) {
1827                 return L::other(j, i);
1828             }
1829             template<class LAYOUT>
1830             static
1831             BOOST_UBLAS_INLINE
1832             size_type element (LAYOUT /* l */, size_type i, size_type size_i, size_type j, size_type size_j) {
1833                 return L::element(typename LAYOUT::transposed_layout(), j, size_j, i, size_i);
1834             }
1835 
1836             static
1837             BOOST_UBLAS_INLINE
1838             size_type restrict1 (size_type i, size_type j, size_type size1, size_type size2) {
1839                 return L::restrict2(j, i, size2, size1);
1840             }
1841             static
1842             BOOST_UBLAS_INLINE
1843             size_type restrict2 (size_type i, size_type j, size_type size1, size_type size2) {
1844                 return L::restrict1(j, i, size2, size1);
1845             }
1846             static
1847             BOOST_UBLAS_INLINE
1848             size_type mutable_restrict1 (size_type i, size_type j, size_type size1, size_type size2) {
1849                 return L::mutable_restrict2(j, i, size2, size1);
1850             }
1851             static
1852             BOOST_UBLAS_INLINE
1853             size_type mutable_restrict2 (size_type i, size_type j, size_type size1, size_type size2) {
1854                 return L::mutable_restrict1(j, i, size2, size1);
1855             }
1856 
1857             static
1858             BOOST_UBLAS_INLINE
1859             size_type global_restrict1 (size_type index1, size_type size1, size_type index2, size_type size2) {
1860                 return L::global_restrict2(index2, size2, index1, size1);
1861             }
1862             static
1863             BOOST_UBLAS_INLINE
1864             size_type global_restrict2 (size_type index1, size_type size1, size_type index2, size_type size2) {
1865                 return L::global_restrict1(index2, size2, index1, size1);
1866             }
1867             static
1868             BOOST_UBLAS_INLINE
1869             size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type index2, size_type size2) {
1870                 return L::global_mutable_restrict2(index2, size2, index1, size1);
1871             }
1872             static
1873             BOOST_UBLAS_INLINE
1874             size_type global_mutable_restrict2 (size_type index1, size_type size1, size_type index2, size_type size2) {
1875                 return L::global_mutable_restrict1(index2, size2, index1, size1);
1876             }
1877         };
1878     }
1879 
1880     template <class Z>
1881     struct basic_lower {
1882         typedef Z size_type;
1883         typedef lower_tag triangular_type;
1884 
1885         template<class L>
1886         static
1887         BOOST_UBLAS_INLINE
1888         size_type packed_size (L, size_type size_i, size_type size_j) {
1889             return L::triangular_size (size_i, size_j);
1890         }
1891 
1892         static
1893         BOOST_UBLAS_INLINE
1894         bool zero (size_type i, size_type j) {
1895             return j > i;
1896         }
1897         static
1898         BOOST_UBLAS_INLINE
1899         bool one (size_type /* i */, size_type /* j */) {
1900             return false;
1901         }
1902         static
1903         BOOST_UBLAS_INLINE
1904         bool other (size_type i, size_type j) {
1905             return j <= i;
1906         }
1907         template<class L>
1908         static
1909         BOOST_UBLAS_INLINE
1910         size_type element (L, size_type i, size_type size_i, size_type j, size_type size_j) {
1911             return L::lower_element (i, size_i, j, size_j);
1912         }
1913 
1914         // return nearest valid index in column j
1915         static
1916         BOOST_UBLAS_INLINE
1917         size_type restrict1 (size_type i, size_type j, size_type size1, size_type /* size2 */) {
1918             return (std::max)(j, (std::min) (size1, i));
1919         }
1920         // return nearest valid index in row i
1921         static
1922         BOOST_UBLAS_INLINE
1923         size_type restrict2 (size_type i, size_type j, size_type /* size1 */, size_type /* size2 */) {
1924             return (std::max)(size_type(0), (std::min) (i+1, j));
1925         }
1926         // return nearest valid mutable index in column j
1927         static
1928         BOOST_UBLAS_INLINE
1929         size_type mutable_restrict1 (size_type i, size_type j, size_type size1, size_type /* size2 */) {
1930             return (std::max)(j, (std::min) (size1, i));
1931         }
1932         // return nearest valid mutable index in row i
1933         static
1934         BOOST_UBLAS_INLINE
1935         size_type mutable_restrict2 (size_type i, size_type j, size_type /* size1 */, size_type /* size2 */) {
1936             return (std::max)(size_type(0), (std::min) (i+1, j));
1937         }
1938 
1939         // return an index between the first and (1+last) filled row
1940         static
1941         BOOST_UBLAS_INLINE
1942         size_type global_restrict1 (size_type index1, size_type size1, size_type /* index2 */, size_type /* size2 */) {
1943             return (std::max)(size_type(0), (std::min)(size1, index1) );
1944         }
1945         // return an index between the first and (1+last) filled column
1946         static
1947         BOOST_UBLAS_INLINE
1948         size_type global_restrict2 (size_type /* index1 */, size_type /* size1 */, size_type index2, size_type size2) {
1949             return (std::max)(size_type(0), (std::min)(size2, index2) );
1950         }
1951 
1952         // return an index between the first and (1+last) filled mutable row
1953         static
1954         BOOST_UBLAS_INLINE
1955         size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type /* index2 */, size_type /* size2 */) {
1956             return (std::max)(size_type(0), (std::min)(size1, index1) );
1957         }
1958         // return an index between the first and (1+last) filled mutable column
1959         static
1960         BOOST_UBLAS_INLINE
1961         size_type global_mutable_restrict2 (size_type /* index1 */, size_type /* size1 */, size_type index2, size_type size2) {
1962             return (std::max)(size_type(0), (std::min)(size2, index2) );
1963         }
1964     };
1965 
1966     // the first row only contains a single 1. Thus it is not stored.
1967     template <class Z>
1968     struct basic_unit_lower : public basic_lower<Z> {
1969         typedef Z size_type;
1970         typedef unit_lower_tag triangular_type;
1971 
1972         template<class L>
1973         static
1974         BOOST_UBLAS_INLINE
1975         size_type packed_size (L, size_type size_i, size_type size_j) {
1976             // Zero size strict triangles are bad at this point
1977             BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0, bad_index ());
1978             return L::triangular_size (size_i - 1, size_j - 1);
1979         }
1980 
1981         static
1982         BOOST_UBLAS_INLINE
1983         bool one (size_type i, size_type j) {
1984             return j == i;
1985         }
1986         static
1987         BOOST_UBLAS_INLINE
1988         bool other (size_type i, size_type j) {
1989             return j < i;
1990         }
1991         template<class L>
1992         static
1993         BOOST_UBLAS_INLINE
1994         size_type element (L, size_type i, size_type size_i, size_type j, size_type size_j) {
1995             // Zero size strict triangles are bad at this point
1996             BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0 && i != 0, bad_index ());
1997             return L::lower_element (i-1, size_i - 1, j, size_j - 1);
1998         }
1999 
2000         static
2001         BOOST_UBLAS_INLINE
2002         size_type mutable_restrict1 (size_type i, size_type j, size_type size1, size_type /* size2 */) {
2003             return (std::max)(j+1, (std::min) (size1, i));
2004         }
2005         static
2006         BOOST_UBLAS_INLINE
2007         size_type mutable_restrict2 (size_type i, size_type j, size_type /* size1 */, size_type /* size2 */) {
2008             return (std::max)(size_type(0), (std::min) (i, j));
2009         }
2010 
2011         // return an index between the first and (1+last) filled mutable row
2012         static
2013         BOOST_UBLAS_INLINE
2014         size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type /* index2 */, size_type /* size2 */) {
2015             return (std::max)(size_type(1), (std::min)(size1, index1) );
2016         }
2017         // return an index between the first and (1+last) filled mutable column
2018         static
2019         BOOST_UBLAS_INLINE
2020         size_type global_mutable_restrict2 (size_type /* index1 */, size_type /* size1 */, size_type index2, size_type size2) {
2021             BOOST_UBLAS_CHECK( size2 >= 1 , external_logic() );
2022             return (std::max)(size_type(0), (std::min)(size2-1, index2) );
2023         }
2024     };
2025 
2026     // the first row only contains no element. Thus it is not stored.
2027     template <class Z>
2028     struct basic_strict_lower : public basic_unit_lower<Z> {
2029         typedef Z size_type;
2030         typedef strict_lower_tag triangular_type;
2031 
2032         template<class L>
2033         static
2034         BOOST_UBLAS_INLINE
2035         size_type packed_size (L, size_type size_i, size_type size_j) {
2036             // Zero size strict triangles are bad at this point
2037             BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0, bad_index ());
2038             return L::triangular_size (size_i - 1, size_j - 1);
2039         }
2040 
2041         static
2042         BOOST_UBLAS_INLINE
2043         bool zero (size_type i, size_type j) {
2044             return j >= i;
2045         }
2046         static
2047         BOOST_UBLAS_INLINE
2048         bool one (size_type /*i*/, size_type /*j*/) {
2049             return false;
2050         }
2051         static
2052         BOOST_UBLAS_INLINE
2053         bool other (size_type i, size_type j) {
2054             return j < i;
2055         }
2056         template<class L>
2057         static
2058         BOOST_UBLAS_INLINE
2059         size_type element (L, size_type i, size_type size_i, size_type j, size_type size_j) {
2060             // Zero size strict triangles are bad at this point
2061             BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0 && i != 0, bad_index ());
2062             return L::lower_element (i-1, size_i - 1, j, size_j - 1);
2063         }
2064 
2065         static
2066         BOOST_UBLAS_INLINE
2067         size_type restrict1 (size_type i, size_type j, size_type size1, size_type size2) {
2068             return basic_unit_lower<Z>::mutable_restrict1(i, j, size1, size2);
2069         }
2070         static
2071         BOOST_UBLAS_INLINE
2072         size_type restrict2 (size_type i, size_type j, size_type size1, size_type size2) {
2073             return basic_unit_lower<Z>::mutable_restrict2(i, j, size1, size2);
2074         }
2075 
2076         // return an index between the first and (1+last) filled row
2077         static
2078         BOOST_UBLAS_INLINE
2079         size_type global_restrict1 (size_type index1, size_type size1, size_type index2, size_type size2) {
2080             return basic_unit_lower<Z>::global_mutable_restrict1(index1, size1, index2, size2);
2081         }
2082         // return an index between the first and (1+last) filled column
2083         static
2084         BOOST_UBLAS_INLINE
2085         size_type global_restrict2 (size_type index1, size_type size1, size_type index2, size_type size2) {
2086             return basic_unit_lower<Z>::global_mutable_restrict2(index1, size1, index2, size2);
2087         }
2088     };
2089 
2090 
2091     template <class Z>
2092     struct basic_upper : public detail::transposed_structure<basic_lower<Z> >
2093     { 
2094         typedef upper_tag triangular_type;
2095     };
2096 
2097     template <class Z>
2098     struct basic_unit_upper : public detail::transposed_structure<basic_unit_lower<Z> >
2099     { 
2100         typedef unit_upper_tag triangular_type;
2101     };
2102 
2103     template <class Z>
2104     struct basic_strict_upper : public detail::transposed_structure<basic_strict_lower<Z> >
2105     { 
2106         typedef strict_upper_tag triangular_type;
2107     };
2108 
2109 
2110 }}}
2111 
2112 #endif