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