npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
OrthoPolyND.hh
Go to the documentation of this file.
1 #ifndef NPSTAT_ORTHOPOLYND_HH_
2 #define NPSTAT_ORTHOPOLYND_HH_
3 
4 /*!
5 // \file OrthoPolyND.hh
6 //
7 // \brief Discrete orthogonal polynomial series of arbitrary dimensionality
8 // in hyperrectangular domains
9 //
10 // These series are intended for use in local filtering.
11 //
12 // Author: I. Volobouev
13 //
14 // October 2009
15 */
16 
17 #include <vector>
18 
19 #include "npstat/nm/ArrayND.hh"
20 
21 namespace npstat {
22  /**
23  // This class is templated on the maximum polynomial degree
24  // that can be used
25  */
26  template <unsigned MaxDeg>
28  {
29  public:
30  enum {deg_size = MaxDeg};
31 
32  /**
33  // Main constructor. The "polyDegree" parameter must not exceed
34  // the "MaxDeg" template parameter.
35  //
36  // "weight" is an arbitrary weight function, specified by its
37  // values on a grid with equidistant steps in each dimension.
38  //
39  // "steps" is the array of steps. It can be specified as NULL.
40  // In such a case the width of the integration region in each
41  // dimension is assumed to be 1.0 and the step in each dimension
42  // D is calculated as 1.0/weight.span(D).
43  */
44  OrthoPolyND(unsigned polyDegree, const ArrayND<double>& weight,
45  const double* steps = 0, unsigned nSteps = 0);
46 
47  /** Copy constructor */
49 
50  // Destructor
51  ~OrthoPolyND();
52 
53  /** The assignment operator */
55 
56  /** What is the dimensionality of the coordinate space? */
57  inline unsigned dim() const {return weight_.rank();}
58 
59  /** Maximum polynomial degree */
60  inline unsigned maxDegree() const {return maxdeg_;}
61 
62  /** How many terms the series will have? */
63  inline unsigned nTerms() const {return poly_.size();}
64 
65  /** What is the degree of the given term in the series? */
66  inline unsigned degree(const unsigned termNumber) const
67  {return degs_.at(termNumber);}
68 
69  /** The step size in the given dimension */
70  inline double step(const unsigned nd) const {return steps_.at(nd);}
71 
72  /** Get the table of weights */
73  inline const ArrayND<double>& weight() const {return weight_;}
74 
75  /**
76  // Return the value of one of the polynomials. "ix" is the
77  // multivariate index of the array point for which the polynomial
78  // value should be returned.
79  */
80  inline double poly(const unsigned termNumber, const unsigned* ix,
81  const unsigned lenIx) const
82  {return poly_.at(termNumber)->valueAt(ix, lenIx);}
83 
84  //@{
85  /** Compare for equality */
86  bool operator==(const OrthoPolyND& r) const;
87  bool operator!=(const OrthoPolyND& r) const;
88  //@}
89 
90  /**
91  // Series at a single point. The first coefficient refers to
92  // the lowest degree polynomial (the constant term). The number
93  // of coefficients provided must be equal to the number of terms
94  // in the series (as returned by the "nTerms" method).
95  */
96  double series(const double* coeffs, unsigned lenCoeffs,
97  const unsigned* ix, unsigned lenIx) const;
98 
99  /** Series on the whole hyperrectangle */
100  ArrayND<double> arraySeries(const double* coeffs,
101  unsigned lenCoeffs) const;
102 
103  /**
104  // Generate a linear filter for the given point. Note that
105  // this filter is generated on the heap and the user must
106  // eventually call the "delete" operator on the result
107  // (or just use a smart pointer to hold it).
108  */
110  const double* coeffs, unsigned lenCoeffs,
111  const unsigned* ix, unsigned lenIx) const;
112 
113  /**
114  // Build the series for the given gridded data.
115  // "shift" is the offset with which the sliding window
116  // of the weight will be placed inside "gridData".
117  // The "shift" array can be NULL in which case it will be
118  // assumed that all shift values are 0.
119  */
120  void calculateCoeffs(const ArrayND<double>& gridData,
121  const unsigned* shift, unsigned lenShift,
122  double *coeffs, unsigned lenCoeffs) const;
123 
124  /**
125  // This method is useful for testing the numerical precision
126  // of the orthonormalization procedure. It returns the scalar
127  // products between various polynomials.
128  */
129  double empiricalKroneckerDelta(unsigned term1, unsigned term2) const;
130 
131  static inline unsigned classMaxDegree() {return MaxDeg;}
132 
133  private:
134  OrthoPolyND();
135 
136  class Monomial
137  {
138  public:
139  Monomial(unsigned mxdim, unsigned deg, unsigned long imono);
140 
141  unsigned degree() const;
142  bool operator<(const Monomial& r) const;
143  bool operator==(const Monomial& r) const;
144  bool operator!=(const Monomial& r) const;
145  double operator()(const double *x, unsigned xlen) const;
146 
147  private:
148  Monomial();
149 
150  unsigned dims[MaxDeg];
151  unsigned nDims;
152  };
153 
154  class GridMonomial
155  {
156  public:
157  GridMonomial(const Monomial& m, const double* steps,
158  double* xwork, unsigned nSteps);
159  double operator()(const unsigned* ind, const unsigned len) const;
160 
161  private:
162  const Monomial& mono_;
163  const double* steps_;
164  double* xwork_;
165  const unsigned nSteps_;
166  };
167 
168  ArrayND<double> weight_;
169  std::vector<ArrayND<double>*> poly_;
170  std::vector<double> steps_;
171  std::vector<unsigned> degs_;
172  double cellVolume_;
173  unsigned maxdeg_;
174 
175  void generateMonomialSet(unsigned mxDeg, std::vector<Monomial>*) const;
176  double scalarProduct(const ArrayND<double>&,
177  const ArrayND<double>&) const;
178  void gramSchmidt();
179 
180  template <unsigned StackLen, unsigned StackDim>
181  long double windowProductLoop(
182  unsigned level,
183  const ArrayND<double,StackLen,StackDim>& data,
184  const ArrayND<double>& poly,
185  const unsigned* polyShift,
186  unsigned long idxData, unsigned long idxPoly) const;
187  };
188 }
189 
190 #include "npstat/nm/OrthoPolyND.icc"
191 
192 #endif // NPSTAT_ORTHOPOLYND_HH_
Arbitrary-dimensional array template.
unsigned rank() const
Definition: ArrayND.hh:329
Definition: OrthoPolyND.hh:28
unsigned maxDegree() const
Definition: OrthoPolyND.hh:60
double poly(const unsigned termNumber, const unsigned *ix, const unsigned lenIx) const
Definition: OrthoPolyND.hh:80
double empiricalKroneckerDelta(unsigned term1, unsigned term2) const
const ArrayND< double > & weight() const
Definition: OrthoPolyND.hh:73
ArrayND< double > * linearFilter(const double *coeffs, unsigned lenCoeffs, const unsigned *ix, unsigned lenIx) const
double step(const unsigned nd) const
Definition: OrthoPolyND.hh:70
unsigned dim() const
Definition: OrthoPolyND.hh:57
ArrayND< double > arraySeries(const double *coeffs, unsigned lenCoeffs) const
unsigned nTerms() const
Definition: OrthoPolyND.hh:63
double series(const double *coeffs, unsigned lenCoeffs, const unsigned *ix, unsigned lenIx) const
OrthoPolyND(unsigned polyDegree, const ArrayND< double > &weight, const double *steps=0, unsigned nSteps=0)
void calculateCoeffs(const ArrayND< double > &gridData, const unsigned *shift, unsigned lenShift, double *coeffs, unsigned lenCoeffs) const
OrthoPolyND & operator=(const OrthoPolyND &)
OrthoPolyND(const OrthoPolyND &)
bool operator==(const OrthoPolyND &r) const
unsigned degree(const unsigned termNumber) const
Definition: OrthoPolyND.hh:66
Definition: AbsArrayProjector.hh:14