Deterministic Gaussian Sampling
Loading...
Searching...
No Matches
lcd_even_binf_closed_form.h
Go to the documentation of this file.
1#ifndef LCD_EVEN_BINF_CLOSED_FORM_H
2#define LCD_EVEN_BINF_CLOSED_FORM_H
3
4#include <cassert>
5#include <cmath>
6#include <cstddef>
7
8#include "lcd_even_closed_form.h" // lcd_ei()
9
41constexpr double lcdBinfEulerGamma = 0.5772156649015328606;
42
66inline double lcd_binf_b0_zero(size_t d, double e0, double ei0, double c) {
67 assert(c > 0.00);
68
69 if (d == 0) return 0.25 * e0 + 0.125 * c * ei0;
70 if (d == 1) return -0.25 * ei0;
71
72 double term = 0.50 / c; // m = d
73 double sum = term;
74 for (size_t m = d; m > 2; --m) {
75 term *= 2.00 * static_cast<double>(m - 2) / c; // step down to m - 1
76 sum += term;
77 }
78
79 return e0 * sum;
80}
81
103inline double lcd_binf_b0_zero_deriv(size_t d, double e0, double ei0,
104 double c) {
105 assert(c > 0.00);
106
107 if (d == 0) return 0.125 * ei0;
108 if (d == 1) return -0.25 * e0 / c;
109
110 double term = 0.50 / c; // m = d
111 double sum = term; // T_d(c)
112 double sumDeriv = -term / c; // T_d'(c), factor -(d - m + 1) = -1 at m = d
113 for (size_t m = d; m > 2; --m) {
114 term *= 2.00 * static_cast<double>(m - 2) / c; // step down to m - 1
115 sum += term;
116 sumDeriv -= static_cast<double>(d - m + 2) * term / c;
117 }
118
119 return e0 * (sumDeriv - 0.50 * sum);
120}
121
132inline double lcd_binf_bkk_zero(size_t k, double c) {
133 assert(k >= 1);
134 assert(c > 0.00);
135
136 const double e0 = std::exp(-0.50 * c);
137 const double ei0 = lcd_ei(-0.50 * c);
138
139 double sum = 0.00;
140 double binomial = 1.00; // binom(k, j)
141 for (size_t j = 0; j <= k; ++j) {
142 const double term = lcd_binf_b0_zero(j, e0, ei0, c);
143 sum += (j % 2 == 0) ? binomial * term : -binomial * term;
144 binomial *= static_cast<double>(k - j) / static_cast<double>(j + 1);
145 }
146
147 return std::ldexp(sum, -static_cast<int>(k));
148}
149
161inline double lcd_binf_bkk_zero_deriv(size_t k, double c) {
162 assert(k >= 1);
163 assert(c > 0.00);
164
165 const double e0 = std::exp(-0.50 * c);
166 const double ei0 = lcd_ei(-0.50 * c);
167
168 double sum = 0.00;
169 double binomial = 1.00; // binom(k, j)
170 for (size_t j = 0; j <= k; ++j) {
171 const double term = lcd_binf_b0_zero_deriv(j, e0, ei0, c);
172 sum += (j % 2 == 0) ? binomial * term : -binomial * term;
173 binomial *= static_cast<double>(k - j) / static_cast<double>(j + 1);
174 }
175
176 return std::ldexp(sum, -static_cast<int>(k));
177}
178
191inline double lcd_binf_s(size_t k, double c) {
192 assert(k >= 1);
193 assert(c > 0.00);
194
195 double sum = 0.00;
196 double binomial = static_cast<double>(k); // binom(k, 1), stepped up below
197 double coefficient = 0.50; // (j-2)! * 2^(j-3), j = 2
198 double cPower = c; // c^(j-1), j = 2
199
200 for (size_t j = 2; j <= k; ++j) {
201 binomial *= static_cast<double>(k - j + 1) / static_cast<double>(j);
202 const double term = binomial * coefficient / cPower;
203 sum += (j % 2 == 0) ? term : -term;
204
205 coefficient *= 2.00 * static_cast<double>(j - 1);
206 cPower *= c;
207 }
208
209 return sum;
210}
211
222inline double lcd_binf_s_deriv(size_t k, double c) {
223 assert(k >= 1);
224 assert(c > 0.00);
225
226 double sum = 0.00;
227 double binomial = static_cast<double>(k); // binom(k, 1), stepped up below
228 double coefficient = 0.50; // (j-2)! * 2^(j-3), j = 2
229 double cPower = c; // c^(j-1), j = 2
230
231 for (size_t j = 2; j <= k; ++j) {
232 binomial *= static_cast<double>(k - j + 1) / static_cast<double>(j);
233 const double term = binomial * coefficient *
234 (1.00 - static_cast<double>(j)) / (cPower * c);
235 sum += (j % 2 == 0) ? term : -term;
236
237 coefficient *= 2.00 * static_cast<double>(j - 1);
238 cPower *= c;
239 }
240
241 return sum;
242}
243
256inline double lcd_binf_phi(size_t k, double c) {
257 assert(k >= 1);
258 assert(c > 0.00);
259
260 return 0.125 * (c + 2.00 * static_cast<double>(k)) * std::log(0.25 * c) +
261 lcd_binf_s(k, c) -
262 std::ldexp(lcd_binf_bkk_zero(k, c), static_cast<int>(k));
263}
264
275inline double lcd_binf_phi_deriv(size_t k, double c) {
276 assert(k >= 1);
277 assert(c > 0.00);
278
279 return 0.125 * std::log(0.25 * c) +
280 (c + 2.00 * static_cast<double>(k)) / (8.00 * c) +
281 lcd_binf_s_deriv(k, c) -
282 std::ldexp(lcd_binf_bkk_zero_deriv(k, c), static_cast<int>(k));
283}
284
297inline double lcd_binf_constant(size_t k) {
298 assert(k >= 1);
299
300 double harmonic = 0.00; // sum_{i=2..k} 1 / (2i)
301 for (size_t i = 2; i <= k; ++i) harmonic += 0.50 / static_cast<double>(i);
302
303 return static_cast<double>(k) * harmonic - 0.50 -
304 0.50 * static_cast<double>(k) * lcdBinfEulerGamma;
305}
306
307#endif // LCD_EVEN_BINF_CLOSED_FORM_H
Definition dirac_to_dirac_approx_short.h:9
double lcd_binf_phi(size_t k, double c)
phi_k(c), the per-sample attraction potential of the bMax-free distance
Definition lcd_even_binf_closed_form.h:256
double lcd_binf_bkk_zero_deriv(size_t k, double c)
d/dc B_{k,k}(0, c)
Definition lcd_even_binf_closed_form.h:161
double lcd_binf_constant(size_t k)
K_k, the sample-independent constant of the bMax-free distance.
Definition lcd_even_binf_closed_form.h:297
double lcd_binf_phi_deriv(size_t k, double c)
phi_k'(c)
Definition lcd_even_binf_closed_form.h:275
double lcd_binf_b0_zero_deriv(size_t d, double e0, double ei0, double c)
d/dc B_{0,d}(0, c)
Definition lcd_even_binf_closed_form.h:103
constexpr double lcdBinfEulerGamma
Euler-Mascheroni constant.
Definition lcd_even_binf_closed_form.h:41
double lcd_binf_s_deriv(size_t k, double c)
S_k'(c)
Definition lcd_even_binf_closed_form.h:222
double lcd_binf_s(size_t k, double c)
S_k(c), the pole-cancelling companion of B_{k,k}(0, c)
Definition lcd_even_binf_closed_form.h:191
double lcd_binf_bkk_zero(size_t k, double c)
B_{k,k}(0, c), the lower-limit attraction term.
Definition lcd_even_binf_closed_form.h:132
double lcd_binf_b0_zero(size_t d, double e0, double ei0, double c)
B_{0,d}(0, c), the lower-limit base case of the attraction term.
Definition lcd_even_binf_closed_form.h:66
quadrature-free closed forms for the LCD / modified Cramer-von-Mises distance of an even-dimensional ...
double lcd_ei(double x)
exponential integral Ei(x) for negative arguments
Definition lcd_even_closed_form.h:35