1 #ifndef STAN_MATH_PRIM_META_IS_VECTOR_HPP
2 #define STAN_MATH_PRIM_META_IS_VECTOR_HPP
3 
4 #include <stan/math/prim/meta/bool_constant.hpp>
5 #include <stan/math/prim/meta/is_eigen.hpp>
6 #include <stan/math/prim/meta/is_var.hpp>
7 #include <stan/math/prim/meta/scalar_type.hpp>
8 #include <stan/math/prim/meta/value_type.hpp>
9 #include <stan/math/prim/meta/require_helpers.hpp>
10 #include <type_traits>
11 #include <vector>
12 
13 namespace stan {
14 
15 /** \ingroup type_trait
16  * Base implementation for checking if type is std vector
17  */
18 template <typename T, typename = void>
19 struct is_std_vector : std::false_type {};
20 
21 namespace internal {
22 /** \ingroup type_trait
23  * Underlying implementation for detecting if an Eigen Matrix is a column
24  * vector.
25  */
26 template <typename T, bool = is_eigen<T>::value>
27 struct is_eigen_col_vector_impl
28     : bool_constant<std::decay_t<T>::ColsAtCompileTime == 1> {};
29 
30 /** \ingroup type_trait
31  * Specialization for when type is not an eigen vector.
32  */
33 template <typename T>
34 struct is_eigen_col_vector_impl<T, false> : std::false_type {};
35 
36 /** \ingroup type_trait
37  * Underlying implementation for detecting if an Eigen Matrix is a row vector.
38  */
39 template <typename T, bool = is_eigen<T>::value>
40 struct is_eigen_row_vector_impl
41     : std::integral_constant<bool, std::decay_t<T>::RowsAtCompileTime == 1> {};
42 
43 /** \ingroup type_trait
44  * Specialization for when type is not an eigen vector.
45  */
46 template <typename T>
47 struct is_eigen_row_vector_impl<T, false> : std::false_type {};
48 
49 /** \ingroup type_trait
50  * Underlying implementation for detecting if a Matrix is a column vector.
51  */
52 template <typename T, bool = bool_constant<is_eigen<T>::value
53                                            || (is_eigen<value_type_t<T>>::value
54                                                && is_var<T>::value)>::value>
55 struct is_col_vector_impl
56     : bool_constant<std::decay_t<T>::ColsAtCompileTime == 1> {};
57 
58 /** \ingroup type_trait
59  * Specialization for when type is not a vector.
60  */
61 template <typename T>
62 struct is_col_vector_impl<T, false> : std::false_type {};
63 
64 /** \ingroup type_trait
65  * Underlying implementation for detecting if a Matrix is a row vector.
66  */
67 template <typename T, bool = bool_constant<is_eigen<T>::value
68                                            || (is_eigen<value_type_t<T>>::value
69                                                && is_var<T>::value)>::value>
70 struct is_row_vector_impl
71     : std::integral_constant<bool, std::decay_t<T>::RowsAtCompileTime == 1> {};
72 
73 /** \ingroup type_trait
74  * Specialization for when type is not an vector.
75  */
76 template <typename T>
77 struct is_row_vector_impl<T, false> : std::false_type {};
78 
79 }  // namespace internal
80 
81 /** \ingroup type_trait
82  * If the input type T is an eigen matrix with 1 row at compile time this
83  * has a static member with a value of true. Else this has a static
84  * member with a value of false.
85  */
86 template <typename T>
87 struct is_eigen_col_vector : internal::is_eigen_col_vector_impl<T> {};
88 
89 STAN_ADD_REQUIRE_UNARY(eigen_col_vector, is_eigen_col_vector,
90                        require_eigens_types);
91 STAN_ADD_REQUIRE_CONTAINER(eigen_col_vector, is_eigen_col_vector,
92                            require_eigens_types);
93 
94 /** \ingroup type_trait
95  * If the input type T has a static comple time constant type
96  * `ColsAtCompileTime` equal to 1 this
97  * has a static member with a value of true. Else this has a static
98  * member with a value of false.
99  */
100 template <typename T>
101 struct is_col_vector : internal::is_col_vector_impl<T> {};
102 
103 STAN_ADD_REQUIRE_UNARY(col_vector, is_col_vector, require_eigens_types);
104 STAN_ADD_REQUIRE_CONTAINER(col_vector, is_col_vector, require_eigens_types);
105 
106 /** \ingroup type_trait
107  * If the input type T is an eigen matrix with 1 column at compile time this
108  * has a static member with a value of true. Else this has a static
109  * member with a value of false.
110  */
111 template <typename T>
112 struct is_eigen_row_vector : internal::is_eigen_row_vector_impl<T> {};
113 
114 STAN_ADD_REQUIRE_UNARY(eigen_row_vector, is_eigen_row_vector,
115                        require_eigens_types);
116 STAN_ADD_REQUIRE_CONTAINER(eigen_row_vector, is_eigen_row_vector,
117                            require_eigens_types);
118 
119 /** \ingroup type_trait
120  * If the input type T has a static comple time constant type
121  * `RowsAtCompileTime` equal to 1 this
122  * has a static member with a value of true. Else this has a static
123  * member with a value of false.
124  */
125 template <typename T>
126 struct is_row_vector : internal::is_row_vector_impl<T> {};
127 
128 STAN_ADD_REQUIRE_UNARY(row_vector, is_row_vector, require_eigens_types);
129 STAN_ADD_REQUIRE_CONTAINER(row_vector, is_row_vector, require_eigens_types);
130 
131 /** \ingroup type_trait
132  * If the input type T is an eigen matrix with 1 column or 1 row at compile time
133  * this has a static member with a value of true. Else this has a static
134  * member with a value of false.
135  */
136 template <typename T>
137 struct is_eigen_vector : bool_constant<is_eigen_col_vector<T>::value
138                                        || is_eigen_row_vector<T>::value> {};
139 
140 STAN_ADD_REQUIRE_UNARY(eigen_vector, is_eigen_vector, require_eigens_types);
141 STAN_ADD_REQUIRE_CONTAINER(eigen_vector, is_eigen_vector, require_eigens_types);
142 
143 /**
144  * Require `Row` is a row vector and `Col` is a column vector.
145  * @ingroup require_eigen_types
146  */
147 template <typename Row, typename Col>
148 using require_eigen_row_and_col_t = require_t<
149     math::conjunction<is_eigen_row_vector<Row>, is_eigen_col_vector<Col>>>;
150 
151 /**
152  * Require `Row` is not a row vector and `Col` is not a column vector.
153  * @ingroup require_eigen_types
154  */
155 template <typename Row, typename Col>
156 using require_not_eigen_row_and_col_t = require_not_t<
157     math::conjunction<is_eigen_row_vector<Row>, is_eigen_col_vector<Col>>>;
158 
159 /**
160  * Require `Row` is a row vector and `Col` is a column vector.
161  * @ingroup require_eigen_types
162  */
163 template <typename Row, typename Col>
164 using require_row_and_col_vector_t
165     = require_t<math::conjunction<is_row_vector<Row>, is_col_vector<Col>>>;
166 
167 /**
168  * Require `Row` is not a row vector and `Col` is not a column vector.
169  * @ingroup require_eigen_types
170  */
171 template <typename Row, typename Col>
172 using require_not_row_and_col_vector_t
173     = require_not_t<math::conjunction<is_row_vector<Row>, is_col_vector<Col>>>;
174 
175 /** \ingroup type_trait
176  * If the input type T is either an eigen matrix with 1 column or 1 row at
177  * compile time or a standard vector, this has a static member with a value
178  * of true. Else this has a static member with a value of false.
179  *
180  */
181 template <typename T>
182 struct is_vector
183     : bool_constant<is_eigen_vector<T>::value || is_std_vector<T>::value
184                     || (is_var<T>::value
185                         && is_eigen_vector<value_type_t<T>>::value)> {};
186 
187 STAN_ADD_REQUIRE_UNARY(vector, is_vector, require_std);
188 STAN_ADD_REQUIRE_CONTAINER(vector, is_vector, require_std);
189 
190 namespace internal {
191 
192 /** \ingroup type_trait
193  * This underlying implementation is used when the type is not an std vector.
194  */
195 template <typename T>
196 struct is_std_vector_impl : std::false_type {};
197 
198 /** \ingroup type_trait
199  * This specialization implementation has a static member named value when the
200  * template type is an std vector.
201  */
202 template <typename... Args>
203 struct is_std_vector_impl<std::vector<Args...>> : std::true_type {};
204 
205 }  // namespace internal
206 
207 /** \ingroup type_trait
208  * Checks if the decayed type of T is a standard vector.
209  */
210 template <typename T>
211 struct is_std_vector<
212     T, std::enable_if_t<internal::is_std_vector_impl<std::decay_t<T>>::value>>
213     : std::true_type {};
214 
215 /** \ingroup type_trait
216  * Specialization of scalar_type for vector to recursively return the inner
217  * scalar type.
218  *
219  * @tparam T type of standard vector
220  */
221 template <typename T>
222 struct scalar_type<T, std::enable_if_t<is_std_vector<T>::value>> {
223   using type = scalar_type_t<typename std::decay_t<T>::value_type>;
224 };
225 
226 /** \ingroup type_trait
227  * Template metaprogram class to compute the type of values stored
228  * in a standard vector.
229  *
230  * @tparam T type of elements in standard vector.
231  */
232 template <typename T>
233 struct value_type<T, std::enable_if_t<is_std_vector<T>::value>> {
234   using type = typename std::decay_t<T>::value_type;
235 };
236 
237 STAN_ADD_REQUIRE_UNARY(std_vector, is_std_vector, require_std);
238 STAN_ADD_REQUIRE_CONTAINER(std_vector, is_std_vector, require_std);
239 
240 }  // namespace stan
241 #endif
242