1 #ifndef STAN_MATH_PRIM_FUN_PROMOTE_ELEMENTS_HPP
2 #define STAN_MATH_PRIM_FUN_PROMOTE_ELEMENTS_HPP
3 
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/fun/Eigen.hpp>
6 #include <cstddef>
7 #include <vector>
8 
9 namespace stan {
10 namespace math {
11 
12 /**
13  * Struct with static function for elementwise type promotion.
14  *
15  * <p>This base implementation promotes one scalar value to another.
16  *
17  * @tparam T type of promoted element
18  * @tparam S type of input element, must be assignable to T
19  */
20 template <typename T, typename S>
21 struct promote_elements {
22   /**
23    * Return input element.
24    *
25    * @param u input of type S, assignable to type T
26    * @returns input as type T
27    */
promotestan::math::promote_elements28   inline static T promote(const S& u) { return u; }
29 };
30 
31 /**
32  * Struct with static function for elementwise type promotion.
33  *
34  * <p>This specialization promotes scalar values of the same type.
35  *
36  * @tparam T type of elements
37  */
38 template <typename T>
39 struct promote_elements<T, T> {
40   /**
41    * Return input element.
42    *
43    * @param u input of type T
44    * @returns input as type T
45    */
promotestan::math::promote_elements46   inline static const T& promote(const T& u) { return u; }
47 };
48 
49 /**
50  * Struct with static function for elementwise type promotion.
51  *
52  * <p>This specialization promotes vector elements of different types
53  * which must be compatible with promotion.
54  *
55  * @tparam T type of promoted elements
56  * @tparam S type of input elements, must be assignable to T
57  */
58 template <typename T, typename S>
59 struct promote_elements<std::vector<T>, std::vector<S> > {
60   /**
61    * Return input vector of type S as vector of type T.
62    *
63    * @param u vector of type S, assignable to type T
64    * @returns vector of type T
65    */
promotestan::math::promote_elements66   inline static std::vector<T> promote(const std::vector<S>& u) {
67     std::vector<T> t;
68     t.reserve(u.size());
69     for (size_t i = 0; i < u.size(); ++i) {
70       t.push_back(promote_elements<T, S>::promote(u[i]));
71     }
72     return t;
73   }
74 };
75 
76 /**
77  * Struct with static function for elementwise type promotion.
78  *
79  * <p>This specialization promotes vector elements of the same type.
80  *
81  * @tparam T type of elements
82  */
83 template <typename T>
84 struct promote_elements<std::vector<T>, std::vector<T> > {
85   /**
86    * Return input vector.
87    *
88    * @param u vector of type T
89    * @returns vector of type T
90    */
promotestan::math::promote_elements91   inline static const std::vector<T>& promote(const std::vector<T>& u) {
92     return u;
93   }
94 };
95 
96 /**
97  * Struct with static function for elementwise type promotion.
98  *
99  * <p>This specialization promotes matrix elements of different types
100  * which must be compatible with promotion.
101  *
102  * @tparam T type of promoted elements
103  * @tparam S type of input elements, must be assignable to T
104  * @tparam R number of rows, can be Eigen::Dynamic
105  * @tparam C number of columns, can be Eigen::Dynamic
106  */
107 template <typename T, typename S, int R, int C>
108 struct promote_elements<Eigen::Matrix<T, R, C>, Eigen::Matrix<S, R, C> > {
109   /**
110    * Return input matrix of type S as matrix of type T.
111    *
112    * @param u matrix of type S, assignable to type T
113    * @returns matrix of type T
114    */
promotestan::math::promote_elements115   inline static Eigen::Matrix<T, R, C> promote(
116       const Eigen::Matrix<S, R, C>& u) {
117     Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> t(u.rows(), u.cols());
118     for (int i = 0; i < u.size(); ++i) {
119       t(i) = promote_elements<T, S>::promote(u(i));
120     }
121     return t;
122   }
123 };
124 
125 /**
126  * Struct with static function for elementwise type promotion.
127  *
128  * <p>This specialization promotes matrix elements of the same type.
129  *
130  * @tparam T type of elements in the matrices
131  * @tparam R number of rows, can be Eigen::Dynamic
132  * @tparam C number of columns, can be Eigen::Dynamic
133  */
134 template <typename T, int R, int C>
135 struct promote_elements<Eigen::Matrix<T, R, C>, Eigen::Matrix<T, R, C> > {
136   /**
137    * Return input matrix.
138    *
139    * @param u matrix of type T
140    * @returns matrix of type T
141    */
promotestan::math::promote_elements142   inline static const Eigen::Matrix<T, R, C>& promote(
143       const Eigen::Matrix<T, R, C>& u) {
144     return u;
145   }
146 };
147 
148 }  // namespace math
149 }  // namespace stan
150 
151 #endif
152