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_DEFINITIONS_
14 #define _BOOST_UBLAS_DEFINITIONS_
15 
16 
17 namespace boost { namespace numeric { namespace ublas {
18 
19     namespace detail {
20         /* Borrowed from boost/concept_checks.hpp
21            "inline" is used for ignore_unused_variable_warning()
22            to make sure there is no overhead with g++.
23          */
24         template <class T> inline
ignore_unused_variable_warning(const T &)25         void ignore_unused_variable_warning(const T&) {}
26     } // namespace detail
27 
28     // Borrowed from Dave Abraham's noncopyable.
29     // I believe this should be part of utility.hpp one day...
30     namespace nonassignable_  // protection from unintended ADL
31     {
32         class nonassignable {
33         protected:
nonassignable()34             nonassignable () {}
~nonassignable()35             ~nonassignable () {}
36         private:  // emphasize the following members are private
37             const nonassignable& operator= (const nonassignable &);
38         }; // nonassignable
39     }
40     typedef nonassignable_::nonassignable nonassignable;
41 
42 
43     // Assignment proxy.
44     // Provides temporary free assigment when LHS has no alias on RHS
45     template<class C>
46     class noalias_proxy:
47         private nonassignable {
48     public:
49         typedef typename C::closure_type closure_type;
50 
51         BOOST_UBLAS_INLINE
noalias_proxy(C & lval)52         noalias_proxy (C& lval):
53             nonassignable (), lval_ (lval) {}
54         BOOST_UBLAS_INLINE
noalias_proxy(const noalias_proxy & p)55         noalias_proxy (const noalias_proxy& p):
56             nonassignable (), lval_ (p.lval_) {}
57 
58         template <class E>
59         BOOST_UBLAS_INLINE
operator =(const E & e)60         closure_type &operator= (const E& e) {
61             lval_.assign (e);
62             return lval_;
63         }
64 
65         template <class E>
66         BOOST_UBLAS_INLINE
operator +=(const E & e)67         closure_type &operator+= (const E& e) {
68             lval_.plus_assign (e);
69             return lval_;
70         }
71 
72         template <class E>
73         BOOST_UBLAS_INLINE
operator -=(const E & e)74         closure_type &operator-= (const E& e) {
75             lval_.minus_assign (e);
76             return lval_;
77         }
78 
79     private:
80         closure_type lval_;
81     };
82 
83     // Improve syntax of efficient assignment where no aliases of LHS appear on the RHS
84     //  noalias(lhs) = rhs_expression
85     template <class C>
86     BOOST_UBLAS_INLINE
noalias(C & lvalue)87     noalias_proxy<C> noalias (C& lvalue) {
88         return noalias_proxy<C> (lvalue);
89     }
90     template <class C>
91     BOOST_UBLAS_INLINE
noalias(const C & lvalue)92     noalias_proxy<const C> noalias (const C& lvalue) {
93         return noalias_proxy<const C> (lvalue);
94     }
95 
96     // Possible future compatible syntax where lvalue possible has an unsafe alias on the RHS
97     //  safe(lhs) = rhs_expression
98     template <class C>
99     BOOST_UBLAS_INLINE
safe(C & lvalue)100     C& safe (C& lvalue) {
101         return lvalue;
102     }
103     template <class C>
104     BOOST_UBLAS_INLINE
safe(const C & lvalue)105     const C& safe (const C& lvalue) {
106         return lvalue;
107     }
108 
109 
110     // Dimension accessors
111     namespace dimension {
112 
113         // Generic accessors
114         template<unsigned dimension>
115         struct dimension_properties {};
116 
117         template<>
118         struct dimension_properties<1> {
119             template <class E>
120             BOOST_UBLAS_INLINE static
sizeboost::numeric::ublas::dimension::dimension_properties121             typename E::size_type size (const vector_expression<E> &e) {
122                 return e ().size ();
123             }
124             template <class E>
125             BOOST_UBLAS_INLINE static
sizeboost::numeric::ublas::dimension::dimension_properties126             typename E::size_type size (const matrix_expression<E> &e) {
127                 return e ().size1 ();
128             }
129             // Note: Index functions cannot deduce dependant template parameter V or M from i
130             template <class V>
131             BOOST_UBLAS_INLINE static
indexboost::numeric::ublas::dimension::dimension_properties132             typename V::size_type index (const typename V::iterator &i) {
133                 return i.index ();
134             }
135             template <class M>
136             BOOST_UBLAS_INLINE static
indexboost::numeric::ublas::dimension::dimension_properties137             typename M::size_type index (const typename M::iterator1 &i) {
138                 return i.index1 ();
139             }
140             template <class M>
141             BOOST_UBLAS_INLINE static
indexboost::numeric::ublas::dimension::dimension_properties142             typename M::size_type index (const typename M::iterator2 &i) {
143                 return i.index1 ();
144             }
145         };
146         template<>
147         struct dimension_properties<2> {
148             template <class E>
149             BOOST_UBLAS_INLINE static
sizeboost::numeric::ublas::dimension::dimension_properties150             typename E::size_type size (const vector_expression<E> &) {
151                 return 1;
152             }
153             template <class E>
154             BOOST_UBLAS_INLINE static
sizeboost::numeric::ublas::dimension::dimension_properties155             typename E::size_type size (const matrix_expression<E> &e) {
156                 return e ().size2 ();
157             }
158             template <class V>
159             BOOST_UBLAS_INLINE static
indexboost::numeric::ublas::dimension::dimension_properties160             typename V::size_type index (const typename V::iterator &) {
161                 return 1;
162             }
163             template <class M>
164             BOOST_UBLAS_INLINE static
indexboost::numeric::ublas::dimension::dimension_properties165             typename M::size_type index (const typename M::iterator1 &i) {
166                 return i.index2 ();
167             }
168             template <class M>
169             BOOST_UBLAS_INLINE static
indexboost::numeric::ublas::dimension::dimension_properties170             typename M::size_type index (const typename M::iterator2 &i) {
171                 return i.index2 ();
172             }
173         };
174 
175         template<unsigned dimension, class E>
176         BOOST_UBLAS_INLINE
size(const E & e)177         typename E::size_type size (const E& e) {
178             return dimension_properties<dimension>::size (e);
179         }
180 
181         template<unsigned dimension, class I>
182         BOOST_UBLAS_INLINE
183         typename I::container_type::size_type
index(const I & i)184         index (const I& i) {
185             typedef typename I::container_type container_type;
186             return dimension_properties<dimension>::template index<container_type> (i);
187         }
188 
189 
190         // Named accessors - just syntactic sugar
191         template<class V>
num_elements(const V & v)192         typename V::size_type num_elements (const V &v) {
193             return v.size ();
194         }
195         template<class M>
num_rows(const M & m)196         typename M::size_type num_rows (const M &m) {
197             return m.size1 ();
198         }
199         template<class M>
num_columns(const M & m)200         typename M::size_type num_columns (const M &m) {
201             return m.size2 ();
202         }
203         template<class MV>
num_non_zeros(const MV & mv)204         typename MV::size_type num_non_zeros (const MV &mv) {
205             return mv.non_zeros ();
206         }
207     }
208 
209 
210 }}}
211 
212 #endif
213