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
|