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