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 |
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: |
34 | 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 |
52 | noalias_proxy (C& lval): |
53 | nonassignable (), lval_ (lval) {} |
54 | BOOST_UBLAS_INLINE |
55 | noalias_proxy (const noalias_proxy& p): |
56 | nonassignable (), lval_ (p.lval_) {} |
57 | |
58 | template <class E> |
59 | BOOST_UBLAS_INLINE |
60 | closure_type &operator= (const E& e) { |
61 | lval_.assign (e); |
62 | return lval_; |
63 | } |
64 | |
65 | template <class E> |
66 | BOOST_UBLAS_INLINE |
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 |
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 |
87 | noalias_proxy<C> noalias (C& lvalue) { |
88 | return noalias_proxy<C> (lvalue); |
89 | } |
90 | template <class C> |
91 | BOOST_UBLAS_INLINE |
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 |
100 | C& safe (C& lvalue) { |
101 | return lvalue; |
102 | } |
103 | template <class C> |
104 | BOOST_UBLAS_INLINE |
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 |
121 | typename E::size_type size (const vector_expression<E> &e) { |
122 | return e ().size (); |
123 | } |
124 | template <class E> |
125 | BOOST_UBLAS_INLINE static |
126 | 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 |
132 | typename V::size_type index (const typename V::iterator &i) { |
133 | return i.index (); |
134 | } |
135 | template <class M> |
136 | BOOST_UBLAS_INLINE static |
137 | typename M::size_type index (const typename M::iterator1 &i) { |
138 | return i.index1 (); |
139 | } |
140 | template <class M> |
141 | BOOST_UBLAS_INLINE static |
142 | 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 |
150 | typename E::size_type size (const vector_expression<E> &) { |
151 | return 1; |
152 | } |
153 | template <class E> |
154 | BOOST_UBLAS_INLINE static |
155 | typename E::size_type size (const matrix_expression<E> &e) { |
156 | return e ().size2 (); |
157 | } |
158 | template <class V> |
159 | BOOST_UBLAS_INLINE static |
160 | typename V::size_type index (const typename V::iterator &) { |
161 | return 1; |
162 | } |
163 | template <class M> |
164 | BOOST_UBLAS_INLINE static |
165 | typename M::size_type index (const typename M::iterator1 &i) { |
166 | return i.index2 (); |
167 | } |
168 | template <class M> |
169 | BOOST_UBLAS_INLINE static |
170 | 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 |
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 |
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> |
192 | typename V::size_type num_elements (const V &v) { |
193 | return v.size (); |
194 | } |
195 | template<class M> |
196 | typename M::size_type num_rows (const M &m) { |
197 | return m.size1 (); |
198 | } |
199 | template<class M> |
200 | typename M::size_type num_columns (const M &m) { |
201 | return m.size2 (); |
202 | } |
203 | template<class 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 | |