Automatic Differentiation
 
Loading...
Searching...
No Matches
elt_function_cl.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_OPENCL_KERNEL_GENERATOR_ELT_FUNCTION_CL_HPP
2#define STAN_MATH_OPENCL_KERNEL_GENERATOR_ELT_FUNCTION_CL_HPP
3#ifdef STAN_OPENCL
4
36#include <array>
37#include <string>
38#include <type_traits>
39#include <set>
40#include <utility>
41
42namespace stan {
43namespace math {
44
55template <typename Derived, typename Scal, typename... T>
56class elt_function_cl : public operation_cl<Derived, Scal, T...> {
57 public:
58 using Scalar = Scal;
59 using base = operation_cl<Derived, Scalar, T...>;
60 using base::var_name_;
61
67 elt_function_cl(const std::string& fun, T&&... args) // NOLINT
68 : base(std::forward<T>(args)...), fun_(fun) {}
69
79 const std::string& row_index_name, const std::string& col_index_name,
80 const bool view_handled,
81 std::conditional_t<false, T, const std::string&>... var_names_arg) const {
82 kernel_parts res{};
83
84 for (const char* incl : base::derived().includes) {
85 res.includes += incl;
86 }
87 std::array<std::string, sizeof...(T)> var_names_arg_arr
88 = {(var_names_arg + ", ")...};
89 std::string var_names_list = std::accumulate(
90 var_names_arg_arr.begin(), var_names_arg_arr.end(), std::string());
91 res.body = type_str<Scalar>() + " " + var_name_ + " = " + fun_ + "((double)"
92 + var_names_list.substr(0, var_names_list.size() - 2) + ");\n";
93 return res;
94 }
95
96 protected:
97 std::string fun_;
98};
99
106#define ADD_BINARY_FUNCTION_WITH_INCLUDES(fun, ...) \
107 template <typename T1, typename T2> \
108 class fun##_ : public elt_function_cl<fun##_<T1, T2>, double, T1, T2> { \
109 using base = elt_function_cl<fun##_<T1, T2>, double, T1, T2>; \
110 using base::arguments_; \
111 \
112 public: \
113 using base::rows; \
114 using base::cols; \
115 static const std::vector<const char*> includes; \
116 explicit fun##_(T1&& a, T2&& b) \
117 : base(#fun, std::forward<T1>(a), std::forward<T2>(b)) { \
118 if (a.rows() != base::dynamic && b.rows() != base::dynamic) { \
119 check_size_match(#fun, "Rows of ", "a", a.rows(), "rows of ", "b", \
120 b.rows()); \
121 } \
122 if (a.cols() != base::dynamic && b.cols() != base::dynamic) { \
123 check_size_match(#fun, "Columns of ", "a", a.cols(), "columns of ", \
124 "b", b.cols()); \
125 } \
126 } \
127 inline auto deep_copy() const { \
128 auto&& arg1_copy = this->template get_arg<0>().deep_copy(); \
129 auto&& arg2_copy = this->template get_arg<1>().deep_copy(); \
130 return fun##_<std::remove_reference_t<decltype(arg1_copy)>, \
131 std::remove_reference_t<decltype(arg2_copy)>>{ \
132 std::move(arg1_copy), std::move(arg2_copy)}; \
133 } \
134 inline std::pair<int, int> extreme_diagonals() const { \
135 return {-rows() + 1, cols() - 1}; \
136 } \
137 }; \
138 \
139 template <typename T1, typename T2, \
140 require_all_kernel_expressions_t<T1, T2>* = nullptr, \
141 require_any_not_stan_scalar_t<T1, T2>* = nullptr> \
142 inline fun##_<as_operation_cl_t<T1>, as_operation_cl_t<T2>> fun(T1&& a, \
143 T2&& b) { \
144 return fun##_<as_operation_cl_t<T1>, as_operation_cl_t<T2>>( \
145 as_operation_cl(std::forward<T1>(a)), \
146 as_operation_cl(std::forward<T2>(b))); \
147 } \
148 template <typename T1, typename T2> \
149 const std::vector<const char*> fun##_<T1, T2>::includes{__VA_ARGS__};
150
157#define ADD_UNARY_FUNCTION_WITH_INCLUDES(fun, ...) \
158 template <typename T> \
159 class fun##_ : public elt_function_cl<fun##_<T>, double, T> { \
160 using base = elt_function_cl<fun##_<T>, double, T>; \
161 using base::arguments_; \
162 \
163 public: \
164 using base::rows; \
165 using base::cols; \
166 static const std::vector<const char*> includes; \
167 explicit fun##_(T&& a) : base(#fun, std::forward<T>(a)) {} \
168 inline auto deep_copy() const { \
169 auto&& arg_copy = this->template get_arg<0>().deep_copy(); \
170 return fun##_<std::remove_reference_t<decltype(arg_copy)>>{ \
171 std::move(arg_copy)}; \
172 } \
173 inline std::pair<int, int> extreme_diagonals() const { \
174 return {-rows() + 1, cols() - 1}; \
175 } \
176 }; \
177 \
178 template <typename T, typename Cond \
179 = require_all_kernel_expressions_and_none_scalar_t<T>> \
180 inline fun##_<as_operation_cl_t<T>> fun(T&& a) { \
181 return fun##_<as_operation_cl_t<T>>(as_operation_cl(std::forward<T>(a))); \
182 } \
183 template <typename T> \
184 const std::vector<const char*> fun##_<T>::includes{__VA_ARGS__};
185
191#define ADD_UNARY_FUNCTION(fun) ADD_UNARY_FUNCTION_WITH_INCLUDES(fun)
192
199#define ADD_UNARY_FUNCTION_PASS_ZERO(fun) \
200 template <typename T> \
201 class fun##_ : public elt_function_cl<fun##_<T>, double, T> { \
202 using base = elt_function_cl<fun##_<T>, double, T>; \
203 using base::arguments_; \
204 \
205 public: \
206 using base::rows; \
207 using base::cols; \
208 static constexpr auto view_transitivness = std::make_tuple(true); \
209 static const std::vector<const char*> includes; \
210 explicit fun##_(T&& a) : base(#fun, std::forward<T>(a)) {} \
211 inline auto deep_copy() const { \
212 auto&& arg_copy = this->template get_arg<0>().deep_copy(); \
213 return fun##_<std::remove_reference_t<decltype(arg_copy)>>{ \
214 std::move(arg_copy)}; \
215 } \
216 }; \
217 \
218 template <typename T, typename Cond \
219 = require_all_kernel_expressions_and_none_scalar_t<T>> \
220 inline fun##_<as_operation_cl_t<T>> fun(T&& a) { \
221 return fun##_<as_operation_cl_t<T>>(as_operation_cl(std::forward<T>(a))); \
222 } \
223 template <typename T> \
224 const std::vector<const char*> fun##_<T>::includes{};
225
232#define ADD_CLASSIFICATION_FUNCTION(fun, ...) \
233 template <typename T> \
234 class fun##_ : public elt_function_cl<fun##_<T>, bool, T> { \
235 using base = elt_function_cl<fun##_<T>, bool, T>; \
236 using base::arguments_; \
237 \
238 public: \
239 using base::rows; \
240 using base::cols; \
241 static constexpr auto view_transitivness = std::make_tuple(true); \
242 static const std::vector<const char*> includes; \
243 explicit fun##_(T&& a) : base(#fun, std::forward<T>(a)) {} \
244 inline auto deep_copy() const { \
245 auto&& arg_copy = this->template get_arg<0>().deep_copy(); \
246 return fun##_<std::remove_reference_t<decltype(arg_copy)>>{ \
247 std::move(arg_copy)}; \
248 } \
249 inline std::pair<int, int> extreme_diagonals() const { \
250 return __VA_ARGS__; \
251 } \
252 }; \
253 \
254 template <typename T, typename Cond \
255 = require_all_kernel_expressions_and_none_scalar_t<T>> \
256 inline fun##_<as_operation_cl_t<T>> fun(T&& a) { \
257 return fun##_<as_operation_cl_t<T>>(as_operation_cl(std::forward<T>(a))); \
258 } \
259 template <typename T> \
260 const std::vector<const char*> fun##_<T>::includes{};
261
265
269
274
287
292
298
300 opencl_kernels::digamma_device_function)
301ADD_UNARY_FUNCTION_WITH_INCLUDES(erfcx, opencl_kernels::erfcx_device_function)
302ADD_UNARY_FUNCTION_WITH_INCLUDES(log1m, opencl_kernels::log1m_device_function)
304 opencl_kernels::log1p_exp_device_function,
305 opencl_kernels::log_inv_logit_device_function)
307 opencl_kernels::log1m_exp_device_function)
309 opencl_kernels::log1p_exp_device_function)
311 opencl_kernels::inv_square_device_function)
313 opencl_kernels::inv_logit_device_function)
314ADD_UNARY_FUNCTION_WITH_INCLUDES(logit, opencl_kernels::log1m_device_function,
315 opencl_kernels::logit_device_function)
316ADD_UNARY_FUNCTION_WITH_INCLUDES(Phi, opencl_kernels::phi_device_function)
318 opencl_kernels::inv_logit_device_function,
319 opencl_kernels::phi_approx_device_function)
322 opencl_kernels::std_normal_lcdf_device_function)
325 opencl_kernels::std_normal_lcdf_device_function)
326ADD_UNARY_FUNCTION_WITH_INCLUDES(inv_Phi, opencl_kernels::log1m_device_function,
327 opencl_kernels::phi_device_function,
328 opencl_kernels::inv_phi_device_function)
330 log1m_inv_logit, opencl_kernels::log1p_exp_device_function,
331 opencl_kernels::log1m_inv_logit_device_function)
333 opencl_kernels::trigamma_device_function)
335 square,
336 "\n#ifndef STAN_MATH_OPENCL_KERNELS_DEVICE_FUNCTIONS_SQUARE\n"
337 "#define STAN_MATH_OPENCL_KERNELS_DEVICE_FUNCTIONS_SQUARE\n"
338 "double square(double x){return x*x;}\n"
339 "#endif\n")
340
341ADD_CLASSIFICATION_FUNCTION(isfinite, {-rows() + 1, cols() - 1})
342ADD_CLASSIFICATION_FUNCTION(isinf,
343 this->template get_arg<0>().extreme_diagonals())
344ADD_CLASSIFICATION_FUNCTION(isnan,
345 this->template get_arg<0>().extreme_diagonals())
346
347ADD_BINARY_FUNCTION_WITH_INCLUDES(fdim)
348ADD_BINARY_FUNCTION_WITH_INCLUDES(fmax)
349ADD_BINARY_FUNCTION_WITH_INCLUDES(fmin)
350ADD_BINARY_FUNCTION_WITH_INCLUDES(fmod)
351ADD_BINARY_FUNCTION_WITH_INCLUDES(hypot)
352ADD_BINARY_FUNCTION_WITH_INCLUDES(ldexp)
353ADD_BINARY_FUNCTION_WITH_INCLUDES(pow)
354ADD_BINARY_FUNCTION_WITH_INCLUDES(copysign)
355
356ADD_BINARY_FUNCTION_WITH_INCLUDES(
357 erfcx_derivative, stan::math::opencl_kernels::erfcx_device_function)
358ADD_BINARY_FUNCTION_WITH_INCLUDES(
359 beta, stan::math::opencl_kernels::beta_device_function)
360ADD_BINARY_FUNCTION_WITH_INCLUDES(
361 binomial_coefficient_log,
362 stan::math::opencl_kernels::lgamma_stirling_device_function,
363 stan::math::opencl_kernels::lgamma_stirling_diff_device_function,
364 stan::math::opencl_kernels::lbeta_device_function,
365 stan::math::opencl_kernels::binomial_coefficient_log_device_function)
366template <typename T1, typename T2>
367class lbeta_ : public elt_function_cl<lbeta_<T1, T2>, double, T1, T2> {
368 using base = elt_function_cl<lbeta_<T1, T2>, double, T1, T2>;
369 using base::arguments_;
370
371 public:
372 using base::cols;
373 using base::rows;
374 static const std::vector<const char*> includes;
375 explicit lbeta_(T1&& a, T2&& b)
376 : base("stan_lbeta", std::forward<T1>(a), std::forward<T2>(b)) {
377 if (a.rows() != base::dynamic && b.rows() != base::dynamic) {
378 check_size_match("lbeta", "Rows of ", "a", a.rows(), "rows of ", "b",
379 b.rows());
380 }
381 if (a.cols() != base::dynamic && b.cols() != base::dynamic) {
382 check_size_match("lbeta", "Columns of ", "a", a.cols(), "columns of ",
383 "b", b.cols());
384 }
385 }
386 inline auto deep_copy() const {
387 auto&& arg1_copy = this->template get_arg<0>().deep_copy();
388 auto&& arg2_copy = this->template get_arg<1>().deep_copy();
389 return lbeta_<std::remove_reference_t<decltype(arg1_copy)>,
390 std::remove_reference_t<decltype(arg2_copy)>>{
391 std::move(arg1_copy), std::move(arg2_copy)};
392 }
393 inline std::pair<int, int> extreme_diagonals() const {
394 return {-rows() + 1, cols() - 1};
395 }
396};
397
398template <typename T1, typename T2,
399 require_all_kernel_expressions_t<T1, T2>* = nullptr,
400 require_any_not_stan_scalar_t<T1, T2>* = nullptr>
401inline lbeta_<as_operation_cl_t<T1>, as_operation_cl_t<T2>> lbeta(T1&& a,
402 T2&& b) {
403 return lbeta_<as_operation_cl_t<T1>, as_operation_cl_t<T2>>(
404 as_operation_cl(std::forward<T1>(a)),
405 as_operation_cl(std::forward<T2>(b)));
406}
407
408template <typename T1, typename T2>
409const std::vector<const char*> lbeta_<T1, T2>::includes{
410 stan::math::opencl_kernels::lgamma_stirling_device_function,
411 stan::math::opencl_kernels::lgamma_stirling_diff_device_function,
412 stan::math::opencl_kernels::lbeta_device_function};
413ADD_BINARY_FUNCTION_WITH_INCLUDES(
414 log_inv_logit_diff, opencl_kernels::log1p_exp_device_function,
415 opencl_kernels::log1m_exp_device_function,
416 opencl_kernels::log_inv_logit_diff_device_function)
417ADD_BINARY_FUNCTION_WITH_INCLUDES(log_diff_exp,
418 opencl_kernels::log1m_exp_device_function,
419 opencl_kernels::log_diff_exp_device_function)
420ADD_BINARY_FUNCTION_WITH_INCLUDES(
421 multiply_log, stan::math::opencl_kernels::multiply_log_device_function)
422ADD_BINARY_FUNCTION_WITH_INCLUDES(
423 lmultiply, stan::math::opencl_kernels::lmultiply_device_function)
424
425#undef ADD_BINARY_FUNCTION_WITH_INCLUDES
426#undef ADD_UNARY_FUNCTION_WITH_INCLUDES
427#undef ADD_UNARY_FUNCTION
428#undef ADD_UNARY_FUNCTION_PASS_ZERO
429#undef ADD_CLASSIFICATION_FUNCTION
430
432} // namespace math
433} // namespace stan
434#endif
435#endif
elt_function_cl(const std::string &fun, T &&... args)
Constructor.
kernel_parts generate(const std::string &row_index_name, const std::string &col_index_name, const bool view_handled, std::conditional_t< false, T, const std::string & >... var_names_arg) const
Generates kernel code for this expression.
Represents an element-wise function in kernel generator expressions.
Derived & derived()
Casts the instance into its derived type.
Base for all kernel generator operations.
rsqrt_< as_operation_cl_t< T > > rsqrt(T &&a)
#define ADD_UNARY_FUNCTION(fun)
Generates a class and function for a general unary function that is defined by OpenCL.
#define ADD_UNARY_FUNCTION_PASS_ZERO(fun)
Generates a class and function for an unary function, defined by OpenCL with special property that it...
#define ADD_UNARY_FUNCTION_WITH_INCLUDES(fun,...)
Generates a class and function for a general unary function that is defined by OpenCL or in the inclu...
std_normal_lcdf_dscaled_impl_< as_operation_cl_t< T > > std_normal_lcdf_dscaled_impl(T &&a)
std_normal_lcdf_scaled_impl_< as_operation_cl_t< T > > std_normal_lcdf_scaled_impl(T &&a)
fvar< T > acos(const fvar< T > &x)
Definition acos.hpp:16
fvar< T > sin(const fvar< T > &x)
Definition sin.hpp:16
fvar< T > acosh(const fvar< T > &x)
Definition acosh.hpp:16
fvar< T > logit(const fvar< T > &x)
Definition logit.hpp:14
fvar< T > expm1(const fvar< T > &x)
Definition expm1.hpp:14
fvar< T > atanh(const fvar< T > &x)
Return inverse hyperbolic tangent of specified value.
Definition atanh.hpp:26
fvar< T > inv_square(const fvar< T > &x)
fvar< T > exp2(const fvar< T > &x)
Definition exp2.hpp:14
constexpr double log2()
Return natural logarithm of two.
Definition log2.hpp:17
fvar< T > log1m_exp(const fvar< T > &x)
Return the natural logarithm of one minus the exponentiation of the specified argument.
Definition log1m_exp.hpp:22
fvar< T > asinh(const fvar< T > &x)
Definition asinh.hpp:16
fvar< T > cosh(const fvar< T > &x)
Definition cosh.hpp:16
fvar< T > log(const fvar< T > &x)
Definition log.hpp:18
fvar< T > erf(const fvar< T > &x)
Definition erf.hpp:16
auto inv_logit(T &&x)
Returns the inverse logit function applied to the argument.
Definition inv_logit.hpp:20
fvar< T > Phi_approx(const fvar< T > &x)
Return an approximation of the unit normal cumulative distribution function (CDF).
fvar< T > log_inv_logit(const fvar< T > &x)
fvar< T > erfcx(const fvar< T > &x)
Return the scaled complementary error function of the argument.
Definition erfcx.hpp:26
fvar< T > cbrt(const fvar< T > &x)
Return cube root of specified argument.
Definition cbrt.hpp:20
fvar< T > sinh(const fvar< T > &x)
Definition sinh.hpp:15
fvar< T > log1p_exp(const fvar< T > &x)
Definition log1p_exp.hpp:14
fvar< T > sqrt(const fvar< T > &x)
Definition sqrt.hpp:18
fvar< T > atan(const fvar< T > &x)
Definition atan.hpp:16
fvar< T > trigamma(const fvar< T > &u)
Return the value of the trigamma function at the specified argument (i.e., the second derivative of t...
Definition trigamma.hpp:25
fvar< T > tan(const fvar< T > &x)
Definition tan.hpp:16
fvar< T > Phi(const fvar< T > &x)
Definition Phi.hpp:16
fvar< T > erfc(const fvar< T > &x)
Definition erfc.hpp:16
fvar< T > log1p(const fvar< T > &x)
Definition log1p.hpp:12
fvar< T > inv_Phi(const fvar< T > &p)
Definition inv_Phi.hpp:16
fvar< T > floor(const fvar< T > &x)
Definition floor.hpp:13
fvar< T > lgamma(const fvar< T > &x)
Return the natural logarithm of the gamma function applied to the specified argument.
Definition lgamma.hpp:21
static constexpr double log10()
Returns the natural logarithm of ten.
fvar< T > tanh(const fvar< T > &x)
Definition tanh.hpp:15
fvar< T > cos(const fvar< T > &x)
Definition cos.hpp:16
fvar< T > round(const fvar< T > &x)
Return the closest integer to the specified argument, with halfway cases rounded away from zero.
Definition round.hpp:24
fvar< T > tgamma(const fvar< T > &x)
Return the result of applying the gamma function to the specified argument.
Definition tgamma.hpp:21
fvar< T > asin(const fvar< T > &x)
Definition asin.hpp:16
fvar< T > ceil(const fvar< T > &x)
Definition ceil.hpp:13
fvar< T > log1m(const fvar< T > &x)
Definition log1m.hpp:12
fvar< T > log1m_inv_logit(const fvar< T > &x)
Return the natural logarithm of one minus the inverse logit of the specified argument.
fvar< T > digamma(const fvar< T > &x)
Return the derivative of the log gamma function at the specified argument.
Definition digamma.hpp:23
fvar< T > square(const fvar< T > &x)
Definition square.hpp:12
fvar< T > trunc(const fvar< T > &x)
Return the nearest integral value that is not larger in magnitude than the specified argument.
Definition trunc.hpp:20
fvar< T > exp(const fvar< T > &x)
Definition exp.hpp:15
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
STL namespace.
Parts of an OpenCL kernel, generated by an expression.