1 /**
2  * \file size.hpp
3  *
4  * \brief The family of \c size operations.
5  *
6  * Copyright (c) 2009-2010, Marco Guazzone
7  *
8  * Distributed under the Boost Software License, Version 1.0. (See
9  * accompanying file LICENSE_1_0.txt or copy at
10  * http://www.boost.org/LICENSE_1_0.txt)
11  *
12  * \author Marco Guazzone, marco.guazzone@gmail.com
13  */
14 
15 #ifndef BOOST_NUMERIC_UBLAS_OPERATION_SIZE_HPP
16 #define BOOST_NUMERIC_UBLAS_OPERATION_SIZE_HPP
17 
18 
19 #include <boost/mpl/has_xxx.hpp>
20 #include <boost/mpl/if.hpp>
21 #include <boost/numeric/ublas/detail/config.hpp>
22 #include <boost/numeric/ublas/expression_types.hpp>
23 #include <boost/numeric/ublas/fwd.hpp>
24 #include <boost/numeric/ublas/tags.hpp>
25 #include <boost/numeric/ublas/traits.hpp>
26 #include <boost/utility/enable_if.hpp>
27 #include <cstddef>
28 
29 
30 namespace boost { namespace numeric { namespace ublas {
31 
32 namespace detail { namespace /*<unnamed>*/ {
33 
34 /// Define a \c has_size_type trait class.
35 BOOST_MPL_HAS_XXX_TRAIT_DEF(size_type)
36 
37 
38 /**
39  * \brief Wrapper type-traits used in \c boost::lazy_enabled_if for getting the
40  *  size type (see below).
41  * \tparam VectorT A vector type.
42  */
43 template <typename VectorT>
44 struct vector_size_type
45 {
46     /// The size type.
47     typedef typename vector_traits<VectorT>::size_type type;
48 };
49 
50 /**
51  * \brief Wrapper type-traits used in \c boost::lazy_enabled_if for getting the
52  *  size type (see below).
53  * \tparam MatrixT A matrix type.
54  */
55 template <typename MatrixT>
56 struct matrix_size_type
57 {
58     /// The size type.
59     typedef typename matrix_traits<MatrixT>::size_type type;
60 };
61 
62 
63 /**
64  * \brief Auxiliary class for computing the size of the given dimension for
65  *  a container of the given category.
66  * \tparam Dim The dimension number (starting from 1).
67  * \tparam CategoryT The category type (e.g., vector_tag).
68  */
69 template <std::size_t Dim, typename CategoryT>
70 struct size_by_dim_impl;
71 
72 
73 /**
74  * \brief Auxiliary class for computing the size of the given dimension for
75  *  a container of the given category and with the given orientation.
76  * \tparam Dim The dimension number (starting from 1).
77  * \tparam CategoryT The category type (e.g., vector_tag).
78  * \tparam OrientationT The orientation category type (e.g., row_major_tag).
79  */
80 template <typename TagT, typename CategoryT, typename OrientationT>
81 struct size_by_tag_impl;
82 
83 
84 /**
85  * \brief Specialization of \c size_by_dim_impl for computing the size of a
86  *  vector.
87  */
88 template <>
89 struct size_by_dim_impl<1, vector_tag>
90 {
91     /**
92      * \brief Compute the size of the given vector.
93      * \tparam ExprT A vector expression type.
94      * \pre ExprT must be a model of VectorExpression.
95      */
96     template <typename ExprT>
97     BOOST_UBLAS_INLINE
applyboost::numeric::ublas::detail::__anonc4b93feb0111::size_by_dim_impl98     static typename vector_traits<ExprT>::size_type apply(vector_expression<ExprT> const& ve)
99     {
100         return ve().size();
101     }
102 };
103 
104 
105 /**
106  * \brief Specialization of \c size_by_dim_impl for computing the number of
107  *  rows of a matrix
108  */
109 template <>
110 struct size_by_dim_impl<1, matrix_tag>
111 {
112     /**
113      * \brief Compute the number of rows of the given matrix.
114      * \tparam ExprT A matrix expression type.
115      * \pre ExprT must be a model of MatrixExpression.
116      */
117     template <typename ExprT>
118     BOOST_UBLAS_INLINE
applyboost::numeric::ublas::detail::__anonc4b93feb0111::size_by_dim_impl119     static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
120     {
121         return me().size1();
122     }
123 };
124 
125 
126 /**
127  * \brief Specialization of \c size_by_dim_impl for computing the number of
128  *  columns of a matrix
129  */
130 template <>
131 struct size_by_dim_impl<2, matrix_tag>
132 {
133     /**
134      * \brief Compute the number of columns of the given matrix.
135      * \tparam ExprT A matrix expression type.
136      * \pre ExprT must be a model of MatrixExpression.
137      */
138     template <typename ExprT>
139     BOOST_UBLAS_INLINE
applyboost::numeric::ublas::detail::__anonc4b93feb0111::size_by_dim_impl140     static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
141     {
142         return me().size2();
143     }
144 };
145 
146 
147 /**
148  * \brief Specialization of \c size_by_tag_impl for computing the size of the
149  *  major dimension of a row-major oriented matrix.
150  */
151 template <>
152 struct size_by_tag_impl<tag::major, matrix_tag, row_major_tag>
153 {
154     /**
155      * \brief Compute the number of rows of the given matrix.
156      * \tparam ExprT A matrix expression type.
157      * \pre ExprT must be a model of MatrixExpression.
158      */
159     template <typename ExprT>
160     BOOST_UBLAS_INLINE
applyboost::numeric::ublas::detail::__anonc4b93feb0111::size_by_tag_impl161     static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
162     {
163         return me().size1();
164     }
165 };
166 
167 
168 /**
169  * \brief Specialization of \c size_by_tag_impl for computing the size of the
170  *  minor dimension of a row-major oriented matrix.
171  */
172 template <>
173 struct size_by_tag_impl<tag::minor, matrix_tag, row_major_tag>
174 {
175     /**
176      * \brief Compute the number of columns of the given matrix.
177      * \tparam ExprT A matrix expression type.
178      * \pre ExprT must be a model of MatrixExpression.
179      */
180     template <typename ExprT>
181     BOOST_UBLAS_INLINE
applyboost::numeric::ublas::detail::__anonc4b93feb0111::size_by_tag_impl182     static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
183     {
184         return me().size2();
185     }
186 };
187 
188 
189 /**
190  * \brief Specialization of \c size_by_tag_impl for computing the size of the
191  *  leading dimension of a row-major oriented matrix.
192  */
193 template <>
194 struct size_by_tag_impl<tag::leading, matrix_tag, row_major_tag>
195 {
196     /**
197      * \brief Compute the number of columns of the given matrix.
198      * \tparam ExprT A matrix expression type.
199      * \pre ExprT must be a model of MatrixExpression.
200      */
201     template <typename ExprT>
202     BOOST_UBLAS_INLINE
applyboost::numeric::ublas::detail::__anonc4b93feb0111::size_by_tag_impl203     static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
204     {
205         return me().size2();
206     }
207 };
208 
209 
210 /// \brief Specialization of \c size_by_tag_impl for computing the size of the
211 ///  major dimension of a column-major oriented matrix.
212 template <>
213 struct size_by_tag_impl<tag::major, matrix_tag, column_major_tag>
214 {
215     /**
216      * \brief Compute the number of columns of the given matrix.
217      * \tparam ExprT A matrix expression type.
218      * \pre ExprT must be a model of MatrixExpression.
219      */
220     template <typename ExprT>
221     BOOST_UBLAS_INLINE
applyboost::numeric::ublas::detail::__anonc4b93feb0111::size_by_tag_impl222     static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
223     {
224         return me().size2();
225     }
226 };
227 
228 
229 /// \brief Specialization of \c size_by_tag_impl for computing the size of the
230 ///  minor dimension of a column-major oriented matrix.
231 template <>
232 struct size_by_tag_impl<tag::minor, matrix_tag, column_major_tag>
233 {
234     /**
235      * \brief Compute the number of rows of the given matrix.
236      * \tparam ExprT A matrix expression type.
237      * \pre ExprT must be a model of MatrixExpression.
238      */
239     template <typename ExprT>
240     BOOST_UBLAS_INLINE
applyboost::numeric::ublas::detail::__anonc4b93feb0111::size_by_tag_impl241     static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
242     {
243         return me().size1();
244     }
245 };
246 
247 
248 /// \brief Specialization of \c size_by_tag_impl for computing the size of the
249 ///  leading dimension of a column-major oriented matrix.
250 template <>
251 struct size_by_tag_impl<tag::leading, matrix_tag, column_major_tag>
252 {
253     /**
254      * \brief Compute the number of rows of the given matrix.
255      * \tparam ExprT A matrix expression type.
256      * \pre ExprT must be a model of MatrixExpression.
257      */
258     template <typename ExprT>
259     BOOST_UBLAS_INLINE
applyboost::numeric::ublas::detail::__anonc4b93feb0111::size_by_tag_impl260     static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
261     {
262         return me().size1();
263     }
264 };
265 
266 
267 /// \brief Specialization of \c size_by_tag_impl for computing the size of the
268 ///  given dimension of a unknown oriented expression.
269 template <typename TagT, typename CategoryT>
270 struct size_by_tag_impl<TagT, CategoryT, unknown_orientation_tag>: size_by_tag_impl<TagT, CategoryT, row_major_tag>
271 {
272     // Empty
273 };
274 
275 }} // Namespace detail::<unnamed>
276 
277 
278 /**
279  * \brief Return the number of columns.
280  * \tparam VectorExprT A type which models the vector expression concept.
281  * \param ve A vector expression.
282  * \return The length of the input vector expression.
283  */
284 template <typename VectorExprT>
285 BOOST_UBLAS_INLINE
286 typename ::boost::lazy_enable_if_c<
287     detail::has_size_type<VectorExprT>::value,
288     detail::vector_size_type<VectorExprT>
size(vector_expression<VectorExprT> const & ve)289 >::type size(vector_expression<VectorExprT> const& ve)
290 {
291     return ve().size();
292 }
293 
294 
295 /**
296  * \brief Return the size of the given dimension for the given vector
297  *  expression.
298  * \tparam Dim The dimension number (starting from 1).
299  * \tparam VectorExprT A vector expression type.
300  * \param ve A vector expression.
301  * \return The length of the input vector expression.
302  */
303 template <std::size_t Dim, typename VectorExprT>
304 BOOST_UBLAS_INLINE
size(vector_expression<VectorExprT> const & ve)305 typename vector_traits<VectorExprT>::size_type size(vector_expression<VectorExprT> const& ve)
306 {
307     return detail::size_by_dim_impl<Dim, vector_tag>::template apply(ve);
308 }
309 
310 
311 /**
312  * \brief Return the size of the given dimension for the given matrix
313  *  expression.
314  * \tparam Dim The dimension number (starting from 1).
315  * \tparam MatrixExprT A matrix expression type.
316  * \param e A matrix expression.
317  * \return The size of the input matrix expression associated to the dimension
318  *  \a Dim.
319  */
320 template <std::size_t Dim, typename MatrixExprT>
321 BOOST_UBLAS_INLINE
size(matrix_expression<MatrixExprT> const & me)322 typename matrix_traits<MatrixExprT>::size_type size(matrix_expression<MatrixExprT> const& me)
323 {
324     return detail::size_by_dim_impl<Dim, matrix_tag>::template apply(me);
325 }
326 
327 
328 /**
329  * \brief Return the size of the given dimension tag for the given matrix
330  *  expression.
331  * \tparam TagT The dimension tag type (e.g., tag::major).
332  * \tparam MatrixExprT A matrix expression type.
333  * \param e A matrix expression.
334  * \return The size of the input matrix expression associated to the dimension
335  *  tag \a TagT.
336  */
337 template <typename TagT, typename MatrixExprT>
338 BOOST_UBLAS_INLINE
339 typename ::boost::lazy_enable_if_c<
340     detail::has_size_type<MatrixExprT>::value,
341     detail::matrix_size_type<MatrixExprT>
size(matrix_expression<MatrixExprT> const & me)342 >::type size(matrix_expression<MatrixExprT> const& me)
343 {
344     return detail::size_by_tag_impl<TagT, matrix_tag, typename matrix_traits<MatrixExprT>::orientation_category>::template apply(me);
345 }
346 
347 }}} // Namespace boost::numeric::ublas
348 
349 
350 #endif // BOOST_NUMERIC_UBLAS_OPERATION_SIZE_HPP
351