source: vendor/nemo/current/NEMOGCM/EXTERNAL/XIOS/extern/boost/include/boost/numeric/ublas/detail/vector_assign.hpp @ 44

Last change on this file since 44 was 44, checked in by cholod, 12 years ago

Load NEMO_TMP into vendor/nemo/current.

File size: 23.5 KB
Line 
1//
2//  Copyright (c) 2000-2002
3//  Joerg Walter, Mathias Koch
4//
5//  Distributed under the Boost Software License, Version 1.0. (See
6//  accompanying file LICENSE_1_0.txt or copy at
7//  http://www.boost.org/LICENSE_1_0.txt)
8//
9//  The authors gratefully acknowledge the support of
10//  GeNeSys mbH & Co. KG in producing this work.
11//
12
13#ifndef _BOOST_UBLAS_VECTOR_ASSIGN_
14#define _BOOST_UBLAS_VECTOR_ASSIGN_
15
16#include <boost/numeric/ublas/functional.hpp> // scalar_assign
17// Required for make_conformant storage
18#include <vector>
19
20// Iterators based on ideas of Jeremy Siek
21
22namespace boost { namespace numeric { namespace ublas {
23namespace detail {
24
25    // Weak equality check - useful to compare equality two arbitary vector expression results.
26    // Since the actual expressions are unknown, we check for and arbitary error bound
27    // on the relative error.
28    // For a linear expression the infinity norm makes sense as we do not know how the elements will be
29    // combined in the expression. False positive results are inevitable for arbirary expressions!
30    template<class E1, class E2, class S>
31    BOOST_UBLAS_INLINE
32    bool equals (const vector_expression<E1> &e1, const vector_expression<E2> &e2, S epsilon, S min_norm) {
33        return norm_inf (e1 - e2) < epsilon *
34               std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
35    }
36
37    template<class E1, class E2>
38    BOOST_UBLAS_INLINE
39    bool expression_type_check (const vector_expression<E1> &e1, const vector_expression<E2> &e2) {
40        typedef typename type_traits<typename promote_traits<typename E1::value_type,
41                                     typename E2::value_type>::promote_type>::real_type real_type;
42        return equals (e1, e2, BOOST_UBLAS_TYPE_CHECK_EPSILON, BOOST_UBLAS_TYPE_CHECK_MIN);
43    }
44
45
46    // Make sparse proxies conformant
47    template<class V, class E>
48    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
49    void make_conformant (V &v, const vector_expression<E> &e) {
50        BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
51        typedef typename V::size_type size_type;
52        typedef typename V::difference_type difference_type;
53        typedef typename V::value_type value_type;
54        // FIXME unbounded_array with push_back maybe better
55        std::vector<size_type> index;
56        typename V::iterator it (v.begin ());
57        typename V::iterator it_end (v.end ());
58        typename E::const_iterator ite (e ().begin ());
59        typename E::const_iterator ite_end (e ().end ());
60        if (it != it_end && ite != ite_end) {
61            size_type it_index = it.index (), ite_index = ite.index ();
62            while (true) {
63                difference_type compare = it_index - ite_index;
64                if (compare == 0) {
65                    ++ it, ++ ite;
66                    if (it != it_end && ite != ite_end) {
67                        it_index = it.index ();
68                        ite_index = ite.index ();
69                    } else
70                        break;
71                } else if (compare < 0) {
72                    increment (it, it_end, - compare);
73                    if (it != it_end)
74                        it_index = it.index ();
75                    else
76                        break;
77                } else if (compare > 0) {
78                    if (*ite != value_type/*zero*/())
79                        index.push_back (ite.index ());
80                    ++ ite;
81                    if (ite != ite_end)
82                        ite_index = ite.index ();
83                    else
84                        break;
85                }
86            }
87        }
88
89        while (ite != ite_end) {
90            if (*ite != value_type/*zero*/())
91                index.push_back (ite.index ());
92            ++ ite;
93        }
94        for (size_type k = 0; k < index.size (); ++ k)
95            v (index [k]) = value_type/*zero*/();
96    }
97
98}//namespace detail
99
100
101    // Explicitly iterating
102    template<template <class T1, class T2> class F, class V, class T>
103    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
104    void iterating_vector_assign_scalar (V &v, const T &t) {
105        typedef F<typename V::iterator::reference, T> functor_type;
106        typedef typename V::difference_type difference_type;
107        difference_type size (v.size ());
108        typename V::iterator it (v.begin ());
109        BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
110#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
111        while (-- size >= 0)
112            functor_type::apply (*it, t), ++ it;
113#else
114        DD (size, 4, r, (functor_type::apply (*it, t), ++ it));
115#endif
116    }
117    // Explicitly case
118    template<template <class T1, class T2> class F, class V, class T>
119    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
120    void indexing_vector_assign_scalar (V &v, const T &t) {
121        typedef F<typename V::reference, T> functor_type;
122        typedef typename V::size_type size_type;
123        size_type size (v.size ());
124#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
125        for (size_type i = 0; i < size; ++ i)
126            functor_type::apply (v (i), t);
127#else
128        size_type i (0);
129        DD (size, 4, r, (functor_type::apply (v (i), t), ++ i));
130#endif
131    }
132
133    // Dense (proxy) case
134    template<template <class T1, class T2> class F, class V, class T>
135    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
136    void vector_assign_scalar (V &v, const T &t, dense_proxy_tag) {
137#ifdef BOOST_UBLAS_USE_INDEXING
138        indexing_vector_assign_scalar<F> (v, t);
139#elif BOOST_UBLAS_USE_ITERATING
140        iterating_vector_assign_scalar<F> (v, t);
141#else
142        typedef typename V::size_type size_type;
143        size_type size (v.size ());
144        if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
145            iterating_vector_assign_scalar<F> (v, t);
146        else
147            indexing_vector_assign_scalar<F> (v, t);
148#endif
149    }
150    // Packed (proxy) case
151    template<template <class T1, class T2> class F, class V, class T>
152    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
153    void vector_assign_scalar (V &v, const T &t, packed_proxy_tag) {
154        typedef F<typename V::iterator::reference, T> functor_type;
155        typedef typename V::difference_type difference_type;
156        typename V::iterator it (v.begin ());
157        difference_type size (v.end () - it);
158        while (-- size >= 0)
159            functor_type::apply (*it, t), ++ it;
160    }
161    // Sparse (proxy) case
162    template<template <class T1, class T2> class F, class V, class T>
163    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
164    void vector_assign_scalar (V &v, const T &t, sparse_proxy_tag) {
165        typedef F<typename V::iterator::reference, T> functor_type;
166        typename V::iterator it (v.begin ());
167        typename V::iterator it_end (v.end ());
168        while (it != it_end)
169            functor_type::apply (*it, t), ++ it;
170    }
171
172    // Dispatcher
173    template<template <class T1, class T2> class F, class V, class T>
174    BOOST_UBLAS_INLINE
175    void vector_assign_scalar (V &v, const T &t) {
176        typedef typename V::storage_category storage_category;
177        vector_assign_scalar<F> (v, t, storage_category ());
178    }
179
180    template<class SC, bool COMPUTED, class RI>
181    struct vector_assign_traits {
182        typedef SC storage_category;
183    };
184
185    template<bool COMPUTED>
186    struct vector_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag> {
187        typedef packed_tag storage_category;
188    };
189    template<>
190    struct vector_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag> {
191        typedef sparse_tag storage_category;
192    };
193    template<>
194    struct vector_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag> {
195        typedef sparse_proxy_tag storage_category;
196    };
197
198    template<bool COMPUTED>
199    struct vector_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag> {
200        typedef packed_proxy_tag storage_category;
201    };
202    template<>
203    struct vector_assign_traits<dense_proxy_tag, false, sparse_bidirectional_iterator_tag> {
204        typedef sparse_proxy_tag storage_category;
205    };
206    template<>
207    struct vector_assign_traits<dense_proxy_tag, true, sparse_bidirectional_iterator_tag> {
208        typedef sparse_proxy_tag storage_category;
209    };
210
211    template<>
212    struct vector_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag> {
213        typedef sparse_tag storage_category;
214    };
215    template<>
216    struct vector_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag> {
217        typedef sparse_proxy_tag storage_category;
218    };
219
220    template<bool COMPUTED>
221    struct vector_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag> {
222        typedef sparse_proxy_tag storage_category;
223    };
224
225    template<>
226    struct vector_assign_traits<sparse_tag, true, dense_random_access_iterator_tag> {
227        typedef sparse_proxy_tag storage_category;
228    };
229    template<>
230    struct vector_assign_traits<sparse_tag, true, packed_random_access_iterator_tag> {
231        typedef sparse_proxy_tag storage_category;
232    };
233    template<>
234    struct vector_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag> {
235        typedef sparse_proxy_tag storage_category;
236    };
237
238    // Explicitly iterating
239    template<template <class T1, class T2> class F, class V, class E>
240    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
241    void iterating_vector_assign (V &v, const vector_expression<E> &e) {
242        typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
243        typedef typename V::difference_type difference_type;
244        difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
245        typename V::iterator it (v.begin ());
246        BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
247        typename E::const_iterator ite (e ().begin ());
248        BOOST_UBLAS_CHECK (e ().end () - ite == size, bad_size ());
249#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
250        while (-- size >= 0)
251            functor_type::apply (*it, *ite), ++ it, ++ ite;
252#else
253        DD (size, 2, r, (functor_type::apply (*it, *ite), ++ it, ++ ite));
254#endif
255    }
256    // Explicitly indexing
257    template<template <class T1, class T2> class F, class V, class E>
258    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
259    void indexing_vector_assign (V &v, const vector_expression<E> &e) {
260        typedef F<typename V::reference, typename E::value_type> functor_type;
261        typedef typename V::size_type size_type;
262        size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
263#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
264        for (size_type i = 0; i < size; ++ i)
265            functor_type::apply (v (i), e () (i));
266#else
267        size_type i (0);
268        DD (size, 2, r, (functor_type::apply (v (i), e () (i)), ++ i));
269#endif
270    }
271
272    // Dense (proxy) case
273    template<template <class T1, class T2> class F, class V, class E>
274    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
275    void vector_assign (V &v, const vector_expression<E> &e, dense_proxy_tag) {
276#ifdef BOOST_UBLAS_USE_INDEXING
277        indexing_vector_assign<F> (v, e);
278#elif BOOST_UBLAS_USE_ITERATING
279        iterating_vector_assign<F> (v, e);
280#else
281        typedef typename V::size_type size_type;
282        size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
283        if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
284            iterating_vector_assign<F> (v, e);
285        else
286            indexing_vector_assign<F> (v, e);
287#endif
288    }
289    // Packed (proxy) case
290    template<template <class T1, class T2> class F, class V, class E>
291    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
292    void vector_assign (V &v, const vector_expression<E> &e, packed_proxy_tag) {
293        BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
294        typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
295        typedef typename V::difference_type difference_type;
296        typedef typename V::value_type value_type;
297#if BOOST_UBLAS_TYPE_CHECK
298        vector<value_type> cv (v.size ());
299        indexing_vector_assign<scalar_assign> (cv, v);
300        indexing_vector_assign<F> (cv, e);
301#endif
302        typename V::iterator it (v.begin ());
303        typename V::iterator it_end (v.end ());
304        typename E::const_iterator ite (e ().begin ());
305        typename E::const_iterator ite_end (e ().end ());
306        difference_type it_size (it_end - it);
307        difference_type ite_size (ite_end - ite);
308        if (it_size > 0 && ite_size > 0) {
309            difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
310            if (size > 0) {
311                ite += size;
312                ite_size -= size;
313            }
314        }
315        if (it_size > 0 && ite_size > 0) {
316            difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
317            if (size > 0) {
318                it_size -= size;
319                if (!functor_type::computed) {
320                    while (-- size >= 0)    // zeroing
321                        functor_type::apply (*it, value_type/*zero*/()), ++ it;
322                } else {
323                    it += size;
324                }
325            }
326        }
327        difference_type size ((std::min) (it_size, ite_size));
328        it_size -= size;
329        ite_size -= size;
330        while (-- size >= 0)
331            functor_type::apply (*it, *ite), ++ it, ++ ite;
332        size = it_size;
333        if (!functor_type::computed) {
334            while (-- size >= 0)    // zeroing
335                functor_type::apply (*it, value_type/*zero*/()), ++ it;
336        } else {
337            it += size;
338        }
339#if BOOST_UBLAS_TYPE_CHECK
340        if (! disable_type_check<bool>::value) 
341            BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv), 
342                               external_logic ("external logic or bad condition of inputs"));
343#endif
344    }
345    // Sparse case
346    template<template <class T1, class T2> class F, class V, class E>
347    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
348    void vector_assign (V &v, const vector_expression<E> &e, sparse_tag) {
349        BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
350        typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
351        BOOST_STATIC_ASSERT ((!functor_type::computed));
352        typedef typename V::value_type value_type;
353#if BOOST_UBLAS_TYPE_CHECK
354        vector<value_type> cv (v.size ());
355        indexing_vector_assign<scalar_assign> (cv, v);
356        indexing_vector_assign<F> (cv, e);
357#endif
358        v.clear ();
359        typename E::const_iterator ite (e ().begin ());
360        typename E::const_iterator ite_end (e ().end ());
361        while (ite != ite_end) {
362            value_type t (*ite);
363            if (t != value_type/*zero*/())
364                v.insert_element (ite.index (), t);
365            ++ ite;
366        }
367#if BOOST_UBLAS_TYPE_CHECK
368        if (! disable_type_check<bool>::value) 
369            BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv), 
370                               external_logic ("external logic or bad condition of inputs"));
371#endif
372    }
373    // Sparse proxy or functional case
374    template<template <class T1, class T2> class F, class V, class E>
375    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
376    void vector_assign (V &v, const vector_expression<E> &e, sparse_proxy_tag) {
377        BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
378        typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
379        typedef typename V::size_type size_type;
380        typedef typename V::difference_type difference_type;
381        typedef typename V::value_type value_type;
382        typedef typename V::reference reference;
383#if BOOST_UBLAS_TYPE_CHECK
384        vector<value_type> cv (v.size ());
385        indexing_vector_assign<scalar_assign> (cv, v);
386        indexing_vector_assign<F> (cv, e);
387#endif
388        detail::make_conformant (v, e);
389
390        typename V::iterator it (v.begin ());
391        typename V::iterator it_end (v.end ());
392        typename E::const_iterator ite (e ().begin ());
393        typename E::const_iterator ite_end (e ().end ());
394        if (it != it_end && ite != ite_end) {
395            size_type it_index = it.index (), ite_index = ite.index ();
396            while (true) {
397                difference_type compare = it_index - ite_index;
398                if (compare == 0) {
399                    functor_type::apply (*it, *ite);
400                    ++ it, ++ ite;
401                    if (it != it_end && ite != ite_end) {
402                        it_index = it.index ();
403                        ite_index = ite.index ();
404                    } else
405                        break;
406                } else if (compare < 0) {
407                    if (!functor_type::computed) {
408                        functor_type::apply (*it, value_type/*zero*/());
409                        ++ it;
410                    } else
411                        increment (it, it_end, - compare);
412                    if (it != it_end)
413                        it_index = it.index ();
414                    else
415                        break;
416                } else if (compare > 0) {
417                    increment (ite, ite_end, compare);
418                    if (ite != ite_end)
419                        ite_index = ite.index ();
420                    else
421                        break;
422                }
423            }
424        }
425
426        if (!functor_type::computed) {
427            while (it != it_end) {  // zeroing
428                functor_type::apply (*it, value_type/*zero*/());
429                ++ it;
430            }
431        } else {
432            it = it_end;
433        }
434#if BOOST_UBLAS_TYPE_CHECK
435        if (! disable_type_check<bool>::value)
436            BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv), 
437                               external_logic ("external logic or bad condition of inputs"));
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
Note: See TracBrowser for help on using the repository browser.