annotate DEPENDENCIES/generic/include/boost/numeric/ublas/detail/vector_assign.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //
Chris@16 2 // Copyright (c) 2000-2002
Chris@16 3 // Joerg Walter, Mathias Koch
Chris@16 4 //
Chris@16 5 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 6 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8 //
Chris@16 9 // The authors gratefully acknowledge the support of
Chris@16 10 // GeNeSys mbH & Co. KG in producing this work.
Chris@16 11 //
Chris@16 12
Chris@16 13 #ifndef _BOOST_UBLAS_VECTOR_ASSIGN_
Chris@16 14 #define _BOOST_UBLAS_VECTOR_ASSIGN_
Chris@16 15
Chris@16 16 #include <boost/numeric/ublas/functional.hpp> // scalar_assign
Chris@16 17 // Required for make_conformant storage
Chris@16 18 #include <vector>
Chris@16 19
Chris@16 20 // Iterators based on ideas of Jeremy Siek
Chris@16 21
Chris@16 22 namespace boost { namespace numeric { namespace ublas {
Chris@16 23 namespace detail {
Chris@16 24
Chris@16 25 // Weak equality check - useful to compare equality two arbitary vector expression results.
Chris@16 26 // Since the actual expressions are unknown, we check for and arbitary error bound
Chris@16 27 // on the relative error.
Chris@16 28 // For a linear expression the infinity norm makes sense as we do not know how the elements will be
Chris@16 29 // combined in the expression. False positive results are inevitable for arbirary expressions!
Chris@16 30 template<class E1, class E2, class S>
Chris@16 31 BOOST_UBLAS_INLINE
Chris@16 32 bool equals (const vector_expression<E1> &e1, const vector_expression<E2> &e2, S epsilon, S min_norm) {
Chris@101 33 return norm_inf (e1 - e2) <= epsilon *
Chris@16 34 std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
Chris@16 35 }
Chris@16 36
Chris@16 37 template<class E1, class E2>
Chris@16 38 BOOST_UBLAS_INLINE
Chris@16 39 bool expression_type_check (const vector_expression<E1> &e1, const vector_expression<E2> &e2) {
Chris@16 40 typedef typename type_traits<typename promote_traits<typename E1::value_type,
Chris@16 41 typename E2::value_type>::promote_type>::real_type real_type;
Chris@16 42 return equals (e1, e2, BOOST_UBLAS_TYPE_CHECK_EPSILON, BOOST_UBLAS_TYPE_CHECK_MIN);
Chris@16 43 }
Chris@16 44
Chris@16 45
Chris@16 46 // Make sparse proxies conformant
Chris@16 47 template<class V, class E>
Chris@16 48 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 49 void make_conformant (V &v, const vector_expression<E> &e) {
Chris@16 50 BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
Chris@16 51 typedef typename V::size_type size_type;
Chris@16 52 typedef typename V::difference_type difference_type;
Chris@16 53 typedef typename V::value_type value_type;
Chris@16 54 // FIXME unbounded_array with push_back maybe better
Chris@16 55 std::vector<size_type> index;
Chris@16 56 typename V::iterator it (v.begin ());
Chris@16 57 typename V::iterator it_end (v.end ());
Chris@16 58 typename E::const_iterator ite (e ().begin ());
Chris@16 59 typename E::const_iterator ite_end (e ().end ());
Chris@16 60 if (it != it_end && ite != ite_end) {
Chris@16 61 size_type it_index = it.index (), ite_index = ite.index ();
Chris@16 62 while (true) {
Chris@16 63 difference_type compare = it_index - ite_index;
Chris@16 64 if (compare == 0) {
Chris@16 65 ++ it, ++ ite;
Chris@16 66 if (it != it_end && ite != ite_end) {
Chris@16 67 it_index = it.index ();
Chris@16 68 ite_index = ite.index ();
Chris@16 69 } else
Chris@16 70 break;
Chris@16 71 } else if (compare < 0) {
Chris@16 72 increment (it, it_end, - compare);
Chris@16 73 if (it != it_end)
Chris@16 74 it_index = it.index ();
Chris@16 75 else
Chris@16 76 break;
Chris@16 77 } else if (compare > 0) {
Chris@16 78 if (*ite != value_type/*zero*/())
Chris@16 79 index.push_back (ite.index ());
Chris@16 80 ++ ite;
Chris@16 81 if (ite != ite_end)
Chris@16 82 ite_index = ite.index ();
Chris@16 83 else
Chris@16 84 break;
Chris@16 85 }
Chris@16 86 }
Chris@16 87 }
Chris@16 88
Chris@16 89 while (ite != ite_end) {
Chris@16 90 if (*ite != value_type/*zero*/())
Chris@16 91 index.push_back (ite.index ());
Chris@16 92 ++ ite;
Chris@16 93 }
Chris@16 94 for (size_type k = 0; k < index.size (); ++ k)
Chris@16 95 v (index [k]) = value_type/*zero*/();
Chris@16 96 }
Chris@16 97
Chris@16 98 }//namespace detail
Chris@16 99
Chris@16 100
Chris@16 101 // Explicitly iterating
Chris@16 102 template<template <class T1, class T2> class F, class V, class T>
Chris@16 103 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 104 void iterating_vector_assign_scalar (V &v, const T &t) {
Chris@16 105 typedef F<typename V::iterator::reference, T> functor_type;
Chris@16 106 typedef typename V::difference_type difference_type;
Chris@16 107 difference_type size (v.size ());
Chris@16 108 typename V::iterator it (v.begin ());
Chris@16 109 BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
Chris@16 110 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
Chris@16 111 while (-- size >= 0)
Chris@16 112 functor_type::apply (*it, t), ++ it;
Chris@16 113 #else
Chris@16 114 DD (size, 4, r, (functor_type::apply (*it, t), ++ it));
Chris@16 115 #endif
Chris@16 116 }
Chris@16 117 // Explicitly case
Chris@16 118 template<template <class T1, class T2> class F, class V, class T>
Chris@16 119 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 120 void indexing_vector_assign_scalar (V &v, const T &t) {
Chris@16 121 typedef F<typename V::reference, T> functor_type;
Chris@16 122 typedef typename V::size_type size_type;
Chris@16 123 size_type size (v.size ());
Chris@16 124 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
Chris@16 125 for (size_type i = 0; i < size; ++ i)
Chris@16 126 functor_type::apply (v (i), t);
Chris@16 127 #else
Chris@16 128 size_type i (0);
Chris@16 129 DD (size, 4, r, (functor_type::apply (v (i), t), ++ i));
Chris@16 130 #endif
Chris@16 131 }
Chris@16 132
Chris@16 133 // Dense (proxy) case
Chris@16 134 template<template <class T1, class T2> class F, class V, class T>
Chris@16 135 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 136 void vector_assign_scalar (V &v, const T &t, dense_proxy_tag) {
Chris@16 137 #ifdef BOOST_UBLAS_USE_INDEXING
Chris@16 138 indexing_vector_assign_scalar<F> (v, t);
Chris@16 139 #elif BOOST_UBLAS_USE_ITERATING
Chris@16 140 iterating_vector_assign_scalar<F> (v, t);
Chris@16 141 #else
Chris@16 142 typedef typename V::size_type size_type;
Chris@16 143 size_type size (v.size ());
Chris@16 144 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
Chris@16 145 iterating_vector_assign_scalar<F> (v, t);
Chris@16 146 else
Chris@16 147 indexing_vector_assign_scalar<F> (v, t);
Chris@16 148 #endif
Chris@16 149 }
Chris@16 150 // Packed (proxy) case
Chris@16 151 template<template <class T1, class T2> class F, class V, class T>
Chris@16 152 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 153 void vector_assign_scalar (V &v, const T &t, packed_proxy_tag) {
Chris@16 154 typedef F<typename V::iterator::reference, T> functor_type;
Chris@16 155 typedef typename V::difference_type difference_type;
Chris@16 156 typename V::iterator it (v.begin ());
Chris@16 157 difference_type size (v.end () - it);
Chris@16 158 while (-- size >= 0)
Chris@16 159 functor_type::apply (*it, t), ++ it;
Chris@16 160 }
Chris@16 161 // Sparse (proxy) case
Chris@16 162 template<template <class T1, class T2> class F, class V, class T>
Chris@16 163 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 164 void vector_assign_scalar (V &v, const T &t, sparse_proxy_tag) {
Chris@16 165 typedef F<typename V::iterator::reference, T> functor_type;
Chris@16 166 typename V::iterator it (v.begin ());
Chris@16 167 typename V::iterator it_end (v.end ());
Chris@16 168 while (it != it_end)
Chris@16 169 functor_type::apply (*it, t), ++ it;
Chris@16 170 }
Chris@16 171
Chris@16 172 // Dispatcher
Chris@16 173 template<template <class T1, class T2> class F, class V, class T>
Chris@16 174 BOOST_UBLAS_INLINE
Chris@16 175 void vector_assign_scalar (V &v, const T &t) {
Chris@16 176 typedef typename V::storage_category storage_category;
Chris@16 177 vector_assign_scalar<F> (v, t, storage_category ());
Chris@16 178 }
Chris@16 179
Chris@16 180 template<class SC, bool COMPUTED, class RI>
Chris@16 181 struct vector_assign_traits {
Chris@16 182 typedef SC storage_category;
Chris@16 183 };
Chris@16 184
Chris@16 185 template<bool COMPUTED>
Chris@16 186 struct vector_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag> {
Chris@16 187 typedef packed_tag storage_category;
Chris@16 188 };
Chris@16 189 template<>
Chris@16 190 struct vector_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag> {
Chris@16 191 typedef sparse_tag storage_category;
Chris@16 192 };
Chris@16 193 template<>
Chris@16 194 struct vector_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag> {
Chris@16 195 typedef sparse_proxy_tag storage_category;
Chris@16 196 };
Chris@16 197
Chris@16 198 template<bool COMPUTED>
Chris@16 199 struct vector_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag> {
Chris@16 200 typedef packed_proxy_tag storage_category;
Chris@16 201 };
Chris@16 202 template<>
Chris@16 203 struct vector_assign_traits<dense_proxy_tag, false, sparse_bidirectional_iterator_tag> {
Chris@16 204 typedef sparse_proxy_tag storage_category;
Chris@16 205 };
Chris@16 206 template<>
Chris@16 207 struct vector_assign_traits<dense_proxy_tag, true, sparse_bidirectional_iterator_tag> {
Chris@16 208 typedef sparse_proxy_tag storage_category;
Chris@16 209 };
Chris@16 210
Chris@16 211 template<>
Chris@16 212 struct vector_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag> {
Chris@16 213 typedef sparse_tag storage_category;
Chris@16 214 };
Chris@16 215 template<>
Chris@16 216 struct vector_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag> {
Chris@16 217 typedef sparse_proxy_tag storage_category;
Chris@16 218 };
Chris@16 219
Chris@16 220 template<bool COMPUTED>
Chris@16 221 struct vector_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag> {
Chris@16 222 typedef sparse_proxy_tag storage_category;
Chris@16 223 };
Chris@16 224
Chris@16 225 template<>
Chris@16 226 struct vector_assign_traits<sparse_tag, true, dense_random_access_iterator_tag> {
Chris@16 227 typedef sparse_proxy_tag storage_category;
Chris@16 228 };
Chris@16 229 template<>
Chris@16 230 struct vector_assign_traits<sparse_tag, true, packed_random_access_iterator_tag> {
Chris@16 231 typedef sparse_proxy_tag storage_category;
Chris@16 232 };
Chris@16 233 template<>
Chris@16 234 struct vector_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag> {
Chris@16 235 typedef sparse_proxy_tag storage_category;
Chris@16 236 };
Chris@16 237
Chris@16 238 // Explicitly iterating
Chris@16 239 template<template <class T1, class T2> class F, class V, class E>
Chris@16 240 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 241 void iterating_vector_assign (V &v, const vector_expression<E> &e) {
Chris@16 242 typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
Chris@16 243 typedef typename V::difference_type difference_type;
Chris@16 244 difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
Chris@16 245 typename V::iterator it (v.begin ());
Chris@16 246 BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
Chris@16 247 typename E::const_iterator ite (e ().begin ());
Chris@16 248 BOOST_UBLAS_CHECK (e ().end () - ite == size, bad_size ());
Chris@16 249 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
Chris@16 250 while (-- size >= 0)
Chris@16 251 functor_type::apply (*it, *ite), ++ it, ++ ite;
Chris@16 252 #else
Chris@16 253 DD (size, 2, r, (functor_type::apply (*it, *ite), ++ it, ++ ite));
Chris@16 254 #endif
Chris@16 255 }
Chris@16 256 // Explicitly indexing
Chris@16 257 template<template <class T1, class T2> class F, class V, class E>
Chris@16 258 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 259 void indexing_vector_assign (V &v, const vector_expression<E> &e) {
Chris@16 260 typedef F<typename V::reference, typename E::value_type> functor_type;
Chris@16 261 typedef typename V::size_type size_type;
Chris@16 262 size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
Chris@16 263 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
Chris@16 264 for (size_type i = 0; i < size; ++ i)
Chris@16 265 functor_type::apply (v (i), e () (i));
Chris@16 266 #else
Chris@16 267 size_type i (0);
Chris@16 268 DD (size, 2, r, (functor_type::apply (v (i), e () (i)), ++ i));
Chris@16 269 #endif
Chris@16 270 }
Chris@16 271
Chris@16 272 // Dense (proxy) case
Chris@16 273 template<template <class T1, class T2> class F, class V, class E>
Chris@16 274 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 275 void vector_assign (V &v, const vector_expression<E> &e, dense_proxy_tag) {
Chris@16 276 #ifdef BOOST_UBLAS_USE_INDEXING
Chris@16 277 indexing_vector_assign<F> (v, e);
Chris@16 278 #elif BOOST_UBLAS_USE_ITERATING
Chris@16 279 iterating_vector_assign<F> (v, e);
Chris@16 280 #else
Chris@16 281 typedef typename V::size_type size_type;
Chris@16 282 size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
Chris@16 283 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
Chris@16 284 iterating_vector_assign<F> (v, e);
Chris@16 285 else
Chris@16 286 indexing_vector_assign<F> (v, e);
Chris@16 287 #endif
Chris@16 288 }
Chris@16 289 // Packed (proxy) case
Chris@16 290 template<template <class T1, class T2> class F, class V, class E>
Chris@16 291 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 292 void vector_assign (V &v, const vector_expression<E> &e, packed_proxy_tag) {
Chris@16 293 BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
Chris@16 294 typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
Chris@16 295 typedef typename V::difference_type difference_type;
Chris@16 296 typedef typename V::value_type value_type;
Chris@16 297 #if BOOST_UBLAS_TYPE_CHECK
Chris@16 298 vector<value_type> cv (v.size ());
Chris@16 299 indexing_vector_assign<scalar_assign> (cv, v);
Chris@16 300 indexing_vector_assign<F> (cv, e);
Chris@16 301 #endif
Chris@16 302 typename V::iterator it (v.begin ());
Chris@16 303 typename V::iterator it_end (v.end ());
Chris@16 304 typename E::const_iterator ite (e ().begin ());
Chris@16 305 typename E::const_iterator ite_end (e ().end ());
Chris@16 306 difference_type it_size (it_end - it);
Chris@16 307 difference_type ite_size (ite_end - ite);
Chris@16 308 if (it_size > 0 && ite_size > 0) {
Chris@16 309 difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
Chris@16 310 if (size > 0) {
Chris@16 311 ite += size;
Chris@16 312 ite_size -= size;
Chris@16 313 }
Chris@16 314 }
Chris@16 315 if (it_size > 0 && ite_size > 0) {
Chris@16 316 difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
Chris@16 317 if (size > 0) {
Chris@16 318 it_size -= size;
Chris@16 319 if (!functor_type::computed) {
Chris@16 320 while (-- size >= 0) // zeroing
Chris@16 321 functor_type::apply (*it, value_type/*zero*/()), ++ it;
Chris@16 322 } else {
Chris@16 323 it += size;
Chris@16 324 }
Chris@16 325 }
Chris@16 326 }
Chris@16 327 difference_type size ((std::min) (it_size, ite_size));
Chris@16 328 it_size -= size;
Chris@16 329 ite_size -= size;
Chris@16 330 while (-- size >= 0)
Chris@16 331 functor_type::apply (*it, *ite), ++ it, ++ ite;
Chris@16 332 size = it_size;
Chris@16 333 if (!functor_type::computed) {
Chris@16 334 while (-- size >= 0) // zeroing
Chris@16 335 functor_type::apply (*it, value_type/*zero*/()), ++ it;
Chris@16 336 } else {
Chris@16 337 it += size;
Chris@16 338 }
Chris@16 339 #if BOOST_UBLAS_TYPE_CHECK
Chris@16 340 if (! disable_type_check<bool>::value)
Chris@16 341 BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
Chris@16 342 external_logic ("external logic or bad condition of inputs"));
Chris@16 343 #endif
Chris@16 344 }
Chris@16 345 // Sparse case
Chris@16 346 template<template <class T1, class T2> class F, class V, class E>
Chris@16 347 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 348 void vector_assign (V &v, const vector_expression<E> &e, sparse_tag) {
Chris@16 349 BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
Chris@16 350 typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
Chris@16 351 BOOST_STATIC_ASSERT ((!functor_type::computed));
Chris@16 352 typedef typename V::value_type value_type;
Chris@16 353 #if BOOST_UBLAS_TYPE_CHECK
Chris@16 354 vector<value_type> cv (v.size ());
Chris@16 355 indexing_vector_assign<scalar_assign> (cv, v);
Chris@16 356 indexing_vector_assign<F> (cv, e);
Chris@16 357 #endif
Chris@16 358 v.clear ();
Chris@16 359 typename E::const_iterator ite (e ().begin ());
Chris@16 360 typename E::const_iterator ite_end (e ().end ());
Chris@16 361 while (ite != ite_end) {
Chris@16 362 value_type t (*ite);
Chris@16 363 if (t != value_type/*zero*/())
Chris@16 364 v.insert_element (ite.index (), t);
Chris@16 365 ++ ite;
Chris@16 366 }
Chris@16 367 #if BOOST_UBLAS_TYPE_CHECK
Chris@16 368 if (! disable_type_check<bool>::value)
Chris@16 369 BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
Chris@16 370 external_logic ("external logic or bad condition of inputs"));
Chris@16 371 #endif
Chris@16 372 }
Chris@16 373 // Sparse proxy or functional case
Chris@16 374 template<template <class T1, class T2> class F, class V, class E>
Chris@16 375 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 376 void vector_assign (V &v, const vector_expression<E> &e, sparse_proxy_tag) {
Chris@16 377 BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
Chris@16 378 typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
Chris@16 379 typedef typename V::size_type size_type;
Chris@16 380 typedef typename V::difference_type difference_type;
Chris@16 381 typedef typename V::value_type value_type;
Chris@101 382
Chris@16 383 #if BOOST_UBLAS_TYPE_CHECK
Chris@16 384 vector<value_type> cv (v.size ());
Chris@16 385 indexing_vector_assign<scalar_assign> (cv, v);
Chris@16 386 indexing_vector_assign<F> (cv, e);
Chris@16 387 #endif
Chris@16 388 detail::make_conformant (v, e);
Chris@16 389
Chris@16 390 typename V::iterator it (v.begin ());
Chris@16 391 typename V::iterator it_end (v.end ());
Chris@16 392 typename E::const_iterator ite (e ().begin ());
Chris@16 393 typename E::const_iterator ite_end (e ().end ());
Chris@16 394 if (it != it_end && ite != ite_end) {
Chris@16 395 size_type it_index = it.index (), ite_index = ite.index ();
Chris@16 396 while (true) {
Chris@16 397 difference_type compare = it_index - ite_index;
Chris@16 398 if (compare == 0) {
Chris@16 399 functor_type::apply (*it, *ite);
Chris@16 400 ++ it, ++ ite;
Chris@16 401 if (it != it_end && ite != ite_end) {
Chris@16 402 it_index = it.index ();
Chris@16 403 ite_index = ite.index ();
Chris@16 404 } else
Chris@16 405 break;
Chris@16 406 } else if (compare < 0) {
Chris@16 407 if (!functor_type::computed) {
Chris@16 408 functor_type::apply (*it, value_type/*zero*/());
Chris@16 409 ++ it;
Chris@16 410 } else
Chris@16 411 increment (it, it_end, - compare);
Chris@16 412 if (it != it_end)
Chris@16 413 it_index = it.index ();
Chris@16 414 else
Chris@16 415 break;
Chris@16 416 } else if (compare > 0) {
Chris@16 417 increment (ite, ite_end, compare);
Chris@16 418 if (ite != ite_end)
Chris@16 419 ite_index = ite.index ();
Chris@16 420 else
Chris@16 421 break;
Chris@16 422 }
Chris@16 423 }
Chris@16 424 }
Chris@16 425
Chris@16 426 if (!functor_type::computed) {
Chris@16 427 while (it != it_end) { // zeroing
Chris@16 428 functor_type::apply (*it, value_type/*zero*/());
Chris@16 429 ++ it;
Chris@16 430 }
Chris@16 431 } else {
Chris@16 432 it = it_end;
Chris@16 433 }
Chris@16 434 #if BOOST_UBLAS_TYPE_CHECK
Chris@16 435 if (! disable_type_check<bool>::value)
Chris@16 436 BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
Chris@16 437 external_logic ("external logic or bad condition of inputs"));
Chris@16 438 #endif
Chris@16 439 }
Chris@16 440
Chris@16 441 // Dispatcher
Chris@16 442 template<template <class T1, class T2> class F, class V, class E>
Chris@16 443 BOOST_UBLAS_INLINE
Chris@16 444 void vector_assign (V &v, const vector_expression<E> &e) {
Chris@16 445 typedef typename vector_assign_traits<typename V::storage_category,
Chris@16 446 F<typename V::reference, typename E::value_type>::computed,
Chris@16 447 typename E::const_iterator::iterator_category>::storage_category storage_category;
Chris@16 448 vector_assign<F> (v, e, storage_category ());
Chris@16 449 }
Chris@16 450
Chris@16 451 template<class SC, class RI>
Chris@16 452 struct vector_swap_traits {
Chris@16 453 typedef SC storage_category;
Chris@16 454 };
Chris@16 455
Chris@16 456 template<>
Chris@16 457 struct vector_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag> {
Chris@16 458 typedef sparse_proxy_tag storage_category;
Chris@16 459 };
Chris@16 460
Chris@16 461 template<>
Chris@16 462 struct vector_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag> {
Chris@16 463 typedef sparse_proxy_tag storage_category;
Chris@16 464 };
Chris@16 465
Chris@16 466 // Dense (proxy) case
Chris@16 467 template<template <class T1, class T2> class F, class V, class E>
Chris@16 468 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 469 void vector_swap (V &v, vector_expression<E> &e, dense_proxy_tag) {
Chris@16 470 typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
Chris@16 471 typedef typename V::difference_type difference_type;
Chris@16 472 difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
Chris@16 473 typename V::iterator it (v.begin ());
Chris@16 474 typename E::iterator ite (e ().begin ());
Chris@16 475 while (-- size >= 0)
Chris@16 476 functor_type::apply (*it, *ite), ++ it, ++ ite;
Chris@16 477 }
Chris@16 478 // Packed (proxy) case
Chris@16 479 template<template <class T1, class T2> class F, class V, class E>
Chris@16 480 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 481 void vector_swap (V &v, vector_expression<E> &e, packed_proxy_tag) {
Chris@16 482 typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
Chris@16 483 typedef typename V::difference_type difference_type;
Chris@16 484 typename V::iterator it (v.begin ());
Chris@16 485 typename V::iterator it_end (v.end ());
Chris@16 486 typename E::iterator ite (e ().begin ());
Chris@16 487 typename E::iterator ite_end (e ().end ());
Chris@16 488 difference_type it_size (it_end - it);
Chris@16 489 difference_type ite_size (ite_end - ite);
Chris@16 490 if (it_size > 0 && ite_size > 0) {
Chris@16 491 difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
Chris@16 492 if (size > 0) {
Chris@16 493 ite += size;
Chris@16 494 ite_size -= size;
Chris@16 495 }
Chris@16 496 }
Chris@16 497 if (it_size > 0 && ite_size > 0) {
Chris@16 498 difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
Chris@16 499 if (size > 0)
Chris@16 500 it_size -= size;
Chris@16 501 }
Chris@16 502 difference_type size ((std::min) (it_size, ite_size));
Chris@16 503 it_size -= size;
Chris@16 504 ite_size -= size;
Chris@16 505 while (-- size >= 0)
Chris@16 506 functor_type::apply (*it, *ite), ++ it, ++ ite;
Chris@16 507 }
Chris@16 508 // Sparse proxy case
Chris@16 509 template<template <class T1, class T2> class F, class V, class E>
Chris@16 510 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 511 void vector_swap (V &v, vector_expression<E> &e, sparse_proxy_tag) {
Chris@16 512 BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
Chris@16 513 typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
Chris@16 514 typedef typename V::size_type size_type;
Chris@16 515 typedef typename V::difference_type difference_type;
Chris@16 516
Chris@16 517 detail::make_conformant (v, e);
Chris@16 518 // FIXME should be a seperate restriction for E
Chris@16 519 detail::make_conformant (e (), v);
Chris@16 520
Chris@16 521 typename V::iterator it (v.begin ());
Chris@16 522 typename V::iterator it_end (v.end ());
Chris@16 523 typename E::iterator ite (e ().begin ());
Chris@16 524 typename E::iterator ite_end (e ().end ());
Chris@16 525 if (it != it_end && ite != ite_end) {
Chris@16 526 size_type it_index = it.index (), ite_index = ite.index ();
Chris@16 527 while (true) {
Chris@16 528 difference_type compare = it_index - ite_index;
Chris@16 529 if (compare == 0) {
Chris@16 530 functor_type::apply (*it, *ite);
Chris@16 531 ++ it, ++ ite;
Chris@16 532 if (it != it_end && ite != ite_end) {
Chris@16 533 it_index = it.index ();
Chris@16 534 ite_index = ite.index ();
Chris@16 535 } else
Chris@16 536 break;
Chris@16 537 } else if (compare < 0) {
Chris@16 538 increment (it, it_end, - compare);
Chris@16 539 if (it != it_end)
Chris@16 540 it_index = it.index ();
Chris@16 541 else
Chris@16 542 break;
Chris@16 543 } else if (compare > 0) {
Chris@16 544 increment (ite, ite_end, compare);
Chris@16 545 if (ite != ite_end)
Chris@16 546 ite_index = ite.index ();
Chris@16 547 else
Chris@16 548 break;
Chris@16 549 }
Chris@16 550 }
Chris@16 551 }
Chris@16 552
Chris@16 553 #if BOOST_UBLAS_TYPE_CHECK
Chris@16 554 increment (ite, ite_end);
Chris@16 555 increment (it, it_end);
Chris@16 556 #endif
Chris@16 557 }
Chris@16 558
Chris@16 559 // Dispatcher
Chris@16 560 template<template <class T1, class T2> class F, class V, class E>
Chris@16 561 BOOST_UBLAS_INLINE
Chris@16 562 void vector_swap (V &v, vector_expression<E> &e) {
Chris@16 563 typedef typename vector_swap_traits<typename V::storage_category,
Chris@16 564 typename E::const_iterator::iterator_category>::storage_category storage_category;
Chris@16 565 vector_swap<F> (v, e, storage_category ());
Chris@16 566 }
Chris@16 567
Chris@16 568 }}}
Chris@16 569
Chris@16 570 #endif