npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
DensityScanND.hh
Go to the documentation of this file.
1 #ifndef NPSTAT_DENSITYSCANND_HH_
2 #define NPSTAT_DENSITYSCANND_HH_
3 
4 /*!
5 // \file DensityScanND.hh
6 //
7 // \brief Fill multivariate arrays with multivariate density values
8 //
9 // Author: I. Volobouev
10 //
11 // December 2011
12 */
13 
14 #include <vector>
15 #include <cassert>
16 #include <stdexcept>
17 #include <memory>
18 #include <climits>
19 
21 
22 namespace npstat {
23  /**
24  // The IndexMapper template parameter is a functor which takes
25  // a double argument (representing unsigned int) and returns
26  // a double (or something which can be automatically converted
27  // to double). IndexMapper can, for example, be set to LinearMapper1d
28  // or CircularMapper1d.
29  */
30  template<class IndexMapper>
32  {
33  public:
34  /**
35  // A mapper for each coordinate in the "maps" constructor argument
36  // will convert the array index into a proper argument for the scanned
37  // density.
38  //
39  // This functor will NOT make a copy of the "fcn" parameter. This
40  // parameter will be used by reference only (aliased). It is up to
41  // the user of this class to ensure proper lifetime of this object.
42  */
43  inline DensityScanND(const AbsDistributionND& fcn,
44  const std::vector<IndexMapper>& maps,
45  double normfactor=1.0)
46  : fcn_(fcn), mapping_(new std::vector<IndexMapper>(maps)),
47  normfactor_(normfactor), dim_(fcn.dim())
48  {
49  if (!(dim_ && dim_ == mapping_->size())) throw std::invalid_argument(
50  "In npstat::DensityScanND constructor: incompatible arguments");
51  if (dim_ > CHAR_BIT*sizeof(unsigned long)) throw std::invalid_argument(
52  "In npstat::DensityScanND constructor: dimensionality is too high");
53  }
54 
55  inline void getCoords(const unsigned* index, const unsigned indexLen,
56  double* coords) const
57  {
58  if (dim_ != indexLen) throw std::invalid_argument(
59  "In npstat::DensityScanND::getCoords: "
60  "incompatible index dimensionality");
61  assert(index);
62  assert(coords);
63  const IndexMapper* mappers = &(*mapping_)[0];
64  for (unsigned i=0; i<indexLen; ++i)
65  coords[i] = mappers[i](static_cast<double>(index[i]));
66  }
67 
68  inline double operator()(const unsigned* index, unsigned indexLen) const
69  {
70  double x[CHAR_BIT*sizeof(unsigned long)];
71  getCoords(index, indexLen, x);
72  return normfactor_*fcn_.density(x, indexLen);
73  }
74 
75  private:
76  DensityScanND();
77 
78  // This functor will be recursively copied by the
79  // scanning code, so it must be lightweight. This
80  // is what std::shared_ptr is here for.
81  const AbsDistributionND& fcn_;
82  std::shared_ptr<std::vector<IndexMapper> > mapping_;
83  double normfactor_;
84  unsigned dim_;
85 
86 #ifdef SWIG
87  public:
88  inline void mapIndex(const unsigned* index, unsigned indexLen,
89  double* coords, unsigned lenCoords)
90  {
91  if (dim_ != lenCoords) throw std::invalid_argument(
92  "In npstat::DensityScanND::mapIndex: "
93  "incompatible coordinate dimensionality");
94  this->getCoords(index, indexLen, coords);
95  }
96 #endif // SWIG
97  };
98 
99  // Helper function for creating DensityScanND objects
100  template<class IndexMapper>
101  inline DensityScanND<IndexMapper> makeDensityScanND(
102  const AbsDistributionND& fcn, const std::vector<IndexMapper>& axes,
103  double normfactor=1.0)
104  {
105  return DensityScanND<IndexMapper>(fcn, axes, normfactor);
106  }
107 }
108 
109 #endif // NPSTAT_DENSITYSCANND_HH_
Interface definition for multivariate continuous statistical distributions.
Definition: AbsDistributionND.hh:26
virtual double density(const double *x, unsigned dim) const =0
Definition: DensityScanND.hh:32
DensityScanND(const AbsDistributionND &fcn, const std::vector< IndexMapper > &maps, double normfactor=1.0)
Definition: DensityScanND.hh:43
Definition: AbsArrayProjector.hh:14