1 //
2 // Copyright (c) 2009 Rutger ter Borg
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 
9 #ifndef BOOST_NUMERIC_BINDINGS_BEGIN_HPP
10 #define BOOST_NUMERIC_BINDINGS_BEGIN_HPP
11 
12 #include <boost/numeric/bindings/detail/adaptor.hpp>
13 #include <boost/numeric/bindings/detail/linear_iterator.hpp>
14 #include <boost/numeric/bindings/detail/generate_functions.hpp>
15 #include <boost/numeric/bindings/rank.hpp>
16 #include <boost/numeric/bindings/stride.hpp>
17 #include <boost/numeric/bindings/value_type.hpp>
18 #include <iostream>
19 
20 namespace boost {
21 namespace numeric {
22 namespace bindings {
23 
24 namespace detail {
25 
26 template< typename T, typename Tag >
27 struct begin_impl {};
28 
29 template< typename T >
30 struct begin_impl< T, tag::value > {
31     typedef typename bindings::value_type< T>::type* result_type;
32 
invokeboost::numeric::bindings::detail::begin_impl33     static result_type invoke( T& t ) {
34         return adaptor_access<T>::begin_value( t );
35     }
36 };
37 
38 template< typename T, int Dimension >
39 struct begin_impl<T, tag::addressing_index<Dimension> > {
40 
41     typedef tag::addressing_index<Dimension> tag_type;
42 
43     typedef linear_iterator<
44         typename bindings::value_type< T>::type,
45         typename result_of::stride< T, tag_type >::type
46     > result_type;
47 
invokeboost::numeric::bindings::detail::begin_impl48     static result_type invoke( T& t ) {
49         return result_type( adaptor_access<T>::begin_value( t ), bindings::stride(t, tag_type() ) );
50     }
51 };
52 
53 template< typename T >
54 struct begin_impl< T, tag::index_major > {
55     typedef typename detail::property_at< T, tag::index_type >::type* result_type;
56 
invokeboost::numeric::bindings::detail::begin_impl57     static result_type invoke( T& t ) {
58         return adaptor_access<T>::begin_index_major( t );
59     }
60 };
61 
62 template< typename T >
63 struct begin_impl< T, tag::compressed_index_major > {
64     typedef typename detail::property_at< T, tag::index_type >::type* result_type;
65 
invokeboost::numeric::bindings::detail::begin_impl66     static result_type invoke( T& t ) {
67         return adaptor_access<T>::begin_compressed_index_major( t );
68     }
69 };
70 
71 template< typename T >
72 struct begin_impl< T, tag::index_minor > {
73     typedef typename detail::property_at< T, tag::index_type >::type* result_type;
74 
invokeboost::numeric::bindings::detail::begin_impl75     static result_type invoke( T& t ) {
76         return adaptor_access<T>::begin_index_minor( t );
77     }
78 };
79 
80 } // namespace detail
81 
82 namespace result_of {
83 
84 template< typename T, typename Tag = tag::addressing_index<1> >
85 struct begin {
86     BOOST_STATIC_ASSERT( (is_tag<Tag>::value) );
87     typedef typename detail::begin_impl<T,Tag>::result_type type;
88 };
89 
90 } // namespace result_of
91 
92 //
93 // Free Functions
94 //
95 
96 //
97 // Overloads like begin( t, tag )
98 //
99 template< typename T, typename Tag >
100 inline typename result_of::begin<T,Tag>::type
begin(T & t,Tag)101 begin( T& t, Tag ) {
102     return detail::begin_impl<T,Tag>::invoke( t );
103 }
104 
105 template< typename T, typename Tag >
106 inline typename result_of::begin<const T,Tag>::type
begin(const T & t,Tag)107 begin( const T& t, Tag ) {
108     return detail::begin_impl<const T,Tag>::invoke( t );
109 }
110 
111 // Overloads for types with rank <= 1 (scalars, vectors)
112 // In theory, we could provide overloads for matrices here, too,
113 // if their minimal_rank is at most 1.
114 
115 template< typename T >
116 typename boost::enable_if< mpl::less< rank<T>, mpl::int_<2> >,
117     typename result_of::begin< T >::type >::type
begin(T & t)118 begin( T& t ) {
119     return detail::begin_impl< T, tag::addressing_index<1> >::invoke( t );
120 }
121 
122 template< typename T >
123 typename boost::enable_if< mpl::less< rank<T>, mpl::int_<2> >,
124     typename result_of::begin< const T >::type >::type
begin(const T & t)125 begin( const T& t ) {
126     return detail::begin_impl< const T, tag::addressing_index<1> >::invoke( t );
127 }
128 
129 #define GENERATE_BEGIN_INDEX( z, which, unused ) \
130 GENERATE_FUNCTIONS( begin, which, tag::addressing_index<which> )
131 
132 BOOST_PP_REPEAT_FROM_TO(1,3,GENERATE_BEGIN_INDEX,~)
133 GENERATE_FUNCTIONS( begin, _value, tag::value )
134 GENERATE_FUNCTIONS( begin, _row, tag::addressing_index<1> )
135 GENERATE_FUNCTIONS( begin, _column, tag::addressing_index<2> )
136 
137 GENERATE_FUNCTIONS( begin, _index_major, tag::index_major )
138 GENERATE_FUNCTIONS( begin, _compressed_index_major, tag::compressed_index_major )
139 GENERATE_FUNCTIONS( begin, _index_minor, tag::index_minor )
140 
141 } // namespace bindings
142 } // namespace numeric
143 } // namespace boost
144 
145 #endif
146