20 #include <gsl/gsl_sf_bessel.h>
21 #include <gsl/gsl_sf_erf.h>
22 #include <gsl/gsl_sf_expint.h>
23 #include <gsl/gsl_sf_trig.h>
32 double MathFunctions::StandardNormal(
double x)
34 return std::exp(-x * x / 2.0) / std::sqrt(M_TWOPI);
37 double MathFunctions::Gaussian(
double x,
double average,
double std_dev)
39 return StandardNormal((x - average) / std_dev) / std_dev;
42 double MathFunctions::IntegratedGaussian(
double x,
double average,
double std_dev)
44 double normalized_x = (x - average) / std_dev;
45 static double root2 = std::sqrt(2.0);
46 return (gsl_sf_erf(normalized_x / root2) + 1.0) / 2.0;
51 return tan(M_PI_2 - x);
61 return gsl_sf_sinc(x / M_PI);
70 if (z == complex_t(0., 0.))
72 return std::sin(z) / z;
77 if (std::abs(z) < std::numeric_limits<double>::epsilon())
79 return std::tanh(z) / z;
84 static const double SQRT6DOUBLE_EPS = std::sqrt(6.0 * std::numeric_limits<double>::epsilon());
85 auto nd =
static_cast<double>(N);
86 if (std::abs(nd * x) < SQRT6DOUBLE_EPS)
88 double num = std::sin(nd * x);
89 double den = std::sin(x);
96 throw std::runtime_error(
"Error in MathFunctions::erf: negative argument is not allowed");
99 return gsl_sf_erf(arg);
117 return gsl_sf_bessel_J0(x);
122 return gsl_sf_bessel_J1(x);
127 return x == 0 ? 0.5 : gsl_sf_bessel_J1(x) / x;
132 return gsl_sf_bessel_I0(x);
137 if (std::imag(z) == 0)
138 return gsl_sf_bessel_J0(std::real(z));
144 if (std::imag(z) == 0)
145 return gsl_sf_bessel_J1(std::real(z));
151 if (std::imag(z) == 0) {
152 double xv = std::real(z);
153 return xv == 0 ? 0.5 : gsl_sf_bessel_J1(xv) / xv;
166 static const double eps = 1e-15;
167 static double a[] = {-7.03125e-2, 0.112152099609375, -0.5725014209747314,
168 6.074042001273483, -1.100171402692467e2, 3.038090510922384e3,
169 -1.188384262567832e5, 6.252951493434797e6, -4.259392165047669e8,
170 3.646840080706556e10, -3.833534661393944e12, 4.854014686852901e14,
171 -7.286857349377656e16, 1.279721941975975e19};
172 static double b[] = {7.32421875e-2, -0.2271080017089844, 1.727727502584457,
173 -2.438052969955606e1, 5.513358961220206e2, -1.825775547429318e4,
174 8.328593040162893e5, -5.006958953198893e7, 3.836255180230433e9,
175 -3.649010818849833e11, 4.218971570284096e13, -5.827244631566907e15,
176 9.476288099260110e17, -1.792162323051699e20};
178 double a0 = std::abs(z);
182 if (std::real(z) < 0.0)
186 complex_t z2 = 0.25 * z * z;
189 for (
size_t k = 1; k <= 40; ++k) {
190 cr *= -z2 / (double)(k * k);
192 if (std::abs(cr) < std::abs(cj0) * eps)
204 complex_t ct1 = z1 - M_PI_4;
206 complex_t cq0 = -0.125;
207 const complex_t z1m2 = 1. / (z1 * z1);
208 complex_t ptmp = z1m2;
209 for (
size_t k = 0; k < kz; ++k) {
214 cj0 = std::sqrt(M_2_PI / z1) * (cp0 * std::cos(ct1) - cq0 / z1 * std::sin(ct1));
226 static const double eps = 1e-15;
228 static double a1[] = {0.1171875,
233 -3.302272294480852e3,
235 -6.656367718817688e6,
237 -3.833857520742790e10,
238 4.011838599133198e12,
239 -5.060568503314727e14,
240 7.572616461117958e16,
241 -1.326257285320556e19};
242 static double b1[] = {-0.1025390625, 0.2775764465332031, -1.993531733751297,
243 2.724882731126854e1, -6.038440767050702e2, 1.971837591223663e4,
244 -8.902978767070678e5, 5.310411010968522e7, -4.043620325107754e9,
245 3.827011346598605e11, -4.406481417852278e13, 6.065091351222699e15,
246 -9.833883876590679e17, 1.855045211579828e20};
248 double a0 = std::abs(z);
253 if (std::real(z) < 0.0)
257 const complex_t z2 = 0.25 * z * z;
260 for (
int k = 1; k <= 40; ++k) {
261 cr *= -z2 / (double)(k * (k + 1));
263 if (std::abs(cr) < std::abs(cj1) * eps)
277 complex_t cq1 = 0.375;
278 const complex_t z1m2 = 1. / (z1 * z1);
279 complex_t ptmp = z1m2;
280 for (
size_t k = 0; k < kz; ++k) {
285 const complex_t ct2 = z1 - 0.75 * M_PI;
286 cj1 = std::sqrt(M_2_PI / z1) * (cp1 * std::cos(ct2) - cq1 / z1 * std::sin(ct2));
288 if (std::real(z) < 0.0)
301 MathFunctions::EFFTDirection ftCase)
304 size_t npx = data.size();
306 fftw_complex* ftData = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) * npx);
307 fftw_complex* ftResult = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) * npx);
308 memset(ftData, 0,
sizeof(fftw_complex) * npx);
309 memset(ftResult, 0,
sizeof(fftw_complex) * npx);
311 for (
size_t i = 0; i < npx; i++) {
312 ftData[i][0] = data[i].real();
313 ftData[i][1] = data[i].imag();
318 case MathFunctions::FORWARD_FFT:
319 plan = fftw_plan_dft_1d((
int)npx, ftData, ftResult, FFTW_FORWARD, FFTW_ESTIMATE);
321 case MathFunctions::BACKWARD_FFT:
322 plan = fftw_plan_dft_1d((
int)npx, ftData, ftResult, FFTW_BACKWARD, FFTW_ESTIMATE);
323 scale = 1. / double(npx);
326 throw std::runtime_error(
327 "MathFunctions::FastFourierTransform -> Panic! Unknown transform case.");
333 std::vector<complex_t> outData;
335 for (
size_t i = 0; i < npx; i++)
336 outData[i] = scale * complex_t(ftResult[i][0], ftResult[i][1]);
338 fftw_destroy_plan(plan);
350 MathFunctions::EFFTDirection ftCase)
352 std::vector<complex_t> cdata;
353 cdata.resize(data.size());
354 for (
size_t i = 0; i < data.size(); i++)
355 cdata[i] = complex_t(data[i], 0);
362 const std::vector<double>& resfunc)
364 if (signal.size() != resfunc.size())
365 throw std::runtime_error(
"MathFunctions::ConvolveFFT() -> This convolution works only for "
366 "two vectors of equal size. Use Convolve class instead.");
367 std::vector<complex_t> fft_signal =
369 std::vector<complex_t> fft_resfunc =
372 std::vector<complex_t> fft_prod;
373 fft_prod.resize(fft_signal.size());
374 for (
size_t i = 0; i < fft_signal.size(); i++)
375 fft_prod[i] = fft_signal[i] * fft_resfunc[i];
377 std::vector<complex_t> result =
386 double MathFunctions::GenerateUniformRandom()
388 int random_int = std::rand();
389 return (
double)random_int / RAND_MAX;
392 double MathFunctions::GenerateStandardNormalRandom()
395 static_cast<unsigned>(std::chrono::system_clock::now().time_since_epoch().count());
396 std::default_random_engine generator(seed);
397 std::normal_distribution<double> distribution(0.0, 1.0);
398 return distribution(generator);
401 double MathFunctions::GenerateNormalRandom(
double average,
double std_dev)
403 return GenerateStandardNormalRandom() * std_dev + average;
406 double MathFunctions::GeneratePoissonRandom(
double average)
409 static_cast<unsigned>(std::chrono::system_clock::now().time_since_epoch().count());
410 std::default_random_engine generator(seed);
413 if (average < 1000.0) {
414 std::poisson_distribution<int> distribution(average);
415 int sample = distribution(generator);
416 return (
double)sample;
418 std::normal_distribution<double> distribution(average, std::sqrt(average));
419 double sample = distribution(generator);
420 return std::max(0.0, sample);
Defines M_PI and some more mathematical constants.
Defines namespace MathFunctions.
Various mathematical functions.
complex_t Bessel_J0_PowSer(const complex_t z)
Computes complex Bessel function J0(z), using power series and asymptotic expansion.
double cot(double x)
cotangent function:
std::vector< complex_t > FastFourierTransform(const std::vector< complex_t > &data, EFFTDirection tcase)
simple (and unoptimized) wrapper function for the discrete fast Fourier transformation library (fftw3...
double Laue(const double x, size_t N)
Real Laue function: .
std::vector< complex_t > ConvolveFFT(const std::vector< double > &signal, const std::vector< double > &resfunc)
convolution of two real vectors of equal size
double sinc(double x)
sinc function:
complex_t tanhc(const complex_t z)
Complex tanhc function: .
double Bessel_J0(double x)
Bessel function of the first kind and order 0.
double Bessel_J1(double x)
Bessel function of the first kind and order 1.
double Bessel_J1c(double x)
Bessel function Bessel_J1(x)/x.
double erf(double arg)
Error function of real-valued argument.
double Si(double x)
Sine integral function: .
double Bessel_I0(double x)
Modified Bessel function of the first kind and order 0.
complex_t Bessel_J1_PowSer(const complex_t z)
Computes complex Bessel function J0(z), using power series and asymptotic expansion.