Simplified IncompleteGamma
							parent
							
								
									8201c77b30
								
							
						
					
					
						commit
						d5771609a4
					
				|  | @ -19,6 +19,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <cmath> | #include <cmath> | ||||||
|  | #include <iostream> | ||||||
| 
 | 
 | ||||||
| namespace gtsam { | namespace gtsam { | ||||||
| 
 | 
 | ||||||
|  | @ -105,13 +106,14 @@ namespace internal { | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| class IncompleteGamma { | class IncompleteGamma { | ||||||
|   /// 50 point Gauss-Legendre quadrature
 |   /// 50 point Gauss-Legendre quadrature values
 | ||||||
|   static constexpr T quadrature_inp_vals(const T lb, const T ub, |   static constexpr T quadrature_inp_vals(const T lb, const T ub, | ||||||
|                                          const int counter) noexcept { |                                          const int counter) noexcept { | ||||||
|     return (ub - lb) * gauss_legendre_50_points[counter] / T(2) + |     return (ub - lb) * gauss_legendre_50_points[counter] / T(2) + | ||||||
|            (ub + lb) / T(2); |            (ub + lb) / T(2); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /// 50 point Gauss-Legendre quadrature weights
 | ||||||
|   static constexpr T quadrature_weight_vals(const T lb, const T ub, |   static constexpr T quadrature_weight_vals(const T lb, const T ub, | ||||||
|                                             const int counter) noexcept { |                                             const int counter) noexcept { | ||||||
|     return (ub - lb) * gauss_legendre_50_weights[counter] / T(2); |     return (ub - lb) * gauss_legendre_50_weights[counter] / T(2); | ||||||
|  | @ -122,19 +124,6 @@ class IncompleteGamma { | ||||||
|     return exp(-x + (a - T(1)) * log(x) - lg_term); |     return exp(-x + (a - T(1)) * log(x) - lg_term); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static constexpr T quadrature_recur(const T lb, const T ub, const T a, |  | ||||||
|                                       const T lg_term, |  | ||||||
|                                       const int counter) noexcept { |  | ||||||
|     if (counter < 49) { |  | ||||||
|       return quadrature_fn(quadrature_inp_vals(lb, ub, counter), a, lg_term) * |  | ||||||
|                  quadrature_weight_vals(lb, ub, counter) + |  | ||||||
|              quadrature_recur(lb, ub, a, lg_term, counter + 1); |  | ||||||
|     } else { |  | ||||||
|       return quadrature_fn(quadrature_inp_vals(lb, ub, counter), a, lg_term) * |  | ||||||
|              quadrature_weight_vals(lb, ub, counter); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   static constexpr T quadrature_lb(const T a, const T z) noexcept { |   static constexpr T quadrature_lb(const T a, const T z) noexcept { | ||||||
|     // break integration into ranges
 |     // break integration into ranges
 | ||||||
|     return a > T(1000)  ? std::max(T(0), std::min(z, a) - 11 * sqrt(a)) |     return a > T(1000)  ? std::max(T(0), std::min(z, a) - 11 * sqrt(a)) | ||||||
|  | @ -163,12 +152,27 @@ class IncompleteGamma { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static constexpr T quadrature(const T a, const T z) noexcept { |   static constexpr T quadrature(const T a, const T z) noexcept { | ||||||
|     return quadrature_recur(quadrature_lb(a, z), quadrature_ub(a, z), a, |     T lb = quadrature_lb(a, z); | ||||||
|                             lgamma(a), 0); |     T ub = quadrature_ub(a, z); | ||||||
|  |     T lg_term = lgamma(a); | ||||||
|  |     T value = quadrature_fn(quadrature_inp_vals(lb, ub, 49), a, lg_term) * | ||||||
|  |               quadrature_weight_vals(lb, ub, 49); | ||||||
|  |     for (size_t counter = 48; counter >= 0; counter--) { | ||||||
|  |       value += quadrature_fn(quadrature_inp_vals(lb, ub, counter), a, lg_term) * | ||||||
|  |                quadrature_weight_vals(lb, ub, counter); | ||||||
|  |     } | ||||||
|  |     return value; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // reverse cf expansion
 |   /**
 | ||||||
|   // see: https://functions.wolfram.com/GammaBetaErf/Gamma2/10/0003/
 |    * @brief Reverse continued fraction expansion | ||||||
|  |    * See: https://functions.wolfram.com/GammaBetaErf/Gamma2/10/0003/
 | ||||||
|  |    * | ||||||
|  |    * @param a | ||||||
|  |    * @param z | ||||||
|  |    * @param depth | ||||||
|  |    * @return constexpr T | ||||||
|  |    */ | ||||||
|   static constexpr T cf_2_recur(const T a, const T z, |   static constexpr T cf_2_recur(const T a, const T z, | ||||||
|                                 const int depth) noexcept { |                                 const int depth) noexcept { | ||||||
|     if (depth < 100) { |     if (depth < 100) { | ||||||
|  | @ -186,22 +190,25 @@ class IncompleteGamma { | ||||||
|    * @param z |    * @param z | ||||||
|    * @return constexpr T |    * @return constexpr T | ||||||
|    */ |    */ | ||||||
|   static constexpr T cf_2(const T a, const T z) noexcept { |   static constexpr T continued_fraction_2(const T a, const T z) noexcept { | ||||||
|     return T(1.0) - exp(a * log(z) - z - lgamma(a)) / cf_2_recur(a, z, 1); |     return T(1.0) - exp(a * log(z) - z - lgamma(a)) / cf_2_recur(a, z, 1); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // continued fraction expansion
 |   /**
 | ||||||
|   // see: http://functions.wolfram.com/GammaBetaErf/Gamma2/10/0009/
 |    * @brief Continued fraction expansion of Gamma function | ||||||
|   static constexpr T cf_1_coef(const T a, const T z, const int depth) noexcept { |    * See: http://functions.wolfram.com/GammaBetaErf/Gamma2/10/0009/
 | ||||||
|     return (is_odd(depth) ? -(a - 1 + T(depth + 1) / T(2)) * z |    * | ||||||
|                           : T(depth) / T(2) * z); |    * @param a | ||||||
|   } |    * @param z | ||||||
| 
 |    * @param depth | ||||||
|  |    * @return constexpr T | ||||||
|  |    */ | ||||||
|   static constexpr T cf_1_recur(const T a, const T z, |   static constexpr T cf_1_recur(const T a, const T z, | ||||||
|                                 const int depth) noexcept { |                                 const int depth) noexcept { | ||||||
|     if (depth < 55) { |     if (depth < 55) { | ||||||
|       return (a + depth - 1) + |       T cf_coef = is_odd(depth) ? -(a - 1 + T(depth + 1) / T(2)) * z | ||||||
|              cf_1_coef(a, z, depth) / cf_1_recur(a, z, depth + 1); |                                 : T(depth) / T(2) * z; | ||||||
|  |       return (a + depth - 1) + cf_coef / cf_1_recur(a, z, depth + 1); | ||||||
|     } else { |     } else { | ||||||
|       return (a + depth - 1); |       return (a + depth - 1); | ||||||
|     } |     } | ||||||
|  | @ -214,7 +221,7 @@ class IncompleteGamma { | ||||||
|    * @param z |    * @param z | ||||||
|    * @return constexpr T |    * @return constexpr T | ||||||
|    */ |    */ | ||||||
|   static constexpr T cf_1(const T a, const T z) noexcept { |   static constexpr T continued_fraction_1(const T a, const T z) noexcept { | ||||||
|     return exp(a * log(z) - z - lgamma(a)) / cf_1_recur(a, z, 1); |     return exp(a * log(z) - z - lgamma(a)) / cf_1_recur(a, z, 1); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -236,9 +243,9 @@ class IncompleteGamma { | ||||||
|     } else if (LIM<T>::min() > a) { |     } else if (LIM<T>::min() > a) { | ||||||
|       return T(1); |       return T(1); | ||||||
|     } else if (a < T(10) && z - a < T(10)) { |     } else if (a < T(10) && z - a < T(10)) { | ||||||
|       return cf_1(a, z); |       return continued_fraction_1(a, z); | ||||||
|     } else if (a < T(10) || z / a > T(3)) { |     } else if (a < T(10) || z / a > T(3)) { | ||||||
|       return cf_2(a, z); |       return continued_fraction_2(a, z); | ||||||
|     } else { |     } else { | ||||||
|       return quadrature(a, z); |       return quadrature(a, z); | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue