BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
MathFunctions Namespace Reference

Enumerations

enum  EFFTDirection { FORWARD_FFT , BACKWARD_FFT }
 

Functions

complex_t Bessel_J0_PowSer (const complex_t z)
 
complex_t Bessel_J1_PowSer (const complex_t z)
 
double StandardNormal (double x)
 
double Gaussian (double x, double average, double std_dev)
 
double IntegratedGaussian (double x, double average, double std_dev)
 
double cot (double x)
 
double Si (double x)
 
double sinc (double x)
 
complex_t sinc (const complex_t z)
 
complex_t tanhc (const complex_t z)
 
double Laue (const double x, size_t N)
 
double erf (double arg)
 
double Bessel_J0 (double x)
 
double Bessel_J1 (double x)
 
double Bessel_J1c (double x)
 
double Bessel_I0 (double x)
 
complex_t Bessel_J0 (const complex_t z)
 
complex_t Bessel_J1 (const complex_t z)
 
complex_t Bessel_J1c (const complex_t z)
 
std::vector< complex_tFastFourierTransform (const std::vector< complex_t > &data, EFFTDirection tcase)
 
std::vector< complex_tFastFourierTransform (const std::vector< double > &data, EFFTDirection tcase)
 
std::vector< complex_tConvolveFFT (const std::vector< double > &signal, const std::vector< double > &resfunc)
 
double GenerateUniformRandom ()
 
double GenerateStandardNormalRandom ()
 
double GenerateNormalRandom (double average, double std_dev)
 
double GeneratePoissonRandom (double average)
 

Detailed Description

Various mathematical functions.

Enumeration Type Documentation

◆ EFFTDirection

Enumerator
FORWARD_FFT 
BACKWARD_FFT 

Definition at line 86 of file MathFunctions.h.

Function Documentation

◆ Bessel_J0_PowSer()

complex_t MathFunctions::Bessel_J0_PowSer ( const complex_t  z)

Computes complex Bessel function J0(z), using power series and asymptotic expansion.

Computes the complex Bessel function J0(z), using power series and asymptotic expansion.

Forked from unoptimized code at http://www.crbond.com/math.htm, who refers to "Computation of Special Functions", Zhang and Jin, John Wiley and Sons, 1996.

Definition at line 163 of file MathFunctions.cpp.

164 {
165  complex_t cj0;
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};
177 
178  double a0 = std::abs(z);
179  complex_t z1 = z;
180  if (a0 == 0.0)
181  return 1.0;
182  if (std::real(z) < 0.0)
183  z1 = -z;
184  if (a0 <= 12.0) {
185  // standard power series [http://dlmf.nist.gov/10.2 (10.2.2)]
186  complex_t z2 = 0.25 * z * z;
187  cj0 = 1.0;
188  complex_t cr = 1.0;
189  for (size_t k = 1; k <= 40; ++k) {
190  cr *= -z2 / (double)(k * k);
191  cj0 += cr;
192  if (std::abs(cr) < std::abs(cj0) * eps)
193  break;
194  }
195  } else {
196  // Hankel's asymptotic expansion [http://dlmf.nist.gov/10.17 (10.17.3)]
197  size_t kz;
198  if (a0 >= 50.0)
199  kz = 8; // can be changed to 10
200  else if (a0 >= 35.0)
201  kz = 10; // " " " 12
202  else
203  kz = 12; // " " " 14
204  complex_t ct1 = z1 - M_PI_4;
205  complex_t cp0 = 1.0;
206  complex_t cq0 = -0.125;
207  const complex_t z1m2 = 1. / (z1 * z1); // faster than std::pow(z1, -2.0) ??
208  complex_t ptmp = z1m2;
209  for (size_t k = 0; k < kz; ++k) {
210  cp0 += a[k] * ptmp;
211  cq0 += b[k] * ptmp;
212  ptmp *= z1m2;
213  }
214  cj0 = std::sqrt(M_2_PI / z1) * (cp0 * std::cos(ct1) - cq0 / z1 * std::sin(ct1));
215  }
216  return cj0;
217 }
std::complex< double > complex_t
Definition: Complex.h:20
#define M_2_PI
Definition: MathConstants.h:43
#define M_PI_4
Definition: MathConstants.h:41

References anonymous_namespace{PolyhedralComponents.cpp}::eps, M_2_PI, and M_PI_4.

Referenced by Bessel_J0().

◆ Bessel_J1_PowSer()

complex_t MathFunctions::Bessel_J1_PowSer ( const complex_t  z)

