File indexing completed on 2025-01-18 09:43:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
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
0044
0045
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
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
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
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
0330
0331
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
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
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
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
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
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 () == 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
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
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
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
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
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
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
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
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
0651 template<class D, class I>
0652 static BOOST_UBLAS_INLINE
0653 result_type apply (D size, I it) {
0654
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
0668 template<class I>
0669 static BOOST_UBLAS_INLINE
0670 result_type apply (I it, const I &it_end) {
0671
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
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
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
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
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
0818
0819
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
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
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
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
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 &,
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
0974 template<class I1, class I2>
0975 static BOOST_UBLAS_INLINE
0976 result_type apply (I1 it1, const I1 &, 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
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
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
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
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
1130 template<class I1, class I2>
1131 static BOOST_UBLAS_INLINE
1132 result_type apply (I1 it1, const I1 &, 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
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 &,
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
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
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
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
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
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
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
1395 template <class Z, class D> struct basic_column_major;
1396
1397
1398
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
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
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
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
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
1437 static
1438 BOOST_UBLAS_INLINE
1439 difference_type distance_i (difference_type k, size_type , 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_type ) {
1445 return k;
1446 }
1447 static
1448 BOOST_UBLAS_INLINE
1449 size_type index_i (difference_type k, size_type , 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_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
1469 template<class I>
1470 static
1471 BOOST_UBLAS_INLINE
1472 void increment_i (I &it, size_type , 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_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_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_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_type ) {
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_type ) {
1503 it += n;
1504 }
1505 template<class I>
1506 static
1507 BOOST_UBLAS_INLINE
1508 void decrement_j (I &it, size_type , size_type ) {
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_type ) {
1515 it -= n;
1516 }
1517
1518
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
1524 BOOST_UBLAS_CHECK (size == 0 || size / 2 < (std::numeric_limits<size_type>::max) () / size , 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
1536
1537
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
1547
1548
1549 return (i * (2 * (std::max) (size_i, size_j) - i + 1)) / 2 + j - i;
1550 }
1551
1552
1553 static
1554 BOOST_UBLAS_INLINE
1555 size_type index_M (size_type index1, size_type ) {
1556 return index1;
1557 }
1558 static
1559 BOOST_UBLAS_INLINE
1560 size_type index_m (size_type , size_type index2) {
1561 return index2;
1562 }
1563 static
1564 BOOST_UBLAS_INLINE
1565 size_type size_M (size_type size_i, size_type ) {
1566 return size_i;
1567 }
1568 static
1569 BOOST_UBLAS_INLINE
1570 size_type size_m (size_type , size_type size_j) {
1571 return size_j;
1572 }
1573 };
1574
1575
1576
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
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
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
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
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
1615 static
1616 BOOST_UBLAS_INLINE
1617 difference_type distance_i (difference_type k, size_type , size_type ) {
1618 return k;
1619 }
1620 static
1621 BOOST_UBLAS_INLINE
1622 difference_type distance_j (difference_type k, size_type size_i, size_type ) {
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 ) {
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 ) {
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
1647 template<class I>
1648 static
1649 BOOST_UBLAS_INLINE
1650 void increment_i (I &it, size_type , size_type ) {
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_type ) {
1657 it += n;
1658 }
1659 template<class I>
1660 static
1661 BOOST_UBLAS_INLINE
1662 void decrement_i (I &it, size_type , size_type ) {
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_type ) {
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 ) {
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 ) {
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 ) {
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 ) {
1693 it -= n* size_i;
1694 }
1695
1696
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
1702 BOOST_UBLAS_CHECK (size == 0 || size / 2 < (std::numeric_limits<size_type>::max) () / size , 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
1712
1713
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
1724
1725
1726 return i + ((j + 1) * j) / 2;
1727 }
1728
1729
1730 static
1731 BOOST_UBLAS_INLINE
1732 size_type index_M (size_type , size_type index2) {
1733 return index2;
1734 }
1735 static
1736 BOOST_UBLAS_INLINE
1737 size_type index_m (size_type index1, size_type ) {
1738 return index1;
1739 }
1740 static
1741 BOOST_UBLAS_INLINE
1742 size_type size_M (size_type , 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 ) {
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 , size_type ) {
1767 return false;
1768 }
1769 static
1770 BOOST_UBLAS_INLINE
1771 bool one (size_type , size_type ) {
1772 return false;
1773 }
1774 static
1775 BOOST_UBLAS_INLINE
1776 bool other (size_type , size_type ) {
1777 return true;
1778 }
1779
1780 static
1781 BOOST_UBLAS_INLINE
1782 size_type restrict1 (size_type i, size_type ) {
1783 return i;
1784 }
1785 static
1786 BOOST_UBLAS_INLINE
1787 size_type restrict2 (size_type , size_type j) {
1788 return j;
1789 }
1790 static
1791 BOOST_UBLAS_INLINE
1792 size_type mutable_restrict1 (size_type i, size_type ) {
1793 return i;
1794 }
1795 static
1796 BOOST_UBLAS_INLINE
1797 size_type mutable_restrict2 (size_type , 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 , 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 , size_type ) {
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
1915 static
1916 BOOST_UBLAS_INLINE
1917 size_type restrict1 (size_type i, size_type j, size_type size1, size_type ) {
1918 return (std::max)(j, (std::min) (size1, i));
1919 }
1920
1921 static
1922 BOOST_UBLAS_INLINE
1923 size_type restrict2 (size_type i, size_type j, size_type , size_type ) {
1924 return (std::max)(size_type(0), (std::min) (i+1, j));
1925 }
1926
1927 static
1928 BOOST_UBLAS_INLINE
1929 size_type mutable_restrict1 (size_type i, size_type j, size_type size1, size_type ) {
1930 return (std::max)(j, (std::min) (size1, i));
1931 }
1932
1933 static
1934 BOOST_UBLAS_INLINE
1935 size_type mutable_restrict2 (size_type i, size_type j, size_type , size_type ) {
1936 return (std::max)(size_type(0), (std::min) (i+1, j));
1937 }
1938
1939
1940 static
1941 BOOST_UBLAS_INLINE
1942 size_type global_restrict1 (size_type index1, size_type size1, size_type , size_type ) {
1943 return (std::max)(size_type(0), (std::min)(size1, index1) );
1944 }
1945
1946 static
1947 BOOST_UBLAS_INLINE
1948 size_type global_restrict2 (size_type , size_type , size_type index2, size_type size2) {
1949 return (std::max)(size_type(0), (std::min)(size2, index2) );
1950 }
1951
1952
1953 static
1954 BOOST_UBLAS_INLINE
1955 size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type , size_type ) {
1956 return (std::max)(size_type(0), (std::min)(size1, index1) );
1957 }
1958
1959 static
1960 BOOST_UBLAS_INLINE
1961 size_type global_mutable_restrict2 (size_type , size_type , size_type index2, size_type size2) {
1962 return (std::max)(size_type(0), (std::min)(size2, index2) );
1963 }
1964 };
1965
1966
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
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
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 ) {
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 , size_type ) {
2008 return (std::max)(size_type(0), (std::min) (i, j));
2009 }
2010
2011
2012 static
2013 BOOST_UBLAS_INLINE
2014 size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type , size_type ) {
2015 return (std::max)(size_type(1), (std::min)(size1, index1) );
2016 }
2017
2018 static
2019 BOOST_UBLAS_INLINE
2020 size_type global_mutable_restrict2 (size_type , size_type , 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
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
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 , size_type ) {
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
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
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
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