Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 09:06:53

0001 #ifndef PERCENTILE_HH
0002 #define PERCENTILE_HH
0003 
0004 #include "Rivet/Event.hh"
0005 #include "Rivet/Projections/CentralityProjection.hh"
0006 #include "Rivet/ProjectionApplier.hh"
0007 
0008 namespace Rivet {
0009 
0010 
0011   /// Forward declaration.
0012   class Analysis;
0013 
0014 
0015   /// @brief PercentileBase is the base class of all Percentile classes.
0016   ///
0017   /// This base class contains all non-templated variables and
0018   /// infrastructure needed.
0019   class PercentileBase {
0020   public:
0021 
0022     /// @brief Constructor
0023     ///
0024     /// Constructor requiring a pointer, @a ana, to the Analysis to which this
0025     /// object belongs and the name of the CentralityProjection, @a
0026     /// projname, to be used.
0027     PercentileBase(Analysis * ana, string projName)
0028       : _ana(ana), _projName(projName) {}
0029 
0030     /// @brief Default constructor.
0031     PercentileBase() {}
0032 
0033     /// @brief Initialize the PercentileBase for a new event.
0034     ///
0035     /// This will perform the assigned CentralityProjection and select
0036     /// out the (indices) of the internal AnalysisObjects that are to be
0037     /// active in this event.
0038     void selectBins(const Event &);
0039 
0040     /// @brief Helper function to check if @a x is within @a range.
0041     static bool inRange(double x, pair<float,float> range) {
0042       return x >= range.first && ( x < range.second || ( x == 100.0 && x == range.second ) );
0043     }
0044 
0045     /// @brief Copy information from @a other PercentileBase
0046     void copyFrom(const PercentileBase & other) {
0047       _ana = other._ana;
0048       _projName = other._projName;
0049       _cent = other._cent;
0050     }
0051 
0052     /// @brief check if @a other PercentileBase is compatible with this.
0053     bool compatible(const PercentileBase & other) const {
0054       return ( _ana == other._ana &&
0055                _projName == other._projName &&
0056                _cent == other._cent );
0057     }
0058 
0059     /// @brief return the list of centrality bins.
0060     ///
0061     /// The size of this vector is the same as number of internal
0062     /// analysis objects in the sub class PercentileTBase.
0063     const vector< pair<float, float> > & centralities() const {
0064       return _cent;
0065     }
0066 
0067 
0068   protected:
0069 
0070     /// The Analysis object to which This object is assigned.
0071     Analysis* _ana;
0072 
0073     /// The name of the CentralityProjection.
0074     string _projName;
0075 
0076     /// The list of indices of the analysis objects that are to be
0077     /// filled in the current event.
0078     vector<int> _activeBins;
0079 
0080     /// The list of centrality intervals, one for each included analysis
0081     /// object.
0082     vector<pair<float, float> > _cent;
0083 
0084   };
0085 
0086 
0087 
0088   /// @brief PercentileTBase is the base class of all Percentile classes.
0089   ///
0090   /// This base class contains all template-dependent variables and
0091   /// infrastructure needed for Percentile and PercentileXaxis.
0092   template<class T>
0093   class PercentileTBase : public PercentileBase {
0094   public:
0095 
0096     /// Convenient typedef.
0097     using TPtr = MultiplexPtr<Multiplexer<T>>;
0098 
0099     /// @brief Main constructor
0100     ///
0101     /// requiring a pointer, @a ana, to the Analysis to which this
0102     /// object belongs and the name of the CentralityProjection, @a
0103     /// projname, to be used.
0104     PercentileTBase(Analysis * ana, string projName)
0105       : PercentileBase(ana, projName), _histos() {}
0106 
0107     /// @brief Default constructor
0108     PercentileTBase() {}
0109 
0110     /// @brief Empty destructor
0111     ~PercentileTBase() {}
0112 
0113     /// @brief Add a new percentile bin
0114     ///
0115     /// Add an analysis objects which are clones of @a temp that should
0116     /// be active for events in the given centrality bin @a
0117     /// cent. Several analysis objects may be added depending on the
0118     /// number of alternative centrality definitions in the
0119     /// CentralityProjection @a proj. This function is common for
0120     /// Percentile and PecentileXaxis, but for the latter the @a cent
0121     /// argument should be left to its default.
0122     void add(TPtr ao, CounterPtr cnt,
0123              pair<float,float> cent = {0.0, 100.0} ) {
0124       _cent.push_back(cent);
0125       _histos.push_back( { ao, cnt } );
0126     }
0127 
0128     /// @brief Copy the information from an @a other Percentile object.
0129     ///
0130     /// This function differs from a simple assignement as the @a other
0131     /// analysis objects are not copied, but supplied separately through
0132     /// @a tv.
0133     bool add(const PercentileBase & other, const vector<TPtr> & tv) {
0134       copyFrom(other);
0135       if ( tv.size() != _cent.size() ) return false;
0136       for ( auto t : tv )
0137         _histos.push_back( { t, CounterPtr() } );
0138       return true;
0139     }
0140 
0141     /// @brief Initialize for a new event. Select which AnalysisObjects
0142     /// should be filled for this event. Keeps track of the number of
0143     /// events seen for each centrality bin and AnalysisAbject.
0144     bool init(const Event & event) {
0145       selectBins(event);
0146       for (const auto bin : _activeBins)
0147         _histos[bin].second->fill();
0148       return !_activeBins.empty();
0149     }
0150 
0151     /// @brief Normalize each AnalysisObject
0152     ///
0153     /// Normalize by dividing by the sum of the events seen for each centrality
0154     /// bin.
0155     void normalizePerEvent() {
0156       for (const auto &hist : _histos)
0157         if ( hist.second->numEntries() > 0 && hist.first->numEntries() > 0)
0158           hist.first->scaleW(1./hist.second->val());
0159     }
0160 
0161     /// Simple scaling of each AnalysisObject
0162     void scale(float scale) {
0163       for (const auto hist : _histos)
0164         hist.first->scaleW(scale);
0165     }
0166 
0167     /// Execute a function for each AnalysisObject
0168     void exec(function<void(T&)> f) { for ( auto hist : _histos) f(hist); }
0169 
0170     /// @brief Access the underlyng AnalysisObjects
0171     ///
0172     /// The returned vector contains a pair, where the first member is
0173     /// the AnalysisObject and the second is a counter keeping track of
0174     /// the sum of event weights for which the AnalysisObject has been
0175     /// active.
0176     const vector<pair<TPtr, CounterPtr > > &
0177     analysisObjects() const{
0178       return _histos;
0179     }
0180 
0181 
0182   protected:
0183 
0184     /// The returned vector contains a pair, where the first member is
0185     /// the AnalysisObject and the second is a counter keeping track of
0186     /// the sum of event weights for which the AnalysisObject has been
0187     /// active.
0188     vector<pair<TPtr, CounterPtr > > _histos;
0189 
0190   };
0191 
0192 
0193 
0194   /// @brief The Percentile class for centrality binning.
0195   ///
0196   /// The Percentile class automatically handles the selection of which
0197   /// AnalysisObject(s) should be filled depending on the centrality of
0198   /// an event. It cointains a list of AnalysisObjects, one for each
0199   /// centrality bin requested (note that these bins may be overlapping)
0200   /// and each centrality definition is available in the assigned
0201   /// CentralityProjection.
0202   template<class T>
0203   class Percentile : public PercentileTBase<T> {
0204   public:
0205 
0206     /// @brief Main constructor
0207     ///
0208     /// Requires a pointer, @a ana, to the Analysis to which this
0209     /// object belongs and the name of the CentralityProjection, @a
0210     /// projname, to be used.
0211     Percentile(Analysis * ana, string projName)
0212       : PercentileTBase<T>(ana, projName) {}
0213 
0214     /// @brief Default constructor.
0215     Percentile() {}
0216 
0217     /// @brief Empty destructor.
0218     ~Percentile() {}
0219 
0220     /// Needed to access members of the templated base class.
0221     using PercentileTBase<T>::_histos;
0222 
0223     /// Needed to access members of the templated base class.
0224     using PercentileTBase<T>::_activeBins;
0225 
0226     /// Fill each AnalysisObject selected in the last call to
0227     /// PercentileTBase<T>init
0228     template<typename... Args>
0229     void fill(Args... args) {
0230       for (const auto bin : _activeBins) {
0231         _histos[bin].first->fill(args...);
0232       }
0233     }
0234 
0235     /// Subtract the contents fro another Pecentile.
0236     Percentile<T> &operator-=(const Percentile<T> &rhs) {
0237       const int nCent = _histos.size();
0238       for (int iCent = 0; iCent < nCent; ++iCent) {
0239         *_histos[iCent].first -= *rhs._histos[iCent].first;
0240       }
0241     }
0242 
0243     /// Add the contents fro another Pecentile.
0244     Percentile<T> &operator+=(const Percentile<T> &rhs) {
0245       const int nCent = _histos.size();
0246       for (int iCent = 0; iCent < nCent; ++iCent) {
0247         *_histos[iCent].first += *rhs._histos[iCent].first;
0248         /// @todo should this also add the Counter?
0249       }
0250     }
0251 
0252     /// Make this object look like a pointer.
0253     Percentile<T> *operator->() { return this; }
0254 
0255     /// Pointer to member operator.
0256     Percentile<T> &operator->*(function<void(T&)> f) { exec(f);  return *this; }
0257 
0258   };
0259 
0260 
0261 
0262   /// @brief The PercentileXaxis class for centrality binning.
0263   ///
0264   /// The PercentileXaxis class automatically handles the x-axis of an
0265   /// AnalysisObject when the x-axis is to be the centrality of an
0266   /// event. This could also be done by eg. filling directly a Histo1D
0267   /// with the result of a CentralityProjection. However, since the
0268   /// CentralityProjection may handle several centrality definitions at
0269   /// the same time it is reasonable to instead use
0270   /// PercentileXaxis<Histo1D> which will fill one histogram for each
0271   /// centrality definition.
0272   ///
0273   /// Operationally this class works like the Percentile class, but only
0274   /// one centrality bin (0-100) is included. When fill()ed the first
0275   /// argument is always given by the assigned CentralityProjection.
0276   template<class T>
0277   class PercentileXaxis : public PercentileTBase<T> {
0278   public:
0279 
0280     /// @brief Main constructor
0281     ///
0282     /// Requires a pointer, @a ana, to the Analysis to which this
0283     /// object belongs and the name of the CentralityProjection, @a
0284     /// projname, to be used.
0285     PercentileXaxis(Analysis * ana, string projName)
0286       : PercentileTBase<T>(ana, projName) {}
0287 
0288     /// @brief Default constructor
0289     PercentileXaxis() {}
0290 
0291     /// @brief Empty destructor
0292     ~PercentileXaxis() {}
0293 
0294     /// Needed to access members of the templated base class
0295     using PercentileTBase<T>::_histos;
0296 
0297     /// Needed to access members of the templated base class
0298     using PercentileTBase<T>::_activeBins;
0299 
0300     /// Fill each AnalysisObject selected in the last call to
0301     /// PercentileTBase<T>init
0302     template<typename... Args>
0303     void fill(Args... args) {
0304       for (const auto bin : _activeBins) {
0305         _histos[bin].first->fill(bin, args...);
0306       }
0307     }
0308 
0309     /// Subtract the contents from another PercentileXaxis.
0310     PercentileXaxis<T> &operator-=(const PercentileXaxis<T> &rhs) {
0311       const int nCent = _histos.size();
0312       for (int iCent = 0; iCent < nCent; ++iCent) {
0313         *_histos[iCent].first -= *rhs._histos[iCent].first;
0314       }
0315     }
0316 
0317     /// Add the contents from another PercentileXaxis.
0318     PercentileXaxis<T> &operator+=(const PercentileXaxis<T> &rhs) {
0319       const int nCent = this->_histos.size();
0320       for (int iCent = 0; iCent < nCent; ++iCent) {
0321         *_histos[iCent].first += *rhs._histos[iCent].first;
0322       }
0323     }
0324 
0325     /// Make this object look like a pointer.
0326     PercentileXaxis<T> *operator->() { return this; }
0327 
0328     /// Pointer to member operator.
0329     PercentileXaxis<T> &operator->*(function<void(T&)> f) { exec(f);  return *this; }
0330 
0331   };
0332 
0333 
0334 
0335   /// @name Combining Percentiles
0336   ///
0337   /// Follows the naming of functions for the underlying AnalysisObjects: global operators
0338   /// @{
0339 
0340   template <typename T>
0341   Percentile<typename ReferenceTraits<T>::RefT>
0342   divide(const Percentile<T> numer, const Percentile<T> denom) {
0343     typedef typename ReferenceTraits<T>::RefT ScatT;
0344     Percentile<ScatT> ret;
0345     vector<typename ScatT::Ptr> scatters;
0346     assert( numer.compatible(denom) );
0347     for ( int i = 0, N = numer.analysisObjects().size(); i < N; ++i )
0348       scatters.push_back(make_shared<ScatT>(divide(*numer.analysisObjects()[i].first,
0349                                                    *denom.analysisObjects()[i].first)));
0350     ret.add(numer, scatters);
0351     return ret;
0352   }
0353 
0354   template <typename T>
0355   Percentile<typename ReferenceTraits<T>::RefT>
0356   divide(const Percentile<T> numer,
0357          const Percentile<typename ReferenceTraits<T>::RefT> denom) {
0358     typedef typename ReferenceTraits<T>::RefT ScatT;
0359     Percentile<ScatT> ret;
0360     vector<typename ScatT::Ptr> scatters;
0361     assert( numer.compatible(denom) );
0362     for ( int i = 0, N = numer.analysisObjects().size(); i < N; ++i )
0363       scatters.push_back(make_shared<ScatT>(divide(*numer.analysisObjects()[i].first,
0364                                                    *denom.analysisObjects()[i].first)));
0365     ret.add(numer, scatters);
0366     return ret;
0367   }
0368 
0369   template <typename T>
0370   Percentile<typename ReferenceTraits<T>::RefT>
0371   divide(const Percentile<typename ReferenceTraits<T>::RefT> numer,
0372          const Percentile<T> denom) {
0373     typedef typename ReferenceTraits<T>::RefT ScatT;
0374     Percentile<typename ReferenceTraits<T>::RefT> ret;
0375     vector<typename ScatT::Ptr> scatters;
0376     assert( numer.compatible(denom) );
0377     for ( int i = 0, N = numer.analysisObjects().size(); i < N; ++i )
0378       scatters.push_back(make_shared<ScatT>(divide(*numer.analysisObjects()[i].first,
0379                                                    *denom.analysisObjects()[i].first)));
0380     ret.add(numer, scatters);
0381     return ret;
0382   }
0383 
0384   template <typename T>
0385   Percentile<T> add(const Percentile<T> pctla, const Percentile<T> pctlb) {
0386     Percentile<T> ret;
0387     vector<typename T::Ptr> aos;
0388     assert( pctla.compatible(pctlb) );
0389     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0390       aos.push_back(make_shared<T>(add(*pctla.analysisObjects()[i].first,
0391                                        *pctlb.analysisObjects()[i].first)));
0392     ret.add(pctla, aos);
0393     return ret;
0394   }
0395 
0396   template <typename T>
0397   Percentile<typename ReferenceTraits<T>::RefT>
0398   add(const Percentile<T> pctla,
0399       const Percentile<typename ReferenceTraits<T>::RefT> pctlb) {
0400     typedef typename ReferenceTraits<T>::RefT ScatT;
0401     Percentile<ScatT> ret;
0402     vector<typename ScatT::Ptr> scatters;
0403     assert( pctla.compatible(pctlb) );
0404     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0405       scatters.push_back(make_shared<ScatT>(add(*pctla.analysisObjects()[i].first,
0406                                                 *pctlb.analysisObjects()[i].first)));
0407     ret.add(pctla, scatters);
0408     return ret;
0409   }
0410 
0411   template <typename T>
0412   Percentile<typename ReferenceTraits<T>::RefT>
0413   add(const Percentile<typename ReferenceTraits<T>::RefT> pctla,
0414       const Percentile<T> pctlb) {
0415     typedef typename ReferenceTraits<T>::RefT ScatT;
0416     Percentile<ScatT> ret;
0417     vector<typename ScatT::Ptr> scatters;
0418     assert( pctla.compatible(pctlb) );
0419     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0420       scatters.push_back(make_shared<ScatT>(add(*pctla.analysisObjects()[i].first,
0421                                                 *pctlb.analysisObjects()[i].first)));
0422     ret.add(pctla, scatters);
0423     return ret;
0424   }
0425 
0426   template <typename T>
0427   Percentile<T> subtract(const Percentile<T> pctla, const Percentile<T> pctlb) {
0428     Percentile<T> ret;
0429     vector<typename T::Ptr> aos;
0430     assert( pctla.compatible(pctlb) );
0431     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0432       aos.push_back(make_shared<T>(subtract(*pctla.analysisObjects()[i].first,
0433                                             *pctlb.analysisObjects()[i].first)));
0434     ret.add(pctla, aos);
0435     return ret;
0436   }
0437 
0438   template <typename T>
0439   Percentile<typename ReferenceTraits<T>::RefT>
0440   subtract(const Percentile<T> pctla,
0441            const Percentile<typename ReferenceTraits<T>::RefT> pctlb) {
0442     typedef typename ReferenceTraits<T>::RefT ScatT;
0443     Percentile<ScatT> ret;
0444     vector<typename ScatT::Ptr> scatters;
0445     assert( pctla.compatible(pctlb) );
0446     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0447       scatters.push_back(make_shared<ScatT>(subtract(*pctla.analysisObjects()[i].first,
0448                                                      *pctlb.analysisObjects()[i].first)));
0449     ret.add(pctla, scatters);
0450     return ret;
0451   }
0452 
0453   template <typename T>
0454   Percentile<typename ReferenceTraits<T>::RefT>
0455   subtract(const Percentile<typename ReferenceTraits<T>::RefT> pctla,
0456            const Percentile<T> pctlb) {
0457     typedef typename ReferenceTraits<T>::RefT ScatT;
0458     Percentile<ScatT> ret;
0459     vector<typename ScatT::Ptr> scatters;
0460     assert( pctla.compatible(pctlb) );
0461     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0462       scatters.push_back(make_shared<ScatT>(subtract(*pctla.analysisObjects()[i].first,
0463                                                      *pctlb.analysisObjects()[i].first)));
0464     ret.add(pctla, scatters);
0465     return ret;
0466   }
0467 
0468   template <typename T>
0469   Percentile<typename ReferenceTraits<T>::RefT>
0470   multiply(const Percentile<T> pctla,
0471            const Percentile<typename ReferenceTraits<T>::RefT> pctlb) {
0472     typedef typename ReferenceTraits<T>::RefT ScatT;
0473     Percentile<ScatT> ret;
0474     vector<typename ScatT::Ptr> scatters;
0475     assert( pctla.compatible(pctlb) );
0476     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0477       scatters.push_back(make_shared<ScatT>(multiply(*pctla.analysisObjects()[i].first,
0478                                                      *pctlb.analysisObjects()[i].first)));
0479     ret.add(pctla, scatters);
0480     return ret;
0481   }
0482 
0483   template <typename T>
0484   Percentile<typename ReferenceTraits<T>::RefT>
0485   multiply(const Percentile<typename ReferenceTraits<T>::RefT> pctla,
0486            const Percentile<T> pctlb) {
0487     typedef typename ReferenceTraits<T>::RefT ScatT;
0488     Percentile<ScatT> ret;
0489     vector<typename ScatT::Ptr> scatters;
0490     assert( pctla.compatible(pctlb) );
0491     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0492       scatters.push_back(make_shared<ScatT>(multiply(*pctla.analysisObjects()[i].first,
0493                                                      *pctlb.analysisObjects()[i].first)));
0494     ret.add(pctla, scatters);
0495     return ret;
0496   }
0497 
0498 
0499 
0500   template <typename T>
0501   PercentileXaxis<typename ReferenceTraits<T>::RefT>
0502   divide(const PercentileXaxis<T> numer, const PercentileXaxis<T> denom) {
0503     typedef typename ReferenceTraits<T>::RefT ScatT;
0504     PercentileXaxis<ScatT> ret;
0505     vector<typename ScatT::Ptr> scatters;
0506     assert( numer.compatible(denom) );
0507     for ( int i = 0, N = numer.analysisObjects().size(); i < N; ++i )
0508       scatters.push_back(make_shared<ScatT>(divide(*numer.analysisObjects()[i].first,
0509                                                    *denom.analysisObjects()[i].first)));
0510     ret.add(numer, scatters);
0511     return ret;
0512   }
0513 
0514   template <typename T>
0515   PercentileXaxis<typename ReferenceTraits<T>::RefT>
0516   divide(const PercentileXaxis<T> numer,
0517          const PercentileXaxis<typename ReferenceTraits<T>::RefT> denom) {
0518     typedef typename ReferenceTraits<T>::RefT ScatT;
0519     PercentileXaxis<ScatT> ret;
0520     vector<typename ScatT::Ptr> scatters;
0521     assert( numer.compatible(denom) );
0522     for ( int i = 0, N = numer.analysisObjects().size(); i < N; ++i )
0523       scatters.push_back(make_shared<ScatT>(divide(*numer.analysisObjects()[i].first,
0524                                                    *denom.analysisObjects()[i].first)));
0525     ret.add(numer, scatters);
0526     return ret;
0527   }
0528 
0529   template <typename T>
0530   PercentileXaxis<typename ReferenceTraits<T>::RefT>
0531   divide(const PercentileXaxis<typename ReferenceTraits<T>::RefT> numer,
0532          const PercentileXaxis<T> denom) {
0533     typedef typename ReferenceTraits<T>::RefT ScatT;
0534     PercentileXaxis<typename ReferenceTraits<T>::RefT> ret;
0535     vector<typename ScatT::Ptr> scatters;
0536     assert( numer.compatible(denom) );
0537     for ( int i = 0, N = numer.analysisObjects().size(); i < N; ++i )
0538       scatters.push_back(make_shared<ScatT>(divide(*numer.analysisObjects()[i].first,
0539                                                    *denom.analysisObjects()[i].first)));
0540     ret.add(numer, scatters);
0541     return ret;
0542   }
0543 
0544   template <typename T>
0545   PercentileXaxis<T> add(const PercentileXaxis<T> pctla, const PercentileXaxis<T> pctlb) {
0546     PercentileXaxis<T> ret;
0547     vector<typename T::Ptr> aos;
0548     assert( pctla.compatible(pctlb) );
0549     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0550       aos.push_back(make_shared<T>(add(*pctla.analysisObjects()[i].first,
0551                                        *pctlb.analysisObjects()[i].first)));
0552     ret.add(pctla, aos);
0553     return ret;
0554   }
0555 
0556   template <typename T>
0557   PercentileXaxis<typename ReferenceTraits<T>::RefT>
0558   add(const PercentileXaxis<T> pctla,
0559       const PercentileXaxis<typename ReferenceTraits<T>::RefT> pctlb) {
0560     typedef typename ReferenceTraits<T>::RefT ScatT;
0561     PercentileXaxis<ScatT> ret;
0562     vector<typename ScatT::Ptr> scatters;
0563     assert( pctla.compatible(pctlb) );
0564     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0565       scatters.push_back(make_shared<ScatT>(add(*pctla.analysisObjects()[i].first,
0566                                                 *pctlb.analysisObjects()[i].first)));
0567     ret.add(pctla, scatters);
0568     return ret;
0569   }
0570 
0571   template <typename T>
0572   PercentileXaxis<typename ReferenceTraits<T>::RefT>
0573   add(const PercentileXaxis<typename ReferenceTraits<T>::RefT> pctla,
0574       const PercentileXaxis<T> pctlb) {
0575     typedef typename ReferenceTraits<T>::RefT ScatT;
0576     PercentileXaxis<ScatT> ret;
0577     vector<typename ScatT::Ptr> scatters;
0578     assert( pctla.compatible(pctlb) );
0579     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0580       scatters.push_back(make_shared<ScatT>(add(*pctla.analysisObjects()[i].first,
0581                                                 *pctlb.analysisObjects()[i].first)));
0582     ret.add(pctla, scatters);
0583     return ret;
0584   }
0585 
0586   template <typename T>
0587   PercentileXaxis<T> subtract(const PercentileXaxis<T> pctla, const PercentileXaxis<T> pctlb) {
0588     PercentileXaxis<T> ret;
0589     vector<typename T::Ptr> aos;
0590     assert( pctla.compatible(pctlb) );
0591     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0592       aos.push_back(make_shared<T>(subtract(*pctla.analysisObjects()[i].first,
0593                                             *pctlb.analysisObjects()[i].first)));
0594     ret.add(pctla, aos);
0595     return ret;
0596   }
0597 
0598   template <typename T>
0599   PercentileXaxis<typename ReferenceTraits<T>::RefT>
0600   subtract(const PercentileXaxis<T> pctla,
0601            const PercentileXaxis<typename ReferenceTraits<T>::RefT> pctlb) {
0602     typedef typename ReferenceTraits<T>::RefT ScatT;
0603     PercentileXaxis<ScatT> ret;
0604     vector<typename ScatT::Ptr> scatters;
0605     assert( pctla.compatible(pctlb) );
0606     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0607       scatters.push_back(make_shared<ScatT>(subtract(*pctla.analysisObjects()[i].first,
0608                                                      *pctlb.analysisObjects()[i].first)));
0609     ret.add(pctla, scatters);
0610     return ret;
0611   }
0612 
0613   template <typename T>
0614   PercentileXaxis<typename ReferenceTraits<T>::RefT>
0615   subtract(const PercentileXaxis<typename ReferenceTraits<T>::RefT> pctla,
0616            const PercentileXaxis<T> pctlb) {
0617     typedef typename ReferenceTraits<T>::RefT ScatT;
0618     PercentileXaxis<ScatT> ret;
0619     vector<typename ScatT::Ptr> scatters;
0620     assert( pctla.compatible(pctlb) );
0621     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0622       scatters.push_back(make_shared<ScatT>(subtract(*pctla.analysisObjects()[i].first,
0623                                                      *pctlb.analysisObjects()[i].first)));
0624     ret.add(pctla, scatters);
0625     return ret;
0626   }
0627 
0628   template <typename T>
0629   PercentileXaxis<typename ReferenceTraits<T>::RefT>
0630   multiply(const PercentileXaxis<T> pctla,
0631            const PercentileXaxis<typename ReferenceTraits<T>::RefT> pctlb) {
0632     typedef typename ReferenceTraits<T>::RefT ScatT;
0633     PercentileXaxis<ScatT> ret;
0634     vector<typename ScatT::Ptr> scatters;
0635     assert( pctla.compatible(pctlb) );
0636     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0637       scatters.push_back(make_shared<ScatT>(multiply(*pctla.analysisObjects()[i].first,
0638                                                      *pctlb.analysisObjects()[i].first)));
0639     ret.add(pctla, scatters);
0640     return ret;
0641   }
0642 
0643   template <typename T>
0644   PercentileXaxis<typename ReferenceTraits<T>::RefT>
0645   multiply(const PercentileXaxis<typename ReferenceTraits<T>::RefT> pctla,
0646            const PercentileXaxis<T> pctlb) {
0647     typedef typename ReferenceTraits<T>::RefT ScatT;
0648     PercentileXaxis<ScatT> ret;
0649     vector<typename ScatT::Ptr> scatters;
0650     assert( pctla.compatible(pctlb) );
0651     for ( int i = 0, N = pctla.analysisObjects().size(); i < N; ++i )
0652       scatters.push_back(make_shared<ScatT>(multiply(*pctla.analysisObjects()[i].first,
0653                                                      *pctlb.analysisObjects()[i].first)));
0654     ret.add(pctla, scatters);
0655     return ret;
0656   }
0657 
0658   template <typename T>
0659   Percentile<T>
0660   operator+(const Percentile<T> pctla, const Percentile<T> pctlb) {
0661     return add(pctla, pctlb);
0662   }
0663 
0664   template <typename T>
0665   Percentile<T>
0666   operator-(const Percentile<T> pctla, const Percentile<T> pctlb) {
0667     return subtract(pctla, pctlb);
0668   }
0669 
0670   template <typename T>
0671   Percentile<typename ReferenceTraits<T>::RefT>
0672   operator/(const Percentile<T> numer, const Percentile<T> denom) {
0673     return divide(numer, denom);
0674   }
0675 
0676   template <typename T>
0677   PercentileXaxis<T>
0678   operator+(const PercentileXaxis<T> pctla, const PercentileXaxis<T> pctlb) {
0679     return add(pctla, pctlb);
0680   }
0681 
0682   template <typename T>
0683   PercentileXaxis<T>
0684   operator-(const PercentileXaxis<T> pctla, const PercentileXaxis<T> pctlb) {
0685     return subtract(pctla, pctlb);
0686   }
0687 
0688   template <typename T>
0689   PercentileXaxis<typename ReferenceTraits<T>::RefT>
0690   operator/(const PercentileXaxis<T> numer, const PercentileXaxis<T> denom) {
0691     return divide(numer, denom);
0692   }
0693 
0694   /// @}
0695 
0696 
0697 }
0698 
0699 #endif