Chemical Data Processing Library C++ API - Version 1.4.0
SpecialFunctions.hpp
Go to the documentation of this file.
1 /*
2  * SpecialFunctions.hpp
3  *
4  * This file is part of the Chemical Data Processing Toolkit
5  *
6  * Copyright (C) 2003 Thomas Seidel <thomas.seidel@univie.ac.at>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; see the file COPYING. If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23 
29 #ifndef CDPL_MATH_SPECIALFUNCTIONS_HPP
30 #define CDPL_MATH_SPECIALFUNCTIONS_HPP
31 
32 #include <cstddef>
33 #include <cmath>
34 #include <limits>
35 
36 #include "CDPL/Math/TypeTraits.hpp"
37 
38 
39 namespace CDPL
40 {
41 
42  namespace Math
43  {
44 
50  template <typename T>
51  T factorial(unsigned int n);
52 
59  template <typename T>
60  T pythag(const T& a, const T& b);
61 
68  template <typename T1, typename T2>
69  T1 sign(const T1& a, const T2& b);
70 
77  template <typename T>
78  T lnGamma(const T& z);
79 
87  template <typename T>
88  T gammaQ(const T& a, const T& x);
89 
98  template <typename T>
99  T generalizedBell(const T& x, const T& a, const T& b, const T& c);
100  } // namespace Math
101 } // namespace CDPL
102 
103 
104 // Implementation
105 // \cond DOC_IMPL_DETAILS
106 
107 namespace CDPL
108 {
109 
110  namespace Math
111  {
112 
113  namespace Detail
114  {
115 
116  // Computes the incomplete gamma function P(a, x) evaluated by its series representation.
117  template <typename T>
118  T gammaPSer(const T& a, const T& x)
119  {
120  using namespace CDPL;
121  using namespace Math;
122 
123  if (x <= 0) {
124  if (x < 0)
125  return std::numeric_limits<T>::quiet_NaN();
126 
127  return 0;
128  }
129 
130  T ap = a;
131  T del = 1 / a;
132  T sum = del;
133 
134  for (unsigned int i = 0; i < 100; i++) {
135  ++ap;
136 
137  del *= x / ap;
138  sum += del;
139 
140  if (TypeTraits<T>::abs(del) < TypeTraits<T>::abs(sum) * std::numeric_limits<T>::epsilon())
141  return (sum * std::exp(-x + a * log(x) - CDPL::Math::lnGamma(a)));
142  }
143 
144  return std::numeric_limits<T>::quiet_NaN();
145  }
146 
147  // Computes the incomplete gamma function Q(a, x) evaluated by its continued fraction representation.
148  template <typename T>
149  T gammaQContFrac(const T& a, const T& x)
150  {
151  using namespace CDPL;
152  using namespace Math;
153 
154  static const T EPS = std::numeric_limits<T>::epsilon();
155  static const T FP_MIN = std::numeric_limits<T>::min() / EPS;
156 
157  T b = x + 1 - a;
158  T c = 1 / FP_MIN;
159  T d = 1 / b;
160  T h = d;
161 
162  for (unsigned int i = 0; i < 100; i++) {
163  T an = -i * (i - a);
164  b += 2;
165  d = an * d + b;
166 
167  if (TypeTraits<T>::abs(d) < FP_MIN)
168  d = FP_MIN;
169 
170  c = b + an / c;
171 
172  if (TypeTraits<T>::abs(c) < FP_MIN)
173  c = FP_MIN;
174 
175  d = 1 / d;
176  T del = d * c;
177  h *= del;
178 
179  if (TypeTraits<T>::abs(del - 1) <= EPS)
180  return (std::exp(-x + a * log(x) - CDPL::Math::lnGamma(a)) * h);
181  }
182 
183  return std::numeric_limits<T>::quiet_NaN();
184  }
185  } // namespace Detail
186  } // namespace Math
187 } // namespace CDPL
188 
189 
190 template <typename T>
191 T CDPL::Math::factorial(unsigned int n)
192 {
193  T f(1);
194 
195  if (n == 0)
196  return f;
197 
198  for (unsigned int i = 2; i <= n; i++)
199  f *= T(i);
200 
201  return f;
202 }
203 
204 template <typename T>
205 T CDPL::Math::pythag(const T& a, const T& b)
206 {
207  T abs_a = TypeTraits<T>::abs(a);
208  T abs_b = TypeTraits<T>::abs(b);
209 
210  if (abs_a > abs_b) {
211  T tmp = abs_b / abs_a;
212 
213  return (abs_a * TypeTraits<T>::sqrt(T(1) + tmp * tmp));
214  }
215 
216  if (abs_b == 0)
217  return 0;
218 
219  T tmp = abs_a / abs_b;
220 
221  return (abs_b * TypeTraits<T>::sqrt(T(1) + tmp * tmp));
222 }
223 
224 template <typename T1, typename T2>
225 T1 CDPL::Math::sign(const T1& a, const T2& b)
226 {
227  return (b >= 0 ? (a >= 0 ? a : -a) : (a >= 0 ? -a : a));
228 }
229 
230 template <typename T>
231 T CDPL::Math::lnGamma(const T& xx)
232 {
233  static const long double cof[6] = {
234  76.18009172947146,
235  -86.50532032941677,
236  24.01409824083091,
237  -1.231739572450155,
238  0.1208650973866179e-2,
239  -0.5395239384953e-5};
240 
241  long double ser = 1.000000000190015;
242  long double x = xx;
243  long double y = xx;
244  long double tmp = x + 5.5;
245 
246  tmp -= (x + 0.5) * std::log(tmp);
247 
248  for (unsigned int i = 0; i < 6; i++)
249  ser += cof[i] / ++y;
250 
251  return T(-tmp + std::log(2.5066282746310005 * ser / x));
252 }
253 
254 template <typename T>
255 T CDPL::Math::gammaQ(const T& a, const T& x)
256 {
257  if (x < T(0) || a <= T(0))
258  return std::numeric_limits<T>::quiet_NaN();
259 
260  if (x < (a + T(1)))
261  return (T(1) - Detail::gammaPSer(a, x));
262 
263  return Detail::gammaQContFrac(a, x);
264 }
265 
266 template <typename T>
267 T CDPL::Math::generalizedBell(const T& x, const T& a, const T& b, const T& c)
268 {
269  return (T(1) / (T(1) + std::pow(std::abs((x - c) / a), T(2) * b)));
270 }
271 
272 // \endcond
273 
274 #endif // CDPL_MATH_SPECIALFUNCTIONS_HPP
Definition of type traits.
constexpr unsigned int T
Specifies Hydrogen (Tritium).
Definition: AtomType.hpp:67
T generalizedBell(const T &x, const T &a, const T &b, const T &c)
Computes the generalized bell function at x.
T factorial(unsigned int n)
Computes the factorial of the non-negative integer n.
T lnGamma(const T &z)
Computes for .
T pythag(const T &a, const T &b)
Computes without destructive underflow or overflow.
GridElementSum< E >::ResultType sum(const GridExpression< E > &ge)
Returns the sum of all elements of the grid expression ge.
Definition: GridExpression.hpp:818
T1 sign(const T1 &a, const T2 &b)
Returns the magnitude of parameter a times the sign of parameter b.
T gammaQ(const T &a, const T &x)
Computes the incomplete gamma function .
The namespace of the Chemical Data Processing Library.
static RealType abs(ConstReference t)
Returns the absolute value of t (std::abs for signed types, the identity for unsigned types).
Definition: TypeTraits.hpp:142
static ValueType sqrt(ConstReference t)
Returns the square root of t.
Definition: TypeTraits.hpp:152