BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
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 <limits>
23 #include <random>
24 #include <stdexcept> // need overlooked by g++ 5.4
25 
26 // ************************************************************************************************
27 // Various functions
28 // ************************************************************************************************
29 
30 double Math::StandardNormal(double x)
31 {
32  return std::exp(-x * x / 2.0) / std::sqrt(M_TWOPI);
33 }
34 
35 double Math::Gaussian(double x, double average, double std_dev)
36 {
37  return StandardNormal((x - average) / std_dev) / std_dev;
38 }
39 
40 double Math::IntegratedGaussian(double x, double average, double std_dev)
41 {
42  double normalized_x = (x - average) / std_dev;
43  static double root2 = std::sqrt(2.0);
44  return (gsl_sf_erf(normalized_x / root2) + 1.0) / 2.0;
45 }
46 
47 double Math::cot(double x)
48 {
49  return tan(M_PI_2 - x);
50 }
51 
52 double Math::sinc(double x) // Sin(x)/x
53 {
54  if (x == 0)
55  return 1;
56  return std::sin(x) / x;
57 }
58 
59 complex_t Math::sinc(const complex_t z) // Sin(x)/x
60 {
61  // This is an exception from the rule that we must not test floating-point numbers for equality.
62  // For small non-zero arguments, sin(z) returns quite accurately z or z-z^3/6.
63  // There is no loss of precision in computing sin(z)/z.
64  // Therefore there is no need for an expensive test like abs(z)<eps.
65  if (z == complex_t(0., 0.))
66  return 1.0;
67  return std::sin(z) / z;
68 }
69 
70 complex_t Math::tanhc(const complex_t z) // tanh(x)/x
71 {
72  if (std::abs(z) < std::numeric_limits<double>::epsilon())
73  return 1.0;
74  return std::tanh(z) / z;
75 }
76 
77 double Math::Laue(const double x, size_t N)
78 {
79  static const double SQRT6DOUBLE_EPS = std::sqrt(6.0 * std::numeric_limits<double>::epsilon());
80  auto nd = static_cast<double>(N);
81  if (std::abs(nd * x) < SQRT6DOUBLE_EPS)
82  return nd;
83  double num = std::sin(nd * x);
84  double den = std::sin(x);
85  return num / den;
86 }
87 
88 double Math::erf(double arg)
89 {
90  if (arg < 0.0)
91  throw std::runtime_error("Error in Math::erf: negative argument is not allowed");
92  if (std::isinf(arg))
93  return 1.0;
94  return gsl_sf_erf(arg);
95 }
96 
97 // ************************************************************************************************
98 // Random number generators
99 // ************************************************************************************************
100 
101 /* currently unused
102 
103 double Math::GenerateUniformRandom()
104 {
105  int random_int = std::rand();
106  return (double)random_int / RAND_MAX;
107 }
108 
109 double Math::GenerateStandardNormalRandom() // using c++11 standard library
110 {
111  unsigned seed =
112  static_cast<unsigned>(std::chrono::system_clock::now().time_since_epoch().count());
113  std::default_random_engine generator(seed);
114  std::normal_distribution<double> distribution(0.0, 1.0);
115  return distribution(generator);
116 }
117 
118 double Math::GenerateNormalRandom(double average, double std_dev)
119 {
120  return GenerateStandardNormalRandom() * std_dev + average;
121 }
122 */
123 
124 double Math::GeneratePoissonRandom(double average) // using c++11 standard library
125 {
126  unsigned seed =
127  static_cast<unsigned>(std::chrono::system_clock::now().time_since_epoch().count());
128  std::default_random_engine generator(seed);
129  if (average <= 0.0)
130  return 0.0;
131  if (average < 1000.0) { // Use std::poisson_distribution
132  std::poisson_distribution<int> distribution(average);
133  int sample = distribution(generator);
134  return (double)sample;
135  }
136  // Use normal approximation
137  std::normal_distribution<double> distribution(average, std::sqrt(average));
138  double sample = distribution(generator);
139  return std::max(0.0, sample);
140 }
Defines M_PI and some more mathematical constants.
#define M_TWOPI
Definition: Constants.h:54
#define M_PI_2
Definition: Constants.h:45
Defines namespace Math.
#define N
Definition: mixmax.h:31
double sinc(double x)
sinc function:
Definition: Functions.cpp:52
complex_t tanhc(complex_t z)
Complex tanhc function: .
Definition: Functions.cpp:70
double Gaussian(double x, double average, double std_dev)
Definition: Functions.cpp:35
double erf(double arg)
Error function of real-valued argument.
Definition: Functions.cpp:88
double GeneratePoissonRandom(double average)
Definition: Functions.cpp:124
double Laue(double x, size_t N)
Real Laue function: .
Definition: Functions.cpp:77
double IntegratedGaussian(double x, double average, double std_dev)
Definition: Functions.cpp:40
double cot(double x)
cotangent function:
Definition: Functions.cpp:47
double StandardNormal(double x)
Definition: Functions.cpp:30