MercuryDPM  Alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ExtendedMath.cc
Go to the documentation of this file.
1 //Copyright (c) 2013-2014, The MercuryDPM Developers Team. All rights reserved.
2 //For the list of developers, see <http://www.MercuryDPM.org/Team>.
3 //
4 //Redistribution and use in source and binary forms, with or without
5 //modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name MercuryDPM nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 //DISCLAIMED. IN NO EVENT SHALL THE MERCURYDPM DEVELOPERS TEAM BE LIABLE FOR ANY
19 //DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 //(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 //ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 //(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #include "ExtendedMath.h"
27 
28 #include <cmath>
29 #include <assert.h>
31 //#include <limits>
32 //#include <iostream>
33 //#include <sys/stat.h>
34 #include <iomanip>
35 //#include <cmath>
36 //#include <sstream>
37 //#include <cstdlib>
38 //#include <limits>
39 //#include <string>
40 
41 // sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ...
43  Mdouble N = floor(x/(2.0*constants::pi)+0.5);
44  x -= N*2.0*constants::pi;
45  Mdouble Sum = 0;
46  Mdouble Power = x;
47  Mdouble Sign = 1;
48  const Mdouble x2 = x * x;
49  Mdouble Fact = 1.0;
50  for (unsigned int i = 1; i < 25; i += 2) {
51  Sum += Sign * Power / Fact;
52  Power *= x2;
53  Fact *= (i + 1) * (i + 2);
54  Sign *= -1.0;
55  }
56  return Sum;
57 }
58 
59 // cos(x) = 1 - x^2/2! + x^4/4! - x^6/6! + ...
61  Mdouble N = floor(x/(2.0*constants::pi)+0.5);
62  x -= N*2.0*constants::pi;
63  Mdouble Sum = 1.0;
64  Mdouble Power = 1;
65  Mdouble Sign = 1;
66  const Mdouble x2 = x * x;
67  Mdouble Fact = 1.0;
68  for (unsigned int i = 2; i < 25; i += 2) {
69  Power *= x2;
70  Fact *= i * (i - 1);
71  Sign *= -1.0;
72  Sum += Sign * Power / Fact;
73  }
74  return Sum;
75 }
76 
77 //from: http://www.codeproject.com/Tips/311714/Natural-Logarithms-and-Exponent
79  Mdouble X, P, Frac, I, L;
80  X = Exponent;
81  Frac = X;
82  P = (1.0 + X);
83  I = 1.0;
84 
85  do
86  {
87  I++;
88  Frac *= (X / I);
89  L = P;
90  P += Frac;
91  }while(L != P);
92 
93  return P;
94 }
95 
98 {
99  Mdouble N, P, L, R, A, E;
100  E = 2.71828182845905;
101  P = Power;
102  N = 0.0;
103 
104  // This speeds up the convergence by calculating the integral
105  while(P >= E)
106  {
107  P /= E;
108  N++;
109  }
110  N += (P / E);
111  P = Power;
112  do
113  {
114  A = N;
115  L = (P / (exp(N - 1.0)));
116  R = ((N - 1.0) * E);
117  N = ((L + R) / E);
118  } while (N < A);
119  //} while (N != A);
120 
121  return N;
122 }
123 
131 {
132  const Mdouble ep = 1e-5;
133 
134  if (gamma_in > 1.0 + ep)
135  {
136  return ((gamma_in - 1) * gamma(gamma_in - 1));
137  }
138  else
139  {
140 
141  if ((gamma_in - ep < 1.0) && (gamma_in + ep > 1.0))
142  return 1.0;
143  else if ((gamma_in - ep < 0.5) && (gamma_in + ep > 0.5))
144  return constants::sqrt_pi;
145  else
146  return std::numeric_limits<Mdouble>::quiet_NaN();
147  }
148 } //end func gamma
149 
153 Mdouble mathsFunc::chi_squared(const Mdouble x, const unsigned int k)
154 {
155 
156  Mdouble prefactor = pow(2, k / 2.0) * gamma(k / 2.0);
157  Mdouble mainfactor = pow(x, k / 2.0 - 1) * exp(x / -2.0);
158 
159  return mainfactor / prefactor;
160 
161 }
162 
169 Mdouble mathsFunc::chi_squared_prob(const Mdouble x_max, const unsigned int k)
170 {
171 
172 //The current value was picked by tried were it stopped effect the 4 d.p.
173  const int num_steps_per_unit = 100;
174  Mdouble sum = 0;
175  Mdouble x = 0;
176  long int num_steps = static_cast<int>(num_steps_per_unit * x_max);
177 //Use trapezional rule, but ignoring the ends
178  for (int i = 0; i < num_steps; i++)
179  {
180  x = x_max / num_steps * (i + 0.5);
181  sum = sum + chi_squared(x, k);
182  }
183  return 1.0 - sum * x_max / num_steps;
184 
185 }
186 
187 Mdouble mathsFunc::goldenSectionSearch(Mdouble(*function)(const Mdouble), Mdouble min, Mdouble cur, Mdouble max, Mdouble endCondition, Mdouble curVal)
188 {
189  if (std::abs(max - min) < endCondition)
190  {
191  return 0.5 * (min + max);
192  }
193  std::cout << "Min=" << min << " Max=" << max << " diff=" << max - min << std::endl;
194  Mdouble resphi = 2 - 0.5 * (1 + std::sqrt(5));
195  Mdouble x;
196  if (max - cur > cur - min)
197  {
198  x = cur + resphi * (max - cur);
199  }
200  else
201  {
202  x = cur - resphi * (cur - min);
203  }
204  if(std::isnan(curVal))
205  curVal = function(cur);
206  Mdouble xVal = function(x);
207  if (xVal < curVal)
208  {
209  if (max - cur > cur - min)
210  {
211  return goldenSectionSearch(function, cur, x, max, endCondition, xVal);
212  }
213  else
214  {
215  return goldenSectionSearch(function, min, x, cur, endCondition, xVal);
216  }
217  }
218  else
219  {
220  if (max - cur > cur - min)
221  {
222  return goldenSectionSearch(function, min, cur, x, endCondition, curVal);
223  }
224  else
225  {
226  return goldenSectionSearch(function, x, cur, max, endCondition, curVal);
227  }
228  }
229 }
230 
232 {
233  return std::abs(v1 - v2) <= absError;
234 }
235 
236 
237 bool mathsFunc::isEqual(Vec3D v1, Vec3D v2, Mdouble absError)
238 {
239  return isEqual(v1.X,v2.X,absError)&&isEqual(v1.Y,v2.Y,absError)&&isEqual(v1.Z,v2.Z,absError);
240 }
241 
243 {
244  const Mdouble *p = coef;
245  Mdouble b0 = *p++;
246  Mdouble b1 = 0, b2;
247  int i = N - 1;
248 
249  assert(i > 0);
250  do
251  {
252  b2 = b1;
253  b1 = b0;
254  b0 = x * b1 - b2 + *p++;
255  }
256  while ( --i);
257 
258  return (0.5 * (b0 - b2));
259 }
260 
262 {
263  // Cooefficients for [0..8]
264  const Mdouble A[] =
265  {
266  -4.415341646479339379501E-18,
267  3.330794518822238097831E-17,
268  -2.431279846547954693591E-16,
269  1.715391285555133030611E-15,
270  -1.168533287799345168081E-14,
271  7.676185498604935616881E-14,
272  -4.856446783111929460901E-13,
273  2.955052663129639834611E-12,
274  -1.726826291441555707231E-11,
275  9.675809035373236912241E-11,
276  -5.189795601635262906661E-10,
277  2.659823724682386650351E-9,
278  -1.300025009986248042121E-8,
279  6.046995022541918949321E-8,
280  -2.670793853940611733911E-7,
281  1.117387539120103718151E-6,
282  -4.416738358458750563591E-6,
283  1.644844807072889708931E-5,
284  -5.754195010082103703981E-5,
285  1.885028850958416557291E-4,
286  -5.763755745385823658851E-4,
287  1.639475616941335798421E-3,
288  -4.324309995050575944301E-3,
289  1.054646039459499831831E-2,
290  -2.373741480589946881561E-2,
291  4.930528423967070848781E-2,
292  -9.490109704804764442101E-2,
293  1.716209015222087753491E-1,
294  -3.046826723431983986831E-1,
295  6.767952744094760849951E-1
296  };
297 
298  // Cooefficients for [8..infinity]
299  const Mdouble B[] =
300  {
301  -7.233180487874753954561E-18,
302  -4.830504485944182071261E-18,
303  4.465621420296759999011E-17,
304  3.461222867697461093101E-17,
305  -2.827623980516583484941E-16,
306  -3.425485619677219134621E-16,
307  1.772560133056526383601E-15,
308  3.811680669352622420751E-15,
309  -9.554846698828307648701E-15,
310  -4.150569347287222086631E-14,
311  1.540086217521409826911E-14,
312  3.852778382742142701141E-13,
313  7.180124451383666233671E-13,
314  -1.794178531506806117781E-12,
315  -1.321581184044771311881E-11,
316  -3.149916527963241364541E-11,
317  1.188914710784643834241E-11,
318  4.940602388224969589101E-10,
319  3.396232025708386345151E-9,
320  2.266668990498178064591E-8,
321  2.048918589469063741831E-7,
322  2.891370520834756482971E-6,
323  6.889758346916823984261E-5,
324  3.369116478255694089901E-3,
325  8.044904110141088316081E-1
326  };
327 
328  if (x < 0)
329  x = -x;
330 
331  if (x <= 8.0)
332  {
333  Mdouble y = (x / 2.0) - 2.0;
334  return (chebyshev(y, A, 30));
335  }
336 
337  return (chebyshev(32.0 / x - 2.0, B, 25) / sqrt(x));
338 
339 }
340 
342 {
343  if (x < 0)
344  x = -x;
345  return exp(x) * I0_exp(x);
346 }
Mdouble X
the vector components
Definition: Vector.h:52
Mdouble chi_squared_prob(const Mdouble x, const unsigned int k)
This is the function which actually gives the probability back using a chi squared test...
Mdouble goldenSectionSearch(Mdouble(*function)(const Mdouble), Mdouble min, Mdouble cur, Mdouble max, Mdouble endCondition, Mdouble curVal=std::numeric_limits< Mdouble >::quiet_NaN())
This function performs a golden section search to find the location of the minimum of a function...
Mdouble exp(Mdouble Exponent)
Definition: ExtendedMath.cc:78
Mdouble I0(Mdouble x)
const Mdouble sqrt_pi
Definition: ExtendedMath.h:43
double Mdouble
Mdouble log(Mdouble Power)
Definition: ExtendedMath.cc:97
bool isEqual(Mdouble v1, Mdouble v2, Mdouble absError)
Compares the difference of two Mdouble with an absolute error, useful in UnitTests.
Mdouble cos(Mdouble x)
Definition: ExtendedMath.cc:60
Mdouble sin(Mdouble x)
Definition: ExtendedMath.cc:42
const Mdouble pi
Definition: ExtendedMath.h:42
Mdouble I0_exp(Mdouble x)
Mdouble chebyshev(Mdouble x, const Mdouble coef[], int N)
Namespace for evaluating the zeroth modified Bessel function of the first kind, I0(x), required in StatisticsPoint.hcc.
Mdouble Y
Definition: Vector.h:52
#define assert(e,...)
Definition: Logger.h:584
Mdouble gamma(Mdouble gamma_in)
This is the gamma function returns the true value for the half integer value.
Mdouble chi_squared(const Mdouble x, const unsigned int k)
This is a chi_squared function return the value x and degrees of freedom k.
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:45
Mdouble Z
Definition: Vector.h:52