npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
AbsClassicalOrthoPoly1D.hh
Go to the documentation of this file.
1 #ifndef NPSTAT_ABSCLASSICALORTHOPOLY1D_HH_
2 #define NPSTAT_ABSCLASSICALORTHOPOLY1D_HH_
3 
4 /*!
5 // \file AbsClassicalOrthoPoly1D.hh
6 //
7 // \brief Base class for classical continuous orthonormal polynomials
8 //
9 // Author: I. Volobouev
10 //
11 // May 2017
12 */
13 
14 #include <utility>
15 #include <algorithm>
16 #include <climits>
17 #include <vector>
18 #include <stdexcept>
19 
20 #include "geners/CPP11_auto_ptr.hh"
21 
22 #include "npstat/nm/Matrix.hh"
25 
26 namespace npstat {
27  class StorablePolySeries1D;
28  class OrthoPoly1DDeg;
29  class OrthoPoly1DWeight;
30 
32  {
33  public:
36 
37  inline virtual ~AbsClassicalOrthoPoly1D() {}
38 
39  /** Virtual copy constructor */
40  virtual AbsClassicalOrthoPoly1D* clone() const = 0;
41 
42  /** The weight function should be normalized */
43  virtual long double weight(long double x) const = 0;
44 
45  //@{
46  /** Support of the polynomial */
47  virtual double xmin() const = 0;
48  virtual double xmax() const = 0;
49  //@}
50 
51  /** Maximum polynomial degree supported */
52  inline virtual unsigned maxDegree() const {return UINT_MAX - 1U;}
53 
54  /**
55  // Generate principal minor of order n of the Jacobi matrix.
56  // n must not exceed the output of "maxDegree()" method.
57  */
58  Matrix<long double> jacobiMatrix(unsigned n) const;
59 
60  /** Polynomial values */
61  long double poly(unsigned deg, long double x) const;
62 
63  /** Values of the corresponding monic polynomials */
64  long double monic(unsigned deg, long double x) const;
65 
66  /**
67  // Values of two orthonormal polynomials.
68  // Faster than calling "poly" two times.
69  */
70  std::pair<long double,long double> twopoly(
71  unsigned deg1, unsigned deg2, long double x) const;
72 
73  /**
74  // Values of all orthonormal polynomials up to some degree.
75  // Faster than calling "poly" multiple times. The size of
76  // the "values" array should be at least maxdeg + 1.
77  */
78  void allpoly(long double x, long double* values, unsigned maxdeg) const;
79 
80  /**
81  // Values of all monic orthonormal polynomials up to some degree.
82  // The size of the "values" array should be at least maxdeg + 1.
83  */
84  void allmonic(long double x, long double* values, unsigned maxdeg) const;
85 
86  /** Polynomial series */
87  double series(const double* coeffs, unsigned maxdeg, double x) const;
88 
89  /** Integral of the series from xmin() to xmax() */
90  double integrateSeries(const double* coeffs, unsigned maxdeg) const;
91 
92  /**
93  // Build the coefficients of the orthogonal polynomial series
94  // for the given function. The length of the array "coeffs"
95  // should be at least maxdeg + 1. Note that the coefficients
96  // are returned in the order of increasing degree (same order
97  // is used by the "series" function).
98  */
99  template <class Functor, class Quadrature>
100  void calculateCoeffs(const Functor& fcn, const Quadrature& quad,
101  double* coeffs, unsigned maxdeg) const;
102 
103  /**
104  // Build the coefficients of the orthogonal polynomial series
105  // for the given sample of points (empirical density function).
106  // The length of the array "coeffs" should be at least maxdeg + 1.
107  // Note that the coefficients are returned in the order of
108  // increasing degree (same order is used by the "series" function).
109  */
110  template <class Numeric>
111  void sampleCoeffs(const Numeric* coords, unsigned long lenCoords,
112  double* coeffs, unsigned maxdeg) const;
113 
114  /**
115  // Estimate the variances of the coefficients returned by
116  // the "sampleCoeffs" function. The "coeffs" array should be
117  // at least maxdeg + 1 elements long and should be filled
118  // by a previous call to "sampleCoeffs". The "variances" array
119  // should have at least maxdeg + 1 elements. It will contain
120  // the respective variances upon return.
121  */
122  template <class Numeric>
123  void sampleCoeffVars(const Numeric* coords, unsigned long lenCoords,
124  const double* coeffs, unsigned maxdeg,
125  double* variances) const;
126 
127  /**
128  // Estimate the covariances of the coefficients returned by
129  // the "sampleCoeffs" function. The "coeffs" array should be
130  // at least maxdeg + 1 elements long and should be filled
131  // by a previous call to "sampleCoeffs". The returned matrix
132  // will be dimensioned (maxdeg + 1) x (maxdeg + 1).
133  */
134  template <class Numeric>
136  sampleCoeffCovariance(const Numeric* coords, unsigned long lenCoords,
137  const double* coeffs, unsigned maxdeg) const;
138 
139  /**
140  // Build the coefficients of the orthogonal polynomial series
141  // for the given sample of points (empirical density function).
142  // The length of the array "coeffs" should be at least maxdeg + 1.
143  // Note that the coefficients are returned in the order of
144  // increasing degree (same order is used by the "series" function).
145  // Before calculating the coefficients, the coordinates are shifted
146  // and scaled according to x_new = (x_original - location)/scale.
147  // The resulting coefficients are also divided by scale.
148  */
149  template <class Numeric>
150  void sampleCoeffs(const Numeric* coords, unsigned long lenCoords,
151  Numeric location, Numeric scale,
152  double* coeffs, unsigned maxdeg) const;
153 
154  /**
155  // Estimate the variances of the coefficients returned by
156  // the "sampleCoeffs" function. The "coeffs" array should be
157  // at least maxdeg + 1 elements long and should be filled
158  // by a previous call to "sampleCoeffs" with the same location
159  // and scale. The "variances" array should have at least maxdeg + 1
160  // elements. It will contain the respective variances upon return.
161  */
162  template <class Numeric>
163  void sampleCoeffVars(const Numeric* coords, unsigned long lenCoords,
164  Numeric location, Numeric scale,
165  const double* coeffs, unsigned maxdeg,
166  double* variances) const;
167 
168  /**
169  // Estimate the covariances of the coefficients returned by
170  // the "sampleCoeffs" function. The "coeffs" array should be
171  // at least maxdeg + 1 elements long and should be filled
172  // by a previous call to "sampleCoeffs" with the same location
173  // and scale. The returned matrix will be dimensioned
174  // (maxdeg + 1) x (maxdeg + 1).
175  */
176  template <class Numeric>
178  sampleCoeffCovariance(const Numeric* coords, unsigned long lenCoords,
179  Numeric location, Numeric scale,
180  const double* coeffs, unsigned maxdeg) const;
181 
182  /**
183  // Build the coefficients of the orthogonal polynomial series for
184  // the given sample of weighted points (empirical density function).
185  // The first element of the pair will be treated as the coordinate
186  // and the second element will be treated as weight. Weights must
187  // not be negative. The length of the array "coeffs" should be
188  // at least maxdeg + 1. Note that the coefficients are returned
189  // in the order of increasing degree (same order is used by the
190  // "series" function).
191  */
192  template <class Pair>
193  void weightedSampleCoeffs(const Pair* points, unsigned long numPoints,
194  double* coeffs, unsigned maxdeg) const;
195 
196  /**
197  // Estimate the variances of the coefficients returned by the
198  // "weightedSampleCoeffs" function. The "coeffs" array should
199  // be at least maxdeg + 1 elements long and should be filled
200  // by a previous call to "weightedSampleCoeffs". The "variances"
201  // array should have at least maxdeg + 1 elements. It will contain
202  // the respective variances upon return. This code assumes that
203  // weights and coordinates are statistically independent from
204  // each other.
205  */
206  template <class Pair>
207  void weightedSampleCoeffVars(const Pair* points, unsigned long nPoints,
208  const double* coeffs, unsigned maxdeg,
209  double* variances) const;
210 
211  /**
212  // Estimate the covariances of the coefficients returned by the
213  // "weightedSampleCoeffs" function. The "coeffs" array should
214  // be at least maxdeg + 1 elements long and should be filled
215  // by a previous call to "weightedSampleCoeffs". The returned
216  // matrix will be dimensioned (maxdeg + 1) x (maxdeg + 1). This
217  // code assumes that weights and coordinates are statistically
218  // independent from each other.
219  */
220  template <class Pair>
222  weightedSampleCoeffCovariance(const Pair* points, unsigned long nPoints,
223  const double* coeffs, unsigned maxdeg) const;
224 
225  /**
226  // Build the coefficients of the orthogonal polynomial series for
227  // the given sample of weighted points (empirical density function).
228  // The first element of the pair will be treated as the coordinate
229  // and the second element will be treated as weight. Weights must
230  // not be negative. The length of the array "coeffs" should be
231  // at least maxdeg + 1. Note that the coefficients are returned
232  // in the order of increasing degree (same order is used by the
233  // "series" function). Before calculating the coefficients, the
234  // coordinates are shifted and scaled according to
235  // x_new = (x_original - location)/scale. The resulting coefficients
236  // are also divided by scale.
237  */
238  template <class Pair>
239  void weightedSampleCoeffs(const Pair* points, unsigned long numPoints,
240  typename Pair::first_type location,
241  typename Pair::first_type scale,
242  double* coeffs, unsigned maxdeg) const;
243 
244  /**
245  // Estimate the variances of the coefficients returned by the
246  // "weightedSampleCoeffs" function. The "coeffs" array should
247  // be at least maxdeg + 1 elements long and should be filled
248  // by a previous call to "weightedSampleCoeffs" with the same
249  // location and scale. The "variances" array should have at least
250  // maxdeg + 1 elements. It will contain the respective variances
251  // upon return. This code assumes that weights and coordinates
252  // are statistically independent from each other.
253  */
254  template <class Pair>
255  void weightedSampleCoeffVars(const Pair* points, unsigned long nPoints,
256  typename Pair::first_type location,
257  typename Pair::first_type scale,
258  const double* coeffs, unsigned maxdeg,
259  double* variances) const;
260 
261  /**
262  // Estimate the covariances of the coefficients returned by the
263  // "weightedSampleCoeffs" function. The "coeffs" array should
264  // be at least maxdeg + 1 elements long and should be filled
265  // by a previous call to "weightedSampleCoeffs" with the same
266  // location and scale. The returned matrix will be dimensioned
267  // (maxdeg + 1) x (maxdeg + 1). This code assumes that weights
268  // and coordinates are statistically independent from each other.
269  */
270  template <class Pair>
272  weightedSampleCoeffCovariance(const Pair* points, unsigned long nPoints,
273  typename Pair::first_type location,
274  typename Pair::first_type scale,
275  const double* coeffs, unsigned maxdeg) const;
276 
277  /**
278  // This method is useful for testing the numerical precision
279  // of the orthonormalization procedure. It returns the scalar
280  // products between various polynomials.
281  */
282  template <class Quadrature>
283  double empiricalKroneckerDelta(const Quadrature& quad,
284  unsigned deg1, unsigned deg2) const;
285 
286  /**
287  // A faster way to generate Kronecker deltas if the whole matrix
288  // of them is needed. The "maxdeg" argument must not exceed the
289  // return value of the "maxDegree" function. The resulting matrix
290  // will be dimensioned (maxdeg + 1) x (maxdeg + 1). Note that this
291  // function will produce meaningful results only for polynomials
292  // supported on compact intervals.
293  */
296  unsigned maxdeg) const;
297 
298  /**
299  // A measure-weighted average of a product of four orthonormal
300  // poly values
301  */
302  template <class Quadrature>
303  double jointAverage(const Quadrature& q, unsigned deg1, unsigned deg2,
304  unsigned deg3, unsigned deg4) const;
305 
306  /**
307  // A measure-weighted average of a product of multiple orthonormal
308  // poly values. "checkedForZeros" argument should be set to "true"
309  // if we are sure that there are no zero elements in the "degrees"
310  // array.
311  */
312  template <class Quadrature>
313  double jointAverage(const Quadrature& q,
314  const unsigned* degrees, unsigned nDegrees,
315  bool checkedForZeros = false) const;
316 
317  /**
318  // Direct unweighted integration of of a product of four orthonormal
319  // poly values. The integration function should support the "integrate"
320  // method without limits. Intended for use with GaussHermiteQuadrature
321  // and such.
322  */
323  template <class Quadrature>
324  double directQuadrature(const Quadrature& q, unsigned deg1, unsigned deg2,
325  unsigned deg3, unsigned deg4) const;
326 
327  /**
328  // Direct unweighted integration of of a product of multiple orthonormal
329  // poly values. The integration function should support the "integrate"
330  // method without limits. Intended for use with GaussHermiteQuadrature
331  // and such. "checkedForZeros" argument should be set to "true" if we are
332  // sure that there are no zero elements in the "degrees" array.
333  */
334  template <class Quadrature>
335  double directQuadrature(const Quadrature& q,
336  const unsigned* degrees, unsigned nDegrees,
337  bool checkedForZeros = false) const;
338 
339  /**
340  // An unweighted integral of the orthonormal polynomial with the
341  // given degree to some power. For this method, it is assumed
342  // that the polynomials are supported on a closed interval (without
343  // such an assumption unweighted integrals do not make much sense)
344  // and that Gauss-Legendre quadratures can be used.
345  */
346  double integratePoly(unsigned degree, unsigned power) const;
347 
348  /**
349  // An unweighted integral of a product of multiple orthonormal
350  // polynomials. For this method, it is assumed that the polynomials
351  // are supported on a closed interval (without such an assumption
352  // unweighted integrals do not make much sense) and that Gauss-Legendre
353  // quadratures can be used.
354  */
355  double jointIntegral(const unsigned* degrees, unsigned nDegrees) const;
356 
357  /**
358  // Unweighted averages of the polynomial values for the given sample.
359  // The length of array "averages" should be at least maxdeg + 1.
360  */
361  template <typename Numeric, typename Real>
362  void sampleAverages(const Numeric* coords, unsigned long lenCoords,
363  Real* averages, unsigned maxdeg) const;
364 
365  /**
366  // Averages of the polynomial values for the given sample of
367  // weighted points (not weighting by the polynomial weight function).
368  // The first element of the pair will be treated as the coordinate
369  // and the second element will be treated as weight. Weights must not
370  // be negative. The length of array "averages" should be at least
371  // maxdeg + 1.
372  */
373  template <class Pair, typename Real>
374  void weightedPointsAverages(const Pair* points, unsigned long numPoints,
375  Real* averages, unsigned maxdeg) const;
376 
377  /**
378  // Averages of the polynomial values weighted by an external
379  // weight function. The length of array "averages" should be
380  // at least maxdeg + 1.
381  */
382  template <class Functor, typename Real>
383  void extWeightAverages(const Functor& extWeight,
384  const AbsIntervalQuadrature1D& quad,
385  Real* averages, unsigned maxdeg) const;
386 
387  /**
388  // Unweighted averages of the pairwise products of the polynomial
389  // values for the given sample. The returned matrix will be symmetric
390  // and will have the dimensions (maxdeg + 1) x (maxdeg + 1).
391  */
392  template <class Numeric>
393  Matrix<double> sampleProductAverages(const Numeric* coords,
394  unsigned long lenCoords,
395  unsigned maxdeg) const;
396 
397  /**
398  // Pairwise products of the polynomial values weighted by
399  // an external weight function. The returned matrix will be
400  // symmetric and will have the dimensions (maxdeg + 1) x (maxdeg + 1).
401  */
402  template <class Functor>
403  Matrix<double> extWeightProductAverages(const Functor& extWeight,
404  const AbsIntervalQuadrature1D& quad, unsigned maxdeg) const;
405 
406  /**
407  // Unweighted average of a product of polynomial values for the
408  // given sample. "degrees" is the collection of polynomial degrees.
409  // Polynomials of these degrees will be included in the product.
410  */
411  template <class Numeric>
412  double jointSampleAverage(const Numeric* coords,
413  unsigned long lenCoords,
414  const unsigned* degrees,
415  unsigned lenDegrees) const;
416 
417  // Similar to the previous method but calculates two averages
418  // simultaneously
419  template <class Numeric>
420  std::pair<double, double> twoJointSampleAverages(
421  const Numeric* coords, unsigned long lenCoords,
422  const unsigned* degrees1, unsigned lenDegrees1,
423  const unsigned* degrees2, unsigned lenDegrees2) const;
424 
425  CPP11_auto_ptr<StorablePolySeries1D> makeStorablePolySeries(
426  unsigned maxPolyDeg,
427  const double *coeffs=0, unsigned maxdeg=0, double shift=0.0) const;
428 
429  // Functions needed for compatibility with certain template codes
430  inline long double location() const {return 0.0;}
431  inline long double scale() const {return 1.0;}
432 
433  // Monic recurrence relationship function should return alpha
434  // as the first element of the pair and beta as the second
435  virtual std::pair<long double,long double>
436  monicRecurrenceCoeffs(unsigned deg) const = 0;
437 
438  // Orthonormal recurrence relationship function should return
439  // alpha as the first element of the pair and the square root
440  // of beta as the second
441  virtual std::pair<long double,long double>
442  recurrenceCoeffs(unsigned deg) const = 0;
443 
444  protected:
445  inline static int kdelta(const unsigned i, const unsigned j)
446  {return i == j ? 1 : 0;}
447 
448  // Helper classes
449  class ProdFcn : public Functor1<long double, long double>
450  {
451  public:
452  inline ProdFcn(const AbsClassicalOrthoPoly1D& p,
453  const unsigned d1,
454  const unsigned d2)
455  : poly(p), deg1(d1), deg2(d2) {}
456 
457  inline virtual ~ProdFcn() {}
458 
459  inline long double operator()(const long double& x) const
460  {
461  const std::pair<long double,long double>& p =
462  poly.twopoly(deg1, deg2, x);
463  return p.first*p.second*poly.weight(x);
464  }
465 
466  private:
467  const AbsClassicalOrthoPoly1D& poly;
468  unsigned deg1;
469  unsigned deg2;
470  };
471 
472  class MultiProdFcn;
473  friend class MultiProdFcn;
474 
475  class MultiProdFcn : public Functor1<long double, long double>
476  {
477  public:
478  inline MultiProdFcn(const AbsClassicalOrthoPoly1D& p,
479  const unsigned* degrees, unsigned lenDegrees,
480  const bool includeWeight=true)
481  : poly(p),
482  degs(degrees, degrees+lenDegrees),
483  maxdeg(0),
484  weighted(includeWeight)
485  {
486  if (lenDegrees)
487  maxdeg = *std::max_element(degrees, degrees+lenDegrees);
488  }
489 
490  inline virtual ~MultiProdFcn() {}
491 
492  inline long double operator()(const long double& x) const
493  {
494  long double w = 1.0L, p = 1.0L;
495  if (weighted)
496  w = poly.weight(x);
497  if (maxdeg)
498  p = poly.normpolyprod(&degs[0], degs.size(), maxdeg, x);
499  return w*p;
500  }
501 
502  private:
503  const AbsClassicalOrthoPoly1D& poly;
504  std::vector<unsigned> degs;
505  unsigned maxdeg;
506  bool weighted;
507  };
508 
509  private:
510  // For calling the function below, maxdeg should be calculated as
511  // *std::max_element(degrees, degrees+nDegrees)
512  long double normpolyprod(const unsigned* degrees, unsigned nDegrees,
513  unsigned maxdeg, long double x) const;
514 #ifdef SWIG
515  public:
516  inline double weight2(const double x) const
517  {return weight(x);}
518 
519  inline double poly2(const unsigned deg, const double x) const
520  {return poly(deg, x);}
521 
522  inline double monic2(const unsigned deg, const double x) const
523  {return monic(deg, x);}
524 
525  inline std::pair<double,double> twopoly2(const unsigned deg1,
526  const unsigned deg2,
527  const double x) const
528  {
529  const std::pair<long double,long double>& p = twopoly(deg1, deg2, x);
530  return std::pair<double,double>(p.first, p.second);
531  }
532 
533  inline std::pair<double,double> monicRecurrenceCoeffs2(const unsigned deg) const
534  {
535  const std::pair<long double,long double>& p = monicRecurrenceCoeffs(deg);
536  return std::pair<double,double>(p.first, p.second);
537  }
538 
539  inline std::pair<double,double> recurrenceCoeffs2(const unsigned deg) const
540  {
541  const std::pair<long double,long double>& p = recurrenceCoeffs(deg);
542  return std::pair<double,double>(p.first, p.second);
543  }
544 
545  inline std::vector<double> allpoly2(const unsigned maxdeg, const double x) const
546  {
547  std::vector<long double> p(maxdeg+1);
548  allpoly(x, &p[0], p.size());
549  return std::vector<double>(p.begin(), p.end());
550  }
551 
552  inline std::vector<double> allmonic2(const unsigned maxdeg, const double x) const
553  {
554  std::vector<long double> p(maxdeg+1);
555  allmonic(x, &p[0], p.size());
556  return std::vector<double>(p.begin(), p.end());
557  }
558 
559  inline StorablePolySeries1D* makeStorablePolySeries_2(
560  unsigned maxPolyDeg, const std::vector<double>& coeffs, double shift=0.0) const
561  {
562  CPP11_auto_ptr<StorablePolySeries1D> ptr;
563  if (coeffs.empty())
564  ptr = this->makeStorablePolySeries(maxPolyDeg, 0, 0, shift);
565  else
566  ptr = this->makeStorablePolySeries(maxPolyDeg, &coeffs[0],
567  coeffs.size() - 1, shift);
568  return ptr.release();
569  }
570 
571  inline Matrix<double> jacobiMatrix_2(const unsigned n) const
572  {return jacobiMatrix(n);}
573 
574  inline double location2() const {return location();}
575 
576  inline double scale2() const {return scale();}
577 #endif // SWIG
578  };
579 
580  /**
581  // A functor for the weight function of the given ortho poly system.
582  // The poly system is not copied, only a reference is used. It is
583  // a responsibility of the user to make sure that the lifetime of
584  // the poly system object exceeds the lifetime of the functor.
585  */
586  class OrthoPoly1DWeight : public Functor1<long double, long double>
587  {
588  public:
589  inline OrthoPoly1DWeight(const AbsClassicalOrthoPoly1D& fcn,
590  const long double normfactor)
591  : fcn_(fcn), norm_(normfactor) {}
592 
593  // Separate constructor here because swig gets confused
594  // by long doubles with defaults
595  inline explicit OrthoPoly1DWeight(const AbsClassicalOrthoPoly1D& fcn)
596  : fcn_(fcn), norm_(1.0L) {}
597 
598  inline virtual ~OrthoPoly1DWeight() {}
599 
600  inline virtual long double operator()(const long double& a) const
601  {return norm_*fcn_.weight(a);}
602 
603  private:
605 
606  const AbsClassicalOrthoPoly1D& fcn_;
607  long double norm_;
608  };
609 
610  /**
611  // A functor for a particular degree polynomial of the given ortho
612  // poly system. The poly system is not copied, only a reference is used.
613  // It is a responsibility of the user to make sure that the lifetime of
614  // the poly system object exceeds the lifetime of the functor.
615  */
616  class OrthoPoly1DDeg : public Functor1<long double, long double>
617  {
618  public:
619  inline OrthoPoly1DDeg(const AbsClassicalOrthoPoly1D& fcn,
620  const unsigned degree,
621  const long double normfactor)
622  : fcn_(fcn), norm_(normfactor), deg_(degree)
623  {
624  if (deg_ > fcn_.maxDegree()) throw std::invalid_argument(
625  "In npstat::OrthoPoly1DDeg::constructor: "
626  "degree argument is out of range");
627  }
628 
629  // Separate constructor here because swig gets confused
630  // by long doubles with defaults
631  inline OrthoPoly1DDeg(const AbsClassicalOrthoPoly1D& fcn,
632  const unsigned degree)
633  : fcn_(fcn), norm_(1.0L), deg_(degree)
634  {
635  if (deg_ > fcn_.maxDegree()) throw std::invalid_argument(
636  "In npstat::OrthoPoly1DDeg::constructor: "
637  "degree argument is out of range");
638  }
639 
640  inline virtual ~OrthoPoly1DDeg() {}
641 
642  inline virtual long double operator()(const long double& a) const
643  {return norm_*fcn_.poly(deg_, a);}
644 
645  private:
646  OrthoPoly1DDeg();
647 
648  const AbsClassicalOrthoPoly1D& fcn_;
649  long double norm_;
650  unsigned deg_;
651  };
652 
653  class UnweightedTwoPolyProd : public Functor1<long double, long double>
654  {
655  public:
657  const unsigned deg1, const unsigned deg2)
658  : fcn_(fcn), degree1_(deg1), degree2_(deg2) {}
659 
660  inline virtual ~UnweightedTwoPolyProd() {}
661 
662  inline virtual long double operator()(const long double& a) const
663  {
664  std::pair<long double,long double> p = fcn_.twopoly(
665  degree1_, degree2_, a);
666  return p.first * p.second;
667  }
668 
669  private:
670  const AbsClassicalOrthoPoly1D& fcn_;
671  unsigned degree1_;
672  unsigned degree2_;
673  };
674 }
675 
676 #include "npstat/nm/AbsClassicalOrthoPoly1D.icc"
677 
678 #endif // NPSTAT_ABSCLASSICALORTHOPOLY1D_HH_
Base class for quadratures on the [-1, 1] interval.
Template matrix class.
Interface definitions and concrete simple functors for a variety of functor-based calculations.
Definition: AbsClassicalOrthoPoly1D.hh:476
Definition: AbsClassicalOrthoPoly1D.hh:450
Definition: AbsClassicalOrthoPoly1D.hh:32
double directQuadrature(const Quadrature &q, const unsigned *degrees, unsigned nDegrees, bool checkedForZeros=false) const
Matrix< double > sampleProductAverages(const Numeric *coords, unsigned long lenCoords, unsigned maxdeg) const
double jointIntegral(const unsigned *degrees, unsigned nDegrees) const
Matrix< long double > jacobiMatrix(unsigned n) const
void sampleAverages(const Numeric *coords, unsigned long lenCoords, Real *averages, unsigned maxdeg) const
virtual double xmin() const =0
void allmonic(long double x, long double *values, unsigned maxdeg) const
void weightedPointsAverages(const Pair *points, unsigned long numPoints, Real *averages, unsigned maxdeg) const
void sampleCoeffs(const Numeric *coords, unsigned long lenCoords, double *coeffs, unsigned maxdeg) const
void weightedSampleCoeffs(const Pair *points, unsigned long numPoints, double *coeffs, unsigned maxdeg) const
Matrix< double > sampleCoeffCovariance(const Numeric *coords, unsigned long lenCoords, const double *coeffs, unsigned maxdeg) const
virtual AbsClassicalOrthoPoly1D * clone() const =0
double jointAverage(const Quadrature &q, unsigned deg1, unsigned deg2, unsigned deg3, unsigned deg4) const
Matrix< double > empiricalKroneckerMatrix(const AbsIntervalQuadrature1D &quad, unsigned maxdeg) const
double integrateSeries(const double *coeffs, unsigned maxdeg) const
long double monic(unsigned deg, long double x) const
Matrix< double > sampleCoeffCovariance(const Numeric *coords, unsigned long lenCoords, Numeric location, Numeric scale, const double *coeffs, unsigned maxdeg) const
void weightedSampleCoeffs(const Pair *points, unsigned long numPoints, typename Pair::first_type location, typename Pair::first_type scale, double *coeffs, unsigned maxdeg) const
Matrix< double > weightedSampleCoeffCovariance(const Pair *points, unsigned long nPoints, const double *coeffs, unsigned maxdeg) const
double jointSampleAverage(const Numeric *coords, unsigned long lenCoords, const unsigned *degrees, unsigned lenDegrees) const
void sampleCoeffs(const Numeric *coords, unsigned long lenCoords, Numeric location, Numeric scale, double *coeffs, unsigned maxdeg) const
double directQuadrature(const Quadrature &q, unsigned deg1, unsigned deg2, unsigned deg3, unsigned deg4) const
void weightedSampleCoeffVars(const Pair *points, unsigned long nPoints, const double *coeffs, unsigned maxdeg, double *variances) const
Matrix< double > extWeightProductAverages(const Functor &extWeight, const AbsIntervalQuadrature1D &quad, unsigned maxdeg) const
void sampleCoeffVars(const Numeric *coords, unsigned long lenCoords, Numeric location, Numeric scale, const double *coeffs, unsigned maxdeg, double *variances) const
double empiricalKroneckerDelta(const Quadrature &quad, unsigned deg1, unsigned deg2) const
void calculateCoeffs(const Functor &fcn, const Quadrature &quad, double *coeffs, unsigned maxdeg) const
void allpoly(long double x, long double *values, unsigned maxdeg) const
virtual long double weight(long double x) const =0
std::pair< long double, long double > twopoly(unsigned deg1, unsigned deg2, long double x) const
double series(const double *coeffs, unsigned maxdeg, double x) const
Matrix< double > weightedSampleCoeffCovariance(const Pair *points, unsigned long nPoints, typename Pair::first_type location, typename Pair::first_type scale, const double *coeffs, unsigned maxdeg) const
virtual unsigned maxDegree() const
Definition: AbsClassicalOrthoPoly1D.hh:52
long double poly(unsigned deg, long double x) const
void sampleCoeffVars(const Numeric *coords, unsigned long lenCoords, const double *coeffs, unsigned maxdeg, double *variances) const
void extWeightAverages(const Functor &extWeight, const AbsIntervalQuadrature1D &quad, Real *averages, unsigned maxdeg) const
double integratePoly(unsigned degree, unsigned power) const
void weightedSampleCoeffVars(const Pair *points, unsigned long nPoints, typename Pair::first_type location, typename Pair::first_type scale, const double *coeffs, unsigned maxdeg, double *variances) const
double jointAverage(const Quadrature &q, const unsigned *degrees, unsigned nDegrees, bool checkedForZeros=false) const
Definition: AbsIntervalQuadrature1D.hh:19
Definition: AbsClassicalOrthoPoly1D.hh:617
Definition: AbsClassicalOrthoPoly1D.hh:587
Definition: AbsClassicalOrthoPoly1D.hh:654
Definition: AbsArrayProjector.hh:14
Definition: SimpleFunctors.hh:58