-
Notifications
You must be signed in to change notification settings - Fork 298
/
size.hpp
155 lines (121 loc) · 4.59 KB
/
size.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//
// Copyright (c) 2009 Rutger ter Borg
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_NUMERIC_BINDINGS_SIZE_HPP
#define BOOST_NUMERIC_BINDINGS_SIZE_HPP
#include <Core/Utils/numeric/bindings/detail/generate_functions.hpp>
#include <Core/Utils/numeric/bindings/detail/get.hpp>
#include <Core/Utils/numeric/bindings/rank.hpp>
#include <Core/Utils/numeric/bindings/addressing_index.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/min.hpp>
#include <boost/mpl/greater.hpp>
#include <boost/mpl/less_equal.hpp>
#include <boost/static_assert.hpp>
namespace boost {
namespace numeric {
namespace bindings {
namespace detail {
template< typename T, typename AddressingIndex, typename Enable = void >
struct size_impl {
typedef typename tag::size_type< AddressingIndex::value > key_type;
typedef typename result_of_get< T, key_type >::type result_type;
static result_type invoke( const T& t ) {
return get< key_type >( t );
}
};
template< typename T, typename AddressingIndex >
struct size_impl< T, AddressingIndex,
typename boost::enable_if< typename mpl::and_<
mpl::greater< AddressingIndex, rank<T> >,
is_same_at< T, tag::size_type<1>, std::ptrdiff_t >
>::type >::type > {
typedef std::ptrdiff_t result_type;
static result_type invoke( const T& t ) {
return std::min< std::ptrdiff_t >( size_impl<T, tag::addressing_index<1> >::invoke(t), 1 );
}
};
template< typename T, typename AddressingIndex >
struct size_impl< T, AddressingIndex,
typename boost::enable_if< typename mpl::and_<
mpl::greater< AddressingIndex, rank<T> >,
mpl::not_< is_same_at< T, tag::size_type<1>, std::ptrdiff_t > >
>::type >::type > {
typedef typename mpl::min<
typename detail::property_at< T, tag::size_type<1> >::type,
mpl::int_<1>
>::type result_type;
static result_type invoke( const T& t ) {
return result_type();
}
};
} // namespace detail
namespace result_of {
template< typename T, typename Tag = tag::addressing_index<1> >
struct size {
BOOST_STATIC_ASSERT( (is_tag<Tag>::value) );
typedef typename detail::size_impl< T, Tag >::result_type type;
};
} // namespace result_of
//
// Overloads for free template functions size( x, tag ),
//
template< typename T, typename Tag >
inline typename result_of::size< const T, Tag >::type
size( const T& t, Tag ) {
return detail::size_impl< const T, Tag >::invoke( t );
}
// Overloads for free template function size( x )
// Valid for types with rank <= 1 (scalars, vectors)
// In theory, we could provide overloads for matrices here, too,
// if their minimal_rank is at most 1.
template< typename T >
typename boost::enable_if< mpl::less< rank<T>, mpl::int_<2> >,
typename result_of::size< const T >::type >::type
size( const T& t ) {
return detail::size_impl< const T, tag::addressing_index<1> >::invoke( t );
}
#define GENERATE_SIZE_INDEX( z, which, unused ) \
GENERATE_FUNCTIONS( size, which, tag::addressing_index<which> )
BOOST_PP_REPEAT_FROM_TO(1,3,GENERATE_SIZE_INDEX,~)
GENERATE_FUNCTIONS( size, _row, tag::addressing_index<1> )
GENERATE_FUNCTIONS( size, _column, tag::addressing_index<2> )
GENERATE_FUNCTIONS( size, _major, typename addressing_index_major<T>::type )
GENERATE_FUNCTIONS( size, _minor, typename addressing_index_minor<T>::type )
//
// Overloads for free template functions size_row( x, tag ),
// Here, tag is assumed to be either one of
// tag::transpose, tag::no_transpose, or tag::conjugate
//
namespace result_of {
template< typename T, typename TransTag >
struct size_row_op {
typedef typename size<
T,
typename addressing_index_trans< tag::addressing_index<1>, TransTag >::type
>::type type;
};
template< typename T, typename TransTag >
struct size_column_op {
typedef typename size< T,
typename addressing_index_trans< tag::addressing_index<2>, TransTag >::type >::type type;
};
} // namespace result_of
template< typename T, typename Tag >
inline typename result_of::size_row_op< const T, Tag >::type
size_row_op( const T& t, Tag ) {
return bindings::size( t, typename addressing_index_trans< tag::addressing_index<1>, Tag >::type() );
}
template< typename T, typename Tag >
inline typename result_of::size_row_op< const T, Tag >::type
size_column_op( const T& t, Tag ) {
return bindings::size( t, typename addressing_index_trans< tag::addressing_index<2>, Tag >::type() );
}
} // namespace bindings
} // namespace numeric
} // namespace boost
#endif