1 #ifndef STAN_MATH_PRIM_META_RETURN_TYPE_HPP 2 #define STAN_MATH_PRIM_META_RETURN_TYPE_HPP 3 4 #include <stan/math/prim/fun/Eigen.hpp> 5 #include <stan/math/prim/meta/promote_args.hpp> 6 #include <stan/math/prim/meta/base_type.hpp> 7 #include <stan/math/prim/meta/scalar_type.hpp> 8 #include <complex> 9 #include <vector> 10 11 namespace stan { 12 13 /** 14 * Provides a member type alias named `type`, the value of which is 15 * the least type under Stan's assignability relation that can be 16 * assigned a `double` and all of the base types of the specified 17 * arguments after removing qualifiers (`const` and `volatile`) and 18 * decaying (lvalue to rvalue by removing references) and array to 19 * pointer). This type trait is used to calculate the return type 20 * of real-valued functions involving heterogeneous arguments. 21 * 22 * @tparam Ts sequence of template parameter types 23 * @see return_type for a definition of the type ordering 24 * @see base_type for definition of base type extraction 25 * @ingroup type_trait 26 */ 27 template <typename... Ts> 28 struct real_return { 29 using type = double; 30 }; 31 32 template <typename T, typename... Ts> 33 struct real_return<T, Ts...> { 34 using type 35 = promote_args_t<base_type_t<T>, typename real_return<Ts...>::type>; 36 }; 37 38 /** 39 * Convenience type to calculate the real return type. 40 * 41 * @tparam Ts sequence of argument types 42 * @see real_return 43 * @ingroup type_trait 44 */ 45 template <typename... Ts> 46 using real_return_t = typename real_return<Ts...>::type; 47 48 /** 49 * Convenience type to calculate the complex return type, which wraps 50 * `std::complex` around the return type of the specified template parameters. 51 * 52 * @tparam Ts sequence of argument types 53 * @see real_return 54 * @ingroup type_trait 55 */ 56 template <typename... Ts> 57 using complex_return_t = std::complex<real_return_t<Ts...>>; 58 59 /** 60 * Convenience type to calculate the complex return type, which wraps 61 * `std::vector` around the return type of the specified template parameters. 62 * 63 * @tparam Ts sequence of argument types 64 * @see real_return 65 * @ingroup type_trait 66 */ 67 template <typename... Ts> 68 using std_vector_return_t = std::vector<real_return_t<Ts...>>; 69 70 /** 71 * Convenience type to calculate the complex return type, which wraps 72 * `Eigen::Matrix< , -1, -1>` around the return type of the specified 73 * template parameters. 74 * 75 * @tparam Ts sequence of argument types 76 * @see real_return 77 * @ingroup type_trait 78 */ 79 template <typename... Ts> 80 using matrix_return_t = Eigen::Matrix<real_return_t<Ts...>, -1, -1>; 81 82 /** 83 * Convenience type to calculate the complex return type, which wraps 84 * `Eigen::Matrix< , -1, 1>` around the return type of the specified 85 * template parameters. 86 * 87 * @tparam Ts sequence of argument types 88 * @see real_return 89 * @ingroup type_trait 90 */ 91 template <typename... Ts> 92 using vector_return_t = Eigen::Matrix<real_return_t<Ts...>, -1, 1>; 93 94 /** 95 * Convenience type to calculate the complex return type, which wraps 96 * `Eigen::Matrix< , 1, -1>` around the return type of the specified 97 * template parameters. 98 * 99 * @tparam Ts sequence of argument types 100 * @see real_return 101 * @ingroup type_trait 102 */ 103 template <typename... Ts> 104 using row_vector_return_t = Eigen::Matrix<real_return_t<Ts...>, 1, -1>; 105 106 /** 107 * Defines a member type named `type` that is the least scalar type to 108 * which both template parameter scalar types are assignable in Stan. 109 * The ordering of types for which this is the least-upper-bound 110 * operation is defined in the class documentation for `return_type`. 111 * 112 * @tparam T1 first scalar type 113 * @tparam T2 second scalar type 114 * @see return_type 115 * @ingroup type_trait 116 */ 117 template <typename T1, typename T2> 118 struct scalar_lub { 119 using type = promote_args_t<T1, T2>; 120 }; 121 122 template <typename T1, typename T2> 123 struct scalar_lub<std::complex<T1>, T2> { 124 using type = std::complex<promote_args_t<T1, T2>>; 125 }; 126 127 template <typename T1, typename T2> 128 struct scalar_lub<T1, std::complex<T2>> { 129 using type = std::complex<promote_args_t<T1, T2>>; 130 }; 131 132 template <typename T1, typename T2> 133 struct scalar_lub<std::complex<T1>, std::complex<T2>> { 134 using type = std::complex<promote_args_t<T1, T2>>; 135 }; 136 137 /** 138 * Convenience type for the least upper bound of the specified 139 * template parameters in Stan's assignment ordering. 140 * 141 * @param T1 first type 142 * @param T2 second type 143 * @see scalar_lub 144 * @ingroup type_trait 145 */ 146 template <typename T1, typename T2> 147 using scalar_lub_t = typename scalar_lub<T1, T2>::type; 148 149 /** 150 * Template metaprogram to calculate the base scalar return type 151 * resulting from promoting all the scalar types of the template 152 * parameters to the least type to which all the base types of the 153 * arguments are assignable. The metaprogram can take an arbitrary 154 * number of template parameters. 155 * 156 * Complex numbers (instances of `std::complex<T>`) are considered 157 * scalars. All C++ primitive types (except `long double`) are 158 * automatically promoted to `double`. 159 * 160 * The set of autodiff types is defined to be the smallest such that 161 * - `var` is an autodiff type, 162 * - `fvar<double>` is an autodiff type, and 163 * - `fvar<T>` is an autodiff type if `T` is an autodiff type. 164 165 * The set of scalar types is defined to be the smallest such that 166 * - `double` and `long double` are scalar types, 167 * - `T` is a scalar type if `T` is an autodiff type, 168 * - `complex<double>` is a scalar type, and 169 * - `complex<T>` is a scalar type if `T` is an autodiff type. 170 * 171 * The assignability relation among scalar types is defined to be 172 * the smallest such that 173 * - `double` is assignable to any type `T`, 174 * - `T1` is assignable to `std::complex<T2>` if `T1` is assignable to 175 * - `T2`, and 176 * - `std::complex<T1>` is assignable to `std::complex<T2>` if `T1` is 177 * assignable to `T2`. 178 * 179 * Example usage: 180 * - `return_type_t<int, double, float>` is `double` 181 * - `return_type_t<double, var>` is `var` 182 * 183 * @tparam Ts sequence of input types 184 * @ingroup type_trait 185 */ 186 template <typename... Ts> 187 struct return_type { 188 using type = double; 189 }; 190 191 template <typename T, typename... Ts> 192 struct return_type<T, Ts...> { 193 using type 194 = scalar_lub_t<scalar_type_t<T>, typename return_type<Ts...>::type>; 195 }; 196 197 /** 198 * Convenience type for the return type of the specified template 199 * parameters. 200 * 201 * @tparam Ts sequence of types 202 * @see return_type 203 * @ingroup type_trait 204 */ 205 template <typename... Ts> 206 using return_type_t = typename return_type<Ts...>::type; 207 208 /** 209 * \ingroup require_stan_scalar_real 210 * \addtogroup autodiff_types 211 * \brief Require return type from parameter pack satisfies `Check` 212 */ 213 template <template <class...> class Check, typename... Ts> 214 using require_return_type_t = require_t<Check<return_type_t<Ts...>>>; 215 216 /** 217 * \ingroup require_stan_scalar_real 218 * \addtogroup autodiff_types 219 * \brief Require return type from parameter pack does not satisfy `Check` 220 */ 221 template <template <class...> class Check, typename... Ts> 222 using require_not_return_type_t = require_not_t<Check<return_type_t<Ts...>>>; 223 224 } // namespace stan 225 #endif 226