Computes complex Bessel function J0(z), using power series and asymptotic expansion.

Computes the complex Bessel function J1(z), using power series and asymptotic expansion.

Forked from same source as for Bessel_J0_PowSer

Definition at line 223 of file MathFunctions.cpp.

224 {
225  complex_t cj1;
226  static const double eps = 1e-15;
227 
228  static double a1[] = {0.1171875,
229  -0.1441955566406250,
230  0.6765925884246826,
231  -6.883914268109947,
232  1.215978918765359e2,
233  -3.302272294480852e3,
234  1.276412726461746e5,
235  -6.656367718817688e6,
236  4.502786003050393e8,
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};
247 
248  double a0 = std::abs(z);
249  if (a0 == 0.0)
250  return 0.0;
251 
252  complex_t z1 = z;
253  if (std::real(z) < 0.0)
254  z1 = -z;
255  if (a0 <= 12.0) {
256  // standard power series [http://dlmf.nist.gov/10.2 (10.2.2)]
257  const complex_t z2 = 0.25 * z * z;
258  cj1 = 1.0;
259  complex_t cr = 1.0; // powers will be computed recursively
260  for (int k = 1; k <= 40; ++k) {
261  cr *= -z2 / (double)(k * (k + 1));
262  cj1 += cr;
263  if (std::abs(cr) < std::abs(cj1) * eps)
264  break;
265  }
266  cj1 *= 0.5 * z1;
267  } else {
268  // Hankel's asymptotic expansion [http://dlmf.nist.gov/10.17 (10.17.3)]
269  size_t kz;
270  if (a0 >= 50.0)
271  kz = 8; // can be changed to 10
272  else if (a0 >= 35.0)
273  kz = 10; // " " " 12
274  else
275  kz = 12; // " " " 14
276  complex_t cp1 = 1.0;
277  complex_t cq1 = 0.375; // division by z1 postponed to final sum
278  const complex_t z1m2 = 1. / (z1 * z1); // faster than std::pow(z1, -2.0) ??
279  complex_t ptmp = z1m2; // powers will be computed recursively
280  for (size_t k = 0; k < kz; ++k) {
281  cp1 += a1[k] * ptmp;
282  cq1 += b1[k] * ptmp; // division by z1 postponed to final sum
283  ptmp *= z1m2;
284  }
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));
287  }
288  if (std::real(z) < 0.0)
289  cj1 = -cj1;
290  return cj1;
291 }
#define M_PI
Definition: MathConstants.h:39

References anonymous_namespace{PolyhedralComponents.cpp}::eps, M_2_PI, and M_PI.

Referenced by Bessel_J1(), and Bessel_J1c().

◆ StandardNormal()

double MathFunctions::StandardNormal ( double  x)

Definition at line 32 of file MathFunctions.cpp.

33 {
34  return std::exp(-x * x / 2.0) / std::sqrt(M_TWOPI);
35 }
#define M_TWOPI
Definition: MathConstants.h:49

References M_TWOPI.

Referenced by Gaussian().

◆ Gaussian()

double MathFunctions::Gaussian ( double  x,
double  average,
double  std_dev 
)

Definition at line 37 of file MathFunctions.cpp.

38 {
39  return StandardNormal((x - average) / std_dev) / std_dev;
40 }
double StandardNormal(double x)

References StandardNormal().

Here is the call graph for this function:

◆ IntegratedGaussian()

double MathFunctions::IntegratedGaussian ( double  x,
double  average,
double  std_dev 
)

Definition at line 42 of file MathFunctions.cpp.

43 {
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;
47 }

Referenced by ResolutionFunction2DGaussian::evaluateCDF().

◆ cot()

◆ Si()

double MathFunctions::Si ( double  x)

Sine integral function: $Si(x)\equiv\int_0^x du \sin(u)/u$.

Definition at line 54 of file MathFunctions.cpp.

55 {
56  return gsl_sf_Si(x);
57 }

Referenced by SpecularMagneticNewStrategy::calculateUpwards().

◆ sinc() [1/2]

◆ sinc() [2/2]

complex_t MathFunctions::sinc ( const complex_t  z)

Complex sinc function: $sinc(x)\equiv\sin(x)/x$.

Definition at line 64 of file MathFunctions.cpp.

65 {
66  // This is an exception from the rule that we must not test floating-point numbers for equality.
67  // For small non-zero arguments, sin(z) returns quite accurately z or z-z^3/6.
68  // There is no loss of precision in computing sin(z)/z.
69  // Therefore there is no need for an expensive test like abs(z)<eps.
70  if (z == complex_t(0., 0.))
71  return 1.0;
72  return std::sin(z) / z;
73 }

