BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
Functions.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Base/Math/Functions.cpp
6 //! @brief Implements functions in namespace Math.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
15 #include "Base/Math/Functions.h"
16 #include "Base/Math/Constants.h"
17 #include <chrono>
18 #include <cstring>
19 #include <fftw3.h>
20 #include <gsl/gsl_sf_erf.h>
21 #include <gsl/gsl_sf_expint.h>
22 #include <gsl/gsl_sf_trig.h>
23 #include <limits>
24 #include <random>
25 #include <stdexcept> // need overlooked by g++ 5.4
26 
27 // ************************************************************************************************
28 // Various functions
29 // ************************************************************************************************
30 
31 double Math::StandardNormal(double x)
32 {
33  return std::exp(-x * x / 2.0) / std::sqrt(M_TWOPI);
34 }
35 
36 double Math::Gaussian(double x, double average, double std_dev)
37 {
38  return StandardNormal((x - average) / std_dev) / std_dev;
39 }
40 
41 double Math::IntegratedGaussian(double x, double average, double std_dev)
42 {
43  double normalized_x = (x - average) / std_dev;
44  static double root2 = std::sqrt(2.0);
45  return (gsl_sf_erf(normalized_x / root2) + 1.0) / 2.0;
46 }
47 
48 double Math::cot(double x)
49 {
50  return tan(M_PI_2 - x);
51 }
52 
53 double Math::sinc(double x) // Sin(x)/x
54 {
55  return gsl_sf_sinc(x / M_PI);
56 }
57 
58 complex_t Math::sinc(const complex_t z) // Sin(x)/x
59 {
60  // This is an exception from the rule that we must not test floating-point numbers for equality.
61  // For small non-zero arguments, sin(z) returns quite accurately z or z-z^3/6.
62  // There is no loss of precision in computing sin(z)/z.
63  // Therefore there is no need for an expensive test like abs(z)<eps.
64  if (z == complex_t(0., 0.))
65  return 1.0;
66  return std::sin(z) / z;
67 }
68 
69 complex_t Math::tanhc(const complex_t z) // tanh(x)/x
70 {
71  if (std::abs(z) < std::numeric_limits<double>::epsilon())
72  return 1.0;
73  return std::tanh(z) / z;
74 }
75 
76 double Math::Laue(const double x, size_t N)
77 {
78  static const double SQRT6DOUBLE_EPS = std::sqrt(6.0 * std::numeric_limits<double>::epsilon());
79  auto nd = static_cast<double>(N);
80  if (std::abs(nd * x) < SQRT6DOUBLE_EPS)
81  return nd;
82  double num = std::sin(nd * x);
83  double den = std::sin(x);
84  return num / den;
85 }
86 
87 double Math::erf(double arg)
88 {
89  if (arg < 0.0)
90  throw std::runtime_error("Error in Math::erf: negative argument is not allowed");
91  if (std::isinf(arg))
92  return 1.0;
93  return gsl_sf_erf(arg);
94 }
95 
96 // ************************************************************************************************
97 // Random number generators
98 // ************************************************************************************************
99 
100 /* currently unused
101 
102 double Math::GenerateUniformRandom()
103 {
104  int random_int = std::rand();
105  return (double)random_int / RAND_MAX;
106 }
107 
108 double Math::GenerateStandardNormalRandom() // using c++11 standard library
109 {
110  unsigned seed =
111  static_cast<unsigned>(std::chrono::system_clock::now().time_since_epoch().count());
112  std::default_random_engine generator(seed);
113  std::normal_distribution<double> distribution(0.0, 1.0);
114  return distribution(generator);
115 }
116 
117 double Math::GenerateNormalRandom(double average, double std_dev)
118 {
119  return GenerateStandardNormalRandom() * std_dev + average;
120 }
121 */
122 
123 double Math::GeneratePoissonRandom(double average) // using c++11 standard library
124 {
125  unsigned seed =
126  static_cast<unsigned>(std::chrono::system_clock::now().time_since_epoch().count());
127  std::default_random_engine generator(seed);
128  if (average <= 0.0)
129  return 0.0;
130  if (average < 1000.0) { // Use std::poisson_distribution
131  std::poisson_distribution<int> distribution(average);
132  int sample = distribution(generator);
133  return (double)sample;
134  } else { // Use normal approximation
135  std::normal_distribution<double> distribution(average, std::sqrt(average));
136  double sample = distribution(generator);
137  return std::max(0.0, sample);
138  }
139 }
std::complex< double > complex_t
Definition: Complex.h:20
Defines M_PI and some more mathematical constants.
#define M_TWOPI
Definition: Constants.h:54
#define M_PI_2
Definition: Constants.h:45
#define M_PI
Definition: Constants.h:44
Defines functions in namespace Math.
double sinc(double x)
sinc function:
Definition: Functions.cpp:53
double Gaussian(double x, double average, double std_dev)
Definition: Functions.cpp:36
complex_t tanhc(const complex_t z)
Complex tanhc function: .
Definition: Functions.cpp:69
double erf(double arg)
Error function of real-valued argument.
Definition: Functions.cpp:87
double GeneratePoissonRandom(double average)
Definition: Functions.cpp:123
double IntegratedGaussian(double x, double average, double std_dev)
Definition: Functions.cpp:41
double cot(double x)
cotangent function:
Definition: Functions.cpp:48
double StandardNormal(double x)
Definition: Functions.cpp:31
double Laue(const double x, size_t N)
Real Laue function: .
Definition: Functions.cpp:76