npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
MathUtils.hh
Go to the documentation of this file.
1 #ifndef NPSTAT_MATHUTILS_HH_
2 #define NPSTAT_MATHUTILS_HH_
3 
4 /*!
5 // \file MathUtils.hh
6 //
7 // \brief Various simple mathematical utilities which did not end up inside
8 // dedicated headers
9 //
10 // Author: I. Volobouev
11 //
12 // March 2010
13 */
14 
15 #include <utility>
16 #include <vector>
17 #include <cassert>
18 
19 namespace npstat {
20  /**
21  // Solve the quadratic equation x*x + b*x + c == 0
22  // in a numerically sound manner. Return the number of roots.
23  */
24  unsigned solveQuadratic(double b, double c,
25  double *x1, double *x2);
26 
27  /**
28  // Find the real roots of the cubic:
29  // x**3 + p*x**2 + q*x + r = 0
30  // The number of real roots is returned, and the roots are placed
31  // into the "v3" array. Original code by Don Herbison-Evans (see
32  // his article "Solving Quartics and Cubics for Graphics" in the
33  // book "Graphics Gems V", page 3), with minimal adaptation for
34  // this package by igv.
35  */
36  unsigned solveCubic(double p, double q, double r, double v3[3]);
37 
38  /**
39  // Find an extremum of a parabola passing through the three given points.
40  // The returned value is "true" for minimum and "false" for maximum.
41  // std::invalid_argument will be thrown in case some of the x values
42  // coincide or if the coordinates describe a straight line.
43  */
44  bool parabolicExtremum(double x0, double y0, double x1, double y1,
45  double x2, double y2, double* extremumCoordinate,
46  double* extremumValue);
47 
48  /**
49  // Volume of the n-dimensional sphere of unit radius. Should be
50  // multuplied by R^n to get the volume of the sphere with arbitrary radius.
51  */
52  double ndUnitSphereVolume(unsigned n);
53 
54  /**
55  // Area of the sphere of unit radius embedded in the n-dimensional space.
56  // Should be multuplied by R^(n-1) to get the area of the sphere with
57  // arbitrary radius.
58  */
59  double ndUnitSphereArea(unsigned n);
60 
61  /**
62  // Sum of polynomial series. The length of the
63  // array of coefficients should be at least degree+1.
64  // The highest degree coefficient is assumed to be
65  // the last one in the "coeffs" array (0th degree
66  // coefficient comes first).
67  */
68  template<typename Numeric>
69  long double polySeriesSum(const Numeric *coeffs,
70  unsigned degree, long double x);
71 
72  /**
73  // Sum and derivative of polynomial series. The length of the
74  // array of coefficients should be at least degree+1.
75  */
76  template<typename Numeric>
77  void polyAndDeriv(const Numeric *coeffs, unsigned degree,
78  long double x, long double *value, long double *deriv);
79 
80  /**
81  // Coefficients for the integral of polynomial series.
82  // The integration constant is set to 0. The length of the
83  // array of coefficients should be at least degree+1,
84  // and the length of the buffer for the integral coefficients
85  // should be at least degree+2.
86  */
87  template<typename Numeric>
88  void polyIntegralCoeffs(const Numeric* coeffs, unsigned degree,
89  Numeric* integralCoeffs);
90 
91  /**
92  // Series using Legendre polynomials. 0th degree coefficient
93  // comes first. Although any value of x can be specified, the result
94  // is not going to be terribly meaningful in case |x| > 1.
95  */
96  template<typename Numeric>
97  long double legendreSeriesSum(const Numeric *coeffs,
98  unsigned degree, long double x);
99 
100  /**
101  // Series for Hermite polynomials orthogonal with weight exp(-x*x/2).
102  // These are sometimes called the "probabilists' Hermite polynomials".
103  */
104  template<typename Numeric>
105  long double hermiteSeriesSumProb(const Numeric *coeffs,
106  unsigned degree, long double x);
107 
108  /**
109  // Series for Hermite polynomials orthogonal with weight exp(-x*x). These
110  // are sometimes called the "physicists' Hermite polynomials". The weight
111  // exp(-x*x) is also used in the "GaussHermiteQuadrature" class.
112  */
113  template<typename Numeric>
114  long double hermiteSeriesSumPhys(const Numeric *coeffs,
115  unsigned degree, long double x);
116 
117  /** Series for Gegenbauer polynomials. "lambda" is the parameter. */
118  template<typename Numeric>
119  long double gegenbauerSeriesSum(const Numeric *coeffs, unsigned degree,
120  long double lambda, long double x);
121 
122  /**
123  // Series for the Chebyshev polynomials of the first kind. The array
124  // of coefficients must be at least degree+1 long.
125  */
126  template<typename Numeric>
127  long double chebyshevSeriesSum(const Numeric *coeffs, unsigned degree,
128  long double x);
129 
130  /**
131  // Convert series for the Chebyshev polynomials of the first kind
132  // into the series for monomials. The arrays of coefficients must be
133  // at least degree+1 long.
134  */
135  template<typename Numeric1, typename Numeric2>
136  void chebyshevMonomialCoeffs(const Numeric1 *coeffs, unsigned degree,
137  Numeric2* monoCoeffs);
138 
139  /**
140  // Series for the Chebyshev polynomials of the first kind
141  // on the given interval [xmin, xmax]
142  */
143  template<typename Numeric>
144  long double chebyshevSeriesSum(const Numeric *coeffs, unsigned degree,
145  long double xmin, long double xmax,
146  long double x);
147 
148  /**
149  // Generate Chebyshev series coefficients for a given functor on the
150  // interval [xmin, xmax]. The array of coefficients must be at least
151  // degree+1 long. The functor will be given a long double argument.
152  */
153  template<typename Functor, typename Numeric>
154  void chebyshevSeriesCoeffs(const Functor& f,
155  long double xmin, long double xmax,
156  unsigned degree, Numeric *coeffs);
157 
158  /**
159  // Converts Chebyshev series coefficients into coefficients
160  // for the function integral. The 0's degree coefficient
161  // will be chosen in such a way that the integral is 0
162  // at xmin. The array of coefficients must be at least
163  // degree+1 long, and the buffer for the integral coefficients
164  // must be at least degree+2 long.
165  */
166  template<typename Numeric>
167  void chebyshevIntegralCoeffs(const Numeric* coeffs, unsigned degree,
168  long double xmin, long double xmax,
169  Numeric* integralCoeffs);
170 
171  /**
172  // Converts Chebyshev series coefficients into coefficients
173  // for the function derivative. The array of coefficients
174  // must be at least degree+1 long, and the buffer for the
175  // derivative coefficients must be at least degree long.
176  */
177  template<typename Numeric>
178  void chebyshevDerivativeCoeffs(const Numeric* coeffs, unsigned degree,
179  long double xmin, long double xmax,
180  Numeric* derivativeCoeffs);
181 
182 #ifdef SWIG
183  inline double polySeriesSum2(const double *c, const unsigned degreep1,
184  const double x)
185  {
186  assert(degreep1);
187  return polySeriesSum(c, degreep1-1U, x);
188  }
189 
190  inline std::pair<double,double> polyAndDeriv2(
191  const double *c, const unsigned degreep1,
192  const double x)
193  {
194  assert(degreep1);
195  long double p, d;
196  polyAndDeriv(c, degreep1-1U, x, &p, &d);
197  return std::pair<double,double>(p, d);
198  }
199 
200  inline std::vector<double> polyIntegralCoeffs2(const double *c, const unsigned degreep1)
201  {
202  assert(degreep1);
203  std::vector<double> tmp(degreep1+1U);
204  polyIntegralCoeffs(c, degreep1-1U, &tmp[0]);
205  return tmp;
206  }
207 
208  inline double legendreSeriesSum2(const double *c, const unsigned degreep1,
209  const double x)
210  {
211  assert(degreep1);
212  return legendreSeriesSum(c, degreep1-1U, x);
213  }
214 
215  inline double hermiteSeriesSumProb2(const double *c, const unsigned degreep1,
216  const double x)
217  {
218  assert(degreep1);
219  return hermiteSeriesSumProb(c, degreep1-1U, x);
220  }
221 
222  inline double hermiteSeriesSumPhys2(const double *c, const unsigned degreep1,
223  const double x)
224  {
225  assert(degreep1);
226  return hermiteSeriesSumPhys(c, degreep1-1U, x);
227  }
228 
229  inline double gegenbauerSeriesSum2(const double *c, const unsigned degreep1,
230  const double lambda, const double x)
231  {
232  assert(degreep1);
233  return gegenbauerSeriesSum(c, degreep1-1U, lambda, x);
234  }
235 
236  inline double chebyshevSeriesSum2(const double *c, const unsigned degreep1,
237  const double xmin, const double xmax,
238  const double x)
239  {
240  assert(degreep1);
241  return chebyshevSeriesSum(c, degreep1-1U, xmin, xmax, x);
242  }
243 
244  inline std::vector<double> chebyshevIntegralCoeffs2(const double *c, const unsigned degreep1,
245  const double xmin, const double xmax)
246  {
247  assert(degreep1);
248  std::vector<double> tmp(degreep1+1U);
249  chebyshevIntegralCoeffs(c, degreep1-1U, xmin, xmax, &tmp[0]);
250  return tmp;
251  }
252 
253  inline std::vector<double> chebyshevDerivativeCoeffs2(const double *c, const unsigned degreep1,
254  const double xmin, const double xmax)
255  {
256  assert(degreep1);
257  std::vector<double> tmp(degreep1-1U);
258  chebyshevDerivativeCoeffs(c, degreep1-1U, xmin, xmax,
259  tmp.empty() ? (double *)0 : &tmp[0]);
260  return tmp;
261  }
262 
263  inline std::vector<double> chebyshevMonomialCoeffs2(const double *c, const unsigned degreep1)
264  {
265  assert(degreep1);
266  std::vector<double> tmp(degreep1);
267  chebyshevMonomialCoeffs(c, degreep1-1U, &tmp[0]);
268  return tmp;
269  }
270 
271  template<typename Functor>
272  inline std::vector<double> chebyshevSeriesCoeffs2(const Functor& f,
273  const double xmin, const double xmax, const unsigned degree)
274  {
275  std::vector<double> tmp(degree+1U);
276  chebyshevSeriesCoeffs(f, xmin, xmax, degree, &tmp[0]);
277  return tmp;
278  }
279 
280  inline std::vector<double> solveQuadratic2(const double b, const double c)
281  {
282  double x[2];
283  const unsigned nRoots = solveQuadratic(b, c, &x[0], &x[1]);
284  return std::vector<double>(x, x+nRoots);
285  }
286 
287  inline std::vector<double> solveCubic2(const double p, const double q,
288  const double r)
289  {
290  double v3[3];
291  const unsigned nRoots = solveCubic(p, q, r, v3);
292  return std::vector<double>(v3, v3+nRoots);
293  }
294 #endif // SWIG
295 }
296 
297 #include "npstat/nm/MathUtils.icc"
298 
299 #endif // NPSTAT_MATHUTILS_HH_
Definition: AbsArrayProjector.hh:14
long double gegenbauerSeriesSum(const Numeric *coeffs, unsigned degree, long double lambda, long double x)
void chebyshevSeriesCoeffs(const Functor &f, long double xmin, long double xmax, unsigned degree, Numeric *coeffs)
long double chebyshevSeriesSum(const Numeric *coeffs, unsigned degree, long double x)
void polyAndDeriv(const Numeric *coeffs, unsigned degree, long double x, long double *value, long double *deriv)
long double hermiteSeriesSumProb(const Numeric *coeffs, unsigned degree, long double x)
void chebyshevDerivativeCoeffs(const Numeric *coeffs, unsigned degree, long double xmin, long double xmax, Numeric *derivativeCoeffs)
double ndUnitSphereArea(unsigned n)
long double hermiteSeriesSumPhys(const Numeric *coeffs, unsigned degree, long double x)
unsigned solveCubic(double p, double q, double r, double v3[3])
void chebyshevIntegralCoeffs(const Numeric *coeffs, unsigned degree, long double xmin, long double xmax, Numeric *integralCoeffs)
void chebyshevMonomialCoeffs(const Numeric1 *coeffs, unsigned degree, Numeric2 *monoCoeffs)
bool parabolicExtremum(double x0, double y0, double x1, double y1, double x2, double y2, double *extremumCoordinate, double *extremumValue)
void polyIntegralCoeffs(const Numeric *coeffs, unsigned degree, Numeric *integralCoeffs)
unsigned solveQuadratic(double b, double c, double *x1, double *x2)
long double legendreSeriesSum(const Numeric *coeffs, unsigned degree, long double x)
double ndUnitSphereVolume(unsigned n)
long double polySeriesSum(const Numeric *coeffs, unsigned degree, long double x)