File indexing completed on 2025-01-18 09:43:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef _BOOST_UBLAS_VECTOR_ASSIGN_
0014 #define _BOOST_UBLAS_VECTOR_ASSIGN_
0015
0016 #include <boost/numeric/ublas/functional.hpp> // scalar_assign
0017
0018 #include <vector>
0019
0020
0021
0022 namespace boost { namespace numeric { namespace ublas {
0023 namespace detail {
0024
0025
0026
0027
0028
0029
0030 template<class E1, class E2, class S>
0031 BOOST_UBLAS_INLINE
0032 bool equals (const vector_expression<E1> &e1, const vector_expression<E2> &e2, S epsilon, S min_norm) {
0033 return norm_inf (e1 - e2) <= epsilon *
0034 std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
0035 }
0036
0037 template<class E1, class E2>
0038 BOOST_UBLAS_INLINE
0039 bool expression_type_check (const vector_expression<E1> &e1, const vector_expression<E2> &e2) {
0040 typedef typename type_traits<typename promote_traits<typename E1::value_type,
0041 typename E2::value_type>::promote_type>::real_type real_type;
0042 return equals (e1, e2, BOOST_UBLAS_TYPE_CHECK_EPSILON, BOOST_UBLAS_TYPE_CHECK_MIN);
0043 }
0044
0045
0046
0047 template<class V, class E>
0048
0049 void make_conformant (V &v, const vector_expression<E> &e) {
0050 BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
0051 typedef typename V::size_type size_type;
0052 typedef typename V::difference_type difference_type;
0053 typedef typename V::value_type value_type;
0054
0055 std::vector<size_type> index;
0056 typename V::iterator it (v.begin ());
0057 typename V::iterator it_end (v.end ());
0058 typename E::const_iterator ite (e ().begin ());
0059 typename E::const_iterator ite_end (e ().end ());
0060 if (it != it_end && ite != ite_end) {
0061 size_type it_index = it.index (), ite_index = ite.index ();
0062 for (;;) {
0063 difference_type compare = it_index - ite_index;
0064 if (compare == 0) {
0065 ++ it, ++ ite;
0066 if (it != it_end && ite != ite_end) {
0067 it_index = it.index ();
0068 ite_index = ite.index ();
0069 } else
0070 break;
0071 } else if (compare < 0) {
0072 increment (it, it_end, - compare);
0073 if (it != it_end)
0074 it_index = it.index ();
0075 else
0076 break;
0077 } else if (compare > 0) {
0078 if (*ite != value_type())
0079 index.push_back (ite.index ());
0080 ++ ite;
0081 if (ite != ite_end)
0082 ite_index = ite.index ();
0083 else
0084 break;
0085 }
0086 }
0087 }
0088
0089 while (ite != ite_end) {
0090 if (*ite != value_type())
0091 index.push_back (ite.index ());
0092 ++ ite;
0093 }
0094 for (size_type k = 0; k < index.size (); ++ k)
0095 v (index [k]) = value_type();
0096 }
0097
0098 }
0099
0100
0101
0102 template<template <class T1, class T2> class F, class V, class T>
0103
0104 void iterating_vector_assign_scalar (V &v, const T &t) {
0105 typedef F<typename V::iterator::reference, T> functor_type;
0106 typedef typename V::difference_type difference_type;
0107 difference_type size (v.size ());
0108 typename V::iterator it (v.begin ());
0109 BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
0110 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0111 while (-- size >= 0)
0112 functor_type::apply (*it, t), ++ it;
0113 #else
0114 DD (size, 4, r, (functor_type::apply (*it, t), ++ it));
0115 #endif
0116 }
0117
0118 template<template <class T1, class T2> class F, class V, class T>
0119
0120 void indexing_vector_assign_scalar (V &v, const T &t) {
0121 typedef F<typename V::reference, T> functor_type;
0122 typedef typename V::size_type size_type;
0123 size_type size (v.size ());
0124 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0125 for (size_type i = 0; i < size; ++ i)
0126 functor_type::apply (v (i), t);
0127 #else
0128 size_type i (0);
0129 DD (size, 4, r, (functor_type::apply (v (i), t), ++ i));
0130 #endif
0131 }
0132
0133
0134 template<template <class T1, class T2> class F, class V, class T>
0135
0136 void vector_assign_scalar (V &v, const T &t, dense_proxy_tag) {
0137 #ifdef BOOST_UBLAS_USE_INDEXING
0138 indexing_vector_assign_scalar<F> (v, t);
0139 #elif BOOST_UBLAS_USE_ITERATING
0140 iterating_vector_assign_scalar<F> (v, t);
0141 #else
0142 typedef typename V::size_type size_type;
0143 size_type size (v.size ());
0144 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
0145 iterating_vector_assign_scalar<F> (v, t);
0146 else
0147 indexing_vector_assign_scalar<F> (v, t);
0148 #endif
0149 }
0150
0151 template<template <class T1, class T2> class F, class V, class T>
0152
0153 void vector_assign_scalar (V &v, const T &t, packed_proxy_tag) {
0154 typedef F<typename V::iterator::reference, T> functor_type;
0155 typedef typename V::difference_type difference_type;
0156 typename V::iterator it (v.begin ());
0157 difference_type size (v.end () - it);
0158 while (-- size >= 0)
0159 functor_type::apply (*it, t), ++ it;
0160 }
0161
0162 template<template <class T1, class T2> class F, class V, class T>
0163
0164 void vector_assign_scalar (V &v, const T &t, sparse_proxy_tag) {
0165 typedef F<typename V::iterator::reference, T> functor_type;
0166 typename V::iterator it (v.begin ());
0167 typename V::iterator it_end (v.end ());
0168 while (it != it_end)
0169 functor_type::apply (*it, t), ++ it;
0170 }
0171
0172
0173 template<template <class T1, class T2> class F, class V, class T>
0174 BOOST_UBLAS_INLINE
0175 void vector_assign_scalar (V &v, const T &t) {
0176 typedef typename V::storage_category storage_category;
0177 vector_assign_scalar<F> (v, t, storage_category ());
0178 }
0179
0180 template<class SC, bool COMPUTED, class RI>
0181 struct vector_assign_traits {
0182 typedef SC storage_category;
0183 };
0184
0185 template<bool COMPUTED>
0186 struct vector_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag> {
0187 typedef packed_tag storage_category;
0188 };
0189 template<>
0190 struct vector_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag> {
0191 typedef sparse_tag storage_category;
0192 };
0193 template<>
0194 struct vector_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag> {
0195 typedef sparse_proxy_tag storage_category;
0196 };
0197
0198 template<bool COMPUTED>
0199 struct vector_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag> {
0200 typedef packed_proxy_tag storage_category;
0201 };
0202 template<>
0203 struct vector_assign_traits<dense_proxy_tag, false, sparse_bidirectional_iterator_tag> {
0204 typedef sparse_proxy_tag storage_category;
0205 };
0206 template<>
0207 struct vector_assign_traits<dense_proxy_tag, true, sparse_bidirectional_iterator_tag> {
0208 typedef sparse_proxy_tag storage_category;
0209 };
0210
0211 template<>
0212 struct vector_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag> {
0213 typedef sparse_tag storage_category;
0214 };
0215 template<>
0216 struct vector_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag> {
0217 typedef sparse_proxy_tag storage_category;
0218 };
0219
0220 template<bool COMPUTED>
0221 struct vector_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag> {
0222 typedef sparse_proxy_tag storage_category;
0223 };
0224
0225 template<>
0226 struct vector_assign_traits<sparse_tag, true, dense_random_access_iterator_tag> {
0227 typedef sparse_proxy_tag storage_category;
0228 };
0229 template<>
0230 struct vector_assign_traits<sparse_tag, true, packed_random_access_iterator_tag> {
0231 typedef sparse_proxy_tag storage_category;
0232 };
0233 template<>
0234 struct vector_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag> {
0235 typedef sparse_proxy_tag storage_category;
0236 };
0237
0238
0239 template<template <class T1, class T2> class F, class V, class E>
0240
0241 void iterating_vector_assign (V &v, const vector_expression<E> &e) {
0242 typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
0243 typedef typename V::difference_type difference_type;
0244 difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
0245 typename V::iterator it (v.begin ());
0246 BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
0247 typename E::const_iterator ite (e ().begin ());
0248 BOOST_UBLAS_CHECK (e ().end () - ite == size, bad_size ());
0249 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0250 while (-- size >= 0)
0251 functor_type::apply (*it, *ite), ++ it, ++ ite;
0252 #else
0253 DD (size, 2, r, (functor_type::apply (*it, *ite), ++ it, ++ ite));
0254 #endif
0255 }
0256
0257 template<template <class T1, class T2> class F, class V, class E>
0258
0259 void indexing_vector_assign (V &v, const vector_expression<E> &e) {
0260 typedef F<typename V::reference, typename E::value_type> functor_type;
0261 typedef typename V::size_type size_type;
0262 size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
0263 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0264 for (size_type i = 0; i < size; ++ i)
0265 functor_type::apply (v (i), e () (i));
0266 #else
0267 size_type i (0);
0268 DD (size, 2, r, (functor_type::apply (v (i), e () (i)), ++ i));
0269 #endif
0270 }
0271
0272
0273 template<template <class T1, class T2> class F, class V, class E>
0274
0275 void vector_assign (V &v, const vector_expression<E> &e, dense_proxy_tag) {
0276 #ifdef BOOST_UBLAS_USE_INDEXING
0277 indexing_vector_assign<F> (v, e);
0278 #elif BOOST_UBLAS_USE_ITERATING
0279 iterating_vector_assign<F> (v, e);
0280 #else
0281 typedef typename V::size_type size_type;
0282 size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
0283 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
0284 iterating_vector_assign<F> (v, e);
0285 else
0286 indexing_vector_assign<F> (v, e);
0287 #endif
0288 }
0289
0290 template<template <class T1, class T2> class F, class V, class E>
0291
0292 void vector_assign (V &v, const vector_expression<E> &e, packed_proxy_tag) {
0293 BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
0294 typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
0295 typedef typename V::difference_type difference_type;
0296 typedef typename V::value_type value_type;
0297 #if BOOST_UBLAS_TYPE_CHECK
0298 vector<value_type> cv (v.size ());
0299 indexing_vector_assign<scalar_assign> (cv, v);
0300 indexing_vector_assign<F> (cv, e);
0301 #endif
0302 typename V::iterator it (v.begin ());
0303 typename V::iterator it_end (v.end ());
0304 typename E::const_iterator ite (e ().begin ());
0305 typename E::const_iterator ite_end (e ().end ());
0306 difference_type it_size (it_end - it);
0307 difference_type ite_size (ite_end - ite);
0308 if (it_size > 0 && ite_size > 0) {
0309 difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
0310 if (size > 0) {
0311 ite += size;
0312 ite_size -= size;
0313 }
0314 }
0315 if (it_size > 0 && ite_size > 0) {
0316 difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
0317 if (size > 0) {
0318 it_size -= size;
0319
0320 #ifdef _MSC_VER
0321 #pragma warning(push)
0322 #pragma warning(disable: 4127)
0323 #endif
0324 if (!functor_type::computed) {
0325 #ifdef _MSC_VER
0326 #pragma warning(pop)
0327 #endif
0328 while (-- size >= 0)
0329 functor_type::apply (*it, value_type()), ++ it;
0330 } else {
0331 it += size;
0332 }
0333 }
0334 }
0335 difference_type size ((std::min) (it_size, ite_size));
0336 it_size -= size;
0337 ite_size -= size;
0338 while (-- size >= 0)
0339 functor_type::apply (*it, *ite), ++ it, ++ ite;
0340 size = it_size;
0341
0342 #ifdef _MSC_VER
0343 #pragma warning(push)
0344 #pragma warning(disable: 4127)
0345 #endif
0346 if (!functor_type::computed) {
0347 #ifdef _MSC_VER
0348 #pragma warning(pop)
0349 #endif
0350 while (-- size >= 0)
0351 functor_type::apply (*it, value_type()), ++ it;
0352 } else {
0353 it += size;
0354 }
0355 #if BOOST_UBLAS_TYPE_CHECK
0356 if (! disable_type_check<bool>::value)
0357 BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
0358 external_logic ("external logic or bad condition of inputs"));
0359 #endif
0360 }
0361
0362 template<template <class T1, class T2> class F, class V, class E>
0363
0364 void vector_assign (V &v, const vector_expression<E> &e, sparse_tag) {
0365 BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
0366 typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
0367
0368 #ifdef _MSC_VER
0369 #pragma warning(push)
0370 #pragma warning(disable: 4127)
0371 #endif
0372 BOOST_STATIC_ASSERT ((!functor_type::computed));
0373 #ifdef _MSC_VER
0374 #pragma warning(pop)
0375 #endif
0376 typedef typename V::value_type value_type;
0377 #if BOOST_UBLAS_TYPE_CHECK
0378 vector<value_type> cv (v.size ());
0379 indexing_vector_assign<scalar_assign> (cv, v);
0380 indexing_vector_assign<F> (cv, e);
0381 #endif
0382 v.clear ();
0383 typename E::const_iterator ite (e ().begin ());
0384 typename E::const_iterator ite_end (e ().end ());
0385 while (ite != ite_end) {
0386 value_type t (*ite);
0387 if (t != value_type())
0388 v.insert_element (ite.index (), t);
0389 ++ ite;
0390 }
0391 #if BOOST_UBLAS_TYPE_CHECK
0392 if (! disable_type_check<bool>::value)
0393 BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
0394 external_logic ("external logic or bad condition of inputs"));
0395 #endif
0396 }
0397
0398 template<template <class T1, class T2> class F, class V, class E>
0399
0400 void vector_assign (V &v, const vector_expression<E> &e, sparse_proxy_tag) {
0401 BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
0402 typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
0403 typedef typename V::size_type size_type;
0404 typedef typename V::difference_type difference_type;
0405 typedef typename V::value_type value_type;
0406
0407 #if BOOST_UBLAS_TYPE_CHECK
0408 vector<value_type> cv (v.size ());
0409 indexing_vector_assign<scalar_assign> (cv, v);
0410 indexing_vector_assign<F> (cv, e);
0411 #endif
0412 detail::make_conformant (v, e);
0413
0414 typename V::iterator it (v.begin ());
0415 typename V::iterator it_end (v.end ());
0416 typename E::const_iterator ite (e ().begin ());
0417 typename E::const_iterator ite_end (e ().end ());
0418 if (it != it_end && ite != ite_end) {
0419 size_type it_index = it.index (), ite_index = ite.index ();
0420 for (;;) {
0421 difference_type compare = it_index - ite_index;
0422 if (compare == 0) {
0423 functor_type::apply (*it, *ite);
0424 ++ it, ++ ite;
0425 if (it != it_end && ite != ite_end) {
0426 it_index = it.index ();
0427 ite_index = ite.index ();
0428 } else
0429 break;
0430 } else if (compare < 0) {
0431
0432 #ifdef _MSC_VER
0433 #pragma warning(push)
0434 #pragma warning(disable: 4127)
0435 #endif
0436 if (!functor_type::computed) {
0437 #ifdef _MSC_VER
0438 #pragma warning(pop)
0439 #endif
0440 functor_type::apply (*it, value_type());
0441 ++ it;
0442 } else
0443 increment (it, it_end, - compare);
0444 if (it != it_end)
0445 it_index = it.index ();
0446 else
0447 break;
0448 } else if (compare > 0) {
0449 increment (ite, ite_end, compare);
0450 if (ite != ite_end)
0451 ite_index = ite.index ();
0452 else
0453 break;
0454 }
0455 }
0456 }
0457
0458 #ifdef _MSC_VER
0459 #pragma warning(push)
0460 #pragma warning(disable: 4127)
0461 #endif
0462 if (!functor_type::computed) {
0463 #ifdef _MSC_VER
0464 #pragma warning(pop)
0465 #endif
0466 while (it != it_end) {
0467 functor_type::apply (*it, value_type());
0468 ++ it;
0469 }
0470 } else {
0471 it = it_end;
0472 }
0473 #if BOOST_UBLAS_TYPE_CHECK
0474 if (! disable_type_check<bool>::value)
0475 BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
0476 external_logic ("external logic or bad condition of inputs"));
0477 #endif
0478 }
0479
0480
0481 template<template <class T1, class T2> class F, class V, class E>
0482 BOOST_UBLAS_INLINE
0483 void vector_assign (V &v, const vector_expression<E> &e) {
0484 typedef typename vector_assign_traits<typename V::storage_category,
0485 F<typename V::reference, typename E::value_type>::computed,
0486 typename E::const_iterator::iterator_category>::storage_category storage_category;
0487 vector_assign<F> (v, e, storage_category ());
0488 }
0489
0490 template<class SC, class RI>
0491 struct vector_swap_traits {
0492 typedef SC storage_category;
0493 };
0494
0495 template<>
0496 struct vector_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag> {
0497 typedef sparse_proxy_tag storage_category;
0498 };
0499
0500 template<>
0501 struct vector_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag> {
0502 typedef sparse_proxy_tag storage_category;
0503 };
0504
0505
0506 template<template <class T1, class T2> class F, class V, class E>
0507
0508 void vector_swap (V &v, vector_expression<E> &e, dense_proxy_tag) {
0509 typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
0510 typedef typename V::difference_type difference_type;
0511 difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
0512 typename V::iterator it (v.begin ());
0513 typename E::iterator ite (e ().begin ());
0514 while (-- size >= 0)
0515 functor_type::apply (*it, *ite), ++ it, ++ ite;
0516 }
0517
0518 template<template <class T1, class T2> class F, class V, class E>
0519
0520 void vector_swap (V &v, vector_expression<E> &e, packed_proxy_tag) {
0521 typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
0522 typedef typename V::difference_type difference_type;
0523 typename V::iterator it (v.begin ());
0524 typename V::iterator it_end (v.end ());
0525 typename E::iterator ite (e ().begin ());
0526 typename E::iterator ite_end (e ().end ());
0527 difference_type it_size (it_end - it);
0528 difference_type ite_size (ite_end - ite);
0529 if (it_size > 0 && ite_size > 0) {
0530 difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
0531 if (size > 0) {
0532 ite += size;
0533 ite_size -= size;
0534 }
0535 }
0536 if (it_size > 0 && ite_size > 0) {
0537 difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
0538 if (size > 0)
0539 it_size -= size;
0540 }
0541 difference_type size ((std::min) (it_size, ite_size));
0542 it_size -= size;
0543 ite_size -= size;
0544 while (-- size >= 0)
0545 functor_type::apply (*it, *ite), ++ it, ++ ite;
0546 }
0547
0548 template<template <class T1, class T2> class F, class V, class E>
0549
0550 void vector_swap (V &v, vector_expression<E> &e, sparse_proxy_tag) {
0551 BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
0552 typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
0553 typedef typename V::size_type size_type;
0554 typedef typename V::difference_type difference_type;
0555
0556 detail::make_conformant (v, e);
0557
0558 detail::make_conformant (e (), v);
0559
0560 typename V::iterator it (v.begin ());
0561 typename V::iterator it_end (v.end ());
0562 typename E::iterator ite (e ().begin ());
0563 typename E::iterator ite_end (e ().end ());
0564 if (it != it_end && ite != ite_end) {
0565 size_type it_index = it.index (), ite_index = ite.index ();
0566 for (;;) {
0567 difference_type compare = it_index - ite_index;
0568 if (compare == 0) {
0569 functor_type::apply (*it, *ite);
0570 ++ it, ++ ite;
0571 if (it != it_end && ite != ite_end) {
0572 it_index = it.index ();
0573 ite_index = ite.index ();
0574 } else
0575 break;
0576 } else if (compare < 0) {
0577 increment (it, it_end, - compare);
0578 if (it != it_end)
0579 it_index = it.index ();
0580 else
0581 break;
0582 } else if (compare > 0) {
0583 increment (ite, ite_end, compare);
0584 if (ite != ite_end)
0585 ite_index = ite.index ();
0586 else
0587 break;
0588 }
0589 }
0590 }
0591
0592 #if BOOST_UBLAS_TYPE_CHECK
0593 increment (ite, ite_end);
0594 increment (it, it_end);
0595 #endif
0596 }
0597
0598
0599 template<template <class T1, class T2> class F, class V, class E>
0600 BOOST_UBLAS_INLINE
0601 void vector_swap (V &v, vector_expression<E> &e) {
0602 typedef typename vector_swap_traits<typename V::storage_category,
0603 typename E::const_iterator::iterator_category>::storage_category storage_category;
0604 vector_swap<F> (v, e, storage_category ());
0605 }
0606
0607 }}}
0608
0609 #endif