CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/src/JetMETCorrections/InterpolationTables/interface/HistoND.h

Go to the documentation of this file.
00001 #ifndef NPSTAT_HISTOND_HH_
00002 #define NPSTAT_HISTOND_HH_
00003 
00014 #include "JetMETCorrections/InterpolationTables/interface/ArrayND.h"
00015 #include "JetMETCorrections/InterpolationTables/interface/HistoAxis.h"
00016 
00017 namespace npstat {
00042     template <typename Numeric, class Axis=HistoAxis>
00043     class HistoND
00044     {
00045         template <typename Num2, class Axis2> friend class HistoND;
00046 
00047     public:
00048         typedef Numeric value_type;
00049         typedef Axis axis_type;
00050 
00052         HistoND(const std::vector<Axis>& axes, const char* title=0,
00053                 const char* accumulatedDataLabel=0);
00054 
00056         HistoND(const Axis& xAxis, const char* title=0,
00057                 const char* accumulatedDataLabel=0);
00058 
00060         HistoND(const Axis& xAxis, const Axis& yAxis,
00061                 const char* title=0, const char* accumulatedDataLabel=0);
00062 
00064         HistoND(const Axis& xAxis, const Axis& yAxis, const Axis& zAxis,
00065                 const char* title=0, const char* accumulatedDataLabel=0);
00066 
00068         HistoND(const Axis& xAxis, const Axis& yAxis,
00069                 const Axis& zAxis, const Axis& tAxis,
00070                 const char* title=0, const char* accumulatedDataLabel=0);
00071 
00073         HistoND(const Axis& xAxis, const Axis& yAxis,
00074                 const Axis& zAxis, const Axis& tAxis, const Axis& vAxis,
00075                 const char* title=0, const char* accumulatedDataLabel=0);
00076 
00082         HistoND(const ArrayShape& shape, const BoxND<double>& boundingBox,
00083                 const char* title=0, const char* accumulatedDataLabel=0);
00084 
00091         template <typename Num2, class Functor>
00092         HistoND(const HistoND<Num2,Axis>& h, const Functor& f,
00093                 const char* title=0, const char* accumulatedDataLabel=0);
00094 
00102         template <typename Num2>
00103         HistoND(const HistoND<Num2,Axis>& h, const unsigned *indices,
00104                 unsigned nIndices, const char* title=0);
00105 
00115         template <typename Num2>
00116         HistoND(const HistoND<Num2,Axis>& h, const Axis& newAxis,
00117                 unsigned newAxisNumber, const char* title=0);
00118 
00120         HistoND(const HistoND&);
00121 
00126         HistoND& operator=(const HistoND&);
00127 
00129         inline unsigned dim() const {return dim_;}
00130 
00132         inline const std::string& title() const {return title_;}
00133 
00135         inline const std::string& accumulatedDataLabel() const
00136             {return accumulatedDataLabel_;}
00137 
00139         inline const ArrayND<Numeric>& binContents() const {return data_;}
00140 
00142         inline const ArrayND<Numeric>& overflows() const {return overflow_;}
00143 
00145         inline const std::vector<Axis>& axes() const {return axes_;}
00146 
00148         inline const Axis& axis(const unsigned i) const
00149             {return axes_.at(i);}
00150 
00152         inline unsigned long nBins() const {return data_.length();}
00153 
00155         inline unsigned long nFillsTotal() const {return fillCount_;}
00156 
00158         inline unsigned long nFillsInRange() const
00159             {return fillCount_ - overCount_;}
00160 
00162         inline unsigned long nFillsOver() const {return overCount_;}
00163 
00168         bool isUniformlyBinned() const;
00169 
00171         inline void setTitle(const char* newtitle)
00172             {title_ = newtitle ? newtitle : ""; ++modCount_;}
00173 
00175         inline void setAccumulatedDataLabel(const char* newlabel)
00176             {accumulatedDataLabel_ = newlabel ? newlabel : ""; ++modCount_;}
00177 
00179         inline void setAxisLabel(const unsigned axisNum, const char* newlabel)
00180             {axes_.at(axisNum).setLabel(newlabel); ++modCount_;}
00181 
00186         double binVolume(unsigned long binNumber=0) const;
00187 
00193         void binCenter(unsigned long binNumber,
00194                        double* coords, unsigned lenCoords) const;
00195 
00203         template <class Point>
00204         void allBinCenters(std::vector<Point>* centers) const;
00205 
00207         void binBox(unsigned long binNumber, BoxND<double>* box) const;
00208 
00210         BoxND<double> boundingBox() const;
00211 
00217         double volume() const;
00218 
00220         double integral() const;
00221 
00223         void clear();
00224 
00226         void clearBinContents();
00227 
00229         void clearOverflows();
00230 
00232         bool operator==(const HistoND&) const;
00233 
00235         bool operator!=(const HistoND&) const;
00236 
00241         bool isSameData(const HistoND&) const;
00242 
00249         template <typename Num2>
00250         void fill(const double* coords, unsigned coordLength,
00251                   const Num2& weight);
00252 
00254 
00258         template <typename Num2>
00259         void fill(const Num2& weight);
00260 
00261         template <typename Num2>
00262         void fill(double x0, const Num2& weight);
00263 
00264         template <typename Num2>
00265         void fill(double x0, double x1, const Num2& weight);
00266 
00267         template <typename Num2>
00268         void fill(double x0, double x1, double x2, const Num2& weight);
00269 
00270         template <typename Num2>
00271         void fill(double x0, double x1, double x2, double x3,
00272                   const Num2& weight);
00273 
00274         template <typename Num2>
00275         void fill(double x0, double x1, double x2, double x3, double x4,
00276                   const Num2& weight);
00277 
00278         template <typename Num2>
00279         void fill(double x0, double x1, double x2, double x3, double x4,
00280                   double x5, const Num2& weight);
00281 
00282         template <typename Num2>
00283         void fill(double x0, double x1, double x2, double x3, double x4,
00284                   double x5, double x6, const Num2& weight);
00285 
00286         template <typename Num2>
00287         void fill(double x0, double x1, double x2, double x3, double x4,
00288                   double x5, double x6, double x7, const Num2& weight);
00289 
00290         template <typename Num2>
00291         void fill(double x0, double x1, double x2, double x3, double x4,
00292                   double x5, double x6, double x7, double x8,
00293                   const Num2& weight);
00294 
00295         template <typename Num2>
00296         void fill(double x0, double x1, double x2, double x3, double x4,
00297                   double x5, double x6, double x7, double x8, double x9,
00298                   const Num2& weight);
00300 
00314         template <typename Num2, class Functor>
00315         void dispatch(const double* coords, unsigned coordLength,
00316                       Num2& weight, Functor& f);
00317 
00319 
00323         template <typename Num2, class Functor>
00324         void dispatch(Num2& weight, Functor& f);
00325 
00326         template <typename Num2, class Functor>
00327         void dispatch(double x0, Num2& weight, Functor& f);
00328 
00329         template <typename Num2, class Functor>
00330         void dispatch(double x0, double x1, Num2& weight, Functor& f);
00331 
00332         template <typename Num2, class Functor>
00333         void dispatch(double x0, double x1, double x2, Num2& weight,
00334                       Functor& f);
00335 
00336         template <typename Num2, class Functor>
00337         void dispatch(double x0, double x1, double x2, double x3,
00338                       Num2& weight, Functor& f);
00339 
00340         template <typename Num2, class Functor>
00341         void dispatch(double x0, double x1, double x2, double x3, double x4,
00342                       Num2& weight, Functor& f);
00343 
00344         template <typename Num2, class Functor>
00345         void dispatch(double x0, double x1, double x2, double x3, double x4,
00346                       double x5, Num2& weight, Functor& f);
00347 
00348         template <typename Num2, class Functor>
00349         void dispatch(double x0, double x1, double x2, double x3, double x4,
00350                       double x5, double x6, Num2& weight, Functor& f);
00351 
00352         template <typename Num2, class Functor>
00353         void dispatch(double x0, double x1, double x2, double x3, double x4,
00354                       double x5, double x6, double x7, Num2& weight,
00355                       Functor& f);
00356 
00357         template <typename Num2, class Functor>
00358         void dispatch(double x0, double x1, double x2, double x3, double x4,
00359                       double x5, double x6, double x7, double x8,
00360                       Num2& weight, Functor& f);
00361 
00362         template <typename Num2, class Functor>
00363         void dispatch(double x0, double x1, double x2, double x3, double x4,
00364                       double x5, double x6, double x7, double x8, double x9,
00365                       Num2& weight, Functor& f);
00367 
00374         const Numeric& examine(const double* coords,
00375                                unsigned coordLength) const;
00376 
00378 
00382         const Numeric& examine() const;
00383 
00384         const Numeric& examine(double x0) const;
00385 
00386         const Numeric& examine(double x0, double x1) const;
00387 
00388         const Numeric& examine(double x0, double x1, double x2) const;
00389 
00390         const Numeric& examine(double x0, double x1, double x2,
00391                                double x3) const;
00392 
00393         const Numeric& examine(double x0, double x1, double x2, double x3,
00394                                double x4) const;
00395 
00396         const Numeric& examine(double x0, double x1, double x2, double x3,
00397                                double x4, double x5) const;
00398 
00399         const Numeric& examine(double x0, double x1, double x2, double x3,
00400                                double x4, double x5, double x6) const;
00401 
00402         const Numeric& examine(double x0, double x1, double x2, double x3,
00403                                double x4, double x5, double x6,
00404                                double x7) const;
00405 
00406         const Numeric& examine(double x0, double x1, double x2, double x3,
00407                                double x4, double x5, double x6, double x7,
00408                                double x8) const;
00409 
00410         const Numeric& examine(double x0, double x1, double x2, double x3,
00411                                double x4, double x5, double x6, double x7,
00412                                double x8, double x9) const;
00414 
00421         const Numeric& closestBin(const double* coords,
00422                                   unsigned coordLength) const;
00423 
00425 
00429         const Numeric& closestBin() const;
00430 
00431         const Numeric& closestBin(double x0) const;
00432 
00433         const Numeric& closestBin(double x0, double x1) const;
00434 
00435         const Numeric& closestBin(double x0, double x1, double x2) const;
00436 
00437         const Numeric& closestBin(double x0, double x1, double x2,
00438                                   double x3) const;
00439 
00440         const Numeric& closestBin(double x0, double x1, double x2, double x3,
00441                                   double x4) const;
00442 
00443         const Numeric& closestBin(double x0, double x1, double x2, double x3,
00444                                   double x4, double x5) const;
00445 
00446         const Numeric& closestBin(double x0, double x1, double x2, double x3,
00447                                   double x4, double x5, double x6) const;
00448 
00449         const Numeric& closestBin(double x0, double x1, double x2, double x3,
00450                                   double x4, double x5, double x6,
00451                                   double x7) const;
00452 
00453         const Numeric& closestBin(double x0, double x1, double x2, double x3,
00454                                   double x4, double x5, double x6, double x7,
00455                                   double x8) const;
00456 
00457         const Numeric& closestBin(double x0, double x1, double x2, double x3,
00458                                   double x4, double x5, double x6, double x7,
00459                                   double x8, double x9) const;
00461 
00484         template <typename Num2>
00485         void fillC(const double* coords, unsigned coordLength,
00486                    const Num2& weight);
00487 
00489 
00493         template <typename Num2>
00494         void fillC(const Num2& weight);
00495 
00496         template <typename Num2>
00497         void fillC(double x0, const Num2& weight);
00498         
00499         template <typename Num2>
00500         void fillC(double x0, double x1, const Num2& weight);
00501         
00502         template <typename Num2>
00503         void fillC(double x0, double x1, double x2, const Num2& weight);
00504         
00505         template <typename Num2>
00506         void fillC(double x0, double x1, double x2, double x3,
00507                    const Num2& weight);
00508         
00509         template <typename Num2>
00510         void fillC(double x0, double x1, double x2, double x3, double x4,
00511                    const Num2& weight);
00512         
00513         template <typename Num2>
00514         void fillC(double x0, double x1, double x2, double x3, double x4,
00515                    double x5, const Num2& weight);
00516         
00517         template <typename Num2>
00518         void fillC(double x0, double x1, double x2, double x3, double x4,
00519                    double x5, double x6, const Num2& weight);
00520         
00521         template <typename Num2>
00522         void fillC(double x0, double x1, double x2, double x3, double x4,
00523                    double x5, double x6, double x7, const Num2& weight);
00524 
00525         template <typename Num2>
00526         void fillC(double x0, double x1, double x2, double x3, double x4,
00527                    double x5, double x6, double x7, double x8,
00528                    const Num2& weight);
00529         
00530         template <typename Num2>
00531         void fillC(double x0, double x1, double x2, double x3, double x4,
00532                    double x5, double x6, double x7, double x8, double x9,
00533                    const Num2& weight);
00535 
00540         template <typename Num2>
00541         HistoND& operator+=(const HistoND<Num2,Axis>& r);
00542 
00552         template <typename Num2>
00553         HistoND& operator-=(const HistoND<Num2,Axis>& r);
00554 
00556 
00557         template <typename Num2>
00558         void setBin(const unsigned *index, unsigned indexLen, const Num2& v);
00559 
00560         template <typename Num2>
00561         void setBin(const Num2& v);
00562 
00563         template <typename Num2>
00564         void setBin(unsigned i0, const Num2& v);
00565 
00566         template <typename Num2>
00567         void setBin(unsigned i0, unsigned i1, const Num2& v);
00568 
00569         template <typename Num2>
00570         void setBin(unsigned i0, unsigned i1, unsigned i2, const Num2& v);
00571 
00572         template <typename Num2>
00573         void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00574                     const Num2& v);
00575 
00576         template <typename Num2>
00577         void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00578                     unsigned i4, const Num2& v);
00579 
00580         template <typename Num2>
00581         void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00582                     unsigned i4, unsigned i5, const Num2& v);
00583 
00584         template <typename Num2>
00585         void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00586                     unsigned i4, unsigned i5, unsigned i6, const Num2& v);
00587 
00588         template <typename Num2>
00589         void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00590                     unsigned i4, unsigned i5, unsigned i6, unsigned i7,
00591                     const Num2& v);
00592 
00593         template <typename Num2>
00594         void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00595                     unsigned i4, unsigned i5, unsigned i6, unsigned i7,
00596                     unsigned i8, const Num2& v);
00597 
00598         template <typename Num2>
00599         void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00600                     unsigned i4, unsigned i5, unsigned i6, unsigned i7,
00601                     unsigned i8, unsigned i9, const Num2& v);
00602 
00603         template <typename Num2>
00604         inline void setLinearBin(const unsigned long index, const Num2& v)
00605             {data_.linearValue(index) = v; ++modCount_;}
00607 
00609 
00610         template <typename Num2>
00611         void setBinAt(const unsigned *index, unsigned indexLen, const Num2& v);
00612 
00613         template <typename Num2>
00614         void setBinAt(const Num2& v);
00615 
00616         template <typename Num2>
00617         void setBinAt(unsigned i0, const Num2& v);
00618 
00619         template <typename Num2>
00620         void setBinAt(unsigned i0, unsigned i1, const Num2& v);
00621 
00622         template <typename Num2>
00623         void setBinAt(unsigned i0, unsigned i1, unsigned i2, const Num2& v);
00624 
00625         template <typename Num2>
00626         void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00627                       const Num2& v);
00628 
00629         template <typename Num2>
00630         void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00631                       unsigned i4, const Num2& v);
00632 
00633         template <typename Num2>
00634         void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00635                       unsigned i4, unsigned i5, const Num2& v);
00636 
00637         template <typename Num2>
00638         void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00639                       unsigned i4, unsigned i5, unsigned i6, const Num2& v);
00640 
00641         template <typename Num2>
00642         void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00643                       unsigned i4, unsigned i5, unsigned i6, unsigned i7,
00644                       const Num2& v);
00645 
00646         template <typename Num2>
00647         void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00648                       unsigned i4, unsigned i5, unsigned i6, unsigned i7,
00649                       unsigned i8, const Num2& v);
00650 
00651         template <typename Num2>
00652         void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
00653                       unsigned i4, unsigned i5, unsigned i6, unsigned i7,
00654                       unsigned i8, unsigned i9, const Num2& v);
00655 
00656         template <typename Num2>
00657         inline void setLinearBinAt(const unsigned long index, const Num2& v)
00658             {data_.linearValueAt(index) = v; ++modCount_;}
00660 
00662         template <typename Num2>
00663         void setBinContents(const Num2* data, unsigned long dataLength,
00664                             bool clearOverflows=true);
00665 
00667         template <typename Num2>
00668         void setOverflows(const Num2* data, unsigned long dataLength);
00669 
00674         template <typename Num2>
00675         inline void setBinsToConst(const Num2& value)
00676             {data_.constFill(value); ++modCount_;}
00677 
00682         template <typename Num2>
00683         inline void setOverflowsToConst(const Num2& value)
00684             {overflow_.constFill(value); ++modCount_;}
00685 
00692         void recalculateNFillsFromData();
00693 
00695 
00699         inline void setNFillsTotal(const unsigned long i)
00700             {fillCount_ = i; ++modCount_;}
00701         inline void setNFillsOver(const unsigned long i)
00702             {overCount_ = i; ++modCount_;}
00704 
00706         template <typename Num2>
00707         HistoND& operator*=(const Num2& r);
00708 
00710         template <typename Num2>
00711         HistoND& operator/=(const Num2& r);
00712 
00714 
00715         template <typename Num2>
00716         void scaleBinContents(const Num2* data, unsigned long dataLength);
00717 
00718         template <typename Num2>
00719         void scaleOverflows(const Num2* data, unsigned long dataLength);
00721 
00723 
00727         template <typename Num2>
00728         void addToBinContents(const Num2& weight);
00729 
00730         template <typename Num2>
00731         void addToOverflows(const Num2& weight);
00733 
00735 
00740         template <typename Num2>
00741         void addToBinContents(const Num2* data, unsigned long dataLength);
00742 
00743         template <typename Num2>
00744         void addToOverflows(const Num2* data, unsigned long dataLength);
00746 
00755         template <typename Acc>
00756         void accumulateBinsInBox(const BoxND<double>& box, Acc* acc) const;
00757 
00759 
00769         template <typename Num2, typename Num3>
00770         void addToProjection(HistoND<Num2,Axis>* projection,
00771                              AbsArrayProjector<Numeric,Num3>& projector,
00772                              const unsigned *projectedIndices,
00773                              unsigned nProjectedIndices) const;
00774 
00775         template <typename Num2, typename Num3>
00776         void addToProjection(HistoND<Num2,Axis>* projection,
00777                              AbsVisitor<Numeric,Num3>& projector,
00778                              const unsigned *projectedIndices,
00779                              unsigned nProjectedIndices) const;
00781 
00783         HistoND transpose(unsigned axisNum1, unsigned axisNum2) const;
00784 
00797         inline unsigned long getModCount() const {return modCount_;}
00798 
00804         inline void incrModCount() {++modCount_;}
00805 
00807 
00808         inline gs::ClassId classId() const {return gs::ClassId(*this);}
00809         bool write(std::ostream& of) const;
00811 
00812         static const char* classname();
00813         static inline unsigned version() {return 1;}
00814         static HistoND* read(const gs::ClassId& id, std::istream& in);
00815 
00816     private:
00817         HistoND();
00818 
00819         // Special constructor which speeds up the "transpose" operation.
00820         // Does not do full error checking (some of it is done in transpose).
00821         HistoND(const HistoND& r, unsigned ax1, unsigned ax2);
00822 
00823         template <typename Num2>
00824         void fillPreservingCentroid(const Num2& weight);
00825 
00826         template <typename Acc>
00827         void accumulateBinsLoop(unsigned level, const BoxND<double>& box,
00828                                 unsigned* idx, Acc* accumulator,
00829                                 double overlapFraction) const;
00830         std::string title_;
00831         std::string accumulatedDataLabel_;
00832         ArrayND<Numeric> data_;
00833         ArrayND<Numeric> overflow_;
00834         std::vector<Axis> axes_;
00835         mutable std::vector<double> weightBuf_;
00836         mutable std::vector<unsigned> indexBuf_;
00837         unsigned long fillCount_;
00838         unsigned long overCount_;
00839         unsigned long modCount_;
00840         unsigned dim_;
00841 
00842     };
00843 
00858     template <typename Histo>
00859     void convertHistoToDensity(Histo* histogram, bool knownNonNegative=false);
00860 
00866     template <typename Histo>
00867     std::vector<LinearMapper1d> densityScanHistoMap(const Histo& histo);
00868 
00879     template <typename Histo>
00880     std::vector<CircularMapper1d> convolutionHistoMap(const Histo& histo,
00881                                                       bool doubleDataRange);
00882 }
00883 
00884 #include <cassert>
00885 #include "JetMETCorrections/InterpolationTables/interface/NpstatException.h"
00886 #include <sstream>
00887 #include <climits>
00888 #include <algorithm>
00889 
00890 #include "Alignment/Geners/interface/CPP11_auto_ptr.hh"
00891 #include "Alignment/Geners/interface/binaryIO.hh"
00892 
00893 namespace npstat {
00894     namespace Private {
00895         template <class Axis>
00896         ArrayShape makeHistoShape(const std::vector<Axis>& axes)
00897         {
00898             const unsigned n = axes.size();
00899             ArrayShape result;
00900             result.reserve(n);
00901             for (unsigned i=0; i<n; ++i)
00902                 result.push_back(axes[i].nBins());
00903             return result;
00904         }
00905 
00906         template <class Axis>
00907         ArrayShape makeHistoShape(const Axis& xAxis)
00908         {
00909             ArrayShape result;
00910             result.reserve(1U);
00911             result.push_back(xAxis.nBins());
00912             return result;
00913         }
00914 
00915         template <class Axis>
00916         ArrayShape makeHistoShape(const Axis& xAxis, const Axis& yAxis)
00917         {
00918             ArrayShape result;
00919             result.reserve(2U);
00920             result.push_back(xAxis.nBins());
00921             result.push_back(yAxis.nBins());
00922             return result;
00923         }
00924 
00925         template <class Axis>
00926         ArrayShape makeHistoShape(const Axis& xAxis,
00927                                   const Axis& yAxis,
00928                                   const Axis& zAxis)
00929         {
00930             ArrayShape result;
00931             result.reserve(3U);
00932             result.push_back(xAxis.nBins());
00933             result.push_back(yAxis.nBins());
00934             result.push_back(zAxis.nBins());
00935             return result;
00936         }
00937 
00938         template <class Axis>
00939         ArrayShape makeHistoShape(const Axis& xAxis, const Axis& yAxis,
00940                                   const Axis& zAxis, const Axis& tAxis)
00941         {
00942             ArrayShape result;
00943             result.reserve(4U);
00944             result.push_back(xAxis.nBins());
00945             result.push_back(yAxis.nBins());
00946             result.push_back(zAxis.nBins());
00947             result.push_back(tAxis.nBins());
00948             return result;
00949         }
00950 
00951         template <class Axis>
00952         ArrayShape makeHistoShape(const Axis& xAxis, const Axis& yAxis,
00953                                   const Axis& zAxis, const Axis& tAxis,
00954                                   const Axis& vAxis)
00955         {
00956             ArrayShape result;
00957             result.reserve(5U);
00958             result.push_back(xAxis.nBins());
00959             result.push_back(yAxis.nBins());
00960             result.push_back(zAxis.nBins());
00961             result.push_back(tAxis.nBins());
00962             result.push_back(vAxis.nBins());
00963             return result;
00964         }
00965 
00966         template <class Axis>
00967         std::vector<Axis> axesOfASlice(const std::vector<Axis>& axes,
00968                                        const unsigned *fixedIndices,
00969                                        const unsigned nFixedIndices)
00970         {
00971             const unsigned dim = axes.size();
00972             std::vector<Axis> newAxes;
00973             if (nFixedIndices == 0U) throw npstat::NpstatInvalidArgument(
00974                 "In npstat::Private::axesOfASlice: "
00975                 "at least one fixed index must be specified");
00976             if (nFixedIndices > dim) throw npstat::NpstatInvalidArgument(
00977                 "In npstat::Private::axesOfASlice: too many fixed indices");
00978             assert(fixedIndices);
00979             for (unsigned i=0; i<nFixedIndices; ++i)
00980                if (fixedIndices[i] >= dim) throw npstat::NpstatInvalidArgument(
00981                   "In npstat::Private::axesOfASlice: fixed index out of range");
00982             newAxes.reserve(dim - nFixedIndices);
00983             for (unsigned i=0; i<dim; ++i)
00984             {
00985                 bool fixed = false;
00986                 for (unsigned j=0; j<nFixedIndices; ++j)
00987                     if (fixedIndices[j] == i)
00988                     {
00989                         fixed = true;
00990                         break;
00991                     }
00992                 if (!fixed)
00993                     newAxes.push_back(axes[i]);
00994             }
00995             if (newAxes.size() != dim - nFixedIndices)
00996                 throw npstat::NpstatInvalidArgument(
00997                     "In npstat::Private::axesOfASlice: duplicate fixed index");
00998             return newAxes;
00999         }
01000 
01001         template <class Axis>
01002         ArrayShape shapeOfASlice(const std::vector<Axis>& axes,
01003                                  const unsigned *fixedIndices,
01004                                  const unsigned nFixedIndices)
01005         {
01006             const unsigned dim = axes.size();
01007             if (nFixedIndices == 0U) throw npstat::NpstatInvalidArgument(
01008                 "In npstat::Private::shapeOfASlice: "
01009                 "at least one fixed index must be specified");
01010             if (nFixedIndices > dim) throw npstat::NpstatInvalidArgument(
01011                 "In npstat::Private::shapeOfASlice: too many fixed indices");
01012             assert(fixedIndices);
01013 
01014             // Check that the fixed indices are within range
01015             for (unsigned j=0; j<nFixedIndices; ++j)
01016               if (fixedIndices[j] >= dim) throw npstat::NpstatInvalidArgument(
01017                 "In npstat::Private::shapeOfASlice: fixed index out of range");
01018 
01019             // Build the shape for the slice
01020             ArrayShape sh;
01021             if (nFixedIndices < dim)
01022                 sh.reserve(dim - nFixedIndices);
01023             for (unsigned i=0; i<dim; ++i)
01024             {
01025                 bool fixed = false;
01026                 for (unsigned j=0; j<nFixedIndices; ++j)
01027                     if (fixedIndices[j] == i)
01028                     {
01029                         fixed = true;
01030                         break;
01031                     }
01032                 if (!fixed)
01033                     sh.push_back(axes[i].nBins());
01034             }
01035             if (sh.size() != dim - nFixedIndices)
01036                 throw npstat::NpstatInvalidArgument(
01037                     "In npstat::Private::shapeOfASlice: duplicate fixed index");
01038             return sh;
01039         }
01040 
01041         template <class Axis>
01042         std::vector<Axis> addAxis(const std::vector<Axis>& axes,
01043                                   const Axis& newAxis,
01044                                   const unsigned newAxisNumber)
01045         {
01046             const unsigned dim = axes.size();
01047             std::vector<Axis> newAxes;
01048             newAxes.reserve(dim + 1U);
01049             unsigned iadd = 0;
01050             for (unsigned i=0; i<dim; ++i)
01051             {
01052                 if (newAxisNumber == i)
01053                     newAxes.push_back(newAxis);
01054                 else
01055                     newAxes.push_back(axes[iadd++]);
01056             }
01057             if (iadd == dim)
01058                 newAxes.push_back(newAxis);
01059             else
01060                 newAxes.push_back(axes[iadd]);
01061             return newAxes;
01062         }
01063 
01064         template <class Axis>
01065         ArrayShape shapeWithExtraAxis(const std::vector<Axis>& axes,
01066                                       const Axis& newAxis,
01067                                       const unsigned newAxisNumber)
01068         {
01069             const unsigned dim = axes.size();
01070             ArrayShape result;
01071             result.reserve(dim + 1U);
01072             unsigned iadd = 0;
01073             for (unsigned i=0; i<dim; ++i)
01074             {
01075                 if (newAxisNumber == i)
01076                     result.push_back(newAxis.nBins());
01077                 else
01078                     result.push_back(axes[iadd++].nBins());
01079             }
01080             if (iadd == dim)
01081                 result.push_back(newAxis.nBins());
01082             else
01083                 result.push_back(axes[iadd].nBins());
01084             return result;
01085         }
01086 
01087         inline void h_badargs(const char* method)
01088         {
01089             std::ostringstream os;
01090             os << "In npstat::HistoND::" << method << ": number of arguments"
01091                << " is incompatible with histogram dimensionality";
01092             throw npstat::NpstatInvalidArgument(os.str());
01093         }
01094     }
01095 
01096     template <typename Numeric, class Axis>
01097     template <typename Acc>
01098     void HistoND<Numeric,Axis>::accumulateBinsLoop(
01099         const unsigned level, const BoxND<double>& box,
01100         unsigned* idx, Acc* accumulator, const double overlapFraction) const
01101     {
01102         const Interval<double>& boxSide(box[level]);
01103         const Axis& axis(axes_[level]);
01104         const unsigned nbins = axis.nBins();
01105         const bool lastLevel = level == dim_ - 1U;
01106         for (unsigned i=0; i<nbins; ++i)
01107         {
01108             const double over = overlapFraction*
01109                 axis.binInterval(i).overlapFraction(boxSide);
01110             if (over > 0.0)
01111             {
01112                 idx[level] = i;
01113                 if (lastLevel)
01114                     *accumulator += over*data_.value(idx, dim_);
01115                 else
01116                     accumulateBinsLoop(level+1U, box, idx, accumulator, over);
01117             }
01118         }
01119     }
01120 
01121     template <typename Numeric, class Axis>
01122     template <typename Acc>
01123     void HistoND<Numeric,Axis>::accumulateBinsInBox(
01124         const BoxND<double>& box, Acc* accumulator) const
01125     {
01126         if (box.size() != dim_) throw npstat::NpstatInvalidArgument(
01127             "In npstat::HistoND::accumulateBinsInBox: "
01128             "incompatible box dimensionality");
01129         assert(accumulator);
01130         if (dim_)
01131         {
01132             for (unsigned i=0; i<dim_; ++i)
01133                 indexBuf_[i] = 0U;
01134             accumulateBinsLoop(0U, box, &indexBuf_[0], accumulator, 1.0);
01135         }
01136         else
01137             *accumulator += 1.0*data_();
01138     }
01139 
01140     template <typename Numeric, class Axis>
01141     inline void HistoND<Numeric,Axis>::clearBinContents()
01142     {
01143         data_.clear();
01144         fillCount_ = 0UL;
01145         ++modCount_;
01146     }
01147 
01148     template <typename Numeric, class Axis>
01149     inline void HistoND<Numeric,Axis>::clearOverflows()
01150     {
01151         overflow_.clear();
01152         overCount_ = 0UL;
01153         ++modCount_;
01154     }
01155 
01156     template <typename Numeric, class Axis>
01157     inline void HistoND<Numeric,Axis>::clear()
01158     {
01159         clearBinContents();
01160         clearOverflows();
01161         ++modCount_;
01162     }
01163 
01164     template <typename Numeric, class Axis>
01165     HistoND<Numeric,Axis>::HistoND(const std::vector<Axis>& axesIn,
01166                                    const char* title, const char* label)
01167         : title_(title ? title : ""),
01168           accumulatedDataLabel_(label ? label : ""),
01169           data_(Private::makeHistoShape(axesIn)),
01170           overflow_(ArrayShape(axesIn.size(), 3U)),
01171           axes_(axesIn),
01172           weightBuf_(axesIn.size()),
01173           indexBuf_(2U*axesIn.size()),
01174           modCount_(0UL),
01175           dim_(axesIn.size())
01176     {
01177         if (dim_ >= CHAR_BIT*sizeof(unsigned long))
01178             throw npstat::NpstatInvalidArgument(
01179                 "In npstat::HistoND constructor: requested histogram "
01180                 "dimensionality is not supported (too large)");
01181         clear();
01182     }
01183 
01184     template <typename Numeric, class Axis>
01185     HistoND<Numeric,Axis>::HistoND(const Axis& xAxis,
01186                                    const char* title, const char* label)
01187         : title_(title ? title : ""),
01188           accumulatedDataLabel_(label ? label : ""),
01189           data_(Private::makeHistoShape(xAxis)),
01190           overflow_(ArrayShape(1U, 3U)),
01191           weightBuf_(1U),
01192           indexBuf_(2U*1U),
01193           modCount_(0UL),
01194           dim_(1U)
01195     {
01196         axes_.reserve(dim_);
01197         axes_.push_back(xAxis);
01198         clear();
01199     }
01200 
01201     template <typename Numeric, class Axis>
01202     HistoND<Numeric,Axis>::HistoND(const Axis& xAxis, const Axis& yAxis,
01203                                    const char* title, const char* label)
01204         : title_(title ? title : ""),
01205           accumulatedDataLabel_(label ? label : ""),
01206           data_(Private::makeHistoShape(xAxis, yAxis)),
01207           overflow_(ArrayShape(2U, 3U)),
01208           weightBuf_(2U),
01209           indexBuf_(2U*2U),
01210           modCount_(0UL),
01211           dim_(2U)
01212     {
01213         axes_.reserve(dim_);
01214         axes_.push_back(xAxis);
01215         axes_.push_back(yAxis);
01216         clear();
01217     }
01218 
01219     template <typename Numeric, class Axis>
01220     HistoND<Numeric,Axis>::HistoND(const Axis& xAxis, const Axis& yAxis,
01221                                    const Axis& zAxis, const char* title,
01222                                    const char* label)
01223         : title_(title ? title : ""),
01224           accumulatedDataLabel_(label ? label : ""),
01225           data_(Private::makeHistoShape(xAxis, yAxis, zAxis)),
01226           overflow_(ArrayShape(3U, 3U)),
01227           weightBuf_(3U),
01228           indexBuf_(2U*3U),
01229           modCount_(0UL),
01230           dim_(3U)
01231     {
01232         axes_.reserve(dim_);
01233         axes_.push_back(xAxis);
01234         axes_.push_back(yAxis);
01235         axes_.push_back(zAxis);
01236         clear();
01237     }
01238 
01239     template <typename Numeric, class Axis>
01240     HistoND<Numeric,Axis>::HistoND(const Axis& xAxis, const Axis& yAxis,
01241                                    const Axis& zAxis, const Axis& tAxis,
01242                                    const char* title, const char* label)
01243         : title_(title ? title : ""),
01244           accumulatedDataLabel_(label ? label : ""),
01245           data_(Private::makeHistoShape(xAxis, yAxis, zAxis, tAxis)),
01246           overflow_(ArrayShape(4U, 3U)),
01247           weightBuf_(4U),
01248           indexBuf_(2U*4U),
01249           modCount_(0UL),
01250           dim_(4U)
01251     {
01252         axes_.reserve(dim_);
01253         axes_.push_back(xAxis);
01254         axes_.push_back(yAxis);
01255         axes_.push_back(zAxis);
01256         axes_.push_back(tAxis);
01257         clear();
01258     }
01259 
01260     template <typename Numeric, class Axis>
01261     HistoND<Numeric,Axis>::HistoND(const Axis& xAxis, const Axis& yAxis,
01262                                    const Axis& zAxis, const Axis& tAxis,
01263                                    const Axis& vAxis,
01264                                    const char* title, const char* label)
01265         : title_(title ? title : ""),
01266           accumulatedDataLabel_(label ? label : ""),
01267           data_(Private::makeHistoShape(xAxis, yAxis, zAxis, tAxis, vAxis)),
01268           overflow_(ArrayShape(5U, 3U)),
01269           weightBuf_(5U),
01270           indexBuf_(2U*5U),
01271           modCount_(0UL),
01272           dim_(5U)
01273     {
01274         axes_.reserve(dim_);
01275         axes_.push_back(xAxis);
01276         axes_.push_back(yAxis);
01277         axes_.push_back(zAxis);
01278         axes_.push_back(tAxis);
01279         axes_.push_back(vAxis);
01280         clear();
01281     }
01282 
01283     template <typename Numeric, class Axis>
01284     HistoND<Numeric,Axis>::HistoND(const ArrayShape& shape,
01285                                    const BoxND<double>& boundingBox,
01286                                    const char* title, const char* label)
01287         : title_(title ? title : ""),
01288           accumulatedDataLabel_(label ? label : ""),
01289           data_(shape),
01290           overflow_(ArrayShape(shape.size(), 3U)),
01291           weightBuf_(shape.size()),
01292           indexBuf_(2U*shape.size()),
01293           modCount_(0UL),
01294           dim_(shape.size())
01295     {
01296         if (boundingBox.size() != dim_) throw npstat::NpstatInvalidArgument(
01297             "In npstat::HistoND constructor: "
01298             "incompatible bounding box dimensionality");
01299         if (dim_ >= CHAR_BIT*sizeof(unsigned long))
01300             throw npstat::NpstatInvalidArgument(
01301                 "In npstat::HistoND constructor: requested histogram "
01302                 "dimensionality is not supported (too large)");
01303         axes_.reserve(dim_);
01304         for (unsigned i=0; i<dim_; ++i)
01305             axes_.push_back(Axis(shape[i],
01306                                  boundingBox[i].min(),
01307                                  boundingBox[i].max()));
01308         clear();
01309     }
01310 
01311     template <typename Numeric, class Axis>
01312     template <typename Num2, class Functor>
01313     HistoND<Numeric,Axis>::HistoND(
01314         const HistoND<Num2,Axis>& r, const Functor& f,
01315         const char* title, const char* label)
01316         : title_(title ? title : ""),
01317           accumulatedDataLabel_(label ? label : ""),
01318           data_(r.data_, f),
01319           overflow_(r.overflow_, f),
01320           axes_(r.axes_),
01321           weightBuf_(r.dim_),
01322           indexBuf_(2U*r.dim_),
01323           fillCount_(r.fillCount_),
01324           overCount_(r.overCount_),
01325           modCount_(0UL),
01326           dim_(r.dim_)
01327     {
01328     }
01329 
01330     template <typename Numeric, class Axis>
01331     template <typename Num2>
01332     HistoND<Numeric,Axis>::HistoND(
01333         const HistoND<Num2,Axis>& h, const unsigned *indices,
01334         const unsigned nIndices, const char* title)
01335         : title_(title ? title : ""),
01336           accumulatedDataLabel_(h.accumulatedDataLabel_),
01337           data_(Private::shapeOfASlice(h.axes_, indices, nIndices)),
01338           overflow_(ArrayShape(data_.rank(), 3U)),
01339           axes_(Private::axesOfASlice(h.axes_, indices, nIndices)),
01340           weightBuf_(data_.rank()),
01341           indexBuf_(2U*data_.rank()),
01342           modCount_(0UL),
01343           dim_(data_.rank())
01344     {
01345         clear();
01346     }
01347 
01348     template <typename Numeric, class Axis>
01349     template <typename Num2>
01350     HistoND<Numeric,Axis>::HistoND(
01351         const HistoND<Num2,Axis>& h, const Axis& newAxis,
01352         const unsigned newAxisNumber, const char* title)
01353         : title_(title ? title : ""),
01354           accumulatedDataLabel_(h.accumulatedDataLabel_),
01355           data_(Private::shapeWithExtraAxis(h.axes_, newAxis, newAxisNumber)),
01356           overflow_(data_.rank(), 3U),
01357           axes_(Private::addAxis(h.axes_, newAxis, newAxisNumber)),
01358           weightBuf_(data_.rank()),
01359           indexBuf_(2U*data_.rank()),
01360           modCount_(0UL),
01361           dim_(data_.rank())
01362     {
01363         if (dim_ >= CHAR_BIT*sizeof(unsigned long))
01364             throw npstat::NpstatInvalidArgument(
01365                 "In npstat::HistoND constructor: requested histogram "
01366                 "dimensionality is not supported (too large)");
01367         clear();
01368     }
01369 
01370     template <typename Numeric, class Axis>
01371     bool HistoND<Numeric,Axis>::isUniformlyBinned() const
01372     {
01373         for (unsigned i=0; i<dim_; ++i)
01374             if (!axes_[i].isUniform())
01375                 return false;
01376         return true;
01377     }
01378 
01379     template <typename Numeric, class Axis>
01380     double HistoND<Numeric,Axis>::integral() const
01381     {
01382         typedef typename PreciseType<Numeric>::type Precise;
01383 
01384         if (dim_ == 0U)
01385             return 0.0;
01386         if (isUniformlyBinned())
01387         {
01388             Precise sum = data_.template sum<Precise>();
01389             return static_cast<double>(sum)*binVolume();
01390         }
01391         else
01392         {
01393             Precise sum = Precise();
01394             const Numeric* data = data_.data();
01395             const unsigned long len = data_.length();
01396             for (unsigned long i=0; i<len; ++i)
01397                 sum += data[i]*binVolume(i);
01398             return static_cast<double>(sum);
01399         }
01400     }
01401 
01402     template <typename Numeric, class Axis>
01403     BoxND<double> HistoND<Numeric,Axis>::boundingBox() const
01404     {
01405         BoxND<double> box;
01406         if (dim_)
01407         {
01408             box.reserve(dim_);
01409             const Axis* ax = &axes_[0];
01410             for (unsigned i=0; i<dim_; ++i)
01411                 box.push_back(ax[i].interval());
01412         }
01413         return box;
01414     }
01415 
01416     template <typename Numeric, class Axis>
01417     void HistoND<Numeric,Axis>::binCenter(
01418         const unsigned long binNumber,
01419         double* coords, const unsigned lenCoords) const
01420     {
01421         if (dim_ != lenCoords) throw npstat::NpstatInvalidArgument(
01422             "In npstat::HistoND::binCenter: "
01423             "incompatible input point dimensionality");
01424         if (dim_)
01425         {
01426             assert(coords);
01427             data_.convertLinearIndex(binNumber, &indexBuf_[0], dim_);
01428             const Axis* ax = &axes_[0];
01429             for (unsigned i=0; i<dim_; ++i)
01430                 coords[i] = ax[i].binCenter(indexBuf_[i]);
01431         }
01432     }
01433 
01434     template <typename Numeric, class Axis>
01435     template <class Point>
01436     void HistoND<Numeric,Axis>::allBinCenters(
01437         std::vector<Point>* centers) const
01438     {
01439         assert(centers);
01440         centers->clear();
01441         const unsigned long len = data_.length();
01442         centers->reserve(len);
01443         unsigned* ibuf = &indexBuf_[0];
01444         const Axis* ax = &axes_[0];
01445         Point center;
01446         if (center.size() < dim_) throw npstat::NpstatInvalidArgument(
01447             "In npstat::HistoND::allBinCenters: "
01448             "incompatible point dimensionality (too small)");
01449         typename Point::value_type* cdat = &center[0];
01450 
01451         for (unsigned long i=0; i<len; ++i)
01452         {
01453             data_.convertLinearIndex(i, ibuf, dim_);
01454             for (unsigned idim=0; idim<dim_; ++idim)
01455                 cdat[idim] = ax[idim].binCenter(ibuf[idim]);
01456             centers->push_back(center);
01457         }
01458     }
01459 
01460     template <typename Numeric, class Axis>
01461     void HistoND<Numeric,Axis>::binBox(const unsigned long binNumber,
01462                                        BoxND<double>* box) const
01463     {
01464         assert(box);
01465         box->clear();
01466         if (dim_)
01467         {
01468             box->reserve(dim_);
01469             data_.convertLinearIndex(binNumber, &indexBuf_[0], dim_);
01470             const Axis* ax = &axes_[0];
01471             for (unsigned i=0; i<dim_; ++i)
01472                 box->push_back(ax[i].binInterval(indexBuf_[i]));
01473         }
01474     }
01475 
01476     template <typename Numeric, class Axis>
01477     inline bool HistoND<Numeric,Axis>::isSameData(const HistoND& r) const
01478     {
01479         return dim_ == r.dim_ &&
01480                overflow_ == r.overflow_ &&
01481                data_ == r.data_;
01482     }
01483 
01484     template <typename Numeric, class Axis>
01485     inline bool HistoND<Numeric,Axis>::operator==(const HistoND& r) const
01486     {
01487         return dim_ == r.dim_ &&
01488                fillCount_ == r.fillCount_ &&
01489                overCount_ == r.overCount_ &&
01490                title_ == r.title_ &&
01491                accumulatedDataLabel_ == r.accumulatedDataLabel_ &&
01492                axes_ == r.axes_ &&
01493                overflow_ == r.overflow_ &&
01494                data_ == r.data_;
01495     }
01496 
01497     template <typename Numeric, class Axis>
01498     inline bool HistoND<Numeric,Axis>::operator!=(const HistoND& r) const
01499     {
01500         return !(*this == r);
01501     }
01502 
01503     template <typename Numeric, class Axis>
01504     double HistoND<Numeric,Axis>::binVolume(
01505         const unsigned long binNumber) const
01506     {
01507         double v = 1.0;
01508         if (dim_)
01509         {
01510             data_.convertLinearIndex(binNumber, &indexBuf_[0], dim_);
01511             const Axis* ax = &axes_[0];
01512             for (unsigned i=0; i<dim_; ++i)
01513                 v *= ax[i].binWidth(indexBuf_[i]);
01514         }
01515         return v;
01516     }
01517 
01518     template <typename Numeric, class Axis>
01519     double HistoND<Numeric,Axis>::volume() const
01520     {
01521         double v = 1.0;
01522         if (dim_)
01523         {
01524             const Axis* ax = &axes_[0];
01525             for (unsigned i=0; i<dim_; ++i)
01526                 v *= (ax[i].max() - ax[i].min());
01527         }
01528         return v;
01529     }
01530 
01531     template <typename Numeric, class Axis>
01532     template <typename Num2>
01533     void HistoND<Numeric,Axis>::fill(
01534         const double* coords, const unsigned coordLength, const Num2& w)
01535     {
01536         if (coordLength != dim_) throw npstat::NpstatInvalidArgument(
01537             "In npstat::HistoND::fill: "
01538             "incompatible input point dimensionality");
01539         if (coordLength)
01540         {
01541             assert(coords);
01542             unsigned* idx = &indexBuf_[0];
01543             unsigned* over = idx + dim_;
01544             const Axis* ax = &axes_[0];
01545             unsigned overflown = 0U;
01546             for (unsigned i=0; i<dim_; ++i)
01547             {
01548                 over[i] = ax[i].overflowIndex(coords[i], idx + i);
01549                 overflown |= (over[i] - 1U);
01550             }
01551             if (overflown)
01552             {
01553                 overflow_.value(over, dim_) += w;
01554                 ++overCount_;
01555             }
01556             else
01557                 data_.value(idx, dim_) += w;
01558         }
01559         else
01560             data_() += w;
01561         ++fillCount_; ++modCount_;
01562     }
01563 
01564     template <typename Numeric, class Axis>
01565     template <typename Num2, class Functor>
01566     void HistoND<Numeric,Axis>::dispatch(
01567         const double* coords, const unsigned coordLength, Num2& w, Functor& f)
01568     {
01569         if (coordLength != dim_) throw npstat::NpstatInvalidArgument(
01570             "In npstat::HistoND::dispatch: "
01571             "incompatible input point dimensionality");
01572         if (coordLength)
01573         {
01574             assert(coords);
01575             unsigned* idx = &indexBuf_[0];
01576             unsigned* over = idx + dim_;
01577             const Axis* ax = &axes_[0];
01578             unsigned overflown = 0U;
01579             for (unsigned i=0; i<dim_; ++i)
01580             {
01581                 over[i] = ax[i].overflowIndex(coords[i], idx + i);
01582                 overflown |= (over[i] - 1U);
01583             }
01584             if (overflown)
01585                 f(overflow_.value(over, dim_), w);
01586             else
01587                 f(data_.value(idx, dim_), w);
01588         }
01589         else
01590             f(data_(), w);
01591          ++modCount_;
01592     }
01593 
01594     template <typename Numeric, class Axis>
01595     const Numeric& HistoND<Numeric,Axis>::examine(
01596         const double* coords, const unsigned coordLength) const
01597     {
01598         if (coordLength != dim_) throw npstat::NpstatInvalidArgument(
01599             "In npstat::HistoND::examine: "
01600             "incompatible input point dimensionality");
01601         if (coordLength)
01602         {
01603             assert(coords);
01604             unsigned* idx = &indexBuf_[0];
01605             unsigned* over = idx + dim_;
01606             const Axis* ax = &axes_[0];
01607             unsigned overflown = 0U;
01608             for (unsigned i=0; i<dim_; ++i)
01609             {
01610                 over[i] = ax[i].overflowIndex(coords[i], idx + i);
01611                 overflown |= (over[i] - 1U);
01612             }
01613             if (overflown)
01614                 return overflow_.value(over, dim_);
01615             else
01616                 return data_.value(idx, dim_);
01617         }
01618         else
01619             return data_();
01620     }
01621 
01622     template <typename Numeric, class Axis>
01623     const Numeric& HistoND<Numeric,Axis>::closestBin(
01624         const double* coords, const unsigned coordLength) const
01625     {
01626         if (coordLength != dim_) throw npstat::NpstatInvalidArgument(
01627             "In npstat::HistoND::closestBin: "
01628             "incompatible input point dimensionality");
01629         if (coordLength)
01630         {
01631             assert(coords);
01632             unsigned* idx = &indexBuf_[0];
01633             const Axis* ax = &axes_[0];
01634             for (unsigned i=0; i<dim_; ++i)
01635                 idx[i] = ax[i].closestValidBin(coords[i]);
01636             return data_.value(idx, dim_);
01637         }
01638         else
01639             return data_();
01640     }
01641 
01642     template <typename Numeric, class Axis>
01643     template <typename Num2>
01644     void HistoND<Numeric,Axis>::fillPreservingCentroid(const Num2& value)
01645     {
01646         const double* weights = &weightBuf_[0];
01647         const unsigned* cell = &indexBuf_[0];
01648         const unsigned long* strides = data_.strides();
01649         const unsigned long maxcycle = 1UL << dim_;
01650         for (unsigned long icycle=0; icycle<maxcycle; ++icycle)
01651         {
01652             double w = 1.0;
01653             unsigned long icell = 0UL;
01654             for (unsigned i=0; i<dim_; ++i)
01655             {
01656                 if (icycle & (1UL << i))
01657                 {
01658                     w *= (1.0 - weights[i]);
01659                     icell += strides[i]*(cell[i] + 1U);
01660                 }
01661                 else
01662                 {
01663                     w *= weights[i];
01664                     icell += strides[i]*cell[i];
01665                 }
01666             }
01667             data_.linearValue(icell) += (value * w);
01668         }
01669     }
01670 
01671     template <typename Numeric, class Axis>
01672     template <typename Num2>
01673     void HistoND<Numeric,Axis>::fillC(
01674         const double* coords, const unsigned coordLength, const Num2& w)
01675     {
01676         if (coordLength != dim_) throw npstat::NpstatInvalidArgument(
01677             "In npstat::HistoND::fillC: "
01678             "incompatible input point dimensionality");
01679         if (coordLength)
01680         {
01681             assert(coords);
01682             double* wg = &weightBuf_[0];
01683             unsigned* idx = &indexBuf_[0];
01684             unsigned* over = idx + dim_;
01685             const Axis* ax = &axes_[0];
01686             unsigned overflown = 0U;
01687             for (unsigned i=0; i<dim_; ++i)
01688             {
01689                 over[i] = ax[i].overflowIndexWeighted(coords[i], idx+i, wg+i);
01690                 overflown |= (over[i] - 1U);
01691             }
01692             if (overflown)
01693             {
01694                 overflow_.value(over, dim_) += w;
01695                 ++overCount_;
01696             }
01697             else
01698                 fillPreservingCentroid(w);
01699         }
01700         else
01701             data_() += w;
01702         ++fillCount_; ++modCount_;
01703     }
01704 
01705     template <typename Numeric, class Axis>
01706     template <typename Num2>
01707     inline void HistoND<Numeric,Axis>::fill(const Num2& w)
01708     {
01709         if (dim_) Private::h_badargs("fill");
01710         data_() += w;
01711         ++fillCount_; ++modCount_;
01712     }
01713 
01714     template <typename Numeric, class Axis>
01715     template <typename Num2, class Functor>
01716     inline void HistoND<Numeric,Axis>::dispatch(Num2& w, Functor& f)
01717     {
01718         if (dim_) Private::h_badargs("dispatch");
01719         f(data_(), w);
01720         ++modCount_;
01721     }
01722 
01723     template <typename Numeric, class Axis>
01724     template <typename Num2>
01725     inline void HistoND<Numeric,Axis>::fillC(const Num2& w)
01726     {
01727         if (dim_) Private::h_badargs("fillC");
01728         data_() += w;
01729         ++fillCount_; ++modCount_;
01730     }
01731 
01732     template <typename Numeric, class Axis>
01733     inline const Numeric& HistoND<Numeric,Axis>::examine() const
01734     {
01735         if (dim_) Private::h_badargs("examine");
01736         return data_();
01737     }
01738 
01739     template <typename Numeric, class Axis>
01740     inline const Numeric& HistoND<Numeric,Axis>::closestBin() const
01741     {
01742         if (dim_) Private::h_badargs("closestBin");
01743         return data_();
01744     }
01745 
01746     template <typename Numeric, class Axis>
01747     template <typename Num2>
01748     void HistoND<Numeric,Axis>::fill(const double x0, const Num2& w)
01749     {
01750         if (dim_ != 1U) Private::h_badargs("fill");
01751         unsigned i0;
01752         const unsigned ov0 = axes_[0].overflowIndex(x0, &i0);
01753         if (ov0 == 1U)
01754             data_(i0) += w;
01755         else
01756         {
01757             overflow_(ov0) += w;
01758             ++overCount_;
01759         }
01760         ++fillCount_; ++modCount_;
01761     }
01762 
01763     template <typename Numeric, class Axis>
01764     template <typename Num2, class Functor>
01765     void HistoND<Numeric,Axis>::dispatch(const double x0, Num2& w, Functor& f)
01766     {
01767         if (dim_ != 1U) Private::h_badargs("dispatch");
01768         unsigned i0;
01769         const unsigned ov0 = axes_[0].overflowIndex(x0, &i0);
01770         if (ov0 == 1U)
01771             f(data_(i0), w);
01772         else
01773             f(overflow_(ov0), w);
01774         ++modCount_;
01775     }
01776 
01777     template <typename Numeric, class Axis>
01778     template <typename Num2>
01779     void HistoND<Numeric,Axis>::fillC(const double x0, const Num2& w)
01780     {
01781         if (dim_ != 1U) Private::h_badargs("fillC");
01782         double* wg = &weightBuf_[0];
01783         unsigned* idx = &indexBuf_[0];
01784         const unsigned ov0 = axes_[0].overflowIndexWeighted(x0, idx, wg);
01785         if (ov0 == 1U)
01786             fillPreservingCentroid(w);
01787         else
01788         {
01789             overflow_(ov0) += w;
01790             ++overCount_;
01791         }
01792         ++fillCount_; ++modCount_;
01793     }
01794 
01795     template <typename Numeric, class Axis>
01796     inline const Numeric& HistoND<Numeric,Axis>::examine(const double x0) const
01797     {
01798         if (dim_ != 1U) Private::h_badargs("examine");
01799         unsigned i0;
01800         const unsigned ov0 = axes_[0].overflowIndex(x0, &i0);
01801         if (ov0 == 1U)
01802             return data_(i0);
01803         else
01804             return overflow_(ov0);
01805     }
01806 
01807     template <typename Numeric, class Axis>
01808     inline const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0) const
01809     {
01810         if (dim_ != 1U) Private::h_badargs("closestBin");
01811         const unsigned i0 = axes_[0].closestValidBin(x0);
01812         return data_(i0);
01813     }
01814 
01815     template <typename Numeric, class Axis>
01816     template <typename Num2>
01817     void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
01818                                      const Num2& w)
01819     {
01820         if (dim_ != 2U) Private::h_badargs("fill");
01821         unsigned i0, i1;
01822         const Axis* ax = &axes_[0];
01823         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
01824         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
01825         if (o0 == 1U && o1 == 1U)
01826             data_(i0, i1) += w;
01827         else
01828         {
01829             overflow_(o0, o1) += w;
01830             ++overCount_;
01831         }
01832         ++fillCount_; ++modCount_;
01833     }
01834 
01835     template <typename Numeric, class Axis>
01836     template <typename Num2, class Functor>
01837     void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
01838                                          Num2& w, Functor& f)
01839     {
01840         if (dim_ != 2U) Private::h_badargs("dispatch");
01841         unsigned i0, i1;
01842         const Axis* ax = &axes_[0];
01843         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
01844         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
01845         if (o0 == 1U && o1 == 1U)
01846             f(data_(i0, i1), w);
01847         else
01848             f(overflow_(o0, o1), w);
01849         ++modCount_;
01850     }
01851 
01852     template <typename Numeric, class Axis>
01853     template <typename Num2>
01854     void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
01855                                       const Num2& w)
01856     {
01857         if (dim_ != 2U) Private::h_badargs("fillC");
01858         double* wg = &weightBuf_[0];
01859         unsigned* idx = &indexBuf_[0];
01860         const Axis* ax = &axes_[0];
01861         const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
01862         const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
01863         if (o0 == 1U && o1 == 1U)
01864             fillPreservingCentroid(w);
01865         else
01866         {
01867             overflow_(o0, o1) += w;
01868             ++overCount_;
01869         }
01870         ++fillCount_; ++modCount_;
01871     }
01872 
01873     template <typename Numeric, class Axis>
01874     const Numeric& HistoND<Numeric,Axis>::examine(const double x0,
01875                                                   const double x1) const
01876     {
01877         if (dim_ != 2U) Private::h_badargs("examine");
01878         unsigned i0, i1;
01879         const Axis* ax = &axes_[0];
01880         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
01881         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
01882         if (o0 == 1U && o1 == 1U)
01883             return data_(i0, i1);
01884         else
01885             return overflow_(o0, o1);
01886     }
01887 
01888     template <typename Numeric, class Axis>
01889     const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
01890                                                      const double x1) const
01891     {
01892         if (dim_ != 2U) Private::h_badargs("closestBin");
01893         const Axis* ax = &axes_[0];
01894         const unsigned i0 = ax[0].closestValidBin(x0);
01895         const unsigned i1 = ax[1].closestValidBin(x1);
01896         return data_(i0, i1);
01897     }
01898 
01899     template <typename Numeric, class Axis>
01900     template <typename Num2>
01901     void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
01902                                      const double x2, const Num2& w)
01903     {
01904         if (dim_ != 3U) Private::h_badargs("fill");
01905         unsigned i0, i1, i2;
01906         const Axis* ax = &axes_[0];
01907         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
01908         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
01909         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
01910         if (o0 == 1U && o1 == 1U && o2 == 1U)
01911             data_(i0, i1, i2) += w;
01912         else
01913         {
01914             overflow_(o0, o1, o2) += w;
01915             ++overCount_;
01916         }
01917         ++fillCount_; ++modCount_;
01918     }
01919 
01920     template <typename Numeric, class Axis>
01921     template <typename Num2, class Functor>
01922     void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
01923                                          const double x2, Num2& w, Functor& f)
01924     {
01925         if (dim_ != 3U) Private::h_badargs("dispatch");
01926         unsigned i0, i1, i2;
01927         const Axis* ax = &axes_[0];
01928         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
01929         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
01930         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
01931         if (o0 == 1U && o1 == 1U && o2 == 1U)
01932             f(data_(i0, i1, i2), w);
01933         else
01934             f(overflow_(o0, o1, o2), w);
01935         ++modCount_;
01936     }
01937 
01938     template <typename Numeric, class Axis>
01939     template <typename Num2>
01940     void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
01941                                  const double x2, const Num2& w)
01942     {
01943         if (dim_ != 3U) Private::h_badargs("fillC");
01944         double* wg = &weightBuf_[0];
01945         unsigned* idx = &indexBuf_[0];
01946         const Axis* ax = &axes_[0];
01947         const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
01948         const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
01949         const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
01950         if (o0 == 1U && o1 == 1U && o2 == 1U)
01951             fillPreservingCentroid(w);
01952         else
01953         {
01954             overflow_(o0, o1, o2) += w;
01955             ++overCount_;
01956         }
01957         ++fillCount_; ++modCount_;
01958     }
01959 
01960     template <typename Numeric, class Axis>
01961     const Numeric& HistoND<Numeric,Axis>::examine(const double x0,
01962                                                   const double x1,
01963                                                   const double x2) const
01964     {
01965         if (dim_ != 3U) Private::h_badargs("examine");
01966         unsigned i0, i1, i2;
01967         const Axis* ax = &axes_[0];
01968         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
01969         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
01970         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
01971         if (o0 == 1U && o1 == 1U && o2 == 1U)
01972             return data_(i0, i1, i2);
01973         else
01974             return overflow_(o0, o1, o2);
01975     }
01976 
01977     template <typename Numeric, class Axis>
01978     const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
01979                                                      const double x1,
01980                                                      const double x2) const
01981     {
01982         if (dim_ != 3U) Private::h_badargs("closestBin");
01983         const Axis* ax = &axes_[0];
01984         const unsigned i0 = ax[0].closestValidBin(x0);
01985         const unsigned i1 = ax[1].closestValidBin(x1);
01986         const unsigned i2 = ax[2].closestValidBin(x2);
01987         return data_(i0, i1, i2);
01988     }
01989 
01990     template <typename Numeric, class Axis>
01991     template <typename Num2>
01992     void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
01993                                      const double x2, const double x3,
01994                                      const Num2& w)
01995     {
01996         if (dim_ != 4U) Private::h_badargs("fill");
01997         unsigned i0, i1, i2, i3;
01998         const Axis* ax = &axes_[0];
01999         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02000         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02001         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02002         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02003         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U)
02004             data_(i0, i1, i2, i3) += w;
02005         else
02006         {
02007             overflow_(o0, o1, o2, o3) += w;
02008             ++overCount_;
02009         }
02010         ++fillCount_; ++modCount_;
02011     }
02012 
02013     template <typename Numeric, class Axis>
02014     template <typename Num2, class Functor>
02015     void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
02016                                          const double x2, const double x3,
02017                                          Num2& w, Functor& f)
02018     {
02019         if (dim_ != 4U) Private::h_badargs("dispatch");
02020         unsigned i0, i1, i2, i3;
02021         const Axis* ax = &axes_[0];
02022         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02023         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02024         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02025         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02026         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U)
02027             f(data_(i0, i1, i2, i3), w);
02028         else
02029             f(overflow_(o0, o1, o2, o3), w);
02030         ++modCount_;
02031     }
02032 
02033     template <typename Numeric, class Axis>
02034     template <typename Num2>
02035     void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
02036                                       const double x2, const double x3,
02037                                       const Num2& w)
02038     {
02039         if (dim_ != 4U) Private::h_badargs("fillC");
02040         double* wg = &weightBuf_[0];
02041         unsigned* idx = &indexBuf_[0];
02042         const Axis* ax = &axes_[0];
02043         const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
02044         const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
02045         const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
02046         const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
02047         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U)
02048             fillPreservingCentroid(w);
02049         else
02050         {
02051             overflow_(o0, o1, o2, o3) += w;
02052             ++overCount_;
02053         }
02054         ++fillCount_; ++modCount_;
02055     }
02056 
02057     template <typename Numeric, class Axis>
02058     const Numeric& HistoND<Numeric,Axis>::examine(const double x0,
02059                                                   const double x1,
02060                                                   const double x2,
02061                                                   const double x3) const
02062     {
02063         if (dim_ != 4U) Private::h_badargs("examine");
02064         unsigned i0, i1, i2, i3;
02065         const Axis* ax = &axes_[0];
02066         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02067         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02068         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02069         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02070         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U)
02071             return data_(i0, i1, i2, i3);
02072         else
02073             return overflow_(o0, o1, o2, o3);
02074     }
02075 
02076     template <typename Numeric, class Axis>
02077     const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
02078                                                      const double x1,
02079                                                      const double x2,
02080                                                      const double x3) const
02081     {
02082         if (dim_ != 4U) Private::h_badargs("closestBin");
02083         const Axis* ax = &axes_[0];
02084         const unsigned i0 = ax[0].closestValidBin(x0);
02085         const unsigned i1 = ax[1].closestValidBin(x1);
02086         const unsigned i2 = ax[2].closestValidBin(x2);
02087         const unsigned i3 = ax[3].closestValidBin(x3);
02088         return data_(i0, i1, i2, i3);
02089     }
02090 
02091     template <typename Numeric, class Axis>
02092     template <typename Num2>
02093     void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
02094                                      const double x2, const double x3,
02095                                      const double x4, const Num2& w)
02096     {
02097         if (dim_ != 5U) Private::h_badargs("fill");
02098         unsigned i0, i1, i2, i3, i4;
02099         const Axis* ax = &axes_[0];
02100         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02101         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02102         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02103         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02104         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02105         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U)
02106             data_(i0, i1, i2, i3, i4) += w;
02107         else
02108         {
02109             overflow_(o0, o1, o2, o3, o4) += w;
02110             ++overCount_;
02111         }
02112         ++fillCount_; ++modCount_;
02113     }
02114 
02115     template <typename Numeric, class Axis>
02116     template <typename Num2, class Functor>
02117     void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
02118                                          const double x2, const double x3,
02119                                          const double x4, Num2& w, Functor& f)
02120     {
02121         if (dim_ != 5U) Private::h_badargs("dispatch");
02122         unsigned i0, i1, i2, i3, i4;
02123         const Axis* ax = &axes_[0];
02124         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02125         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02126         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02127         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02128         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02129         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U)
02130             f(data_(i0, i1, i2, i3, i4), w);
02131         else
02132             f(overflow_(o0, o1, o2, o3, o4), w);
02133         ++modCount_;
02134     }
02135 
02136     template <typename Numeric, class Axis>
02137     template <typename Num2>
02138     void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
02139                                       const double x2, const double x3,
02140                                       const double x4, const Num2& w)
02141     {
02142         if (dim_ != 5U) Private::h_badargs("fillC");
02143         double* wg = &weightBuf_[0];
02144         unsigned* idx = &indexBuf_[0];
02145         const Axis* ax = &axes_[0];
02146         const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
02147         const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
02148         const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
02149         const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
02150         const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
02151         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U)
02152             fillPreservingCentroid(w);
02153         else
02154         {
02155             overflow_(o0, o1, o2, o3, o4) += w;
02156             ++overCount_;
02157         }
02158         ++fillCount_; ++modCount_;
02159     }
02160 
02161     template <typename Numeric, class Axis>
02162     const Numeric& HistoND<Numeric,Axis>::examine(
02163         const double x0, const double x1,
02164         const double x2, const double x3,
02165         const double x4) const
02166     {
02167         if (dim_ != 5U) Private::h_badargs("examine");
02168         unsigned i0, i1, i2, i3, i4;
02169         const Axis* ax = &axes_[0];
02170         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02171         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02172         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02173         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02174         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02175         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U)
02176             return data_(i0, i1, i2, i3, i4);
02177         else
02178             return overflow_(o0, o1, o2, o3, o4);
02179     }
02180 
02181     template <typename Numeric, class Axis>
02182     const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
02183                                                      const double x1,
02184                                                      const double x2,
02185                                                      const double x3,
02186                                                      const double x4) const
02187     {
02188         if (dim_ != 5U) Private::h_badargs("closestBin");
02189         const Axis* ax = &axes_[0];
02190         const unsigned i0 = ax[0].closestValidBin(x0);
02191         const unsigned i1 = ax[1].closestValidBin(x1);
02192         const unsigned i2 = ax[2].closestValidBin(x2);
02193         const unsigned i3 = ax[3].closestValidBin(x3);
02194         const unsigned i4 = ax[4].closestValidBin(x4);
02195         return data_(i0, i1, i2, i3, i4);
02196     }
02197 
02198     template <typename Numeric, class Axis>
02199     template <typename Num2>
02200     void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
02201                                      const double x2, const double x3,
02202                                      const double x4, const double x5,
02203                                      const Num2& w)
02204     {
02205         if (dim_ != 6U) Private::h_badargs("fill");
02206         unsigned i0, i1, i2, i3, i4, i5;
02207         const Axis* ax = &axes_[0];
02208         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02209         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02210         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02211         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02212         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02213         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02214         if (o0 == 1U && o1 == 1U && o2 == 1U &&
02215             o3 == 1U && o4 == 1U && o5 == 1U)
02216             data_(i0, i1, i2, i3, i4, i5) += w;
02217         else
02218         {
02219             overflow_(o0, o1, o2, o3, o4, o5) += w;
02220             ++overCount_;
02221         }
02222         ++fillCount_; ++modCount_;
02223     }
02224     
02225     template <typename Numeric, class Axis>
02226     template <typename Num2, class Functor>
02227     void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
02228                                          const double x2, const double x3,
02229                                          const double x4, const double x5,
02230                                          Num2& w, Functor& f)
02231     {
02232         if (dim_ != 6U) Private::h_badargs("dispatch");
02233         unsigned i0, i1, i2, i3, i4, i5;
02234         const Axis* ax = &axes_[0];
02235         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02236         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02237         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02238         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02239         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02240         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02241         if (o0 == 1U && o1 == 1U && o2 == 1U &&
02242             o3 == 1U && o4 == 1U && o5 == 1U)
02243             f(data_(i0, i1, i2, i3, i4, i5), w);
02244         else
02245             f(overflow_(o0, o1, o2, o3, o4, o5), w);
02246         ++modCount_;
02247     }
02248 
02249     template <typename Numeric, class Axis>
02250     template <typename Num2>
02251     void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
02252                                       const double x2, const double x3,
02253                                       const double x4, const double x5,
02254                                       const Num2& w)
02255     {
02256         if (dim_ != 6U) Private::h_badargs("fillC");
02257         double* wg = &weightBuf_[0];
02258         unsigned* idx = &indexBuf_[0];
02259         const Axis* ax = &axes_[0];
02260         const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
02261         const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
02262         const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
02263         const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
02264         const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
02265         const unsigned o5 = ax[5].overflowIndexWeighted(x5, idx+5, wg+5);
02266         if (o0 == 1U && o1 == 1U && o2 == 1U &&
02267             o3 == 1U && o4 == 1U && o5 == 1U)
02268             fillPreservingCentroid(w);
02269         else
02270         {
02271             overflow_(o0, o1, o2, o3, o4, o5) += w;
02272             ++overCount_;
02273         }
02274         ++fillCount_; ++modCount_;
02275     }
02276     
02277     template <typename Numeric, class Axis>
02278     const Numeric& HistoND<Numeric,Axis>::examine(const double x0,
02279                                                   const double x1,
02280                                                   const double x2,
02281                                                   const double x3,
02282                                                   const double x4,
02283                                                   const double x5) const
02284     {
02285         if (dim_ != 6U) Private::h_badargs("examine");
02286         unsigned i0, i1, i2, i3, i4, i5;
02287         const Axis* ax = &axes_[0];
02288         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02289         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02290         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02291         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02292         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02293         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02294         if (o0 == 1U && o1 == 1U && o2 == 1U &&
02295             o3 == 1U && o4 == 1U && o5 == 1U)
02296             return data_(i0, i1, i2, i3, i4, i5);
02297         else
02298             return overflow_(o0, o1, o2, o3, o4, o5);
02299     }
02300 
02301     template <typename Numeric, class Axis>
02302     const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
02303                                                      const double x1,
02304                                                      const double x2,
02305                                                      const double x3,
02306                                                      const double x4,
02307                                                      const double x5) const
02308     {
02309         if (dim_ != 6U) Private::h_badargs("closestBin");
02310         const Axis* ax = &axes_[0];
02311         const unsigned i0 = ax[0].closestValidBin(x0);
02312         const unsigned i1 = ax[1].closestValidBin(x1);
02313         const unsigned i2 = ax[2].closestValidBin(x2);
02314         const unsigned i3 = ax[3].closestValidBin(x3);
02315         const unsigned i4 = ax[4].closestValidBin(x4);
02316         const unsigned i5 = ax[5].closestValidBin(x5);
02317         return data_(i0, i1, i2, i3, i4, i5);
02318     }
02319 
02320     template <typename Numeric, class Axis>
02321     template <typename Num2>
02322     void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
02323                                      const double x2, const double x3,
02324                                      const double x4, const double x5,
02325                                      const double x6, const Num2& w)
02326     {
02327         if (dim_ != 7U) Private::h_badargs("fill");
02328         unsigned i0, i1, i2, i3, i4, i5, i6;
02329         const Axis* ax = &axes_[0];
02330         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02331         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02332         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02333         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02334         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02335         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02336         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02337         if (o0 == 1U && o1 == 1U && o2 == 1U &&
02338             o3 == 1U && o4 == 1U && o5 == 1U && o6 == 1U)
02339             data_(i0, i1, i2, i3, i4, i5, i6) += w;
02340         else
02341         {
02342             overflow_(o0, o1, o2, o3, o4, o5, o6) += w;
02343             ++overCount_;
02344         }
02345         ++fillCount_; ++modCount_;
02346     }
02347 
02348     template <typename Numeric, class Axis>
02349     template <typename Num2, class Functor>
02350     void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
02351                                          const double x2, const double x3,
02352                                          const double x4, const double x5,
02353                                          const double x6, Num2& w, Functor& f)
02354     {
02355         if (dim_ != 7U) Private::h_badargs("dispatch");
02356         unsigned i0, i1, i2, i3, i4, i5, i6;
02357         const Axis* ax = &axes_[0];
02358         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02359         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02360         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02361         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02362         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02363         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02364         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02365         if (o0 == 1U && o1 == 1U && o2 == 1U &&
02366             o3 == 1U && o4 == 1U && o5 == 1U && o6 == 1U)
02367             f(data_(i0, i1, i2, i3, i4, i5, i6), w);
02368         else
02369             f(overflow_(o0, o1, o2, o3, o4, o5, o6), w);
02370         ++modCount_;
02371     }
02372 
02373     template <typename Numeric, class Axis>
02374     template <typename Num2>
02375     void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
02376                                       const double x2, const double x3,
02377                                       const double x4, const double x5,
02378                                       const double x6, const Num2& w)
02379     {
02380         if (dim_ != 7U) Private::h_badargs("fillC");
02381         double* wg = &weightBuf_[0];
02382         unsigned* idx = &indexBuf_[0];
02383         const Axis* ax = &axes_[0];
02384         const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
02385         const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
02386         const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
02387         const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
02388         const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
02389         const unsigned o5 = ax[5].overflowIndexWeighted(x5, idx+5, wg+5);
02390         const unsigned o6 = ax[6].overflowIndexWeighted(x6, idx+6, wg+6);
02391         if (o0 == 1U && o1 == 1U && o2 == 1U &&
02392             o3 == 1U && o4 == 1U && o5 == 1U && o6 == 1U)
02393             fillPreservingCentroid(w);
02394         else
02395         {
02396             overflow_(o0, o1, o2, o3, o4, o5, o6) += w;
02397             ++overCount_;
02398         }
02399         ++fillCount_; ++modCount_;
02400     }
02401 
02402     template <typename Numeric, class Axis>
02403     const Numeric& HistoND<Numeric,Axis>::examine(
02404         const double x0, const double x1,
02405         const double x2, const double x3,
02406         const double x4, const double x5,
02407         const double x6) const
02408     {
02409         if (dim_ != 7U) Private::h_badargs("examine");
02410         unsigned i0, i1, i2, i3, i4, i5, i6;
02411         const Axis* ax = &axes_[0];
02412         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02413         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02414         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02415         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02416         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02417         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02418         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02419         if (o0 == 1U && o1 == 1U && o2 == 1U &&
02420             o3 == 1U && o4 == 1U && o5 == 1U && o6 == 1U)
02421             return data_(i0, i1, i2, i3, i4, i5, i6);
02422         else
02423             return overflow_(o0, o1, o2, o3, o4, o5, o6);
02424     }
02425 
02426     template <typename Numeric, class Axis>
02427     const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
02428                                                      const double x1,
02429                                                      const double x2,
02430                                                      const double x3,
02431                                                      const double x4,
02432                                                      const double x5,
02433                                                      const double x6) const
02434     {
02435         if (dim_ != 7U) Private::h_badargs("closestBin");
02436         const Axis* ax = &axes_[0];
02437         const unsigned i0 = ax[0].closestValidBin(x0);
02438         const unsigned i1 = ax[1].closestValidBin(x1);
02439         const unsigned i2 = ax[2].closestValidBin(x2);
02440         const unsigned i3 = ax[3].closestValidBin(x3);
02441         const unsigned i4 = ax[4].closestValidBin(x4);
02442         const unsigned i5 = ax[5].closestValidBin(x5);
02443         const unsigned i6 = ax[6].closestValidBin(x6);
02444         return data_(i0, i1, i2, i3, i4, i5, i6);
02445     }
02446 
02447     template <typename Numeric, class Axis>
02448     template <typename Num2>
02449     void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
02450                                      const double x2, const double x3,
02451                                      const double x4, const double x5,
02452                                      const double x6, const double x7,
02453                                      const Num2& w)
02454     {
02455         if (dim_ != 8U) Private::h_badargs("fill");
02456         unsigned i0, i1, i2, i3, i4, i5, i6, i7;
02457         const Axis* ax = &axes_[0];
02458         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02459         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02460         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02461         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02462         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02463         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02464         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02465         const unsigned o7 = ax[7].overflowIndex(x7, &i7);
02466         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U &&
02467             o4 == 1U && o5 == 1U && o6 == 1U && o7 == 1U)
02468             data_(i0, i1, i2, i3, i4, i5, i6, i7) += w;
02469         else
02470         {
02471             overflow_(o0, o1, o2, o3, o4, o5, o6, o7) += w;
02472             ++overCount_;
02473         }
02474         ++fillCount_; ++modCount_;
02475     }
02476 
02477     template <typename Numeric, class Axis>
02478     template <typename Num2, class Functor>
02479     void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
02480                                          const double x2, const double x3,
02481                                          const double x4, const double x5,
02482                                          const double x6, const double x7,
02483                                          Num2& w, Functor& f)
02484     {
02485         if (dim_ != 8U) Private::h_badargs("dispatch");
02486         unsigned i0, i1, i2, i3, i4, i5, i6, i7;
02487         const Axis* ax = &axes_[0];
02488         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02489         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02490         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02491         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02492         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02493         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02494         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02495         const unsigned o7 = ax[7].overflowIndex(x7, &i7);
02496         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U &&
02497             o4 == 1U && o5 == 1U && o6 == 1U && o7 == 1U)
02498             f(data_(i0, i1, i2, i3, i4, i5, i6, i7), w);
02499         else
02500             f(overflow_(o0, o1, o2, o3, o4, o5, o6, o7), w);
02501         ++modCount_;
02502     }
02503 
02504     template <typename Numeric, class Axis>
02505     template <typename Num2>
02506     void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
02507                                       const double x2, const double x3,
02508                                       const double x4, const double x5,
02509                                       const double x6, const double x7,
02510                                       const Num2& w)
02511     {
02512         if (dim_ != 8U) Private::h_badargs("fillC");
02513         double* wg = &weightBuf_[0];
02514         unsigned* idx = &indexBuf_[0];
02515         const Axis* ax = &axes_[0];
02516         const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
02517         const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
02518         const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
02519         const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
02520         const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
02521         const unsigned o5 = ax[5].overflowIndexWeighted(x5, idx+5, wg+5);
02522         const unsigned o6 = ax[6].overflowIndexWeighted(x6, idx+6, wg+6);
02523         const unsigned o7 = ax[7].overflowIndexWeighted(x7, idx+7, wg+7);
02524         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U &&
02525             o4 == 1U && o5 == 1U && o6 == 1U && o7 == 1U)
02526             fillPreservingCentroid(w);
02527         else
02528         {
02529             overflow_(o0, o1, o2, o3, o4, o5, o6, o7) += w;
02530             ++overCount_;
02531         }
02532         ++fillCount_; ++modCount_;
02533     }
02534 
02535     template <typename Numeric, class Axis>
02536     const Numeric& HistoND<Numeric,Axis>::examine(
02537         const double x0, const double x1,
02538         const double x2, const double x3,
02539         const double x4, const double x5,
02540         const double x6,
02541         const double x7) const
02542     {
02543         if (dim_ != 8U) Private::h_badargs("examine");
02544         unsigned i0, i1, i2, i3, i4, i5, i6, i7;
02545         const Axis* ax = &axes_[0];
02546         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02547         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02548         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02549         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02550         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02551         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02552         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02553         const unsigned o7 = ax[7].overflowIndex(x7, &i7);
02554         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U &&
02555             o4 == 1U && o5 == 1U && o6 == 1U && o7 == 1U)
02556             return data_(i0, i1, i2, i3, i4, i5, i6, i7);
02557         else
02558             return overflow_(o0, o1, o2, o3, o4, o5, o6, o7);
02559     }
02560 
02561     template <typename Numeric, class Axis>
02562     const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
02563                                                      const double x1,
02564                                                      const double x2,
02565                                                      const double x3,
02566                                                      const double x4,
02567                                                      const double x5,
02568                                                      const double x6,
02569                                                      const double x7) const
02570     {
02571         if (dim_ != 8U) Private::h_badargs("closestBin");
02572         const Axis* ax = &axes_[0];
02573         const unsigned i0 = ax[0].closestValidBin(x0);
02574         const unsigned i1 = ax[1].closestValidBin(x1);
02575         const unsigned i2 = ax[2].closestValidBin(x2);
02576         const unsigned i3 = ax[3].closestValidBin(x3);
02577         const unsigned i4 = ax[4].closestValidBin(x4);
02578         const unsigned i5 = ax[5].closestValidBin(x5);
02579         const unsigned i6 = ax[6].closestValidBin(x6);
02580         const unsigned i7 = ax[7].closestValidBin(x7);
02581         return data_(i0, i1, i2, i3, i4, i5, i6, i7);
02582     }
02583 
02584     template <typename Numeric, class Axis>
02585     template <typename Num2>
02586     void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
02587                                      const double x2, const double x3,
02588                                      const double x4, const double x5,
02589                                      const double x6, const double x7,
02590                                      const double x8, const Num2& w)
02591     {
02592         if (dim_ != 9U) Private::h_badargs("fill");
02593         unsigned i0, i1, i2, i3, i4, i5, i6, i7, i8;
02594         const Axis* ax = &axes_[0];
02595         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02596         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02597         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02598         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02599         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02600         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02601         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02602         const unsigned o7 = ax[7].overflowIndex(x7, &i7);
02603         const unsigned o8 = ax[8].overflowIndex(x8, &i8);
02604         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
02605             o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U)
02606             data_(i0, i1, i2, i3, i4, i5, i6, i7, i8) += w;
02607         else
02608         {
02609             overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8) += w;
02610             ++overCount_;
02611         }
02612         ++fillCount_; ++modCount_;
02613     }
02614 
02615     template <typename Numeric, class Axis>
02616     template <typename Num2, class Functor>
02617     void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
02618                                          const double x2, const double x3,
02619                                          const double x4, const double x5,
02620                                          const double x6, const double x7,
02621                                          const double x8, Num2& w, Functor& f)
02622     {
02623         if (dim_ != 9U) Private::h_badargs("dispatch");
02624         unsigned i0, i1, i2, i3, i4, i5, i6, i7, i8;
02625         const Axis* ax = &axes_[0];
02626         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02627         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02628         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02629         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02630         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02631         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02632         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02633         const unsigned o7 = ax[7].overflowIndex(x7, &i7);
02634         const unsigned o8 = ax[8].overflowIndex(x8, &i8);
02635         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
02636             o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U)
02637             f(data_(i0, i1, i2, i3, i4, i5, i6, i7, i8), w);
02638         else
02639             f(overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8), w);
02640         ++modCount_;
02641     }
02642 
02643     template <typename Numeric, class Axis>
02644     template <typename Num2>
02645     void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
02646                                       const double x2, const double x3,
02647                                       const double x4, const double x5,
02648                                       const double x6, const double x7,
02649                                       const double x8, const Num2& w)
02650     {
02651         if (dim_ != 9U) Private::h_badargs("fillC");
02652         double* wg = &weightBuf_[0];
02653         unsigned* idx = &indexBuf_[0];
02654         const Axis* ax = &axes_[0];
02655         const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
02656         const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
02657         const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
02658         const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
02659         const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
02660         const unsigned o5 = ax[5].overflowIndexWeighted(x5, idx+5, wg+5);
02661         const unsigned o6 = ax[6].overflowIndexWeighted(x6, idx+6, wg+6);
02662         const unsigned o7 = ax[7].overflowIndexWeighted(x7, idx+7, wg+7);
02663         const unsigned o8 = ax[8].overflowIndexWeighted(x8, idx+8, wg+8);
02664         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
02665             o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U)
02666             fillPreservingCentroid(w);
02667         else
02668         {
02669             overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8) += w;
02670             ++overCount_;
02671         }
02672         ++fillCount_; ++modCount_;
02673     }
02674 
02675     template <typename Numeric, class Axis>
02676     const Numeric& HistoND<Numeric,Axis>::examine(
02677         const double x0, const double x1,
02678         const double x2, const double x3,
02679         const double x4, const double x5,
02680         const double x6, const double x7,
02681         const double x8) const
02682     {
02683         if (dim_ != 9U) Private::h_badargs("examine");
02684         unsigned i0, i1, i2, i3, i4, i5, i6, i7, i8;
02685         const Axis* ax = &axes_[0];
02686         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02687         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02688         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02689         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02690         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02691         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02692         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02693         const unsigned o7 = ax[7].overflowIndex(x7, &i7);
02694         const unsigned o8 = ax[8].overflowIndex(x8, &i8);
02695         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
02696             o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U)
02697             return data_(i0, i1, i2, i3, i4, i5, i6, i7, i8);
02698         else
02699             return overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8);
02700     }
02701 
02702     template <typename Numeric, class Axis>
02703     const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
02704                                                      const double x1,
02705                                                      const double x2,
02706                                                      const double x3,
02707                                                      const double x4,
02708                                                      const double x5,
02709                                                      const double x6,
02710                                                      const double x7,
02711                                                      const double x8) const
02712     {
02713         if (dim_ != 9U) Private::h_badargs("closestBin");
02714         const Axis* ax = &axes_[0];
02715         const unsigned i0 = ax[0].closestValidBin(x0);
02716         const unsigned i1 = ax[1].closestValidBin(x1);
02717         const unsigned i2 = ax[2].closestValidBin(x2);
02718         const unsigned i3 = ax[3].closestValidBin(x3);
02719         const unsigned i4 = ax[4].closestValidBin(x4);
02720         const unsigned i5 = ax[5].closestValidBin(x5);
02721         const unsigned i6 = ax[6].closestValidBin(x6);
02722         const unsigned i7 = ax[7].closestValidBin(x7);
02723         const unsigned i8 = ax[8].closestValidBin(x8);
02724         return data_(i0, i1, i2, i3, i4, i5, i6, i7, i8);
02725     }
02726 
02727     template <typename Numeric, class Axis>
02728     template <typename Num2>
02729     void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
02730                                      const double x2, const double x3,
02731                                      const double x4, const double x5,
02732                                      const double x6, const double x7,
02733                                      const double x8, const double x9,
02734                                      const Num2& w)
02735     {
02736         if (dim_ != 10U) Private::h_badargs("fill");
02737         unsigned i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
02738         const Axis* ax = &axes_[0];
02739         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02740         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02741         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02742         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02743         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02744         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02745         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02746         const unsigned o7 = ax[7].overflowIndex(x7, &i7);
02747         const unsigned o8 = ax[8].overflowIndex(x8, &i8);
02748         const unsigned o9 = ax[9].overflowIndex(x9, &i9);
02749         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
02750             o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U && o9 == 1U)
02751             data_(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) += w;
02752         else
02753         {
02754             overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8, o9) += w;
02755             ++overCount_;
02756         }
02757         ++fillCount_; ++modCount_;
02758     }
02759 
02760     template <typename Numeric, class Axis>
02761     template <typename Num2, class Functor>
02762     void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
02763                                          const double x2, const double x3,
02764                                          const double x4, const double x5,
02765                                          const double x6, const double x7,
02766                                          const double x8, const double x9,
02767                                          Num2& w, Functor& f)
02768     {
02769         if (dim_ != 10U) Private::h_badargs("dispatch");
02770         unsigned i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
02771         const Axis* ax = &axes_[0];
02772         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02773         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02774         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02775         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02776         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02777         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02778         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02779         const unsigned o7 = ax[7].overflowIndex(x7, &i7);
02780         const unsigned o8 = ax[8].overflowIndex(x8, &i8);
02781         const unsigned o9 = ax[9].overflowIndex(x9, &i9);
02782         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
02783             o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U && o9 == 1U)
02784             f(data_(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9), w);
02785         else
02786             f(overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8, o9), w);
02787         ++modCount_;
02788     }
02789 
02790     template <typename Numeric, class Axis>
02791     template <typename Num2>
02792     void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
02793                                       const double x2, const double x3,
02794                                       const double x4, const double x5,
02795                                       const double x6, const double x7,
02796                                       const double x8, const double x9,
02797                                       const Num2& w)
02798     {
02799         if (dim_ != 10U) Private::h_badargs("fillC");
02800         double* wg = &weightBuf_[0];
02801         unsigned* idx = &indexBuf_[0];
02802         const Axis* ax = &axes_[0];
02803         const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
02804         const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
02805         const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
02806         const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
02807         const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
02808         const unsigned o5 = ax[5].overflowIndexWeighted(x5, idx+5, wg+5);
02809         const unsigned o6 = ax[6].overflowIndexWeighted(x6, idx+6, wg+6);
02810         const unsigned o7 = ax[7].overflowIndexWeighted(x7, idx+7, wg+7);
02811         const unsigned o8 = ax[8].overflowIndexWeighted(x8, idx+8, wg+8);
02812         const unsigned o9 = ax[9].overflowIndexWeighted(x9, idx+9, wg+9);
02813         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
02814             o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U && o9 == 1U)
02815             fillPreservingCentroid(w);
02816         else
02817         {
02818             overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8, o9) += w;
02819             ++overCount_;
02820         }
02821         ++fillCount_; ++modCount_;
02822     }
02823 
02824     template <typename Numeric, class Axis>
02825     const Numeric& HistoND<Numeric,Axis>::examine(
02826         const double x0, const double x1,
02827         const double x2, const double x3,
02828         const double x4, const double x5,
02829         const double x6, const double x7,
02830         const double x8,
02831         const double x9) const
02832     {
02833         if (dim_ != 10U) Private::h_badargs("examine");
02834         unsigned i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
02835         const Axis* ax = &axes_[0];
02836         const unsigned o0 = ax[0].overflowIndex(x0, &i0);
02837         const unsigned o1 = ax[1].overflowIndex(x1, &i1);
02838         const unsigned o2 = ax[2].overflowIndex(x2, &i2);
02839         const unsigned o3 = ax[3].overflowIndex(x3, &i3);
02840         const unsigned o4 = ax[4].overflowIndex(x4, &i4);
02841         const unsigned o5 = ax[5].overflowIndex(x5, &i5);
02842         const unsigned o6 = ax[6].overflowIndex(x6, &i6);
02843         const unsigned o7 = ax[7].overflowIndex(x7, &i7);
02844         const unsigned o8 = ax[8].overflowIndex(x8, &i8);
02845         const unsigned o9 = ax[9].overflowIndex(x9, &i9);
02846         if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
02847             o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U && o9 == 1U)
02848             return data_(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9);
02849         else
02850             return overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8, o9);
02851     }
02852 
02853     template <typename Numeric, class Axis>
02854     const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
02855                                                      const double x1,
02856                                                      const double x2,
02857                                                      const double x3,
02858                                                      const double x4,
02859                                                      const double x5,
02860                                                      const double x6,
02861                                                      const double x7,
02862                                                      const double x8,
02863                                                      const double x9) const
02864     {
02865         if (dim_ != 10U) Private::h_badargs("closestBin");
02866         const Axis* ax = &axes_[0];
02867         const unsigned i0 = ax[0].closestValidBin(x0);
02868         const unsigned i1 = ax[1].closestValidBin(x1);
02869         const unsigned i2 = ax[2].closestValidBin(x2);
02870         const unsigned i3 = ax[3].closestValidBin(x3);
02871         const unsigned i4 = ax[4].closestValidBin(x4);
02872         const unsigned i5 = ax[5].closestValidBin(x5);
02873         const unsigned i6 = ax[6].closestValidBin(x6);
02874         const unsigned i7 = ax[7].closestValidBin(x7);
02875         const unsigned i8 = ax[8].closestValidBin(x8);
02876         const unsigned i9 = ax[9].closestValidBin(x9);
02877         return data_(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9);
02878     }
02879 
02880     template <typename Numeric, class Axis>
02881     template <typename Num2>
02882     inline void HistoND<Numeric,Axis>::setBin(const unsigned *index,
02883                                               const unsigned indexLen,
02884                                               const Num2& v)
02885     {
02886         data_.value(index, indexLen) = v;
02887         ++modCount_;
02888     }
02889 
02890     template <typename Numeric, class Axis>
02891     template <typename Num2>
02892     inline void HistoND<Numeric,Axis>::setBinAt(const unsigned *index,
02893                                                 const unsigned indexLen,
02894                                                 const Num2& v)
02895     {
02896         data_.valueAt(index, indexLen) = v;
02897         ++modCount_;
02898     }
02899 
02900     template <typename Numeric, class Axis>
02901     template <typename Num2>
02902     inline void HistoND<Numeric,Axis>::setBin(const Num2& v)
02903     {
02904         data_() = v;
02905         ++modCount_;
02906     }
02907 
02908     template <typename Numeric, class Axis>
02909     template <typename Num2>
02910     inline void HistoND<Numeric,Axis>::setBinAt(const Num2& v)
02911     {
02912         data_.at() = v;
02913         ++modCount_;
02914     }
02915 
02916     template <typename Numeric, class Axis>
02917     template <typename Num2>
02918     inline void HistoND<Numeric,Axis>::setBin(
02919         const unsigned i0, const Num2& v)
02920     {
02921         data_(i0) = v;
02922         ++modCount_;
02923     }
02924 
02925     template <typename Numeric, class Axis>
02926     template <typename Num2>
02927     inline void HistoND<Numeric,Axis>::setBinAt(
02928         const unsigned i0, const Num2& v)
02929     {
02930         data_.at(i0) = v;
02931         ++modCount_;
02932     }
02933 
02934     template <typename Numeric, class Axis>
02935     template <typename Num2>
02936     inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
02937                                               const unsigned i1,
02938                                               const Num2& v)
02939     {
02940         data_(i0, i1) = v;
02941         ++modCount_;
02942     }
02943 
02944     template <typename Numeric, class Axis>
02945     template <typename Num2>
02946     inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
02947                                                 const unsigned i1,
02948                                                 const Num2& v)
02949     {
02950         data_.at(i0, i1) = v;
02951         ++modCount_;
02952     }
02953 
02954     template <typename Numeric, class Axis>
02955     template <typename Num2>
02956     inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
02957                                               const unsigned i1,
02958                                               const unsigned i2,
02959                                               const Num2& v)
02960     {
02961         data_(i0, i1, i2) = v;
02962         ++modCount_;
02963     }
02964 
02965     template <typename Numeric, class Axis>
02966     template <typename Num2>
02967     inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
02968                                               const unsigned i1,
02969                                               const unsigned i2,
02970                                               const unsigned i3,
02971                                               const Num2& v)
02972     {
02973         data_(i0, i1, i2, i3) = v;
02974         ++modCount_;
02975     }
02976 
02977     template <typename Numeric, class Axis>
02978     template <typename Num2>
02979     inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
02980                                               const unsigned i1,
02981                                               const unsigned i2,
02982                                               const unsigned i3,
02983                                               const unsigned i4,
02984                                               const Num2& v)
02985     {
02986         data_(i0, i1, i2, i3, i4) = v;
02987         ++modCount_;
02988     }
02989 
02990     template <typename Numeric, class Axis>
02991     template <typename Num2>
02992     inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
02993                                               const unsigned i1,
02994                                               const unsigned i2,
02995                                               const unsigned i3,
02996                                               const unsigned i4,
02997                                               const unsigned i5,
02998                                               const Num2& v)
02999     {
03000         data_(i0, i1, i2, i3, i4, i5) = v;
03001         ++modCount_;
03002     }
03003 
03004     template <typename Numeric, class Axis>
03005     template <typename Num2>
03006     inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
03007                                               const unsigned i1,
03008                                               const unsigned i2,
03009                                               const unsigned i3,
03010                                               const unsigned i4,
03011                                               const unsigned i5,
03012                                               const unsigned i6,
03013                                               const Num2& v)
03014     {
03015         data_(i0, i1, i2, i3, i4, i5, i6) = v;
03016         ++modCount_;
03017     }
03018 
03019     template <typename Numeric, class Axis>
03020     template <typename Num2>
03021     inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
03022                                               const unsigned i1,
03023                                               const unsigned i2,
03024                                               const unsigned i3,
03025                                               const unsigned i4,
03026                                               const unsigned i5,
03027                                               const unsigned i6,
03028                                               const unsigned i7,
03029                                               const Num2& v)
03030     {
03031         data_(i0, i1, i2, i3, i4, i5, i6, i7) = v;
03032         ++modCount_;
03033     }
03034 
03035     template <typename Numeric, class Axis>
03036     template <typename Num2>
03037     inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
03038                                               const unsigned i1,
03039                                               const unsigned i2,
03040                                               const unsigned i3,
03041                                               const unsigned i4,
03042                                               const unsigned i5,
03043                                               const unsigned i6,
03044                                               const unsigned i7,
03045                                               const unsigned i8,
03046                                               const Num2& v)
03047     {
03048         data_(i0, i1, i2, i3, i4, i5, i6, i7, i8) = v;
03049         ++modCount_;
03050     }
03051 
03052     template <typename Numeric, class Axis>
03053     template <typename Num2>
03054     inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
03055                                               const unsigned i1,
03056                                               const unsigned i2,
03057                                               const unsigned i3,
03058                                               const unsigned i4,
03059                                               const unsigned i5,
03060                                               const unsigned i6,
03061                                               const unsigned i7,
03062                                               const unsigned i8,
03063                                               const unsigned i9,
03064                                               const Num2& v)
03065     {
03066         data_(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) = v;
03067         ++modCount_;
03068     }
03069 
03070     template <typename Numeric, class Axis>
03071     template <typename Num2>
03072     inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
03073                                                 const unsigned i1,
03074                                                 const unsigned i2,
03075                                                 const Num2& v)
03076     {
03077         data_.at(i0, i1, i2) = v;
03078         ++modCount_;
03079     }
03080 
03081     template <typename Numeric, class Axis>
03082     template <typename Num2>
03083     inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
03084                                                 const unsigned i1,
03085                                                 const unsigned i2,
03086                                                 const unsigned i3,
03087                                                 const Num2& v)
03088     {
03089         data_.at(i0, i1, i2, i3) = v;
03090         ++modCount_;
03091     }
03092 
03093     template <typename Numeric, class Axis>
03094     template <typename Num2>
03095     inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
03096                                                 const unsigned i1,
03097                                                 const unsigned i2,
03098                                                 const unsigned i3,
03099                                                 const unsigned i4,
03100                                                 const Num2& v)
03101     {
03102         data_.at(i0, i1, i2, i3, i4) = v;
03103         ++modCount_;
03104     }
03105 
03106     template <typename Numeric, class Axis>
03107     template <typename Num2>
03108     inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
03109                                                 const unsigned i1,
03110                                                 const unsigned i2,
03111                                                 const unsigned i3,
03112                                                 const unsigned i4,
03113                                                 const unsigned i5,
03114                                                 const Num2& v)
03115     {
03116         data_.at(i0, i1, i2, i3, i4, i5) = v;
03117         ++modCount_;
03118     }
03119 
03120     template <typename Numeric, class Axis>
03121     template <typename Num2>
03122     inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
03123                                                 const unsigned i1,
03124                                                 const unsigned i2,
03125                                                 const unsigned i3,
03126                                                 const unsigned i4,
03127                                                 const unsigned i5,
03128                                                 const unsigned i6,
03129                                                 const Num2& v)
03130     {
03131         data_.at(i0, i1, i2, i3, i4, i5, i6) = v;
03132         ++modCount_;
03133     }
03134 
03135     template <typename Numeric, class Axis>
03136     template <typename Num2>
03137     inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
03138                                                 const unsigned i1,
03139                                                 const unsigned i2,
03140                                                 const unsigned i3,
03141                                                 const unsigned i4,
03142                                                 const unsigned i5,
03143                                                 const unsigned i6,
03144                                                 const unsigned i7,
03145                                                 const Num2& v)
03146     {
03147         data_.at(i0, i1, i2, i3, i4, i5, i6, i7) = v;
03148         ++modCount_;
03149     }
03150 
03151     template <typename Numeric, class Axis>
03152     template <typename Num2>
03153     inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
03154                                                 const unsigned i1,
03155                                                 const unsigned i2,
03156                                                 const unsigned i3,
03157                                                 const unsigned i4,
03158                                                 const unsigned i5,
03159                                                 const unsigned i6,
03160                                                 const unsigned i7,
03161                                                 const unsigned i8,
03162                                                 const Num2& v)
03163     {
03164         data_.at(i0, i1, i2, i3, i4, i5, i6, i7, i8) = v;
03165         ++modCount_;
03166     }
03167 
03168     template <typename Numeric, class Axis>
03169     template <typename Num2>
03170     inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
03171                                                 const unsigned i1,
03172                                                 const unsigned i2,
03173                                                 const unsigned i3,
03174                                                 const unsigned i4,
03175                                                 const unsigned i5,
03176                                                 const unsigned i6,
03177                                                 const unsigned i7,
03178                                                 const unsigned i8,
03179                                                 const unsigned i9,
03180                                                 const Num2& v)
03181     {
03182         data_.at(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) = v;
03183         ++modCount_;
03184     }
03185 
03186     template <typename Numeric, class Axis>
03187     template <typename Num2>
03188     inline HistoND<Numeric,Axis>& HistoND<Numeric,Axis>::operator+=(
03189         const HistoND<Num2,Axis>& r)
03190     {
03191         data_ += r.data_;
03192         overflow_ += r.overflow_;
03193         fillCount_ += r.fillCount_;
03194         overCount_ += r.overCount_;
03195         ++modCount_;
03196         return *this;
03197     }
03198 
03199     template <typename Numeric, class Axis>
03200     template <typename Num2>
03201     inline HistoND<Numeric,Axis>& HistoND<Numeric,Axis>::operator-=(
03202         const HistoND<Num2,Axis>& r)
03203     {
03204         data_ -= r.data_;
03205         overflow_ -= r.overflow_;
03206 
03207         // Subtraction does not make much sense for fill counts.
03208         // We will assume that what we want should be equivalent
03209         // to the in-place multiplication of the other histogram
03210         // by -1 and then adding.
03211         //
03212         fillCount_ += r.fillCount_;
03213         overCount_ += r.overCount_;
03214 
03215         ++modCount_;
03216         return *this;
03217     }
03218 
03219     template <typename Numeric, class Axis>
03220     template <typename Num2>
03221     inline HistoND<Numeric,Axis>&
03222     HistoND<Numeric,Axis>::operator*=(const Num2& r)
03223     {
03224         data_ *= r;
03225         overflow_ *= r;
03226         ++modCount_;
03227         return *this;
03228     }
03229 
03230     template <typename Numeric, class Axis>
03231     template <typename Num2>
03232     inline HistoND<Numeric,Axis>&
03233     HistoND<Numeric,Axis>::operator/=(const Num2& r)
03234     {
03235         data_ /= r;
03236         overflow_ /= r;
03237         ++modCount_;
03238         return *this;
03239     }
03240 
03241     template <typename Numeric, class Axis>
03242     HistoND<Numeric,Axis>::HistoND(const HistoND& r,
03243                                    const unsigned ax1,
03244                                    const unsigned ax2)
03245         : title_(r.title_),
03246           accumulatedDataLabel_(r.accumulatedDataLabel_),
03247           data_(r.data_.transpose(ax1, ax2)),
03248           overflow_(r.overflow_.transpose(ax1, ax2)),
03249           axes_(r.axes_),
03250           weightBuf_(r.weightBuf_),
03251           indexBuf_(r.indexBuf_),
03252           fillCount_(r.fillCount_),
03253           overCount_(r.overCount_),
03254           modCount_(0UL),
03255           dim_(r.dim_)
03256     {
03257         std::swap(axes_[ax1], axes_[ax2]);
03258     }
03259 
03260     template <typename Numeric, class Axis>
03261     HistoND<Numeric,Axis>::HistoND(const HistoND& r)
03262         : title_(r.title_),
03263           accumulatedDataLabel_(r.accumulatedDataLabel_),
03264           data_(r.data_),
03265           overflow_(r.overflow_),
03266           axes_(r.axes_),
03267           weightBuf_(r.weightBuf_),
03268           indexBuf_(r.indexBuf_),
03269           fillCount_(r.fillCount_),
03270           overCount_(r.overCount_),
03271           modCount_(0UL),
03272           dim_(r.dim_)
03273     {
03274     }
03275 
03276     template <typename Numeric, class Axis>
03277     HistoND<Numeric,Axis>& HistoND<Numeric,Axis>::operator=(const HistoND& r)
03278     {
03279         if (&r != this)
03280         {
03281             title_ = r.title_;
03282             accumulatedDataLabel_ = r.accumulatedDataLabel_;
03283             data_.uninitialize();
03284             data_ = r.data_;
03285             overflow_.uninitialize();
03286             overflow_ = r.overflow_;
03287             axes_ = r.axes_;
03288             weightBuf_ = r.weightBuf_;
03289             indexBuf_ = r.indexBuf_;
03290             fillCount_ = r.fillCount_;
03291             overCount_ = r.overCount_;
03292             dim_ = r.dim_;
03293             ++modCount_;
03294         }
03295         return *this;
03296     }
03297 
03298     template <typename Numeric, class Axis>
03299     HistoND<Numeric,Axis> HistoND<Numeric,Axis>::transpose(
03300         const unsigned axisNum1, const unsigned axisNum2) const
03301     {
03302         if (axisNum1 >= dim_ || axisNum2 >= dim_)
03303             throw npstat::NpstatOutOfRange("In npstat::HistoND::transpose: "
03304                                     "axis number is out of range");
03305         if (axisNum1 == axisNum2)
03306             // Just make a copy
03307             return *this;
03308         else
03309             return HistoND(*this, axisNum1, axisNum2);
03310     }
03311 
03312     template <typename Numeric, class Axis>
03313     template <typename Num2>
03314     void HistoND<Numeric,Axis>::addToBinContents(const Num2& weight)
03315     {
03316         const unsigned long nDat = data_.length();
03317         Numeric* data = const_cast<Numeric*>(data_.data());
03318         for (unsigned long i=0; i<nDat; ++i)
03319             data[i] += weight;
03320         fillCount_ += nDat;
03321         ++modCount_;
03322     }
03323 
03324     template <typename Numeric, class Axis>
03325     template <typename Num2>
03326     void HistoND<Numeric,Axis>::addToOverflows(const Num2& weight)
03327     {
03328         const unsigned long nOver = overflow_.length();
03329         Numeric* data = const_cast<Numeric*>(overflow_.data());
03330         for (unsigned long i=0; i<nOver; ++i)
03331             data[i] += weight;
03332         overCount_ += nOver;
03333         fillCount_ += nOver;
03334         ++modCount_;
03335     }
03336 
03337     template <typename Numeric, class Axis>
03338     template <typename Num2>
03339     void HistoND<Numeric,Axis>::addToBinContents(
03340         const Num2* data, const unsigned long dataLength)
03341     {
03342         if (dataLength != data_.length()) throw npstat::NpstatInvalidArgument(
03343             "In npstat::HistoND::addToBinContents: incompatible data length");
03344         assert(data);
03345         Numeric* dat = const_cast<Numeric*>(data_.data());
03346         for (unsigned long i=0; i<dataLength; ++i)
03347             dat[i] += data[i];
03348         fillCount_ += dataLength;
03349         ++modCount_;
03350     }
03351 
03352     template <typename Numeric, class Axis>
03353     template <typename Num2>
03354     void HistoND<Numeric,Axis>::addToOverflows(
03355         const Num2* data, const unsigned long dataLength)
03356     {
03357         if (dataLength != overflow_.length()) throw npstat::NpstatInvalidArgument(
03358             "In npstat::HistoND::addToOverflows: incompatible data length");
03359         assert(data);
03360         Numeric* dat = const_cast<Numeric*>(overflow_.data());
03361         for (unsigned long i=0; i<dataLength; ++i)
03362             dat[i] += data[i];
03363         overCount_ += dataLength;
03364         fillCount_ += dataLength;
03365         ++modCount_;
03366     }
03367 
03368     template <typename Numeric, class Axis>
03369     template <typename Num2>
03370     void HistoND<Numeric,Axis>::scaleBinContents(
03371         const Num2* data, const unsigned long dataLength)
03372     {
03373         if (dataLength != data_.length()) throw npstat::NpstatInvalidArgument(
03374             "In npstat::HistoND::scaleBinContents: incompatible data length");
03375         assert(data);
03376         Numeric* dat = const_cast<Numeric*>(data_.data());
03377         for (unsigned long i=0; i<dataLength; ++i)
03378             dat[i] *= data[i];
03379         ++modCount_;
03380     }
03381 
03382     template <typename Numeric, class Axis>
03383     template <typename Num2>
03384     void HistoND<Numeric,Axis>::scaleOverflows(
03385         const Num2* data, const unsigned long dataLength)
03386     {
03387         if (dataLength != overflow_.length()) throw npstat::NpstatInvalidArgument(
03388             "In npstat::HistoND::scaleOverflows: incompatible data length");
03389         assert(data);
03390         Numeric* dat = const_cast<Numeric*>(overflow_.data());
03391         for (unsigned long i=0; i<dataLength; ++i)
03392             dat[i] *= data[i];
03393         ++modCount_;
03394     }
03395 
03396     template <typename Numeric, class Axis>
03397     template <typename Num2>
03398     inline void HistoND<Numeric,Axis>::setBinContents(
03399         const Num2* data, const unsigned long dataLength,
03400         const bool clearOverflowsNow)
03401     {
03402         data_.setData(data, dataLength);
03403         if (clearOverflowsNow)
03404             clearOverflows();
03405         ++modCount_;
03406     }
03407 
03408     template <typename Numeric, class Axis>
03409     template <typename Num2>
03410     inline void HistoND<Numeric,Axis>::setOverflows(
03411         const Num2* data, const unsigned long dataLength)
03412     {
03413         overflow_.setData(data, dataLength);
03414         ++modCount_;
03415     }
03416 
03417     template <typename Numeric, class Axis>
03418     inline void HistoND<Numeric,Axis>::recalculateNFillsFromData()
03419     {
03420         const long double nOver = overflow_.template sum<long double>();
03421         const long double nData = data_.template sum<long double>();
03422         overCount_ = static_cast<unsigned long>(nOver);
03423         fillCount_ = static_cast<unsigned long>(nData + nOver);
03424         ++modCount_;
03425     }
03426 
03427     template <typename Numeric, class Axis>
03428     template <typename Num2, typename Num3>
03429     inline void HistoND<Numeric,Axis>::addToProjection(
03430         HistoND<Num2,Axis>* projection,
03431         AbsArrayProjector<Numeric,Num3>& projector,
03432         const unsigned *projectedIndices,
03433         const unsigned nProjectedIndices) const
03434     {
03435         assert(projection);
03436         data_.addToProjection(&projection->data_, projector,
03437                               projectedIndices, nProjectedIndices);
03438         projection->fillCount_ += projection->nBins();
03439         projection->modCount_++;
03440     }
03441 
03442     template <typename Numeric, class Axis>
03443     template <typename Num2, typename Num3>
03444     inline void HistoND<Numeric,Axis>::addToProjection(
03445         HistoND<Num2,Axis>* projection,
03446         AbsVisitor<Numeric,Num3>& projector,
03447         const unsigned *projectedIndices,
03448         const unsigned nProjectedIndices) const
03449     {
03450         assert(projection);
03451         data_.addToProjection(&projection->data_, projector,
03452                               projectedIndices, nProjectedIndices);
03453         projection->fillCount_ += projection->nBins();
03454         projection->modCount_++;
03455     }
03456 
03457     template <typename Numeric, class Axis>
03458     const char* HistoND<Numeric,Axis>::classname()
03459     {
03460         static const std::string myClass(gs::template_class_name<Numeric,Axis>(
03461                                              "npstat::HistoND"));
03462         return myClass.c_str();
03463     }
03464 
03465     template<typename Numeric, class Axis>
03466     bool HistoND<Numeric,Axis>::write(std::ostream& of) const
03467     {
03468         gs::write_pod(of, title_);
03469         gs::write_pod(of, accumulatedDataLabel_);
03470         gs::write_pod(of, fillCount_);
03471         gs::write_pod(of, overCount_);
03472 
03473         return !of.fail() &&
03474             gs::write_obj_vector(of, axes_) && 
03475             data_.classId().write(of) &&
03476             data_.write(of) &&
03477             overflow_.write(of);
03478     }
03479 
03480     template<typename Numeric, class Axis>
03481     HistoND<Numeric,Axis>* HistoND<Numeric,Axis>::read(const gs::ClassId& id,
03482                                                        std::istream& in)
03483     {
03484         static const gs::ClassId current(
03485             gs::ClassId::makeId<HistoND<Numeric,Axis> >());
03486         current.ensureSameId(id);
03487 
03488         std::string title;
03489         gs::read_pod(in, &title);
03490 
03491         std::string accumulatedDataLabel;
03492         gs::read_pod(in, &accumulatedDataLabel);
03493 
03494         unsigned long fillCount = 0, overCount = 0;
03495         gs::read_pod(in, &fillCount);
03496         gs::read_pod(in, &overCount);
03497         if (in.fail()) throw gs::IOReadFailure(
03498             "In npstat::HistoND::read: input stream failure");
03499 
03500         std::vector<Axis> axes;
03501         gs::read_heap_obj_vector_as_placed(in, &axes);
03502         gs::ClassId ida(in, 1);
03503         ArrayND<Numeric> data, over;
03504         ArrayND<Numeric>::restore(ida, in, &data);
03505         ArrayND<Numeric>::restore(ida, in, &over);
03506         CPP11_auto_ptr<HistoND<Numeric,Axis> > result(
03507             new HistoND<Numeric,Axis>(axes, title.c_str(),
03508                                       accumulatedDataLabel.c_str()));
03509         result->data_ = data;
03510         result->overflow_ = over;
03511         result->fillCount_ = fillCount;
03512         result->overCount_ = overCount;
03513         return result.release();
03514     }
03515 
03516     template <typename Histo>
03517     void convertHistoToDensity(Histo* h, const bool knownNonNegative)
03518     {
03519         assert(h);
03520         if (!knownNonNegative)
03521             (const_cast<ArrayND<typename 
03522                 Histo::value_type>&>(h->binContents())).makeNonNegative();
03523         const double integ = h->integral();
03524         *h /= integ;
03525     }
03526 
03527     template <typename Histo>
03528     std::vector<LinearMapper1d> densityScanHistoMap(const Histo& histo)
03529     {
03530         std::vector<LinearMapper1d> result;
03531         const unsigned d = histo.dim();
03532         result.reserve(d);
03533         for (unsigned i=0; i<d; ++i)
03534         {
03535             const LinearMapper1d& m = histo.axis(i).binNumberMapper(false);
03536             result.push_back(m.inverse());
03537         }
03538         return result;
03539     }
03540 
03541     template <typename Histo>
03542     std::vector<CircularMapper1d> convolutionHistoMap(
03543         const Histo& histo, const bool doubleRange)
03544     {
03545         std::vector<CircularMapper1d> result;
03546         const unsigned d = histo.dim();
03547         result.reserve(d);
03548         for (unsigned i=0; i<d; ++i)
03549             result.push_back(histo.axis(i).kernelScanMapper(doubleRange));
03550         return result;
03551     }
03552 }
03553 
03554 
03555 #endif // NPSTAT_HISTOND_HH_
03556