◆ tanhc()

complex_t MathFunctions::tanhc ( const complex_t  z)

Complex tanhc function: $tanhc(x)\equiv\tanh(x)/x$.

Definition at line 75 of file MathFunctions.cpp.

76 {
77  if (std::abs(z) < std::numeric_limits<double>::epsilon())
78  return 1.0;
79  return std::tanh(z) / z;
80 }

Referenced by SpecularMagneticNewTanhStrategy::computeRoughnessMatrix(), and SpecularScalarTanhStrategy::transition().

◆ Laue()

double MathFunctions::Laue ( const double  x,
size_t  N 
)

Real Laue function: $Laue(x,N)\equiv\sin(Nx)/sin(x)$.

Definition at line 82 of file MathFunctions.cpp.

83 {
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)
87  return nd;
88  double num = std::sin(nd * x);
89  double den = std::sin(x);
90  return num / den;
91 }

Referenced by InterferenceFunction2DSuperLattice::iff_without_dw(), InterferenceFunctionFinite3DLattice::iff_without_dw(), and InterferenceFunctionFinite2DLattice::interferenceForXi().

◆ erf()

double MathFunctions::erf ( double  arg)

Error function of real-valued argument.

Definition at line 93 of file MathFunctions.cpp.

94 {
95  if (arg < 0.0)
96  throw std::runtime_error("Error in MathFunctions::erf: negative argument is not allowed");
97  if (std::isinf(arg))
98  return 1.0;
99  return gsl_sf_erf(arg);
100 }

Referenced by FootprintGauss::calculate().

◆ Bessel_J0() [1/2]

double MathFunctions::Bessel_J0 ( double  x)

Bessel function of the first kind and order 0.

Definition at line 115 of file MathFunctions.cpp.

116 {
117  return gsl_sf_bessel_J0(x);
118 }

Referenced by FTDistribution2DCone::evaluate(), and InterferenceFunctionHardDisk::integrand().

◆ Bessel_J1() [1/2]

double MathFunctions::Bessel_J1 ( double  x)

Bessel function of the first kind and order 1.

Definition at line 120 of file MathFunctions.cpp.

121 {
122  return gsl_sf_bessel_J1(x);
123 }

◆ Bessel_J1c() [1/2]

double MathFunctions::Bessel_J1c ( double  x)

◆ Bessel_I0()

double MathFunctions::Bessel_I0 ( double  x)

Modified Bessel function of the first kind and order 0.

Definition at line 130 of file MathFunctions.cpp.

131 {
132  return gsl_sf_bessel_I0(x);
133 }

Referenced by anonymous_namespace{IPeakShape.cpp}::MisesPrefactor().

◆ Bessel_J0() [2/2]

complex_t MathFunctions::Bessel_J0 ( const complex_t  z)

Complex Bessel function of the first kind and order 0.

Definition at line 135 of file MathFunctions.cpp.

136 {
137  if (std::imag(z) == 0)
138  return gsl_sf_bessel_J0(std::real(z));
139  return Bessel_J0_PowSer(z);
140 }
complex_t Bessel_J0_PowSer(const complex_t z)
Computes complex Bessel function J0(z), using power series and asymptotic expansion.

References Bessel_J0_PowSer().

Here is the call graph for this function:

◆ Bessel_J1() [2/2]

complex_t MathFunctions::Bessel_J1 ( const complex_t  z)

Complex Bessel function of the first kind and order 1.

Definition at line 142 of file MathFunctions.cpp.

143 {
144  if (std::imag(z) == 0)
145  return gsl_sf_bessel_J1(std::real(z));
146  return Bessel_J1_PowSer(z);
147 }
complex_t Bessel_J1_PowSer(const complex_t z)
Computes complex Bessel function J0(z), using power series and asymptotic expansion.

References Bessel_J1_PowSer().

Here is the call graph for this function:

◆ Bessel_J1c() [2/2]

complex_t MathFunctions::Bessel_J1c ( const complex_t  z)

Complex Bessel function Bessel_J1(x)/x.

Definition at line 149 of file MathFunctions.cpp.

150 {
151  if (std::imag(z) == 0) {
152  double xv = std::real(z);
153  return xv == 0 ? 0.5 : gsl_sf_bessel_J1(xv) / xv;
154  }
155  return z == 0. ? 0.5 : MathFunctions::Bessel_J1_PowSer(z) / z;
156 }

