npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
ClassicalOrthoPolys1D.hh
Go to the documentation of this file.
1 #ifndef NPSTAT_CLASSICALORTHOPOLYS1D_HH_
2 #define NPSTAT_CLASSICALORTHOPOLYS1D_HH_
3 
4 /*!
5 // \file ClassicalOrthoPolys1D.hh
6 //
7 // \brief Orthonormal versions of some classical orthogonal polynomials
8 //
9 // Author: I. Volobouev
10 //
11 // July 2018
12 */
13 
14 #include <cmath>
15 #include <vector>
16 #include <algorithm>
17 
19 
20 namespace npstat {
21  /** Orthonormal Legendre polynomials on [-1, 1] */
23  {
24  public:
25  inline virtual LegendreOrthoPoly1D* clone() const
26  {return new LegendreOrthoPoly1D(*this);}
27 
28  inline virtual ~LegendreOrthoPoly1D() {}
29 
30  inline long double weight(const long double x) const
31  {return (x >= -1.0L && x <= 1.0L) ? 0.5L : 0.0L;}
32  inline double xmin() const {return -1.0L;}
33  inline double xmax() const {return 1.0L;}
34 
35  /**
36  // Derive the series coefficients for the integral of the
37  // argument series from -1 to x. The array of coefficients
38  // must be at least degree+1 long, and the buffer for the
39  // integral coefficients must be at least degree+2 long.
40  */
41  void integralCoeffs(const double* coeffs, unsigned degree,
42  double* integCoeffs) const;
43  /**
44  // Derive the series coefficients for the derivative of the
45  // argument series. The array of coefficients must be at least
46  // degree+1 long, and the buffer for the derivative coefficients
47  // must be at least degree long.
48  */
49  void derivativeCoeffs(const double* coeffs, unsigned degree,
50  double* derivCoeffs) const;
51  /**
52  // Derive the series coefficients for the monomial
53  // expansion. The arrays of coefficients must be
54  // at least degree+1 long.
55  */
56  void monomialCoeffs(const double* coeffs, unsigned degree,
57  long double* monoCoeffs) const;
58  /**
59  // Expand a squared polynomial into polynomial series.
60  // The number of coefficients will be 2*degree + 1.
61  */
62  void squaredPolyCoeffs(unsigned degree,
63  long double* expansionCoeffs) const;
64 
65  inline virtual std::pair<long double,long double>
66  monicRecurrenceCoeffs(const unsigned k) const
67  {
68  long double beta = 1.0L;
69  if (k)
70  beta = 1.0L/(4.0L - 1.0L/k/k);
71  return std::pair<long double,long double>(0.0L, beta);
72  }
73 
74  inline virtual std::pair<long double,long double>
75  recurrenceCoeffs(const unsigned k) const
76  {
77  long double sqb = 1.0L;
78  if (k)
79  sqb = 1.0L/sqrtl(4.0L - 1.0L/k/k);
80  return std::pair<long double,long double>(0.0L, sqb);
81  }
82 
83 #ifdef SWIG
84  public:
85  inline std::vector<double>
86  integralCoeffs2(const double *c, const unsigned degreep1) const
87  {
88  std::vector<double> tmp(degreep1+1U);
89  integralCoeffs(c, degreep1-1U, &tmp[0]);
90  return tmp;
91  }
92 
93  inline std::vector<double>
94  derivativeCoeffs2(const double *c, const unsigned degreep1) const
95  {
96  std::vector<double> tmp(std::max(degreep1-1U, 1U));
97  derivativeCoeffs(c, degreep1-1U, &tmp[0]);
98  return tmp;
99  }
100 
101  inline std::vector<double>
102  monomialCoeffs2(const double *c, const unsigned degreep1) const
103  {
104  std::vector<long double> ldtmp(degreep1+1U);
105  monomialCoeffs(c, degreep1-1U, &ldtmp[0]);
106  return std::vector<double>(ldtmp.begin(), ldtmp.end());
107  }
108 
109  inline std::vector<double>
110  squaredPolyCoeffs2(const unsigned degree) const
111  {
112  std::vector<long double> tmp(2U*degree + 1U);
113  squaredPolyCoeffs(degree, &tmp[0]);
114  return std::vector<double>(tmp.begin(), tmp.end());
115  }
116 #endif
117  };
118 
119  /** Orthonormal Legendre polynomials on [0, 1] (that is, shifted) */
121  {
122  public:
123  inline virtual ShiftedLegendreOrthoPoly1D* clone() const
124  {return new ShiftedLegendreOrthoPoly1D(*this);}
125 
126  inline virtual ~ShiftedLegendreOrthoPoly1D() {}
127 
128  inline long double weight(const long double x) const
129  {return (x >= 0.0L && x <= 1.0L) ? 1.0L : 0.0L;}
130  inline double xmin() const {return 0.0L;}
131  inline double xmax() const {return 1.0L;}
132 
133  /**
134  // Derive the series coefficients for the integral of the
135  // argument series from 0 to x. The array of coefficients
136  // must be at least degree+1 long, and the buffer for the
137  // integral coefficients must be at least degree+2 long.
138  */
139  void integralCoeffs(const double* coeffs, unsigned degree,
140  double* integCoeffs) const;
141  /**
142  // Derive the series coefficients for the derivative of the
143  // argument series. The array of coefficients must be at least
144  // degree+1 long, and the buffer for the derivative coefficients
145  // must be at least degree long.
146  */
147  void derivativeCoeffs(const double* coeffs, unsigned degree,
148  double* derivCoeffs) const;
149  /**
150  // Expand a squared polynomial into polynomial series.
151  // The number of coefficients will be 2*degree + 1.
152  */
153  void squaredPolyCoeffs(unsigned degree,
154  long double* expansionCoeffs) const;
155 
156  inline virtual std::pair<long double,long double>
157  monicRecurrenceCoeffs(const unsigned k) const
158  {
159  long double beta = 1.0L;
160  if (k)
161  beta = 0.25L/(4.0L - 1.0L/k/k);
162  return std::pair<long double,long double>(0.5L, beta);
163  }
164 
165  inline virtual std::pair<long double,long double>
166  recurrenceCoeffs(const unsigned k) const
167  {
168  long double sqb = 1.0L;
169  if (k)
170  sqb = 0.5L/sqrtl(4.0L - 1.0L/k/k);
171  return std::pair<long double,long double>(0.5L, sqb);
172  }
173 
174 #ifdef SWIG
175  public:
176  inline std::vector<double>
177  integralCoeffs2(const double *c, const unsigned degreep1) const
178  {
179  std::vector<double> tmp(degreep1+1U);
180  integralCoeffs(c, degreep1-1U, &tmp[0]);
181  return tmp;
182  }
183 
184  inline std::vector<double>
185  derivativeCoeffs2(const double *c, const unsigned degreep1) const
186  {
187  std::vector<double> tmp(std::max(degreep1-1U, 1U));
188  derivativeCoeffs(c, degreep1-1U, &tmp[0]);
189  return tmp;
190  }
191 
192  inline std::vector<double>
193  squaredPolyCoeffs2(const unsigned degree) const
194  {
195  std::vector<long double> tmp(2U*degree + 1U);
196  squaredPolyCoeffs(degree, &tmp[0]);
197  return std::vector<double>(tmp.begin(), tmp.end());
198  }
199 #endif
200  };
201 
202  /**
203  // The weight function for Jacobi polynomials is proportional
204  // to (1 - x)^alpha (1 + x)^beta
205  */
207  {
208  public:
209  JacobiOrthoPoly1D(double alpha, double beta);
210 
211  inline virtual JacobiOrthoPoly1D* clone() const
212  {return new JacobiOrthoPoly1D(*this);}
213 
214  inline virtual ~JacobiOrthoPoly1D() {}
215 
216  inline double alpha() const {return alpha_;}
217  inline double beta() const {return beta_;}
218 
219  long double weight(long double x) const;
220  inline double xmin() const {return -1.0L;}
221  inline double xmax() const {return 1.0L;}
222 
223  /**
224  // The following function generates coefficients for derivatives
225  // of the Jacobi polynomial series. The derivative series should be
226  // evaluated using a JacobiOrthoPoly1D(alpha_+1, beta_+1) object and
227  // with maxdeg argument decreased by 1. The array "coeffs" should
228  // have at least maxdeg+1 elements, while the "derivativeCoeffs"
229  // buffer should have at least maxdeg elements.
230  */
231  void derivativeCoeffs(const double* coeffs,
232  unsigned maxdeg,
233  double* derivCoeffs) const;
234 
235  virtual std::pair<long double,long double>
236  monicRecurrenceCoeffs(unsigned k) const;
237 
238  virtual std::pair<long double,long double>
239  recurrenceCoeffs(unsigned k) const;
240 
241  private:
242  double alpha_;
243  double beta_;
244  long double norm_;
245 
246 #ifdef SWIG
247  public:
248  inline std::vector<double>
249  derivativeCoeffs2(const double *c, const unsigned degreep1) const
250  {
251  std::vector<double> tmp(degreep1-1U);
252  derivativeCoeffs(c, degreep1-1U,
253  tmp.empty() ? (double *)0 : &tmp[0]);
254  return tmp;
255  }
256 #endif
257  };
258 
259  /** Orthonormal Chebyshev polynomials of the 1st kind */
261  {
262  public:
263  inline virtual ChebyshevOrthoPoly1st* clone() const
264  {return new ChebyshevOrthoPoly1st(*this);}
265 
266  inline virtual ~ChebyshevOrthoPoly1st() {}
267 
268  inline long double weight(const long double x) const
269  {
270  const long double Pi = 3.14159265358979323846264338L;
271  return (x > -1.0L && x < 1.0L) ? 1.0/sqrtl(1.0L - x*x)/Pi : 0.0L;
272  }
273  inline double xmin() const {return -1.0L;}
274  inline double xmax() const {return 1.0L;}
275 
276  inline virtual std::pair<long double,long double>
277  monicRecurrenceCoeffs(const unsigned k) const
278  {
279  long double beta = 0.25L;
280  if (k == 0U)
281  beta = 3.14159265358979323846264338328L;
282  else if (k == 1U)
283  beta = 0.5L;
284  return std::pair<long double,long double>(0.0L, beta);
285  }
286 
287  inline virtual std::pair<long double,long double>
288  recurrenceCoeffs(const unsigned k) const
289  {
290  long double sqb = 0.5L;
291  if (k == 0U)
292  sqb = 1.772453850905516027298167483L; // sqrt(Pi)
293  else if (k == 1U)
294  sqb = 0.7071067811865475244008443621L; // 1/sqrt(2)
295  return std::pair<long double,long double>(0.0L, sqb);
296  }
297  };
298 
299  /** Orthonormal Chebyshev polynomials of the 2nd kind */
301  {
302  public:
303  inline virtual ChebyshevOrthoPoly2nd* clone() const
304  {return new ChebyshevOrthoPoly2nd(*this);}
305 
306  inline virtual ~ChebyshevOrthoPoly2nd() {}
307 
308  inline long double weight(const long double x) const
309  {
310  const long double PiOver2 = 1.57079632679489661923132169L;
311  return (x > -1.0L && x < 1.0L) ? sqrtl(1.0L - x*x)/PiOver2 : 0.0L;
312  }
313  inline double xmin() const {return -1.0L;}
314  inline double xmax() const {return 1.0L;}
315 
316  inline virtual std::pair<long double,long double>
317  monicRecurrenceCoeffs(const unsigned k) const
318  {
319  long double beta = 0.25L;
320  if (!k)
321  beta = 1.57079632679489661923132169164L; // Pi/2
322  return std::pair<long double,long double>(0.0L, beta);
323  }
324 
325  inline virtual std::pair<long double,long double>
326  recurrenceCoeffs(const unsigned k) const
327  {
328  long double sqb = 0.5L;
329  if (!k)
330  sqb = 1.25331413731550025120788264L; // sqrt(Pi/2)
331  return std::pair<long double,long double>(0.0L, sqb);
332  }
333  };
334 
335  /** Orthonormal(!) probabilist's Hermite polynomials */
337  {
338  public:
339  inline virtual HermiteProbOrthoPoly1D* clone() const
340  {return new HermiteProbOrthoPoly1D(*this);}
341 
342  inline virtual ~HermiteProbOrthoPoly1D() {}
343 
344  long double weight(long double x) const;
345  inline double xmin() const {return -xmax();}
346  inline double xmax() const {return 150.0;}
347 
348  virtual std::pair<long double,long double>
349  monicRecurrenceCoeffs(unsigned k) const;
350 
351  virtual std::pair<long double,long double>
352  recurrenceCoeffs(unsigned k) const;
353  };
354 }
355 
356 #endif // NPSTAT_CLASSICALORTHOPOLYS1D_HH_
Base class for classical continuous orthonormal polynomials.
Definition: AbsClassicalOrthoPoly1D.hh:32
Definition: ClassicalOrthoPolys1D.hh:261
virtual ChebyshevOrthoPoly1st * clone() const
Definition: ClassicalOrthoPolys1D.hh:263
long double weight(const long double x) const
Definition: ClassicalOrthoPolys1D.hh:268
double xmin() const
Definition: ClassicalOrthoPolys1D.hh:273
Definition: ClassicalOrthoPolys1D.hh:301
virtual ChebyshevOrthoPoly2nd * clone() const
Definition: ClassicalOrthoPolys1D.hh:303
double xmin() const
Definition: ClassicalOrthoPolys1D.hh:313
long double weight(const long double x) const
Definition: ClassicalOrthoPolys1D.hh:308
Definition: ClassicalOrthoPolys1D.hh:337
virtual HermiteProbOrthoPoly1D * clone() const
Definition: ClassicalOrthoPolys1D.hh:339
double xmin() const
Definition: ClassicalOrthoPolys1D.hh:345
long double weight(long double x) const
Definition: ClassicalOrthoPolys1D.hh:207
void derivativeCoeffs(const double *coeffs, unsigned maxdeg, double *derivCoeffs) const
virtual JacobiOrthoPoly1D * clone() const
Definition: ClassicalOrthoPolys1D.hh:211
long double weight(long double x) const
double xmin() const
Definition: ClassicalOrthoPolys1D.hh:220
Definition: ClassicalOrthoPolys1D.hh:23
long double weight(const long double x) const
Definition: ClassicalOrthoPolys1D.hh:30
void integralCoeffs(const double *coeffs, unsigned degree, double *integCoeffs) const
double xmin() const
Definition: ClassicalOrthoPolys1D.hh:32
void derivativeCoeffs(const double *coeffs, unsigned degree, double *derivCoeffs) const
void squaredPolyCoeffs(unsigned degree, long double *expansionCoeffs) const
void monomialCoeffs(const double *coeffs, unsigned degree, long double *monoCoeffs) const
virtual LegendreOrthoPoly1D * clone() const
Definition: ClassicalOrthoPolys1D.hh:25
Definition: ClassicalOrthoPolys1D.hh:121
double xmin() const
Definition: ClassicalOrthoPolys1D.hh:130
void derivativeCoeffs(const double *coeffs, unsigned degree, double *derivCoeffs) const
virtual ShiftedLegendreOrthoPoly1D * clone() const
Definition: ClassicalOrthoPolys1D.hh:123
void squaredPolyCoeffs(unsigned degree, long double *expansionCoeffs) const
long double weight(const long double x) const
Definition: ClassicalOrthoPolys1D.hh:128
void integralCoeffs(const double *coeffs, unsigned degree, double *integCoeffs) const
Definition: AbsArrayProjector.hh:14