1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_CUDA_SPECIALFUNCTIONS_H
11 #define EIGEN_CUDA_SPECIALFUNCTIONS_H
12 
13 namespace Eigen {
14 
15 namespace internal {
16 
17 // Make sure this is only available when targeting a GPU: we don't want to
18 // introduce conflicts between these packet_traits definitions and the ones
19 // we'll use on the host side (SSE, AVX, ...)
20 #if defined(__CUDACC__) && defined(EIGEN_USE_GPU)
21 
22 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
23 float4 plgamma<float4>(const float4& a)
24 {
25   return make_float4(lgammaf(a.x), lgammaf(a.y), lgammaf(a.z), lgammaf(a.w));
26 }
27 
28 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
29 double2 plgamma<double2>(const double2& a)
30 {
31   using numext::lgamma;
32   return make_double2(lgamma(a.x), lgamma(a.y));
33 }
34 
35 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
36 float4 pdigamma<float4>(const float4& a)
37 {
38   using numext::digamma;
39   return make_float4(digamma(a.x), digamma(a.y), digamma(a.z), digamma(a.w));
40 }
41 
42 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
43 double2 pdigamma<double2>(const double2& a)
44 {
45   using numext::digamma;
46   return make_double2(digamma(a.x), digamma(a.y));
47 }
48 
49 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
50 float4 pzeta<float4>(const float4& x, const float4& q)
51 {
52     using numext::zeta;
53     return make_float4(zeta(x.x, q.x), zeta(x.y, q.y), zeta(x.z, q.z), zeta(x.w, q.w));
54 }
55 
56 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
57 double2 pzeta<double2>(const double2& x, const double2& q)
58 {
59     using numext::zeta;
60     return make_double2(zeta(x.x, q.x), zeta(x.y, q.y));
61 }
62 
63 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
64 float4 ppolygamma<float4>(const float4& n, const float4& x)
65 {
66     using numext::polygamma;
67     return make_float4(polygamma(n.x, x.x), polygamma(n.y, x.y), polygamma(n.z, x.z), polygamma(n.w, x.w));
68 }
69 
70 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
71 double2 ppolygamma<double2>(const double2& n, const double2& x)
72 {
73     using numext::polygamma;
74     return make_double2(polygamma(n.x, x.x), polygamma(n.y, x.y));
75 }
76 
77 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
78 float4 perf<float4>(const float4& a)
79 {
80   return make_float4(erff(a.x), erff(a.y), erff(a.z), erff(a.w));
81 }
82 
83 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
84 double2 perf<double2>(const double2& a)
85 {
86   using numext::erf;
87   return make_double2(erf(a.x), erf(a.y));
88 }
89 
90 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
91 float4 perfc<float4>(const float4& a)
92 {
93   using numext::erfc;
94   return make_float4(erfc(a.x), erfc(a.y), erfc(a.z), erfc(a.w));
95 }
96 
97 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
98 double2 perfc<double2>(const double2& a)
99 {
100   using numext::erfc;
101   return make_double2(erfc(a.x), erfc(a.y));
102 }
103 
104 
105 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
106 float4 pigamma<float4>(const float4& a, const float4& x)
107 {
108   using numext::igamma;
109   return make_float4(
110       igamma(a.x, x.x),
111       igamma(a.y, x.y),
112       igamma(a.z, x.z),
113       igamma(a.w, x.w));
114 }
115 
116 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
117 double2 pigamma<double2>(const double2& a, const double2& x)
118 {
119   using numext::igamma;
120   return make_double2(igamma(a.x, x.x), igamma(a.y, x.y));
121 }
122 
123 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
124 float4 pigammac<float4>(const float4& a, const float4& x)
125 {
126   using numext::igammac;
127   return make_float4(
128       igammac(a.x, x.x),
129       igammac(a.y, x.y),
130       igammac(a.z, x.z),
131       igammac(a.w, x.w));
132 }
133 
134 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
135 double2 pigammac<double2>(const double2& a, const double2& x)
136 {
137   using numext::igammac;
138   return make_double2(igammac(a.x, x.x), igammac(a.y, x.y));
139 }
140 
141 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
142 float4 pbetainc<float4>(const float4& a, const float4& b, const float4& x)
143 {
144   using numext::betainc;
145   return make_float4(
146       betainc(a.x, b.x, x.x),
147       betainc(a.y, b.y, x.y),
148       betainc(a.z, b.z, x.z),
149       betainc(a.w, b.w, x.w));
150 }
151 
152 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
153 double2 pbetainc<double2>(const double2& a, const double2& b, const double2& x)
154 {
155   using numext::betainc;
156   return make_double2(betainc(a.x, b.x, x.x), betainc(a.y, b.y, x.y));
157 }
158 
159 #endif
160 
161 } // end namespace internal
162 
163 } // end namespace Eigen
164 
165 #endif // EIGEN_CUDA_SPECIALFUNCTIONS_H
166