References Bessel_J1_PowSer().

Here is the call graph for this function:

◆ FastFourierTransform() [1/2]

std::vector< complex_t > MathFunctions::FastFourierTransform ( const std::vector< complex_t > &  data,
MathFunctions::EFFTDirection  ftCase 
)

simple (and unoptimized) wrapper function for the discrete fast Fourier transformation library (fftw3)

Definition at line 300 of file MathFunctions.cpp.

302 {
303  double scale(1.);
304  size_t npx = data.size();
305 
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);
310 
311  for (size_t i = 0; i < npx; i++) {
312  ftData[i][0] = data[i].real();
313  ftData[i][1] = data[i].imag();
314  }
315 
316  fftw_plan plan;
317  switch (ftCase) {
319  plan = fftw_plan_dft_1d((int)npx, ftData, ftResult, FFTW_FORWARD, FFTW_ESTIMATE);
320  break;
322  plan = fftw_plan_dft_1d((int)npx, ftData, ftResult, FFTW_BACKWARD, FFTW_ESTIMATE);
323  scale = 1. / double(npx);
324  break;
325  default:
326  throw std::runtime_error(
327  "MathFunctions::FastFourierTransform -> Panic! Unknown transform case.");
328  }
329 
330  fftw_execute(plan);
331 
332  // saving data for user
333  std::vector<complex_t> outData;
334  outData.resize(npx);
335  for (size_t i = 0; i < npx; i++)
336  outData[i] = scale * complex_t(ftResult[i][0], ftResult[i][1]);
337 
338  fftw_destroy_plan(plan);
339  fftw_free(ftData);
340  fftw_free(ftResult);
341 
342  return outData;
343 }

References BACKWARD_FFT, and FORWARD_FFT.

Referenced by ConvolveFFT(), and FastFourierTransform().

◆ FastFourierTransform() [2/2]

std::vector< complex_t > MathFunctions::FastFourierTransform ( const std::vector< double > &  data,
MathFunctions::EFFTDirection  ftCase 
)

simple (and unoptimized) wrapper function for the discrete fast Fourier transformation library (fftw3); transforms real to complex

Definition at line 349 of file MathFunctions.cpp.

351 {
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);
356  return MathFunctions::FastFourierTransform(cdata, ftCase);
357 }
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...

References FastFourierTransform().

Here is the call graph for this function:

◆ ConvolveFFT()

std::vector< complex_t > MathFunctions::ConvolveFFT ( const std::vector< double > &  signal,
const std::vector< double > &  resfunc 
)

convolution of two real vectors of equal size

Definition at line 361 of file MathFunctions.cpp.

363 {
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 =
371 
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];
376 
377  std::vector<complex_t> result =
379  return result;
380 }

References BACKWARD_FFT, FastFourierTransform(), and FORWARD_FFT.

Here is the call graph for this function:

◆ GenerateUniformRandom()

double MathFunctions::GenerateUniformRandom ( )

Definition at line 386 of file MathFunctions.cpp.

387 {
388  int random_int = std::rand();
389  return (double)random_int / RAND_MAX;
390 }

◆ GenerateStandardNormalRandom()

double MathFunctions::GenerateStandardNormalRandom ( )

Definition at line 392 of file MathFunctions.cpp.

393 {
394  unsigned seed =
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);
399 }

Referenced by GenerateNormalRandom().

◆ GenerateNormalRandom()

double MathFunctions::GenerateNormalRandom ( double  average,
double  std_dev 
)

Definition at line 401 of file MathFunctions.cpp.

402 {
403  return GenerateStandardNormalRandom() * std_dev + average;
404 }
double GenerateStandardNormalRandom()

References GenerateStandardNormalRandom().

Here is the call graph for this function:

◆ GeneratePoissonRandom()

double MathFunctions::GeneratePoissonRandom ( double  average)

Definition at line 406 of file MathFunctions.cpp.

407 {
408  unsigned seed =
409  static_cast<unsigned>(std::chrono::system_clock::now().time_since_epoch().count());
410  std::default_random_engine generator(seed);
411  if (average <= 0.0)
412  return 0.0;
413  if (average < 1000.0) { // Use std::poisson_distribution
414  std::poisson_distribution<int> distribution(average);
415  int sample = distribution(generator);
416  return (double)sample;
417  } else { // Use normal approximation
418  std::normal_distribution<double> distribution(average, std::sqrt(average));
419  double sample = distribution(generator);
420  return std::max(0.0, sample);
421  }
422 }

Referenced by PoissonNoiseBackground::addBackground().