CMS 3D CMS Logo

HistoND.h
Go to the documentation of this file.
1 #ifndef NPSTAT_HISTOND_HH_
2 #define NPSTAT_HISTOND_HH_
3 
16 
17 namespace npstat {
42  template <typename Numeric, class Axis=HistoAxis>
43  class HistoND
44  {
45  template <typename Num2, class Axis2> friend class HistoND;
46 
47  public:
48  typedef Numeric value_type;
49  typedef Axis axis_type;
50 
51  enum RebinType {
52  SAMPLE = 0,
53  SUM,
55  };
56 
58  explicit HistoND(const std::vector<Axis>& axes, const char* title=nullptr,
59  const char* accumulatedDataLabel=nullptr);
60 
62  explicit HistoND(const Axis& xAxis, const char* title=nullptr,
63  const char* accumulatedDataLabel=nullptr);
64 
66  HistoND(const Axis& xAxis, const Axis& yAxis,
67  const char* title=nullptr, const char* accumulatedDataLabel=nullptr);
68 
70  HistoND(const Axis& xAxis, const Axis& yAxis, const Axis& zAxis,
71  const char* title=nullptr, const char* accumulatedDataLabel=nullptr);
72 
74  HistoND(const Axis& xAxis, const Axis& yAxis,
75  const Axis& zAxis, const Axis& tAxis,
76  const char* title=nullptr, const char* accumulatedDataLabel=nullptr);
77 
79  HistoND(const Axis& xAxis, const Axis& yAxis,
80  const Axis& zAxis, const Axis& tAxis, const Axis& vAxis,
81  const char* title=nullptr, const char* accumulatedDataLabel=nullptr);
82 
88  HistoND(const ArrayShape& shape, const BoxND<double>& boundingBox,
89  const char* title=nullptr, const char* accumulatedDataLabel=nullptr);
90 
97  template <typename Num2, class Functor>
98  HistoND(const HistoND<Num2,Axis>& h, const Functor& f,
99  const char* title=nullptr, const char* accumulatedDataLabel=nullptr);
100 
108  template <typename Num2>
109  HistoND(const HistoND<Num2,Axis>& h, const unsigned *indices,
110  unsigned nIndices, const char* title=nullptr);
111 
121  template <typename Num2>
122  HistoND(const HistoND<Num2,Axis>& h, const Axis& newAxis,
123  unsigned newAxisNumber, const char* title=nullptr);
124 
142  template <typename Num2>
143  HistoND(const HistoND<Num2,Axis>& h, RebinType rType,
144  const unsigned *newBinCounts, unsigned lenNewBinCounts,
145  const double* shifts=nullptr, const char* title=nullptr);
146 
148  HistoND(const HistoND&);
149 
154  HistoND& operator=(const HistoND&);
155 
157  inline unsigned dim() const {return dim_;}
158 
160  inline const std::string& title() const {return title_;}
161 
163  inline const std::string& accumulatedDataLabel() const
164  {return accumulatedDataLabel_;}
165 
167  inline const ArrayND<Numeric>& binContents() const {return data_;}
168 
170  inline const ArrayND<Numeric>& overflows() const {return overflow_;}
171 
173  inline const std::vector<Axis>& axes() const {return axes_;}
174 
176  inline const Axis& axis(const unsigned i) const
177  {return axes_.at(i);}
178 
180  inline unsigned long nBins() const {return data_.length();}
181 
183  inline unsigned long nFillsTotal() const {return fillCount_;}
184 
186  inline unsigned long nFillsInRange() const
187  {return fillCount_ - overCount_;}
188 
190  inline unsigned long nFillsOver() const {return overCount_;}
191 
196  bool isUniformlyBinned() const;
197 
199  inline void setTitle(const char* newtitle)
200  {title_ = newtitle ? newtitle : ""; ++modCount_;}
201 
203  inline void setAccumulatedDataLabel(const char* newlabel)
204  {accumulatedDataLabel_ = newlabel ? newlabel : ""; ++modCount_;}
205 
207  inline void setAxisLabel(const unsigned axisNum, const char* newlabel)
208  {axes_.at(axisNum).setLabel(newlabel); ++modCount_;}
209 
214  double binVolume(unsigned long binNumber=0) const;
215 
221  void binCenter(unsigned long binNumber,
222  double* coords, unsigned lenCoords) const;
223 
231  template <class Point>
232  void allBinCenters(std::vector<Point>* centers) const;
233 
235  void binBox(unsigned long binNumber, BoxND<double>* box) const;
236 
238  BoxND<double> boundingBox() const;
239 
245  double volume() const;
246 
248  double integral() const;
249 
251  void clear();
252 
254  void clearBinContents();
255 
257  void clearOverflows();
258 
260  bool operator==(const HistoND&) const;
261 
263  bool operator!=(const HistoND&) const;
264 
269  bool isSameData(const HistoND&) const;
270 
277  template <typename Num2>
278  void fill(const double* coords, unsigned coordLength,
279  const Num2& weight);
280 
282 
286  template <typename Num2>
287  void fill(const Num2& weight);
288 
289  template <typename Num2>
290  void fill(double x0, const Num2& weight);
291 
292  template <typename Num2>
293  void fill(double x0, double x1, const Num2& weight);
294 
295  template <typename Num2>
296  void fill(double x0, double x1, double x2, const Num2& weight);
297 
298  template <typename Num2>
299  void fill(double x0, double x1, double x2, double x3,
300  const Num2& weight);
301 
302  template <typename Num2>
303  void fill(double x0, double x1, double x2, double x3, double x4,
304  const Num2& weight);
305 
306  template <typename Num2>
307  void fill(double x0, double x1, double x2, double x3, double x4,
308  double x5, const Num2& weight);
309 
310  template <typename Num2>
311  void fill(double x0, double x1, double x2, double x3, double x4,
312  double x5, double x6, const Num2& weight);
313 
314  template <typename Num2>
315  void fill(double x0, double x1, double x2, double x3, double x4,
316  double x5, double x6, double x7, const Num2& weight);
317 
318  template <typename Num2>
319  void fill(double x0, double x1, double x2, double x3, double x4,
320  double x5, double x6, double x7, double x8,
321  const Num2& weight);
322 
323  template <typename Num2>
324  void fill(double x0, double x1, double x2, double x3, double x4,
325  double x5, double x6, double x7, double x8, double x9,
326  const Num2& weight);
328 
342  template <typename Num2, class Functor>
343  void dispatch(const double* coords, unsigned coordLength,
344  Num2& weight, Functor& f);
345 
347 
351  template <typename Num2, class Functor>
352  void dispatch(Num2& weight, Functor& f);
353 
354  template <typename Num2, class Functor>
355  void dispatch(double x0, Num2& weight, Functor& f);
356 
357  template <typename Num2, class Functor>
358  void dispatch(double x0, double x1, Num2& weight, Functor& f);
359 
360  template <typename Num2, class Functor>
361  void dispatch(double x0, double x1, double x2, Num2& weight,
362  Functor& f);
363 
364  template <typename Num2, class Functor>
365  void dispatch(double x0, double x1, double x2, double x3,
366  Num2& weight, Functor& f);
367 
368  template <typename Num2, class Functor>
369  void dispatch(double x0, double x1, double x2, double x3, double x4,
370  Num2& weight, Functor& f);
371 
372  template <typename Num2, class Functor>
373  void dispatch(double x0, double x1, double x2, double x3, double x4,
374  double x5, Num2& weight, Functor& f);
375 
376  template <typename Num2, class Functor>
377  void dispatch(double x0, double x1, double x2, double x3, double x4,
378  double x5, double x6, Num2& weight, Functor& f);
379 
380  template <typename Num2, class Functor>
381  void dispatch(double x0, double x1, double x2, double x3, double x4,
382  double x5, double x6, double x7, Num2& weight,
383  Functor& f);
384 
385  template <typename Num2, class Functor>
386  void dispatch(double x0, double x1, double x2, double x3, double x4,
387  double x5, double x6, double x7, double x8,
388  Num2& weight, Functor& f);
389 
390  template <typename Num2, class Functor>
391  void dispatch(double x0, double x1, double x2, double x3, double x4,
392  double x5, double x6, double x7, double x8, double x9,
393  Num2& weight, Functor& f);
395 
402  const Numeric& examine(const double* coords,
403  unsigned coordLength) const;
404 
406 
410  const Numeric& examine() const;
411 
412  const Numeric& examine(double x0) const;
413 
414  const Numeric& examine(double x0, double x1) const;
415 
416  const Numeric& examine(double x0, double x1, double x2) const;
417 
418  const Numeric& examine(double x0, double x1, double x2,
419  double x3) const;
420 
421  const Numeric& examine(double x0, double x1, double x2, double x3,
422  double x4) const;
423 
424  const Numeric& examine(double x0, double x1, double x2, double x3,
425  double x4, double x5) const;
426 
427  const Numeric& examine(double x0, double x1, double x2, double x3,
428  double x4, double x5, double x6) const;
429 
430  const Numeric& examine(double x0, double x1, double x2, double x3,
431  double x4, double x5, double x6,
432  double x7) const;
433 
434  const Numeric& examine(double x0, double x1, double x2, double x3,
435  double x4, double x5, double x6, double x7,
436  double x8) const;
437 
438  const Numeric& examine(double x0, double x1, double x2, double x3,
439  double x4, double x5, double x6, double x7,
440  double x8, double x9) const;
442 
449  const Numeric& closestBin(const double* coords,
450  unsigned coordLength) const;
451 
453 
457  const Numeric& closestBin() const;
458 
459  const Numeric& closestBin(double x0) const;
460 
461  const Numeric& closestBin(double x0, double x1) const;
462 
463  const Numeric& closestBin(double x0, double x1, double x2) const;
464 
465  const Numeric& closestBin(double x0, double x1, double x2,
466  double x3) const;
467 
468  const Numeric& closestBin(double x0, double x1, double x2, double x3,
469  double x4) const;
470 
471  const Numeric& closestBin(double x0, double x1, double x2, double x3,
472  double x4, double x5) const;
473 
474  const Numeric& closestBin(double x0, double x1, double x2, double x3,
475  double x4, double x5, double x6) const;
476 
477  const Numeric& closestBin(double x0, double x1, double x2, double x3,
478  double x4, double x5, double x6,
479  double x7) const;
480 
481  const Numeric& closestBin(double x0, double x1, double x2, double x3,
482  double x4, double x5, double x6, double x7,
483  double x8) const;
484 
485  const Numeric& closestBin(double x0, double x1, double x2, double x3,
486  double x4, double x5, double x6, double x7,
487  double x8, double x9) const;
489 
512  template <typename Num2>
513  void fillC(const double* coords, unsigned coordLength,
514  const Num2& weight);
515 
517 
521  template <typename Num2>
522  void fillC(const Num2& weight);
523 
524  template <typename Num2>
525  void fillC(double x0, const Num2& weight);
526 
527  template <typename Num2>
528  void fillC(double x0, double x1, const Num2& weight);
529 
530  template <typename Num2>
531  void fillC(double x0, double x1, double x2, const Num2& weight);
532 
533  template <typename Num2>
534  void fillC(double x0, double x1, double x2, double x3,
535  const Num2& weight);
536 
537  template <typename Num2>
538  void fillC(double x0, double x1, double x2, double x3, double x4,
539  const Num2& weight);
540 
541  template <typename Num2>
542  void fillC(double x0, double x1, double x2, double x3, double x4,
543  double x5, const Num2& weight);
544 
545  template <typename Num2>
546  void fillC(double x0, double x1, double x2, double x3, double x4,
547  double x5, double x6, const Num2& weight);
548 
549  template <typename Num2>
550  void fillC(double x0, double x1, double x2, double x3, double x4,
551  double x5, double x6, double x7, const Num2& weight);
552 
553  template <typename Num2>
554  void fillC(double x0, double x1, double x2, double x3, double x4,
555  double x5, double x6, double x7, double x8,
556  const Num2& weight);
557 
558  template <typename Num2>
559  void fillC(double x0, double x1, double x2, double x3, double x4,
560  double x5, double x6, double x7, double x8, double x9,
561  const Num2& weight);
563 
568  template <typename Num2>
570 
580  template <typename Num2>
582 
584 
585  template <typename Num2>
586  void setBin(const unsigned *index, unsigned indexLen, const Num2& v);
587 
588  template <typename Num2>
589  void setBin(const Num2& v);
590 
591  template <typename Num2>
592  void setBin(unsigned i0, const Num2& v);
593 
594  template <typename Num2>
595  void setBin(unsigned i0, unsigned i1, const Num2& v);
596 
597  template <typename Num2>
598  void setBin(unsigned i0, unsigned i1, unsigned i2, const Num2& v);
599 
600  template <typename Num2>
601  void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
602  const Num2& v);
603 
604  template <typename Num2>
605  void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
606  unsigned i4, const Num2& v);
607 
608  template <typename Num2>
609  void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
610  unsigned i4, unsigned i5, const Num2& v);
611 
612  template <typename Num2>
613  void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
614  unsigned i4, unsigned i5, unsigned i6, const Num2& v);
615 
616  template <typename Num2>
617  void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
618  unsigned i4, unsigned i5, unsigned i6, unsigned i7,
619  const Num2& v);
620 
621  template <typename Num2>
622  void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
623  unsigned i4, unsigned i5, unsigned i6, unsigned i7,
624  unsigned i8, const Num2& v);
625 
626  template <typename Num2>
627  void setBin(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
628  unsigned i4, unsigned i5, unsigned i6, unsigned i7,
629  unsigned i8, unsigned i9, const Num2& v);
630 
631  template <typename Num2>
632  inline void setLinearBin(const unsigned long index, const Num2& v)
633  {data_.linearValue(index) = v; ++modCount_;}
635 
637 
638  template <typename Num2>
639  void setBinAt(const unsigned *index, unsigned indexLen, const Num2& v);
640 
641  template <typename Num2>
642  void setBinAt(const Num2& v);
643 
644  template <typename Num2>
645  void setBinAt(unsigned i0, const Num2& v);
646 
647  template <typename Num2>
648  void setBinAt(unsigned i0, unsigned i1, const Num2& v);
649 
650  template <typename Num2>
651  void setBinAt(unsigned i0, unsigned i1, unsigned i2, const Num2& v);
652 
653  template <typename Num2>
654  void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
655  const Num2& v);
656 
657  template <typename Num2>
658  void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
659  unsigned i4, const Num2& v);
660 
661  template <typename Num2>
662  void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
663  unsigned i4, unsigned i5, const Num2& v);
664 
665  template <typename Num2>
666  void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
667  unsigned i4, unsigned i5, unsigned i6, const Num2& v);
668 
669  template <typename Num2>
670  void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
671  unsigned i4, unsigned i5, unsigned i6, unsigned i7,
672  const Num2& v);
673 
674  template <typename Num2>
675  void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
676  unsigned i4, unsigned i5, unsigned i6, unsigned i7,
677  unsigned i8, const Num2& v);
678 
679  template <typename Num2>
680  void setBinAt(unsigned i0, unsigned i1, unsigned i2, unsigned i3,
681  unsigned i4, unsigned i5, unsigned i6, unsigned i7,
682  unsigned i8, unsigned i9, const Num2& v);
683 
684  template <typename Num2>
685  inline void setLinearBinAt(const unsigned long index, const Num2& v)
686  {data_.linearValueAt(index) = v; ++modCount_;}
688 
690  template <typename Num2>
691  void setBinContents(const Num2* data, unsigned long dataLength,
692  bool clearOverflows=true);
693 
695  template <typename Num2>
696  void setOverflows(const Num2* data, unsigned long dataLength);
697 
702  template <typename Num2>
703  inline void setBinsToConst(const Num2& value)
704  {data_.constFill(value); ++modCount_;}
705 
710  template <typename Num2>
711  inline void setOverflowsToConst(const Num2& value)
712  {overflow_.constFill(value); ++modCount_;}
713 
721 
723 
727  inline void setNFillsTotal(const unsigned long i)
728  {fillCount_ = i; ++modCount_;}
729  inline void setNFillsOver(const unsigned long i)
730  {overCount_ = i; ++modCount_;}
732 
734  template <typename Num2>
735  HistoND& operator*=(const Num2& r);
736 
738  template <typename Num2>
739  HistoND& operator/=(const Num2& r);
740 
742 
743  template <typename Num2>
744  void scaleBinContents(const Num2* data, unsigned long dataLength);
745 
746  template <typename Num2>
747  void scaleOverflows(const Num2* data, unsigned long dataLength);
749 
751 
755  template <typename Num2>
756  void addToBinContents(const Num2& weight);
757 
758  template <typename Num2>
759  void addToOverflows(const Num2& weight);
761 
763 
768  template <typename Num2>
769  void addToBinContents(const Num2* data, unsigned long dataLength);
770 
771  template <typename Num2>
772  void addToOverflows(const Num2* data, unsigned long dataLength);
774 
783  template <typename Acc>
784  void accumulateBinsInBox(const BoxND<double>& box, Acc* acc,
785  bool calculateAverage = false) const;
786 
788 
798  template <typename Num2, typename Num3>
799  void addToProjection(HistoND<Num2,Axis>* projection,
801  const unsigned *projectedIndices,
802  unsigned nProjectedIndices) const;
803 
804  template <typename Num2, typename Num3>
805  void addToProjection(HistoND<Num2,Axis>* projection,
806  AbsVisitor<Numeric,Num3>& projector,
807  const unsigned *projectedIndices,
808  unsigned nProjectedIndices) const;
810 
812  HistoND transpose(unsigned axisNum1, unsigned axisNum2) const;
813 
826  inline unsigned long getModCount() const {return modCount_;}
827 
833  inline void incrModCount() {++modCount_;}
834 
836 
837  inline gs::ClassId classId() const {return gs::ClassId(*this);}
838  bool write(std::ostream& of) const;
840 
841  static const char* classname();
842  static inline unsigned version() {return 1;}
843  static HistoND* read(const gs::ClassId& id, std::istream& in);
844 
845  private:
846  HistoND() = delete;
847 
848  // Special constructor which speeds up the "transpose" operation.
849  // Does not do full error checking (some of it is done in transpose).
850  HistoND(const HistoND& r, unsigned ax1, unsigned ax2);
851 
852  template <typename Num2>
853  void fillPreservingCentroid(const Num2& weight);
854 
855  template <typename Acc>
856  void accumulateBinsLoop(unsigned level, const BoxND<double>& box,
857  unsigned* idx, Acc* accumulator,
858  double overlapFraction, long double* wsum) const;
863  std::vector<Axis> axes_;
864  mutable std::vector<double> weightBuf_;
865  mutable std::vector<unsigned> indexBuf_;
866  unsigned long fillCount_;
867  unsigned long overCount_;
868  unsigned long modCount_;
869  unsigned dim_;
870 
871  };
872 
887  template <typename Histo>
888  void convertHistoToDensity(Histo* histogram, bool knownNonNegative=false);
889 
895  template <typename Histo>
896  std::vector<LinearMapper1d> densityScanHistoMap(const Histo& histo);
897 
908  template <typename Histo>
909  std::vector<CircularMapper1d> convolutionHistoMap(const Histo& histo,
910  bool doubleDataRange);
911 }
912 
913 #include <cassert>
915 #include <sstream>
916 #include <climits>
917 #include <algorithm>
918 
919 #include "Alignment/Geners/interface/CPP11_auto_ptr.hh"
920 #include "Alignment/Geners/interface/binaryIO.hh"
921 
922 namespace npstat {
923  namespace Private {
924  template <class Axis>
925  ArrayShape makeHistoShape(const std::vector<Axis>& axes)
926  {
927  const unsigned n = axes.size();
929  result.reserve(n);
930  for (unsigned i=0; i<n; ++i)
931  result.push_back(axes[i].nBins());
932  return result;
933  }
934 
935  template <class Axis>
937  {
939  result.reserve(1U);
940  result.push_back(xAxis.nBins());
941  return result;
942  }
943 
944  template <class Axis>
945  ArrayShape makeHistoShape(const Axis& xAxis, const Axis& yAxis)
946  {
948  result.reserve(2U);
949  result.push_back(xAxis.nBins());
950  result.push_back(yAxis.nBins());
951  return result;
952  }
953 
954  template <class Axis>
956  const Axis& yAxis,
957  const Axis& zAxis)
958  {
960  result.reserve(3U);
961  result.push_back(xAxis.nBins());
962  result.push_back(yAxis.nBins());
963  result.push_back(zAxis.nBins());
964  return result;
965  }
966 
967  template <class Axis>
968  ArrayShape makeHistoShape(const Axis& xAxis, const Axis& yAxis,
969  const Axis& zAxis, const Axis& tAxis)
970  {
972  result.reserve(4U);
973  result.push_back(xAxis.nBins());
974  result.push_back(yAxis.nBins());
975  result.push_back(zAxis.nBins());
976  result.push_back(tAxis.nBins());
977  return result;
978  }
979 
980  template <class Axis>
981  ArrayShape makeHistoShape(const Axis& xAxis, const Axis& yAxis,
982  const Axis& zAxis, const Axis& tAxis,
983  const Axis& vAxis)
984  {
986  result.reserve(5U);
987  result.push_back(xAxis.nBins());
988  result.push_back(yAxis.nBins());
989  result.push_back(zAxis.nBins());
990  result.push_back(tAxis.nBins());
991  result.push_back(vAxis.nBins());
992  return result;
993  }
994 
995  template <class Axis>
996  std::vector<Axis> rebinAxes(const std::vector<Axis>& axes,
997  const unsigned *newBins,
998  const unsigned lenNewBins)
999  {
1000  const unsigned dim = axes.size();
1001  if (lenNewBins != dim) throw npstat::NpstatInvalidArgument(
1002  "In npstat::Private::rebinAxes: invalid length "
1003  "of the new bins array");
1004  assert(newBins);
1005  std::vector<Axis> newAxes;
1006  newAxes.reserve(dim);
1007  for (unsigned i=0; i<dim; ++i)
1008  newAxes.push_back(axes[i].rebin(newBins[i]));
1009  return newAxes;
1010  }
1011 
1012  template <class Axis>
1013  std::vector<Axis> axesOfASlice(const std::vector<Axis>& axes,
1014  const unsigned *fixedIndices,
1015  const unsigned nFixedIndices)
1016  {
1017  const unsigned dim = axes.size();
1018  std::vector<Axis> newAxes;
1019  if (nFixedIndices == 0U) throw npstat::NpstatInvalidArgument(
1020  "In npstat::Private::axesOfASlice: "
1021  "at least one fixed index must be specified");
1022  if (nFixedIndices > dim) throw npstat::NpstatInvalidArgument(
1023  "In npstat::Private::axesOfASlice: too many fixed indices");
1024  assert(fixedIndices);
1025  for (unsigned i=0; i<nFixedIndices; ++i)
1026  if (fixedIndices[i] >= dim) throw npstat::NpstatInvalidArgument(
1027  "In npstat::Private::axesOfASlice: fixed index out of range");
1028  newAxes.reserve(dim - nFixedIndices);
1029  for (unsigned i=0; i<dim; ++i)
1030  {
1031  bool fixed = false;
1032  for (unsigned j=0; j<nFixedIndices; ++j)
1033  if (fixedIndices[j] == i)
1034  {
1035  fixed = true;
1036  break;
1037  }
1038  if (!fixed)
1039  newAxes.push_back(axes[i]);
1040  }
1041  if (newAxes.size() != dim - nFixedIndices)
1043  "In npstat::Private::axesOfASlice: duplicate fixed index");
1044  return newAxes;
1045  }
1046 
1047  template <class Axis>
1048  ArrayShape shapeOfASlice(const std::vector<Axis>& axes,
1049  const unsigned *fixedIndices,
1050  const unsigned nFixedIndices)
1051  {
1052  const unsigned dim = axes.size();
1053  if (nFixedIndices == 0U) throw npstat::NpstatInvalidArgument(
1054  "In npstat::Private::shapeOfASlice: "
1055  "at least one fixed index must be specified");
1056  if (nFixedIndices > dim) throw npstat::NpstatInvalidArgument(
1057  "In npstat::Private::shapeOfASlice: too many fixed indices");
1058  assert(fixedIndices);
1059 
1060  // Check that the fixed indices are within range
1061  for (unsigned j=0; j<nFixedIndices; ++j)
1062  if (fixedIndices[j] >= dim) throw npstat::NpstatInvalidArgument(
1063  "In npstat::Private::shapeOfASlice: fixed index out of range");
1064 
1065  // Build the shape for the slice
1066  ArrayShape sh;
1067  if (nFixedIndices < dim)
1068  sh.reserve(dim - nFixedIndices);
1069  for (unsigned i=0; i<dim; ++i)
1070  {
1071  bool fixed = false;
1072  for (unsigned j=0; j<nFixedIndices; ++j)
1073  if (fixedIndices[j] == i)
1074  {
1075  fixed = true;
1076  break;
1077  }
1078  if (!fixed)
1079  sh.push_back(axes[i].nBins());
1080  }
1081  if (sh.size() != dim - nFixedIndices)
1083  "In npstat::Private::shapeOfASlice: duplicate fixed index");
1084  return sh;
1085  }
1086 
1087  template <class Axis>
1088  std::vector<Axis> addAxis(const std::vector<Axis>& axes,
1089  const Axis& newAxis,
1090  const unsigned newAxisNumber)
1091  {
1092  const unsigned dim = axes.size();
1093  std::vector<Axis> newAxes;
1094  newAxes.reserve(dim + 1U);
1095  unsigned iadd = 0;
1096  for (unsigned i=0; i<dim; ++i)
1097  {
1098  if (newAxisNumber == i)
1099  newAxes.push_back(newAxis);
1100  else
1101  newAxes.push_back(axes[iadd++]);
1102  }
1103  if (iadd == dim)
1104  newAxes.push_back(newAxis);
1105  else
1106  newAxes.push_back(axes[iadd]);
1107  return newAxes;
1108  }
1109 
1110  template <class Axis>
1111  ArrayShape shapeWithExtraAxis(const std::vector<Axis>& axes,
1112  const Axis& newAxis,
1113  const unsigned newAxisNumber)
1114  {
1115  const unsigned dim = axes.size();
1117  result.reserve(dim + 1U);
1118  unsigned iadd = 0;
1119  for (unsigned i=0; i<dim; ++i)
1120  {
1121  if (newAxisNumber == i)
1122  result.push_back(newAxis.nBins());
1123  else
1124  result.push_back(axes[iadd++].nBins());
1125  }
1126  if (iadd == dim)
1127  result.push_back(newAxis.nBins());
1128  else
1129  result.push_back(axes[iadd].nBins());
1130  return result;
1131  }
1132 
1133  inline void h_badargs(const char* method)
1134  {
1135  std::ostringstream os;
1136  os << "In npstat::HistoND::" << method << ": number of arguments"
1137  << " is incompatible with histogram dimensionality";
1138  throw npstat::NpstatInvalidArgument(os.str());
1139  }
1140  }
1141 
1142  template <typename Numeric, class Axis>
1143  template <typename Acc>
1145  const unsigned level, const BoxND<double>& box,
1146  unsigned* idx, Acc* accumulator, const double overlapFraction,
1147  long double* wsum) const
1148  {
1149  const Interval<double>& boxSide(box[level]);
1150  const Axis& axis(axes_[level]);
1151  const unsigned nbins = axis.nBins();
1152  const bool lastLevel = level == dim_ - 1U;
1153  for (unsigned i=0; i<nbins; ++i)
1154  {
1155  const double over = overlapFraction*
1156  axis.binInterval(i).overlapFraction(boxSide);
1157  if (over > 0.0)
1158  {
1159  idx[level] = i;
1160  if (lastLevel)
1161  {
1162  *accumulator += over*data_.value(idx, dim_);
1163  *wsum += over;
1164  }
1165  else
1166  accumulateBinsLoop(level+1U, box, idx, accumulator,
1167  over, wsum);
1168  }
1169  }
1170  }
1171 
1172  template <typename Numeric, class Axis>
1173  template <typename Acc>
1175  const BoxND<double>& box, Acc* accumulator,
1176  const bool calculateAverage) const
1177  {
1178  if (box.size() != dim_) throw npstat::NpstatInvalidArgument(
1179  "In npstat::HistoND::accumulateBinsInBox: "
1180  "incompatible box dimensionality");
1181  assert(accumulator);
1182  if (dim_)
1183  {
1184  long double wsum = 0.0L;
1185  for (unsigned i=0; i<dim_; ++i)
1186  indexBuf_[i] = 0U;
1187  accumulateBinsLoop(0U, box, &indexBuf_[0], accumulator, 1.0, &wsum);
1188  if (calculateAverage && wsum > 0.0L)
1189  *accumulator *= static_cast<double>(1.0L/wsum);
1190  }
1191  else
1192  *accumulator += 1.0*data_();
1193  }
1194 
1195  template <typename Numeric, class Axis>
1197  {
1198  data_.clear();
1199  fillCount_ = 0UL;
1200  ++modCount_;
1201  }
1202 
1203  template <typename Numeric, class Axis>
1205  {
1206  overflow_.clear();
1207  overCount_ = 0UL;
1208  ++modCount_;
1209  }
1210 
1211  template <typename Numeric, class Axis>
1213  {
1214  clearBinContents();
1215  clearOverflows();
1216  ++modCount_;
1217  }
1218 
1219  template <typename Numeric, class Axis>
1220  HistoND<Numeric,Axis>::HistoND(const std::vector<Axis>& axesIn,
1221  const char* title, const char* label)
1222  : title_(title ? title : ""),
1223  accumulatedDataLabel_(label ? label : ""),
1224  data_(Private::makeHistoShape(axesIn)),
1225  overflow_(ArrayShape(axesIn.size(), 3U)),
1226  axes_(axesIn),
1227  weightBuf_(axesIn.size()),
1228  indexBuf_(2U*axesIn.size()),
1229  modCount_(0UL),
1230  dim_(axesIn.size())
1231  {
1232  if (dim_ >= CHAR_BIT*sizeof(unsigned long))
1234  "In npstat::HistoND constructor: requested histogram "
1235  "dimensionality is not supported (too large)");
1236  clear();
1237  }
1238 
1239  template <typename Numeric, class Axis>
1241  const char* title, const char* label)
1242  : title_(title ? title : ""),
1243  accumulatedDataLabel_(label ? label : ""),
1244  data_(Private::makeHistoShape(xAxis)),
1245  overflow_(ArrayShape(1U, 3U)),
1246  weightBuf_(1U),
1247  indexBuf_(2U*1U),
1248  modCount_(0UL),
1249  dim_(1U)
1250  {
1251  axes_.reserve(dim_);
1252  axes_.push_back(xAxis);
1253  clear();
1254  }
1255 
1256  template <typename Numeric, class Axis>
1257  HistoND<Numeric,Axis>::HistoND(const Axis& xAxis, const Axis& yAxis,
1258  const char* title, const char* label)
1259  : title_(title ? title : ""),
1260  accumulatedDataLabel_(label ? label : ""),
1261  data_(Private::makeHistoShape(xAxis, yAxis)),
1262  overflow_(ArrayShape(2U, 3U)),
1263  weightBuf_(2U),
1264  indexBuf_(2U*2U),
1265  modCount_(0UL),
1266  dim_(2U)
1267  {
1268  axes_.reserve(dim_);
1269  axes_.push_back(xAxis);
1270  axes_.push_back(yAxis);
1271  clear();
1272  }
1273 
1274  template <typename Numeric, class Axis>
1275  HistoND<Numeric,Axis>::HistoND(const Axis& xAxis, const Axis& yAxis,
1276  const Axis& zAxis, const char* title,
1277  const char* label)
1278  : title_(title ? title : ""),
1279  accumulatedDataLabel_(label ? label : ""),
1280  data_(Private::makeHistoShape(xAxis, yAxis, zAxis)),
1281  overflow_(ArrayShape(3U, 3U)),
1282  weightBuf_(3U),
1283  indexBuf_(2U*3U),
1284  modCount_(0UL),
1285  dim_(3U)
1286  {
1287  axes_.reserve(dim_);
1288  axes_.push_back(xAxis);
1289  axes_.push_back(yAxis);
1290  axes_.push_back(zAxis);
1291  clear();
1292  }
1293 
1294  template <typename Numeric, class Axis>
1295  HistoND<Numeric,Axis>::HistoND(const Axis& xAxis, const Axis& yAxis,
1296  const Axis& zAxis, const Axis& tAxis,
1297  const char* title, const char* label)
1298  : title_(title ? title : ""),
1299  accumulatedDataLabel_(label ? label : ""),
1300  data_(Private::makeHistoShape(xAxis, yAxis, zAxis, tAxis)),
1301  overflow_(ArrayShape(4U, 3U)),
1302  weightBuf_(4U),
1303  indexBuf_(2U*4U),
1304  modCount_(0UL),
1305  dim_(4U)
1306  {
1307  axes_.reserve(dim_);
1308  axes_.push_back(xAxis);
1309  axes_.push_back(yAxis);
1310  axes_.push_back(zAxis);
1311  axes_.push_back(tAxis);
1312  clear();
1313  }
1314 
1315  template <typename Numeric, class Axis>
1316  HistoND<Numeric,Axis>::HistoND(const Axis& xAxis, const Axis& yAxis,
1317  const Axis& zAxis, const Axis& tAxis,
1318  const Axis& vAxis,
1319  const char* title, const char* label)
1320  : title_(title ? title : ""),
1321  accumulatedDataLabel_(label ? label : ""),
1322  data_(Private::makeHistoShape(xAxis, yAxis, zAxis, tAxis, vAxis)),
1323  overflow_(ArrayShape(5U, 3U)),
1324  weightBuf_(5U),
1325  indexBuf_(2U*5U),
1326  modCount_(0UL),
1327  dim_(5U)
1328  {
1329  axes_.reserve(dim_);
1330  axes_.push_back(xAxis);
1331  axes_.push_back(yAxis);
1332  axes_.push_back(zAxis);
1333  axes_.push_back(tAxis);
1334  axes_.push_back(vAxis);
1335  clear();
1336  }
1337 
1338  template <typename Numeric, class Axis>
1340  const BoxND<double>& boundingBox,
1341  const char* title, const char* label)
1342  : title_(title ? title : ""),
1343  accumulatedDataLabel_(label ? label : ""),
1344  data_(shape),
1345  overflow_(ArrayShape(shape.size(), 3U)),
1346  weightBuf_(shape.size()),
1347  indexBuf_(2U*shape.size()),
1348  modCount_(0UL),
1349  dim_(shape.size())
1350  {
1351  if (boundingBox.size() != dim_) throw npstat::NpstatInvalidArgument(
1352  "In npstat::HistoND constructor: "
1353  "incompatible bounding box dimensionality");
1354  if (dim_ >= CHAR_BIT*sizeof(unsigned long))
1356  "In npstat::HistoND constructor: requested histogram "
1357  "dimensionality is not supported (too large)");
1358  axes_.reserve(dim_);
1359  for (unsigned i=0; i<dim_; ++i)
1360  axes_.push_back(Axis(shape[i],
1361  boundingBox[i].min(),
1362  boundingBox[i].max()));
1363  clear();
1364  }
1365 
1366  template <typename Numeric, class Axis>
1367  template <typename Num2, class Functor>
1369  const HistoND<Num2,Axis>& r, const Functor& f,
1370  const char* title, const char* label)
1371  : title_(title ? title : ""),
1372  accumulatedDataLabel_(label ? label : ""),
1373  data_(r.data_, f),
1374  overflow_(r.overflow_, f),
1375  axes_(r.axes_),
1376  weightBuf_(r.dim_),
1377  indexBuf_(2U*r.dim_),
1380  modCount_(0UL),
1381  dim_(r.dim_)
1382  {
1383  }
1384 
1385  template <typename Numeric, class Axis>
1386  template <typename Num2>
1388  const HistoND<Num2,Axis>& h, const unsigned *indices,
1389  const unsigned nIndices, const char* title)
1390  : title_(title ? title : ""),
1392  data_(Private::shapeOfASlice(h.axes_, indices, nIndices)),
1393  overflow_(ArrayShape(data_.rank(), 3U)),
1394  axes_(Private::axesOfASlice(h.axes_, indices, nIndices)),
1395  weightBuf_(data_.rank()),
1396  indexBuf_(2U*data_.rank()),
1397  modCount_(0UL),
1398  dim_(data_.rank())
1399  {
1400  clear();
1401  }
1402 
1403  template <typename Numeric, class Axis>
1404  template <typename Num2>
1406  const HistoND<Num2,Axis>& h, const Axis& newAxis,
1407  const unsigned newAxisNumber, const char* title)
1408  : title_(title ? title : ""),
1410  data_(Private::shapeWithExtraAxis(h.axes_, newAxis, newAxisNumber)),
1411  overflow_(data_.rank(), 3U),
1412  axes_(Private::addAxis(h.axes_, newAxis, newAxisNumber)),
1413  weightBuf_(data_.rank()),
1414  indexBuf_(2U*data_.rank()),
1415  modCount_(0UL),
1416  dim_(data_.rank())
1417  {
1418  if (dim_ >= CHAR_BIT*sizeof(unsigned long))
1420  "In npstat::HistoND constructor: requested histogram "
1421  "dimensionality is not supported (too large)");
1422  clear();
1423  }
1424 
1425  template <typename Numeric, class Axis>
1426  template <typename Num2>
1428  const HistoND<Num2,Axis>& h, const RebinType rType,
1429  const unsigned *newBinCounts, const unsigned lenNewBinCounts,
1430  const double* shifts, const char* title)
1431  : title_(title ? title : h.title_.c_str()),
1433  data_(newBinCounts, lenNewBinCounts),
1434  overflow_(h.overflow_),
1435  axes_(Private::rebinAxes(h.axes_, newBinCounts, lenNewBinCounts)),
1436  weightBuf_(h.dim_),
1437  indexBuf_(2U*h.dim_),
1440  modCount_(0UL),
1441  dim_(h.dim_)
1442  {
1443  const unsigned long newBins = data_.length();
1444  const Axis* ax = &axes_[0];
1445  unsigned* ubuf = &indexBuf_[0];
1446 
1447  // Fill out the bins of the new histogram
1448  if (rType == SAMPLE)
1449  {
1450  double* buf = &weightBuf_[0];
1451  for (unsigned long ibin=0; ibin<newBins; ++ibin)
1452  {
1453  data_.convertLinearIndex(ibin, ubuf, dim_);
1454  if (shifts)
1455  for (unsigned i=0; i<dim_; ++i)
1456  buf[i] = ax[i].binCenter(ubuf[i]) + shifts[i];
1457  else
1458  for (unsigned i=0; i<dim_; ++i)
1459  buf[i] = ax[i].binCenter(ubuf[i]);
1460  data_.linearValue(ibin) = h.examine(buf, dim_);
1461  }
1462  }
1463  else
1464  {
1465  const Numeric zero = Numeric();
1466  BoxND<double> binLimits(dim_);
1467  for (unsigned long ibin=0; ibin<newBins; ++ibin)
1468  {
1469  data_.convertLinearIndex(ibin, ubuf, dim_);
1470  for (unsigned i=0; i<dim_; ++i)
1471  binLimits[i] = ax[i].binInterval(ubuf[i]);
1472  Numeric& thisBin(data_.linearValue(ibin));
1473  thisBin = zero;
1474  h.accumulateBinsInBox(binLimits, &thisBin, rType == AVERAGE);
1475  }
1476  }
1477  }
1478 
1479  template <typename Numeric, class Axis>
1481  {
1482  for (unsigned i=0; i<dim_; ++i)
1483  if (!axes_[i].isUniform())
1484  return false;
1485  return true;
1486  }
1487 
1488  template <typename Numeric, class Axis>
1490  {
1491  typedef typename PreciseType<Numeric>::type Precise;
1492 
1493  if (dim_ == 0U)
1494  return 0.0;
1495  if (isUniformlyBinned())
1496  {
1497  Precise sum = data_.template sum<Precise>();
1498  return static_cast<double>(sum)*binVolume();
1499  }
1500  else
1501  {
1502  Precise sum = Precise();
1503  const Numeric* data = data_.data();
1504  const unsigned long len = data_.length();
1505  for (unsigned long i=0; i<len; ++i)
1506  sum += data[i]*binVolume(i);
1507  return static_cast<double>(sum);
1508  }
1509  }
1510 
1511  template <typename Numeric, class Axis>
1513  {
1514  BoxND<double> box;
1515  if (dim_)
1516  {
1517  box.reserve(dim_);
1518  const Axis* ax = &axes_[0];
1519  for (unsigned i=0; i<dim_; ++i)
1520  box.push_back(ax[i].interval());
1521  }
1522  return box;
1523  }
1524 
1525  template <typename Numeric, class Axis>
1527  const unsigned long binNumber,
1528  double* coords, const unsigned lenCoords) const
1529  {
1530  if (dim_ != lenCoords) throw npstat::NpstatInvalidArgument(
1531  "In npstat::HistoND::binCenter: "
1532  "incompatible input point dimensionality");
1533  if (dim_)
1534  {
1535  assert(coords);
1536  data_.convertLinearIndex(binNumber, &indexBuf_[0], dim_);
1537  const Axis* ax = &axes_[0];
1538  for (unsigned i=0; i<dim_; ++i)
1539  coords[i] = ax[i].binCenter(indexBuf_[i]);
1540  }
1541  }
1542 
1543  template <typename Numeric, class Axis>
1544  template <class Point>
1546  std::vector<Point>* centers) const
1547  {
1548  assert(centers);
1549  centers->clear();
1550  const unsigned long len = data_.length();
1551  centers->reserve(len);
1552  unsigned* ibuf = &indexBuf_[0];
1553  const Axis* ax = &axes_[0];
1554  Point center;
1555  if (center.size() < dim_) throw npstat::NpstatInvalidArgument(
1556  "In npstat::HistoND::allBinCenters: "
1557  "incompatible point dimensionality (too small)");
1558  typename Point::value_type* cdat = &center[0];
1559 
1560  for (unsigned long i=0; i<len; ++i)
1561  {
1562  data_.convertLinearIndex(i, ibuf, dim_);
1563  for (unsigned idim=0; idim<dim_; ++idim)
1564  cdat[idim] = ax[idim].binCenter(ibuf[idim]);
1565  centers->push_back(center);
1566  }
1567  }
1568 
1569  template <typename Numeric, class Axis>
1570  void HistoND<Numeric,Axis>::binBox(const unsigned long binNumber,
1571  BoxND<double>* box) const
1572  {
1573  assert(box);
1574  box->clear();
1575  if (dim_)
1576  {
1577  box->reserve(dim_);
1578  data_.convertLinearIndex(binNumber, &indexBuf_[0], dim_);
1579  const Axis* ax = &axes_[0];
1580  for (unsigned i=0; i<dim_; ++i)
1581  box->push_back(ax[i].binInterval(indexBuf_[i]));
1582  }
1583  }
1584 
1585  template <typename Numeric, class Axis>
1586  inline bool HistoND<Numeric,Axis>::isSameData(const HistoND& r) const
1587  {
1588  return dim_ == r.dim_ &&
1589  overflow_ == r.overflow_ &&
1590  data_ == r.data_;
1591  }
1592 
1593  template <typename Numeric, class Axis>
1594  inline bool HistoND<Numeric,Axis>::operator==(const HistoND& r) const
1595  {
1596  return dim_ == r.dim_ &&
1597  fillCount_ == r.fillCount_ &&
1598  overCount_ == r.overCount_ &&
1599  title_ == r.title_ &&
1600  accumulatedDataLabel_ == r.accumulatedDataLabel_ &&
1601  axes_ == r.axes_ &&
1602  overflow_ == r.overflow_ &&
1603  data_ == r.data_;
1604  }
1605 
1606  template <typename Numeric, class Axis>
1607  inline bool HistoND<Numeric,Axis>::operator!=(const HistoND& r) const
1608  {
1609  return !(*this == r);
1610  }
1611 
1612  template <typename Numeric, class Axis>
1614  const unsigned long binNumber) const
1615  {
1616  double v = 1.0;
1617  if (dim_)
1618  {
1619  data_.convertLinearIndex(binNumber, &indexBuf_[0], dim_);
1620  const Axis* ax = &axes_[0];
1621  for (unsigned i=0; i<dim_; ++i)
1622  v *= ax[i].binWidth(indexBuf_[i]);
1623  }
1624  return v;
1625  }
1626 
1627  template <typename Numeric, class Axis>
1629  {
1630  double v = 1.0;
1631  if (dim_)
1632  {
1633  const Axis* ax = &axes_[0];
1634  for (unsigned i=0; i<dim_; ++i)
1635  v *= (ax[i].max() - ax[i].min());
1636  }
1637  return v;
1638  }
1639 
1640  template <typename Numeric, class Axis>
1641  template <typename Num2>
1643  const double* coords, const unsigned coordLength, const Num2& w)
1644  {
1645  if (coordLength != dim_) throw npstat::NpstatInvalidArgument(
1646  "In npstat::HistoND::fill: "
1647  "incompatible input point dimensionality");
1648  if (coordLength)
1649  {
1650  assert(coords);
1651  unsigned* idx = &indexBuf_[0];
1652  unsigned* over = idx + dim_;
1653  const Axis* ax = &axes_[0];
1654  unsigned overflown = 0U;
1655  for (unsigned i=0; i<dim_; ++i)
1656  {
1657  over[i] = ax[i].overflowIndex(coords[i], idx + i);
1658  overflown |= (over[i] - 1U);
1659  }
1660  if (overflown)
1661  {
1662  overflow_.value(over, dim_) += w;
1663  ++overCount_;
1664  }
1665  else
1666  data_.value(idx, dim_) += w;
1667  }
1668  else
1669  data_() += w;
1670  ++fillCount_; ++modCount_;
1671  }
1672 
1673  template <typename Numeric, class Axis>
1674  template <typename Num2, class Functor>
1676  const double* coords, const unsigned coordLength, Num2& w, Functor& f)
1677  {
1678  if (coordLength != dim_) throw npstat::NpstatInvalidArgument(
1679  "In npstat::HistoND::dispatch: "
1680  "incompatible input point dimensionality");
1681  if (coordLength)
1682  {
1683  assert(coords);
1684  unsigned* idx = &indexBuf_[0];
1685  unsigned* over = idx + dim_;
1686  const Axis* ax = &axes_[0];
1687  unsigned overflown = 0U;
1688  for (unsigned i=0; i<dim_; ++i)
1689  {
1690  over[i] = ax[i].overflowIndex(coords[i], idx + i);
1691  overflown |= (over[i] - 1U);
1692  }
1693  if (overflown)
1694  f(overflow_.value(over, dim_), w);
1695  else
1696  f(data_.value(idx, dim_), w);
1697  }
1698  else
1699  f(data_(), w);
1700  ++modCount_;
1701  }
1702 
1703  template <typename Numeric, class Axis>
1705  const double* coords, const unsigned coordLength) const
1706  {
1707  if (coordLength != dim_) throw npstat::NpstatInvalidArgument(
1708  "In npstat::HistoND::examine: "
1709  "incompatible input point dimensionality");
1710  if (coordLength)
1711  {
1712  assert(coords);
1713  unsigned* idx = &indexBuf_[0];
1714  unsigned* over = idx + dim_;
1715  const Axis* ax = &axes_[0];
1716  unsigned overflown = 0U;
1717  for (unsigned i=0; i<dim_; ++i)
1718  {
1719  over[i] = ax[i].overflowIndex(coords[i], idx + i);
1720  overflown |= (over[i] - 1U);
1721  }
1722  if (overflown)
1723  return overflow_.value(over, dim_);
1724  else
1725  return data_.value(idx, dim_);
1726  }
1727  else
1728  return data_();
1729  }
1730 
1731  template <typename Numeric, class Axis>
1733  const double* coords, const unsigned coordLength) const
1734  {
1735  if (coordLength != dim_) throw npstat::NpstatInvalidArgument(
1736  "In npstat::HistoND::closestBin: "
1737  "incompatible input point dimensionality");
1738  if (coordLength)
1739  {
1740  assert(coords);
1741  unsigned* idx = &indexBuf_[0];
1742  const Axis* ax = &axes_[0];
1743  for (unsigned i=0; i<dim_; ++i)
1744  idx[i] = ax[i].closestValidBin(coords[i]);
1745  return data_.value(idx, dim_);
1746  }
1747  else
1748  return data_();
1749  }
1750 
1751  template <typename Numeric, class Axis>
1752  template <typename Num2>
1754  {
1755  const double* weights = &weightBuf_[0];
1756  const unsigned* cell = &indexBuf_[0];
1757  const unsigned long* strides = data_.strides();
1758  const unsigned long maxcycle = 1UL << dim_;
1759  for (unsigned long icycle=0; icycle<maxcycle; ++icycle)
1760  {
1761  double w = 1.0;
1762  unsigned long icell = 0UL;
1763  for (unsigned i=0; i<dim_; ++i)
1764  {
1765  if (icycle & (1UL << i))
1766  {
1767  w *= (1.0 - weights[i]);
1768  icell += strides[i]*(cell[i] + 1U);
1769  }
1770  else
1771  {
1772  w *= weights[i];
1773  icell += strides[i]*cell[i];
1774  }
1775  }
1776  data_.linearValue(icell) += (value * w);
1777  }
1778  }
1779 
1780  template <typename Numeric, class Axis>
1781  template <typename Num2>
1783  const double* coords, const unsigned coordLength, const Num2& w)
1784  {
1785  if (coordLength != dim_) throw npstat::NpstatInvalidArgument(
1786  "In npstat::HistoND::fillC: "
1787  "incompatible input point dimensionality");
1788  if (coordLength)
1789  {
1790  assert(coords);
1791  double* wg = &weightBuf_[0];
1792  unsigned* idx = &indexBuf_[0];
1793  unsigned* over = idx + dim_;
1794  const Axis* ax = &axes_[0];
1795  unsigned overflown = 0U;
1796  for (unsigned i=0; i<dim_; ++i)
1797  {
1798  over[i] = ax[i].overflowIndexWeighted(coords[i], idx+i, wg+i);
1799  overflown |= (over[i] - 1U);
1800  }
1801  if (overflown)
1802  {
1803  overflow_.value(over, dim_) += w;
1804  ++overCount_;
1805  }
1806  else
1808  }
1809  else
1810  data_() += w;
1811  ++fillCount_; ++modCount_;
1812  }
1813 
1814  template <typename Numeric, class Axis>
1815  template <typename Num2>
1816  inline void HistoND<Numeric,Axis>::fill(const Num2& w)
1817  {
1818  if (dim_) Private::h_badargs("fill");
1819  data_() += w;
1820  ++fillCount_; ++modCount_;
1821  }
1822 
1823  template <typename Numeric, class Axis>
1824  template <typename Num2, class Functor>
1825  inline void HistoND<Numeric,Axis>::dispatch(Num2& w, Functor& f)
1826  {
1827  if (dim_) Private::h_badargs("dispatch");
1828  f(data_(), w);
1829  ++modCount_;
1830  }
1831 
1832  template <typename Numeric, class Axis>
1833  template <typename Num2>
1834  inline void HistoND<Numeric,Axis>::fillC(const Num2& w)
1835  {
1836  if (dim_) Private::h_badargs("fillC");
1837  data_() += w;
1838  ++fillCount_; ++modCount_;
1839  }
1840 
1841  template <typename Numeric, class Axis>
1842  inline const Numeric& HistoND<Numeric,Axis>::examine() const
1843  {
1844  if (dim_) Private::h_badargs("examine");
1845  return data_();
1846  }
1847 
1848  template <typename Numeric, class Axis>
1849  inline const Numeric& HistoND<Numeric,Axis>::closestBin() const
1850  {
1851  if (dim_) Private::h_badargs("closestBin");
1852  return data_();
1853  }
1854 
1855  template <typename Numeric, class Axis>
1856  template <typename Num2>
1857  void HistoND<Numeric,Axis>::fill(const double x0, const Num2& w)
1858  {
1859  if (dim_ != 1U) Private::h_badargs("fill");
1860  unsigned i0 = 0;
1861  const unsigned ov0 = axes_[0].overflowIndex(x0, &i0);
1862  if (ov0 == 1U)
1863  data_(i0) += w;
1864  else
1865  {
1866  overflow_(ov0) += w;
1867  ++overCount_;
1868  }
1869  ++fillCount_; ++modCount_;
1870  }
1871 
1872  template <typename Numeric, class Axis>
1873  template <typename Num2, class Functor>
1874  void HistoND<Numeric,Axis>::dispatch(const double x0, Num2& w, Functor& f)
1875  {
1876  if (dim_ != 1U) Private::h_badargs("dispatch");
1877  unsigned i0 = 0;
1878  const unsigned ov0 = axes_[0].overflowIndex(x0, &i0);
1879  if (ov0 == 1U)
1880  f(data_(i0), w);
1881  else
1882  f(overflow_(ov0), w);
1883  ++modCount_;
1884  }
1885 
1886  template <typename Numeric, class Axis>
1887  template <typename Num2>
1888  void HistoND<Numeric,Axis>::fillC(const double x0, const Num2& w)
1889  {
1890  if (dim_ != 1U) Private::h_badargs("fillC");
1891  double* wg = &weightBuf_[0];
1892  unsigned* idx = &indexBuf_[0];
1893  const unsigned ov0 = axes_[0].overflowIndexWeighted(x0, idx, wg);
1894  if (ov0 == 1U)
1896  else
1897  {
1898  overflow_(ov0) += w;
1899  ++overCount_;
1900  }
1901  ++fillCount_; ++modCount_;
1902  }
1903 
1904  template <typename Numeric, class Axis>
1905  inline const Numeric& HistoND<Numeric,Axis>::examine(const double x0) const
1906  {
1907  if (dim_ != 1U) Private::h_badargs("examine");
1908  unsigned i0 = 0;
1909  const unsigned ov0 = axes_[0].overflowIndex(x0, &i0);
1910  if (ov0 == 1U)
1911  return data_(i0);
1912  else
1913  return overflow_(ov0);
1914  }
1915 
1916  template <typename Numeric, class Axis>
1917  inline const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0) const
1918  {
1919  if (dim_ != 1U) Private::h_badargs("closestBin");
1920  const unsigned i0 = axes_[0].closestValidBin(x0);
1921  return data_(i0);
1922  }
1923 
1924  template <typename Numeric, class Axis>
1925  template <typename Num2>
1926  void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
1927  const Num2& w)
1928  {
1929  if (dim_ != 2U) Private::h_badargs("fill");
1930  unsigned i0 = 0, i1 = 0;
1931  const Axis* ax = &axes_[0];
1932  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
1933  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
1934  if (o0 == 1U && o1 == 1U)
1935  data_(i0, i1) += w;
1936  else
1937  {
1938  overflow_(o0, o1) += w;
1939  ++overCount_;
1940  }
1941  ++fillCount_; ++modCount_;
1942  }
1943 
1944  template <typename Numeric, class Axis>
1945  template <typename Num2, class Functor>
1946  void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
1947  Num2& w, Functor& f)
1948  {
1949  if (dim_ != 2U) Private::h_badargs("dispatch");
1950  unsigned i0 = 0, i1 = 0;
1951  const Axis* ax = &axes_[0];
1952  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
1953  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
1954  if (o0 == 1U && o1 == 1U)
1955  f(data_(i0, i1), w);
1956  else
1957  f(overflow_(o0, o1), w);
1958  ++modCount_;
1959  }
1960 
1961  template <typename Numeric, class Axis>
1962  template <typename Num2>
1963  void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
1964  const Num2& w)
1965  {
1966  if (dim_ != 2U) Private::h_badargs("fillC");
1967  double* wg = &weightBuf_[0];
1968  unsigned* idx = &indexBuf_[0];
1969  const Axis* ax = &axes_[0];
1970  const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
1971  const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
1972  if (o0 == 1U && o1 == 1U)
1974  else
1975  {
1976  overflow_(o0, o1) += w;
1977  ++overCount_;
1978  }
1979  ++fillCount_; ++modCount_;
1980  }
1981 
1982  template <typename Numeric, class Axis>
1983  const Numeric& HistoND<Numeric,Axis>::examine(const double x0,
1984  const double x1) const
1985  {
1986  if (dim_ != 2U) Private::h_badargs("examine");
1987  unsigned i0 = 0, i1 = 0;
1988  const Axis* ax = &axes_[0];
1989  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
1990  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
1991  if (o0 == 1U && o1 == 1U)
1992  return data_(i0, i1);
1993  else
1994  return overflow_(o0, o1);
1995  }
1996 
1997  template <typename Numeric, class Axis>
1998  const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
1999  const double x1) const
2000  {
2001  if (dim_ != 2U) Private::h_badargs("closestBin");
2002  const Axis* ax = &axes_[0];
2003  const unsigned i0 = ax[0].closestValidBin(x0);
2004  const unsigned i1 = ax[1].closestValidBin(x1);
2005  return data_(i0, i1);
2006  }
2007 
2008  template <typename Numeric, class Axis>
2009  template <typename Num2>
2010  void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
2011  const double x2, const Num2& w)
2012  {
2013  if (dim_ != 3U) Private::h_badargs("fill");
2014  unsigned i0 = 0, i1 = 0, i2 = 0;
2015  const Axis* ax = &axes_[0];
2016  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2017  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2018  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2019  if (o0 == 1U && o1 == 1U && o2 == 1U)
2020  data_(i0, i1, i2) += w;
2021  else
2022  {
2023  overflow_(o0, o1, o2) += w;
2024  ++overCount_;
2025  }
2026  ++fillCount_; ++modCount_;
2027  }
2028 
2029  template <typename Numeric, class Axis>
2030  template <typename Num2, class Functor>
2031  void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
2032  const double x2, Num2& w, Functor& f)
2033  {
2034  if (dim_ != 3U) Private::h_badargs("dispatch");
2035  unsigned i0 = 0, i1 = 0, i2 = 0;
2036  const Axis* ax = &axes_[0];
2037  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2038  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2039  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2040  if (o0 == 1U && o1 == 1U && o2 == 1U)
2041  f(data_(i0, i1, i2), w);
2042  else
2043  f(overflow_(o0, o1, o2), w);
2044  ++modCount_;
2045  }
2046 
2047  template <typename Numeric, class Axis>
2048  template <typename Num2>
2049  void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
2050  const double x2, const Num2& w)
2051  {
2052  if (dim_ != 3U) Private::h_badargs("fillC");
2053  double* wg = &weightBuf_[0];
2054  unsigned* idx = &indexBuf_[0];
2055  const Axis* ax = &axes_[0];
2056  const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
2057  const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
2058  const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
2059  if (o0 == 1U && o1 == 1U && o2 == 1U)
2061  else
2062  {
2063  overflow_(o0, o1, o2) += w;
2064  ++overCount_;
2065  }
2066  ++fillCount_; ++modCount_;
2067  }
2068 
2069  template <typename Numeric, class Axis>
2070  const Numeric& HistoND<Numeric,Axis>::examine(const double x0,
2071  const double x1,
2072  const double x2) const
2073  {
2074  if (dim_ != 3U) Private::h_badargs("examine");
2075  unsigned i0 = 0, i1 = 0, i2 = 0;
2076  const Axis* ax = &axes_[0];
2077  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2078  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2079  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2080  if (o0 == 1U && o1 == 1U && o2 == 1U)
2081  return data_(i0, i1, i2);
2082  else
2083  return overflow_(o0, o1, o2);
2084  }
2085 
2086  template <typename Numeric, class Axis>
2087  const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
2088  const double x1,
2089  const double x2) const
2090  {
2091  if (dim_ != 3U) Private::h_badargs("closestBin");
2092  const Axis* ax = &axes_[0];
2093  const unsigned i0 = ax[0].closestValidBin(x0);
2094  const unsigned i1 = ax[1].closestValidBin(x1);
2095  const unsigned i2 = ax[2].closestValidBin(x2);
2096  return data_(i0, i1, i2);
2097  }
2098 
2099  template <typename Numeric, class Axis>
2100  template <typename Num2>
2101  void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
2102  const double x2, const double x3,
2103  const Num2& w)
2104  {
2105  if (dim_ != 4U) Private::h_badargs("fill");
2106  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0;
2107  const Axis* ax = &axes_[0];
2108  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2109  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2110  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2111  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2112  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U)
2113  data_(i0, i1, i2, i3) += w;
2114  else
2115  {
2116  overflow_(o0, o1, o2, o3) += w;
2117  ++overCount_;
2118  }
2119  ++fillCount_; ++modCount_;
2120  }
2121 
2122  template <typename Numeric, class Axis>
2123  template <typename Num2, class Functor>
2124  void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
2125  const double x2, const double x3,
2126  Num2& w, Functor& f)
2127  {
2128  if (dim_ != 4U) Private::h_badargs("dispatch");
2129  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0;
2130  const Axis* ax = &axes_[0];
2131  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2132  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2133  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2134  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2135  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U)
2136  f(data_(i0, i1, i2, i3), w);
2137  else
2138  f(overflow_(o0, o1, o2, o3), w);
2139  ++modCount_;
2140  }
2141 
2142  template <typename Numeric, class Axis>
2143  template <typename Num2>
2144  void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
2145  const double x2, const double x3,
2146  const Num2& w)
2147  {
2148  if (dim_ != 4U) Private::h_badargs("fillC");
2149  double* wg = &weightBuf_[0];
2150  unsigned* idx = &indexBuf_[0];
2151  const Axis* ax = &axes_[0];
2152  const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
2153  const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
2154  const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
2155  const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
2156  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U)
2158  else
2159  {
2160  overflow_(o0, o1, o2, o3) += w;
2161  ++overCount_;
2162  }
2163  ++fillCount_; ++modCount_;
2164  }
2165 
2166  template <typename Numeric, class Axis>
2167  const Numeric& HistoND<Numeric,Axis>::examine(const double x0,
2168  const double x1,
2169  const double x2,
2170  const double x3) const
2171  {
2172  if (dim_ != 4U) Private::h_badargs("examine");
2173  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0;
2174  const Axis* ax = &axes_[0];
2175  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2176  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2177  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2178  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2179  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U)
2180  return data_(i0, i1, i2, i3);
2181  else
2182  return overflow_(o0, o1, o2, o3);
2183  }
2184 
2185  template <typename Numeric, class Axis>
2186  const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
2187  const double x1,
2188  const double x2,
2189  const double x3) const
2190  {
2191  if (dim_ != 4U) Private::h_badargs("closestBin");
2192  const Axis* ax = &axes_[0];
2193  const unsigned i0 = ax[0].closestValidBin(x0);
2194  const unsigned i1 = ax[1].closestValidBin(x1);
2195  const unsigned i2 = ax[2].closestValidBin(x2);
2196  const unsigned i3 = ax[3].closestValidBin(x3);
2197  return data_(i0, i1, i2, i3);
2198  }
2199 
2200  template <typename Numeric, class Axis>
2201  template <typename Num2>
2202  void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
2203  const double x2, const double x3,
2204  const double x4, const Num2& w)
2205  {
2206  if (dim_ != 5U) Private::h_badargs("fill");
2207  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0;
2208  const Axis* ax = &axes_[0];
2209  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2210  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2211  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2212  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2213  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2214  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U)
2215  data_(i0, i1, i2, i3, i4) += w;
2216  else
2217  {
2218  overflow_(o0, o1, o2, o3, o4) += w;
2219  ++overCount_;
2220  }
2221  ++fillCount_; ++modCount_;
2222  }
2223 
2224  template <typename Numeric, class Axis>
2225  template <typename Num2, class Functor>
2226  void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
2227  const double x2, const double x3,
2228  const double x4, Num2& w, Functor& f)
2229  {
2230  if (dim_ != 5U) Private::h_badargs("dispatch");
2231  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0;
2232  const Axis* ax = &axes_[0];
2233  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2234  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2235  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2236  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2237  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2238  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U)
2239  f(data_(i0, i1, i2, i3, i4), w);
2240  else
2241  f(overflow_(o0, o1, o2, o3, o4), w);
2242  ++modCount_;
2243  }
2244 
2245  template <typename Numeric, class Axis>
2246  template <typename Num2>
2247  void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
2248  const double x2, const double x3,
2249  const double x4, const Num2& w)
2250  {
2251  if (dim_ != 5U) Private::h_badargs("fillC");
2252  double* wg = &weightBuf_[0];
2253  unsigned* idx = &indexBuf_[0];
2254  const Axis* ax = &axes_[0];
2255  const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
2256  const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
2257  const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
2258  const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
2259  const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
2260  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U)
2262  else
2263  {
2264  overflow_(o0, o1, o2, o3, o4) += w;
2265  ++overCount_;
2266  }
2267  ++fillCount_; ++modCount_;
2268  }
2269 
2270  template <typename Numeric, class Axis>
2272  const double x0, const double x1,
2273  const double x2, const double x3,
2274  const double x4) const
2275  {
2276  if (dim_ != 5U) Private::h_badargs("examine");
2277  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0;
2278  const Axis* ax = &axes_[0];
2279  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2280  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2281  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2282  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2283  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2284  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U)
2285  return data_(i0, i1, i2, i3, i4);
2286  else
2287  return overflow_(o0, o1, o2, o3, o4);
2288  }
2289 
2290  template <typename Numeric, class Axis>
2291  const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
2292  const double x1,
2293  const double x2,
2294  const double x3,
2295  const double x4) const
2296  {
2297  if (dim_ != 5U) Private::h_badargs("closestBin");
2298  const Axis* ax = &axes_[0];
2299  const unsigned i0 = ax[0].closestValidBin(x0);
2300  const unsigned i1 = ax[1].closestValidBin(x1);
2301  const unsigned i2 = ax[2].closestValidBin(x2);
2302  const unsigned i3 = ax[3].closestValidBin(x3);
2303  const unsigned i4 = ax[4].closestValidBin(x4);
2304  return data_(i0, i1, i2, i3, i4);
2305  }
2306 
2307  template <typename Numeric, class Axis>
2308  template <typename Num2>
2309  void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
2310  const double x2, const double x3,
2311  const double x4, const double x5,
2312  const Num2& w)
2313  {
2314  if (dim_ != 6U) Private::h_badargs("fill");
2315  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0;
2316  const Axis* ax = &axes_[0];
2317  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2318  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2319  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2320  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2321  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2322  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2323  if (o0 == 1U && o1 == 1U && o2 == 1U &&
2324  o3 == 1U && o4 == 1U && o5 == 1U)
2325  data_(i0, i1, i2, i3, i4, i5) += w;
2326  else
2327  {
2328  overflow_(o0, o1, o2, o3, o4, o5) += w;
2329  ++overCount_;
2330  }
2331  ++fillCount_; ++modCount_;
2332  }
2333 
2334  template <typename Numeric, class Axis>
2335  template <typename Num2, class Functor>
2336  void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
2337  const double x2, const double x3,
2338  const double x4, const double x5,
2339  Num2& w, Functor& f)
2340  {
2341  if (dim_ != 6U) Private::h_badargs("dispatch");
2342  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0;
2343  const Axis* ax = &axes_[0];
2344  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2345  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2346  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2347  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2348  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2349  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2350  if (o0 == 1U && o1 == 1U && o2 == 1U &&
2351  o3 == 1U && o4 == 1U && o5 == 1U)
2352  f(data_(i0, i1, i2, i3, i4, i5), w);
2353  else
2354  f(overflow_(o0, o1, o2, o3, o4, o5), w);
2355  ++modCount_;
2356  }
2357 
2358  template <typename Numeric, class Axis>
2359  template <typename Num2>
2360  void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
2361  const double x2, const double x3,
2362  const double x4, const double x5,
2363  const Num2& w)
2364  {
2365  if (dim_ != 6U) Private::h_badargs("fillC");
2366  double* wg = &weightBuf_[0];
2367  unsigned* idx = &indexBuf_[0];
2368  const Axis* ax = &axes_[0];
2369  const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
2370  const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
2371  const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
2372  const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
2373  const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
2374  const unsigned o5 = ax[5].overflowIndexWeighted(x5, idx+5, wg+5);
2375  if (o0 == 1U && o1 == 1U && o2 == 1U &&
2376  o3 == 1U && o4 == 1U && o5 == 1U)
2378  else
2379  {
2380  overflow_(o0, o1, o2, o3, o4, o5) += w;
2381  ++overCount_;
2382  }
2383  ++fillCount_; ++modCount_;
2384  }
2385 
2386  template <typename Numeric, class Axis>
2387  const Numeric& HistoND<Numeric,Axis>::examine(const double x0,
2388  const double x1,
2389  const double x2,
2390  const double x3,
2391  const double x4,
2392  const double x5) const
2393  {
2394  if (dim_ != 6U) Private::h_badargs("examine");
2395  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0;
2396  const Axis* ax = &axes_[0];
2397  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2398  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2399  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2400  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2401  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2402  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2403  if (o0 == 1U && o1 == 1U && o2 == 1U &&
2404  o3 == 1U && o4 == 1U && o5 == 1U)
2405  return data_(i0, i1, i2, i3, i4, i5);
2406  else
2407  return overflow_(o0, o1, o2, o3, o4, o5);
2408  }
2409 
2410  template <typename Numeric, class Axis>
2411  const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
2412  const double x1,
2413  const double x2,
2414  const double x3,
2415  const double x4,
2416  const double x5) const
2417  {
2418  if (dim_ != 6U) Private::h_badargs("closestBin");
2419  const Axis* ax = &axes_[0];
2420  const unsigned i0 = ax[0].closestValidBin(x0);
2421  const unsigned i1 = ax[1].closestValidBin(x1);
2422  const unsigned i2 = ax[2].closestValidBin(x2);
2423  const unsigned i3 = ax[3].closestValidBin(x3);
2424  const unsigned i4 = ax[4].closestValidBin(x4);
2425  const unsigned i5 = ax[5].closestValidBin(x5);
2426  return data_(i0, i1, i2, i3, i4, i5);
2427  }
2428 
2429  template <typename Numeric, class Axis>
2430  template <typename Num2>
2431  void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
2432  const double x2, const double x3,
2433  const double x4, const double x5,
2434  const double x6, const Num2& w)
2435  {
2436  if (dim_ != 7U) Private::h_badargs("fill");
2437  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0;
2438  const Axis* ax = &axes_[0];
2439  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2440  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2441  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2442  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2443  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2444  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2445  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2446  if (o0 == 1U && o1 == 1U && o2 == 1U &&
2447  o3 == 1U && o4 == 1U && o5 == 1U && o6 == 1U)
2448  data_(i0, i1, i2, i3, i4, i5, i6) += w;
2449  else
2450  {
2451  overflow_(o0, o1, o2, o3, o4, o5, o6) += w;
2452  ++overCount_;
2453  }
2454  ++fillCount_; ++modCount_;
2455  }
2456 
2457  template <typename Numeric, class Axis>
2458  template <typename Num2, class Functor>
2459  void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
2460  const double x2, const double x3,
2461  const double x4, const double x5,
2462  const double x6, Num2& w, Functor& f)
2463  {
2464  if (dim_ != 7U) Private::h_badargs("dispatch");
2465  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0;
2466  const Axis* ax = &axes_[0];
2467  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2468  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2469  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2470  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2471  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2472  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2473  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2474  if (o0 == 1U && o1 == 1U && o2 == 1U &&
2475  o3 == 1U && o4 == 1U && o5 == 1U && o6 == 1U)
2476  f(data_(i0, i1, i2, i3, i4, i5, i6), w);
2477  else
2478  f(overflow_(o0, o1, o2, o3, o4, o5, o6), w);
2479  ++modCount_;
2480  }
2481 
2482  template <typename Numeric, class Axis>
2483  template <typename Num2>
2484  void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
2485  const double x2, const double x3,
2486  const double x4, const double x5,
2487  const double x6, const Num2& w)
2488  {
2489  if (dim_ != 7U) Private::h_badargs("fillC");
2490  double* wg = &weightBuf_[0];
2491  unsigned* idx = &indexBuf_[0];
2492  const Axis* ax = &axes_[0];
2493  const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
2494  const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
2495  const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
2496  const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
2497  const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
2498  const unsigned o5 = ax[5].overflowIndexWeighted(x5, idx+5, wg+5);
2499  const unsigned o6 = ax[6].overflowIndexWeighted(x6, idx+6, wg+6);
2500  if (o0 == 1U && o1 == 1U && o2 == 1U &&
2501  o3 == 1U && o4 == 1U && o5 == 1U && o6 == 1U)
2503  else
2504  {
2505  overflow_(o0, o1, o2, o3, o4, o5, o6) += w;
2506  ++overCount_;
2507  }
2508  ++fillCount_; ++modCount_;
2509  }
2510 
2511  template <typename Numeric, class Axis>
2513  const double x0, const double x1,
2514  const double x2, const double x3,
2515  const double x4, const double x5,
2516  const double x6) const
2517  {
2518  if (dim_ != 7U) Private::h_badargs("examine");
2519  unsigned i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0;
2520  const Axis* ax = &axes_[0];
2521  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2522  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2523  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2524  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2525  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2526  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2527  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2528  if (o0 == 1U && o1 == 1U && o2 == 1U &&
2529  o3 == 1U && o4 == 1U && o5 == 1U && o6 == 1U)
2530  return data_(i0, i1, i2, i3, i4, i5, i6);
2531  else
2532  return overflow_(o0, o1, o2, o3, o4, o5, o6);
2533  }
2534 
2535  template <typename Numeric, class Axis>
2536  const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
2537  const double x1,
2538  const double x2,
2539  const double x3,
2540  const double x4,
2541  const double x5,
2542  const double x6) const
2543  {
2544  if (dim_ != 7U) Private::h_badargs("closestBin");
2545  const Axis* ax = &axes_[0];
2546  const unsigned i0 = ax[0].closestValidBin(x0);
2547  const unsigned i1 = ax[1].closestValidBin(x1);
2548  const unsigned i2 = ax[2].closestValidBin(x2);
2549  const unsigned i3 = ax[3].closestValidBin(x3);
2550  const unsigned i4 = ax[4].closestValidBin(x4);
2551  const unsigned i5 = ax[5].closestValidBin(x5);
2552  const unsigned i6 = ax[6].closestValidBin(x6);
2553  return data_(i0, i1, i2, i3, i4, i5, i6);
2554  }
2555 
2556  template <typename Numeric, class Axis>
2557  template <typename Num2>
2558  void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
2559  const double x2, const double x3,
2560  const double x4, const double x5,
2561  const double x6, const double x7,
2562  const Num2& w)
2563  {
2564  if (dim_ != 8U) Private::h_badargs("fill");
2565  unsigned i0=0, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0;
2566  const Axis* ax = &axes_[0];
2567  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2568  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2569  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2570  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2571  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2572  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2573  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2574  const unsigned o7 = ax[7].overflowIndex(x7, &i7);
2575  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U &&
2576  o4 == 1U && o5 == 1U && o6 == 1U && o7 == 1U)
2577  data_(i0, i1, i2, i3, i4, i5, i6, i7) += w;
2578  else
2579  {
2580  overflow_(o0, o1, o2, o3, o4, o5, o6, o7) += w;
2581  ++overCount_;
2582  }
2583  ++fillCount_; ++modCount_;
2584  }
2585 
2586  template <typename Numeric, class Axis>
2587  template <typename Num2, class Functor>
2588  void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
2589  const double x2, const double x3,
2590  const double x4, const double x5,
2591  const double x6, const double x7,
2592  Num2& w, Functor& f)
2593  {
2594  if (dim_ != 8U) Private::h_badargs("dispatch");
2595  unsigned i0=0, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0;
2596  const Axis* ax = &axes_[0];
2597  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2598  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2599  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2600  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2601  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2602  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2603  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2604  const unsigned o7 = ax[7].overflowIndex(x7, &i7);
2605  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U &&
2606  o4 == 1U && o5 == 1U && o6 == 1U && o7 == 1U)
2607  f(data_(i0, i1, i2, i3, i4, i5, i6, i7), w);
2608  else
2609  f(overflow_(o0, o1, o2, o3, o4, o5, o6, o7), w);
2610  ++modCount_;
2611  }
2612 
2613  template <typename Numeric, class Axis>
2614  template <typename Num2>
2615  void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
2616  const double x2, const double x3,
2617  const double x4, const double x5,
2618  const double x6, const double x7,
2619  const Num2& w)
2620  {
2621  if (dim_ != 8U) Private::h_badargs("fillC");
2622  double* wg = &weightBuf_[0];
2623  unsigned* idx = &indexBuf_[0];
2624  const Axis* ax = &axes_[0];
2625  const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
2626  const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
2627  const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
2628  const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
2629  const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
2630  const unsigned o5 = ax[5].overflowIndexWeighted(x5, idx+5, wg+5);
2631  const unsigned o6 = ax[6].overflowIndexWeighted(x6, idx+6, wg+6);
2632  const unsigned o7 = ax[7].overflowIndexWeighted(x7, idx+7, wg+7);
2633  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U &&
2634  o4 == 1U && o5 == 1U && o6 == 1U && o7 == 1U)
2636  else
2637  {
2638  overflow_(o0, o1, o2, o3, o4, o5, o6, o7) += w;
2639  ++overCount_;
2640  }
2641  ++fillCount_; ++modCount_;
2642  }
2643 
2644  template <typename Numeric, class Axis>
2646  const double x0, const double x1,
2647  const double x2, const double x3,
2648  const double x4, const double x5,
2649  const double x6,
2650  const double x7) const
2651  {
2652  if (dim_ != 8U) Private::h_badargs("examine");
2653  unsigned i0=0, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0;
2654  const Axis* ax = &axes_[0];
2655  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2656  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2657  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2658  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2659  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2660  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2661  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2662  const unsigned o7 = ax[7].overflowIndex(x7, &i7);
2663  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U &&
2664  o4 == 1U && o5 == 1U && o6 == 1U && o7 == 1U)
2665  return data_(i0, i1, i2, i3, i4, i5, i6, i7);
2666  else
2667  return overflow_(o0, o1, o2, o3, o4, o5, o6, o7);
2668  }
2669 
2670  template <typename Numeric, class Axis>
2671  const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
2672  const double x1,
2673  const double x2,
2674  const double x3,
2675  const double x4,
2676  const double x5,
2677  const double x6,
2678  const double x7) const
2679  {
2680  if (dim_ != 8U) Private::h_badargs("closestBin");
2681  const Axis* ax = &axes_[0];
2682  const unsigned i0 = ax[0].closestValidBin(x0);
2683  const unsigned i1 = ax[1].closestValidBin(x1);
2684  const unsigned i2 = ax[2].closestValidBin(x2);
2685  const unsigned i3 = ax[3].closestValidBin(x3);
2686  const unsigned i4 = ax[4].closestValidBin(x4);
2687  const unsigned i5 = ax[5].closestValidBin(x5);
2688  const unsigned i6 = ax[6].closestValidBin(x6);
2689  const unsigned i7 = ax[7].closestValidBin(x7);
2690  return data_(i0, i1, i2, i3, i4, i5, i6, i7);
2691  }
2692 
2693  template <typename Numeric, class Axis>
2694  template <typename Num2>
2695  void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
2696  const double x2, const double x3,
2697  const double x4, const double x5,
2698  const double x6, const double x7,
2699  const double x8, const Num2& w)
2700  {
2701  if (dim_ != 9U) Private::h_badargs("fill");
2702  unsigned i0=0, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0;
2703  const Axis* ax = &axes_[0];
2704  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2705  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2706  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2707  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2708  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2709  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2710  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2711  const unsigned o7 = ax[7].overflowIndex(x7, &i7);
2712  const unsigned o8 = ax[8].overflowIndex(x8, &i8);
2713  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
2714  o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U)
2715  data_(i0, i1, i2, i3, i4, i5, i6, i7, i8) += w;
2716  else
2717  {
2718  overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8) += w;
2719  ++overCount_;
2720  }
2721  ++fillCount_; ++modCount_;
2722  }
2723 
2724  template <typename Numeric, class Axis>
2725  template <typename Num2, class Functor>
2726  void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
2727  const double x2, const double x3,
2728  const double x4, const double x5,
2729  const double x6, const double x7,
2730  const double x8, Num2& w, Functor& f)
2731  {
2732  if (dim_ != 9U) Private::h_badargs("dispatch");
2733  unsigned i0=0, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0;
2734  const Axis* ax = &axes_[0];
2735  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2736  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2737  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2738  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2739  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2740  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2741  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2742  const unsigned o7 = ax[7].overflowIndex(x7, &i7);
2743  const unsigned o8 = ax[8].overflowIndex(x8, &i8);
2744  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
2745  o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U)
2746  f(data_(i0, i1, i2, i3, i4, i5, i6, i7, i8), w);
2747  else
2748  f(overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8), w);
2749  ++modCount_;
2750  }
2751 
2752  template <typename Numeric, class Axis>
2753  template <typename Num2>
2754  void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
2755  const double x2, const double x3,
2756  const double x4, const double x5,
2757  const double x6, const double x7,
2758  const double x8, const Num2& w)
2759  {
2760  if (dim_ != 9U) Private::h_badargs("fillC");
2761  double* wg = &weightBuf_[0];
2762  unsigned* idx = &indexBuf_[0];
2763  const Axis* ax = &axes_[0];
2764  const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
2765  const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
2766  const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
2767  const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
2768  const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
2769  const unsigned o5 = ax[5].overflowIndexWeighted(x5, idx+5, wg+5);
2770  const unsigned o6 = ax[6].overflowIndexWeighted(x6, idx+6, wg+6);
2771  const unsigned o7 = ax[7].overflowIndexWeighted(x7, idx+7, wg+7);
2772  const unsigned o8 = ax[8].overflowIndexWeighted(x8, idx+8, wg+8);
2773  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
2774  o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U)
2776  else
2777  {
2778  overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8) += w;
2779  ++overCount_;
2780  }
2781  ++fillCount_; ++modCount_;
2782  }
2783 
2784  template <typename Numeric, class Axis>
2786  const double x0, const double x1,
2787  const double x2, const double x3,
2788  const double x4, const double x5,
2789  const double x6, const double x7,
2790  const double x8) const
2791  {
2792  if (dim_ != 9U) Private::h_badargs("examine");
2793  unsigned i0=0, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0;
2794  const Axis* ax = &axes_[0];
2795  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2796  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2797  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2798  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2799  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2800  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2801  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2802  const unsigned o7 = ax[7].overflowIndex(x7, &i7);
2803  const unsigned o8 = ax[8].overflowIndex(x8, &i8);
2804  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
2805  o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U)
2806  return data_(i0, i1, i2, i3, i4, i5, i6, i7, i8);
2807  else
2808  return overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8);
2809  }
2810 
2811  template <typename Numeric, class Axis>
2812  const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
2813  const double x1,
2814  const double x2,
2815  const double x3,
2816  const double x4,
2817  const double x5,
2818  const double x6,
2819  const double x7,
2820  const double x8) const
2821  {
2822  if (dim_ != 9U) Private::h_badargs("closestBin");
2823  const Axis* ax = &axes_[0];
2824  const unsigned i0 = ax[0].closestValidBin(x0);
2825  const unsigned i1 = ax[1].closestValidBin(x1);
2826  const unsigned i2 = ax[2].closestValidBin(x2);
2827  const unsigned i3 = ax[3].closestValidBin(x3);
2828  const unsigned i4 = ax[4].closestValidBin(x4);
2829  const unsigned i5 = ax[5].closestValidBin(x5);
2830  const unsigned i6 = ax[6].closestValidBin(x6);
2831  const unsigned i7 = ax[7].closestValidBin(x7);
2832  const unsigned i8 = ax[8].closestValidBin(x8);
2833  return data_(i0, i1, i2, i3, i4, i5, i6, i7, i8);
2834  }
2835 
2836  template <typename Numeric, class Axis>
2837  template <typename Num2>
2838  void HistoND<Numeric,Axis>::fill(const double x0, const double x1,
2839  const double x2, const double x3,
2840  const double x4, const double x5,
2841  const double x6, const double x7,
2842  const double x8, const double x9,
2843  const Num2& w)
2844  {
2845  if (dim_ != 10U) Private::h_badargs("fill");
2846  unsigned i0=0, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0;
2847  const Axis* ax = &axes_[0];
2848  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2849  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2850  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2851  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2852  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2853  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2854  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2855  const unsigned o7 = ax[7].overflowIndex(x7, &i7);
2856  const unsigned o8 = ax[8].overflowIndex(x8, &i8);
2857  const unsigned o9 = ax[9].overflowIndex(x9, &i9);
2858  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
2859  o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U && o9 == 1U)
2860  data_(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) += w;
2861  else
2862  {
2863  overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8, o9) += w;
2864  ++overCount_;
2865  }
2866  ++fillCount_; ++modCount_;
2867  }
2868 
2869  template <typename Numeric, class Axis>
2870  template <typename Num2, class Functor>
2871  void HistoND<Numeric,Axis>::dispatch(const double x0, const double x1,
2872  const double x2, const double x3,
2873  const double x4, const double x5,
2874  const double x6, const double x7,
2875  const double x8, const double x9,
2876  Num2& w, Functor& f)
2877  {
2878  if (dim_ != 10U) Private::h_badargs("dispatch");
2879  unsigned i0=0, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0;
2880  const Axis* ax = &axes_[0];
2881  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2882  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2883  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2884  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2885  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2886  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2887  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2888  const unsigned o7 = ax[7].overflowIndex(x7, &i7);
2889  const unsigned o8 = ax[8].overflowIndex(x8, &i8);
2890  const unsigned o9 = ax[9].overflowIndex(x9, &i9);
2891  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
2892  o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U && o9 == 1U)
2893  f(data_(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9), w);
2894  else
2895  f(overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8, o9), w);
2896  ++modCount_;
2897  }
2898 
2899  template <typename Numeric, class Axis>
2900  template <typename Num2>
2901  void HistoND<Numeric,Axis>::fillC(const double x0, const double x1,
2902  const double x2, const double x3,
2903  const double x4, const double x5,
2904  const double x6, const double x7,
2905  const double x8, const double x9,
2906  const Num2& w)
2907  {
2908  if (dim_ != 10U) Private::h_badargs("fillC");
2909  double* wg = &weightBuf_[0];
2910  unsigned* idx = &indexBuf_[0];
2911  const Axis* ax = &axes_[0];
2912  const unsigned o0 = ax[0].overflowIndexWeighted(x0, idx+0, wg+0);
2913  const unsigned o1 = ax[1].overflowIndexWeighted(x1, idx+1, wg+1);
2914  const unsigned o2 = ax[2].overflowIndexWeighted(x2, idx+2, wg+2);
2915  const unsigned o3 = ax[3].overflowIndexWeighted(x3, idx+3, wg+3);
2916  const unsigned o4 = ax[4].overflowIndexWeighted(x4, idx+4, wg+4);
2917  const unsigned o5 = ax[5].overflowIndexWeighted(x5, idx+5, wg+5);
2918  const unsigned o6 = ax[6].overflowIndexWeighted(x6, idx+6, wg+6);
2919  const unsigned o7 = ax[7].overflowIndexWeighted(x7, idx+7, wg+7);
2920  const unsigned o8 = ax[8].overflowIndexWeighted(x8, idx+8, wg+8);
2921  const unsigned o9 = ax[9].overflowIndexWeighted(x9, idx+9, wg+9);
2922  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
2923  o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U && o9 == 1U)
2925  else
2926  {
2927  overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8, o9) += w;
2928  ++overCount_;
2929  }
2930  ++fillCount_; ++modCount_;
2931  }
2932 
2933  template <typename Numeric, class Axis>
2935  const double x0, const double x1,
2936  const double x2, const double x3,
2937  const double x4, const double x5,
2938  const double x6, const double x7,
2939  const double x8,
2940  const double x9) const
2941  {
2942  if (dim_ != 10U) Private::h_badargs("examine");
2943  unsigned i0=0, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0;
2944  const Axis* ax = &axes_[0];
2945  const unsigned o0 = ax[0].overflowIndex(x0, &i0);
2946  const unsigned o1 = ax[1].overflowIndex(x1, &i1);
2947  const unsigned o2 = ax[2].overflowIndex(x2, &i2);
2948  const unsigned o3 = ax[3].overflowIndex(x3, &i3);
2949  const unsigned o4 = ax[4].overflowIndex(x4, &i4);
2950  const unsigned o5 = ax[5].overflowIndex(x5, &i5);
2951  const unsigned o6 = ax[6].overflowIndex(x6, &i6);
2952  const unsigned o7 = ax[7].overflowIndex(x7, &i7);
2953  const unsigned o8 = ax[8].overflowIndex(x8, &i8);
2954  const unsigned o9 = ax[9].overflowIndex(x9, &i9);
2955  if (o0 == 1U && o1 == 1U && o2 == 1U && o3 == 1U && o4 == 1U &&
2956  o5 == 1U && o6 == 1U && o7 == 1U && o8 == 1U && o9 == 1U)
2957  return data_(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9);
2958  else
2959  return overflow_(o0, o1, o2, o3, o4, o5, o6, o7, o8, o9);
2960  }
2961 
2962  template <typename Numeric, class Axis>
2963  const Numeric& HistoND<Numeric,Axis>::closestBin(const double x0,
2964  const double x1,
2965  const double x2,
2966  const double x3,
2967  const double x4,
2968  const double x5,
2969  const double x6,
2970  const double x7,
2971  const double x8,
2972  const double x9) const
2973  {
2974  if (dim_ != 10U) Private::h_badargs("closestBin");
2975  const Axis* ax = &axes_[0];
2976  const unsigned i0 = ax[0].closestValidBin(x0);
2977  const unsigned i1 = ax[1].closestValidBin(x1);
2978  const unsigned i2 = ax[2].closestValidBin(x2);
2979  const unsigned i3 = ax[3].closestValidBin(x3);
2980  const unsigned i4 = ax[4].closestValidBin(x4);
2981  const unsigned i5 = ax[5].closestValidBin(x5);
2982  const unsigned i6 = ax[6].closestValidBin(x6);
2983  const unsigned i7 = ax[7].closestValidBin(x7);
2984  const unsigned i8 = ax[8].closestValidBin(x8);
2985  const unsigned i9 = ax[9].closestValidBin(x9);
2986  return data_(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9);
2987  }
2988 
2989  template <typename Numeric, class Axis>
2990  template <typename Num2>
2991  inline void HistoND<Numeric,Axis>::setBin(const unsigned *index,
2992  const unsigned indexLen,
2993  const Num2& v)
2994  {
2995  data_.value(index, indexLen) = v;
2996  ++modCount_;
2997  }
2998 
2999  template <typename Numeric, class Axis>
3000  template <typename Num2>
3001  inline void HistoND<Numeric,Axis>::setBinAt(const unsigned *index,
3002  const unsigned indexLen,
3003  const Num2& v)
3004  {
3005  data_.valueAt(index, indexLen) = v;
3006  ++modCount_;
3007  }
3008 
3009  template <typename Numeric, class Axis>
3010  template <typename Num2>
3011  inline void HistoND<Numeric,Axis>::setBin(const Num2& v)
3012  {
3013  data_() = v;
3014  ++modCount_;
3015  }
3016 
3017  template <typename Numeric, class Axis>
3018  template <typename Num2>
3019  inline void HistoND<Numeric,Axis>::setBinAt(const Num2& v)
3020  {
3021  data_.at() = v;
3022  ++modCount_;
3023  }
3024 
3025  template <typename Numeric, class Axis>
3026  template <typename Num2>
3028  const unsigned i0, const Num2& v)
3029  {
3030  data_(i0) = v;
3031  ++modCount_;
3032  }
3033 
3034  template <typename Numeric, class Axis>
3035  template <typename Num2>
3037  const unsigned i0, const Num2& v)
3038  {
3039  data_.at(i0) = v;
3040  ++modCount_;
3041  }
3042 
3043  template <typename Numeric, class Axis>
3044  template <typename Num2>
3045  inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
3046  const unsigned i1,
3047  const Num2& v)
3048  {
3049  data_(i0, i1) = v;
3050  ++modCount_;
3051  }
3052 
3053  template <typename Numeric, class Axis>
3054  template <typename Num2>
3055  inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
3056  const unsigned i1,
3057  const Num2& v)
3058  {
3059  data_.at(i0, i1) = v;
3060  ++modCount_;
3061  }
3062 
3063  template <typename Numeric, class Axis>
3064  template <typename Num2>
3065  inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
3066  const unsigned i1,
3067  const unsigned i2,
3068  const Num2& v)
3069  {
3070  data_(i0, i1, i2) = v;
3071  ++modCount_;
3072  }
3073 
3074  template <typename Numeric, class Axis>
3075  template <typename Num2>
3076  inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
3077  const unsigned i1,
3078  const unsigned i2,
3079  const unsigned i3,
3080  const Num2& v)
3081  {
3082  data_(i0, i1, i2, i3) = v;
3083  ++modCount_;
3084  }
3085 
3086  template <typename Numeric, class Axis>
3087  template <typename Num2>
3088  inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
3089  const unsigned i1,
3090  const unsigned i2,
3091  const unsigned i3,
3092  const unsigned i4,
3093  const Num2& v)
3094  {
3095  data_(i0, i1, i2, i3, i4) = v;
3096  ++modCount_;
3097  }
3098 
3099  template <typename Numeric, class Axis>
3100  template <typename Num2>
3101  inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
3102  const unsigned i1,
3103  const unsigned i2,
3104  const unsigned i3,
3105  const unsigned i4,
3106  const unsigned i5,
3107  const Num2& v)
3108  {
3109  data_(i0, i1, i2, i3, i4, i5) = v;
3110  ++modCount_;
3111  }
3112 
3113  template <typename Numeric, class Axis>
3114  template <typename Num2>
3115  inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
3116  const unsigned i1,
3117  const unsigned i2,
3118  const unsigned i3,
3119  const unsigned i4,
3120  const unsigned i5,
3121  const unsigned i6,
3122  const Num2& v)
3123  {
3124  data_(i0, i1, i2, i3, i4, i5, i6) = v;
3125  ++modCount_;
3126  }
3127 
3128  template <typename Numeric, class Axis>
3129  template <typename Num2>
3130  inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
3131  const unsigned i1,
3132  const unsigned i2,
3133  const unsigned i3,
3134  const unsigned i4,
3135  const unsigned i5,
3136  const unsigned i6,
3137  const unsigned i7,
3138  const Num2& v)
3139  {
3140  data_(i0, i1, i2, i3, i4, i5, i6, i7) = v;
3141  ++modCount_;
3142  }
3143 
3144  template <typename Numeric, class Axis>
3145  template <typename Num2>
3146  inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
3147  const unsigned i1,
3148  const unsigned i2,
3149  const unsigned i3,
3150  const unsigned i4,
3151  const unsigned i5,
3152  const unsigned i6,
3153  const unsigned i7,
3154  const unsigned i8,
3155  const Num2& v)
3156  {
3157  data_(i0, i1, i2, i3, i4, i5, i6, i7, i8) = v;
3158  ++modCount_;
3159  }
3160 
3161  template <typename Numeric, class Axis>
3162  template <typename Num2>
3163  inline void HistoND<Numeric,Axis>::setBin(const unsigned i0,
3164  const unsigned i1,
3165  const unsigned i2,
3166  const unsigned i3,
3167  const unsigned i4,
3168  const unsigned i5,
3169  const unsigned i6,
3170  const unsigned i7,
3171  const unsigned i8,
3172  const unsigned i9,
3173  const Num2& v)
3174  {
3175  data_(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) = v;
3176  ++modCount_;
3177  }
3178 
3179  template <typename Numeric, class Axis>
3180  template <typename Num2>
3181  inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
3182  const unsigned i1,
3183  const unsigned i2,
3184  const Num2& v)
3185  {
3186  data_.at(i0, i1, i2) = v;
3187  ++modCount_;
3188  }
3189 
3190  template <typename Numeric, class Axis>
3191  template <typename Num2>
3192  inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
3193  const unsigned i1,
3194  const unsigned i2,
3195  const unsigned i3,
3196  const Num2& v)
3197  {
3198  data_.at(i0, i1, i2, i3) = v;
3199  ++modCount_;
3200  }
3201 
3202  template <typename Numeric, class Axis>
3203  template <typename Num2>
3204  inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
3205  const unsigned i1,
3206  const unsigned i2,
3207  const unsigned i3,
3208  const unsigned i4,
3209  const Num2& v)
3210  {
3211  data_.at(i0, i1, i2, i3, i4) = v;
3212  ++modCount_;
3213  }
3214 
3215  template <typename Numeric, class Axis>
3216  template <typename Num2>
3217  inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
3218  const unsigned i1,
3219  const unsigned i2,
3220  const unsigned i3,
3221  const unsigned i4,
3222  const unsigned i5,
3223  const Num2& v)
3224  {
3225  data_.at(i0, i1, i2, i3, i4, i5) = v;
3226  ++modCount_;
3227  }
3228 
3229  template <typename Numeric, class Axis>
3230  template <typename Num2>
3231  inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
3232  const unsigned i1,
3233  const unsigned i2,
3234  const unsigned i3,
3235  const unsigned i4,
3236  const unsigned i5,
3237  const unsigned i6,
3238  const Num2& v)
3239  {
3240  data_.at(i0, i1, i2, i3, i4, i5, i6) = v;
3241  ++modCount_;
3242  }
3243 
3244  template <typename Numeric, class Axis>
3245  template <typename Num2>
3246  inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
3247  const unsigned i1,
3248  const unsigned i2,
3249  const unsigned i3,
3250  const unsigned i4,
3251  const unsigned i5,
3252  const unsigned i6,
3253  const unsigned i7,
3254  const Num2& v)
3255  {
3256  data_.at(i0, i1, i2, i3, i4, i5, i6, i7) = v;
3257  ++modCount_;
3258  }
3259 
3260  template <typename Numeric, class Axis>
3261  template <typename Num2>
3262  inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
3263  const unsigned i1,
3264  const unsigned i2,
3265  const unsigned i3,
3266  const unsigned i4,
3267  const unsigned i5,
3268  const unsigned i6,
3269  const unsigned i7,
3270  const unsigned i8,
3271  const Num2& v)
3272  {
3273  data_.at(i0, i1, i2, i3, i4, i5, i6, i7, i8) = v;
3274  ++modCount_;
3275  }
3276 
3277  template <typename Numeric, class Axis>
3278  template <typename Num2>
3279  inline void HistoND<Numeric,Axis>::setBinAt(const unsigned i0,
3280  const unsigned i1,
3281  const unsigned i2,
3282  const unsigned i3,
3283  const unsigned i4,
3284  const unsigned i5,
3285  const unsigned i6,
3286  const unsigned i7,
3287  const unsigned i8,
3288  const unsigned i9,
3289  const Num2& v)
3290  {
3291  data_.at(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) = v;
3292  ++modCount_;
3293  }
3294 
3295  template <typename Numeric, class Axis>
3296  template <typename Num2>
3298  const HistoND<Num2,Axis>& r)
3299  {
3300  data_ += r.data_;
3301  overflow_ += r.overflow_;
3302  fillCount_ += r.fillCount_;
3303  overCount_ += r.overCount_;
3304  ++modCount_;
3305  return *this;
3306  }
3307 
3308  template <typename Numeric, class Axis>
3309  template <typename Num2>
3311  const HistoND<Num2,Axis>& r)
3312  {
3313  data_ -= r.data_;
3314  overflow_ -= r.overflow_;
3315 
3316  // Subtraction does not make much sense for fill counts.
3317  // We will assume that what we want should be equivalent
3318  // to the in-place multiplication of the other histogram
3319  // by -1 and then adding.
3320  //
3321  fillCount_ += r.fillCount_;
3322  overCount_ += r.overCount_;
3323 
3324  ++modCount_;
3325  return *this;
3326  }
3327 
3328  template <typename Numeric, class Axis>
3329  template <typename Num2>
3330  inline HistoND<Numeric,Axis>&
3332  {
3333  data_ *= r;
3334  overflow_ *= r;
3335  ++modCount_;
3336  return *this;
3337  }
3338 
3339  template <typename Numeric, class Axis>
3340  template <typename Num2>
3341  inline HistoND<Numeric,Axis>&
3343  {
3344  data_ /= r;
3345  overflow_ /= r;
3346  ++modCount_;
3347  return *this;
3348  }
3349 
3350  template <typename Numeric, class Axis>
3352  const unsigned ax1,
3353  const unsigned ax2)
3354  : title_(r.title_),
3356  data_(r.data_.transpose(ax1, ax2)),
3357  overflow_(r.overflow_.transpose(ax1, ax2)),
3358  axes_(r.axes_),
3360  indexBuf_(r.indexBuf_),
3363  modCount_(0UL),
3364  dim_(r.dim_)
3365  {
3366  std::swap(axes_[ax1], axes_[ax2]);
3367  }
3368 
3369  template <typename Numeric, class Axis>
3371  : title_(r.title_),
3373  data_(r.data_),
3374  overflow_(r.overflow_),
3375  axes_(r.axes_),
3377  indexBuf_(r.indexBuf_),
3380  modCount_(0UL),
3381  dim_(r.dim_)
3382  {
3383  }
3384 
3385  template <typename Numeric, class Axis>
3387  {
3388  if (&r != this)
3389  {
3390  title_ = r.title_;
3391  accumulatedDataLabel_ = r.accumulatedDataLabel_;
3392  data_.uninitialize();
3393  data_ = r.data_;
3395  overflow_ = r.overflow_;
3396  axes_ = r.axes_;
3397  weightBuf_ = r.weightBuf_;
3398  indexBuf_ = r.indexBuf_;
3399  fillCount_ = r.fillCount_;
3400  overCount_ = r.overCount_;
3401  dim_ = r.dim_;
3402  ++modCount_;
3403  }
3404  return *this;
3405  }
3406 
3407  template <typename Numeric, class Axis>
3409  const unsigned axisNum1, const unsigned axisNum2) const
3410  {
3411  if (axisNum1 >= dim_ || axisNum2 >= dim_)
3412  throw npstat::NpstatOutOfRange("In npstat::HistoND::transpose: "
3413  "axis number is out of range");
3414  if (axisNum1 == axisNum2)
3415  // Just make a copy
3416  return *this;
3417  else
3418  return HistoND(*this, axisNum1, axisNum2);
3419  }
3420 
3421  template <typename Numeric, class Axis>
3422  template <typename Num2>
3424  {
3425  const unsigned long nDat = data_.length();
3426  Numeric* data = const_cast<Numeric*>(data_.data());
3427  for (unsigned long i=0; i<nDat; ++i)
3428  data[i] += weight;
3429  fillCount_ += nDat;
3430  ++modCount_;
3431  }
3432 
3433  template <typename Numeric, class Axis>
3434  template <typename Num2>
3436  {
3437  const unsigned long nOver = overflow_.length();
3438  Numeric* data = const_cast<Numeric*>(overflow_.data());
3439  for (unsigned long i=0; i<nOver; ++i)
3440  data[i] += weight;
3441  overCount_ += nOver;
3442  fillCount_ += nOver;
3443  ++modCount_;
3444  }
3445 
3446  template <typename Numeric, class Axis>
3447  template <typename Num2>
3449  const Num2* data, const unsigned long dataLength)
3450  {
3451  if (dataLength != data_.length()) throw npstat::NpstatInvalidArgument(
3452  "In npstat::HistoND::addToBinContents: incompatible data length");
3453  assert(data);
3454  Numeric* dat = const_cast<Numeric*>(data_.data());
3455  for (unsigned long i=0; i<dataLength; ++i)
3456  dat[i] += data[i];
3457  fillCount_ += dataLength;
3458  ++modCount_;
3459  }
3460 
3461  template <typename Numeric, class Axis>
3462  template <typename Num2>
3464  const Num2* data, const unsigned long dataLength)
3465  {
3466  if (dataLength != overflow_.length()) throw npstat::NpstatInvalidArgument(
3467  "In npstat::HistoND::addToOverflows: incompatible data length");
3468  assert(data);
3469  Numeric* dat = const_cast<Numeric*>(overflow_.data());
3470  for (unsigned long i=0; i<dataLength; ++i)
3471  dat[i] += data[i];
3472  overCount_ += dataLength;
3473  fillCount_ += dataLength;
3474  ++modCount_;
3475  }
3476 
3477  template <typename Numeric, class Axis>
3478  template <typename Num2>
3480  const Num2* data, const unsigned long dataLength)
3481  {
3482  if (dataLength != data_.length()) throw npstat::NpstatInvalidArgument(
3483  "In npstat::HistoND::scaleBinContents: incompatible data length");
3484  assert(data);
3485  Numeric* dat = const_cast<Numeric*>(data_.data());
3486  for (unsigned long i=0; i<dataLength; ++i)
3487  dat[i] *= data[i];
3488  ++modCount_;
3489  }
3490 
3491  template <typename Numeric, class Axis>
3492  template <typename Num2>
3494  const Num2* data, const unsigned long dataLength)
3495  {
3496  if (dataLength != overflow_.length()) throw npstat::NpstatInvalidArgument(
3497  "In npstat::HistoND::scaleOverflows: incompatible data length");
3498  assert(data);
3499  Numeric* dat = const_cast<Numeric*>(overflow_.data());
3500  for (unsigned long i=0; i<dataLength; ++i)
3501  dat[i] *= data[i];
3502  ++modCount_;
3503  }
3504 
3505  template <typename Numeric, class Axis>
3506  template <typename Num2>
3508  const Num2* data, const unsigned long dataLength,
3509  const bool clearOverflowsNow)
3510  {
3511  data_.setData(data, dataLength);
3512  if (clearOverflowsNow)
3513  clearOverflows();
3514  ++modCount_;
3515  }
3516 
3517  template <typename Numeric, class Axis>
3518  template <typename Num2>
3520  const Num2* data, const unsigned long dataLength)
3521  {
3522  overflow_.setData(data, dataLength);
3523  ++modCount_;
3524  }
3525 
3526  template <typename Numeric, class Axis>
3528  {
3529  const long double nOver = overflow_.template sum<long double>();
3530  const long double nData = data_.template sum<long double>();
3531  overCount_ = static_cast<unsigned long>(nOver);
3532  fillCount_ = static_cast<unsigned long>(nData + nOver);
3533  ++modCount_;
3534  }
3535 
3536  template <typename Numeric, class Axis>
3537  template <typename Num2, typename Num3>
3539  HistoND<Num2,Axis>* projection,
3541  const unsigned *projectedIndices,
3542  const unsigned nProjectedIndices) const
3543  {
3544  assert(projection);
3545  data_.addToProjection(&projection->data_, projector,
3546  projectedIndices, nProjectedIndices);
3547  projection->fillCount_ += projection->nBins();
3548  projection->modCount_++;
3549  }
3550 
3551  template <typename Numeric, class Axis>
3552  template <typename Num2, typename Num3>
3554  HistoND<Num2,Axis>* projection,
3555  AbsVisitor<Numeric,Num3>& projector,
3556  const unsigned *projectedIndices,
3557  const unsigned nProjectedIndices) const
3558  {
3559  assert(projection);
3560  data_.addToProjection(&projection->data_, projector,
3561  projectedIndices, nProjectedIndices);
3562  projection->fillCount_ += projection->nBins();
3563  projection->modCount_++;
3564  }
3565 
3566  template <typename Numeric, class Axis>
3568  {
3569  static const std::string myClass(gs::template_class_name<Numeric,Axis>(
3570  "npstat::HistoND"));
3571  return myClass.c_str();
3572  }
3573 
3574  template<typename Numeric, class Axis>
3575  bool HistoND<Numeric,Axis>::write(std::ostream& of) const
3576  {
3577  gs::write_pod(of, title_);
3578  gs::write_pod(of, accumulatedDataLabel_);
3579  gs::write_pod(of, fillCount_);
3580  gs::write_pod(of, overCount_);
3581 
3582  return !of.fail() &&
3583  gs::write_obj_vector(of, axes_) &&
3584  data_.classId().write(of) &&
3585  data_.write(of) &&
3586  overflow_.write(of);
3587  }
3588 
3589  template<typename Numeric, class Axis>
3591  std::istream& in)
3592  {
3593  static const gs::ClassId current(
3594  gs::ClassId::makeId<HistoND<Numeric,Axis> >());
3595  current.ensureSameId(id);
3596 
3598  gs::read_pod(in, &title);
3599 
3601  gs::read_pod(in, &accumulatedDataLabel);
3602 
3603  unsigned long fillCount = 0, overCount = 0;
3604  gs::read_pod(in, &fillCount);
3605  gs::read_pod(in, &overCount);
3606  if (in.fail()) throw gs::IOReadFailure(
3607  "In npstat::HistoND::read: input stream failure");
3608 
3609  std::vector<Axis> axes;
3610  gs::read_heap_obj_vector_as_placed(in, &axes);
3611  gs::ClassId ida(in, 1);
3612  ArrayND<Numeric> data, over;
3613  ArrayND<Numeric>::restore(ida, in, &data);
3614  ArrayND<Numeric>::restore(ida, in, &over);
3615  CPP11_auto_ptr<HistoND<Numeric,Axis> > result(
3616  new HistoND<Numeric,Axis>(axes, title.c_str(),
3617  accumulatedDataLabel.c_str()));
3618  result->data_ = data;
3619  result->overflow_ = over;
3620  result->fillCount_ = fillCount;
3621  result->overCount_ = overCount;
3622  return result.release();
3623  }
3624 
3625  template <typename Histo>
3626  void convertHistoToDensity(Histo* h, const bool knownNonNegative)
3627  {
3628  assert(h);
3629  if (!knownNonNegative)
3630  (const_cast<ArrayND<typename
3631  Histo::value_type>&>(h->binContents())).makeNonNegative();
3632  const double integ = h->integral();
3633  *h /= integ;
3634  }
3635 
3636  template <typename Histo>
3637  std::vector<LinearMapper1d> densityScanHistoMap(const Histo& histo)
3638  {
3639  std::vector<LinearMapper1d> result;
3640  const unsigned d = histo.dim();
3641  result.reserve(d);
3642  for (unsigned i=0; i<d; ++i)
3643  {
3644  const LinearMapper1d& m = histo.axis(i).binNumberMapper(false);
3645  result.push_back(m.inverse());
3646  }
3647  return result;
3648  }
3649 
3650  template <typename Histo>
3651  std::vector<CircularMapper1d> convolutionHistoMap(
3652  const Histo& histo, const bool doubleRange)
3653  {
3654  std::vector<CircularMapper1d> result;
3655  const unsigned d = histo.dim();
3656  result.reserve(d);
3657  for (unsigned i=0; i<d; ++i)
3658  result.push_back(histo.axis(i).kernelScanMapper(doubleRange));
3659  return result;
3660  }
3661 }
3662 
3663 
3664 #endif // NPSTAT_HISTOND_HH_
3665 
size
Write out results.
HistoND()=delete
void setBinAt(const unsigned *index, unsigned indexLen, const Num2 &v)
Definition: HistoND.h:3001
ArrayND & setData(const Num2 *data, unsigned long dataLength)
void accumulateBinsLoop(unsigned level, const BoxND< double > &box, unsigned *idx, Acc *accumulator, double overlapFraction, long double *wsum) const
Definition: HistoND.h:1144
static unsigned version()
Definition: HistoND.h:842
void convertLinearIndex(unsigned long l, unsigned *index, unsigned indexLen) const
Definition: ArrayND.h:3234
bool operator==(const HistoND &) const
Definition: HistoND.h:1594
const double w
Definition: UKUtility.cc:23
unsigned long fillCount_
Definition: HistoND.h:866
unsigned dim_
Definition: HistoND.h:869
unsigned long getModCount() const
Definition: HistoND.h:826
bool write(std::ostream &of) const
Definition: HistoND.h:3575
HistoND & operator+=(const HistoND< Num2, Axis > &r)
std::vector< CircularMapper1d > convolutionHistoMap(const Histo &histo, bool doubleDataRange)
Definition: HistoND.h:3651
bool write(std::ostream &of) const
Definition: ArrayND.h:6041
void addToProjection(HistoND< Num2, Axis > *projection, AbsArrayProjector< Numeric, Num3 > &projector, const unsigned *projectedIndices, unsigned nProjectedIndices) const
Definition: HistoND.h:3538
const std::string & accumulatedDataLabel() const
Definition: HistoND.h:163
void clear()
Definition: HistoND.h:1212
unsigned long modCount_
Definition: HistoND.h:868
const Numeric & examine() const
Definition: HistoND.h:1842
bool isSameData(const HistoND &) const
Definition: HistoND.h:1586
unsigned long nFillsTotal() const
Definition: HistoND.h:183
void binCenter(unsigned long binNumber, double *coords, unsigned lenCoords) const
Definition: HistoND.h:1526
Definition: weight.py:1
const Axis & axis(const unsigned i) const
Definition: HistoND.h:176
HistoND & operator=(const HistoND &)
Definition: HistoND.h:3386
void dispatch(const double *coords, unsigned coordLength, Num2 &weight, Functor &f)
Definition: HistoND.h:1675
std::vector< unsigned > ArrayShape
Definition: ArrayShape.h:21
HistoND & operator*=(const Num2 &r)
Numeric & linearValue(unsigned long index)
Definition: ArrayND.h:3321
unsigned long length() const
Definition: ArrayND.h:231
Numeric value_type
Definition: HistoND.h:48
ArrayND & clear()
Definition: ArrayND.h:4777
void setLinearBin(const unsigned long index, const Num2 &v)
Definition: HistoND.h:632
void fill(const double *coords, unsigned coordLength, const Num2 &weight)
Definition: HistoND.h:1642
Numeric & value(const unsigned *index, unsigned indexLen)
Definition: ArrayND.h:3281
const std::string & title() const
Definition: HistoND.h:160
void addToProjection(ArrayND< Num2, Len2, Dim2 > *projection, AbsArrayProjector< Numeric, Num3 > &projector, const unsigned *projectedIndices, unsigned nProjectedIndices) const
Definition: ArrayND.h:2169
Numeric & at()
Definition: ArrayND.h:3503
std::string title_
Definition: HistoND.h:859
Numeric & linearValueAt(unsigned long index)
Definition: ArrayND.h:3335
void recalculateNFillsFromData()
Definition: HistoND.h:3527
void scaleBinContents(const Num2 *data, unsigned long dataLength)
Definition: HistoND.h:3479
LinearMapper1d inverse() const
std::string accumulatedDataLabel_
Definition: HistoND.h:860
double volume() const
Definition: HistoND.h:1628
void convertHistoToDensity(Histo *histogram, bool knownNonNegative=false)
Definition: HistoND.h:3626
ArrayND & constFill(Numeric c)
Definition: ArrayND.h:4766
void setNFillsOver(const unsigned long i)
Definition: HistoND.h:729
double binVolume(unsigned long binNumber=0) const
Definition: HistoND.h:1613
gs::ClassId classId() const
Definition: HistoND.h:837
Axis axis_type
Definition: HistoND.h:49
const ArrayND< Numeric > & binContents() const
Definition: HistoND.h:167
Exceptions for the npstat namespace.
void h_badargs(const char *method)
Definition: HistoND.h:1133
void setAccumulatedDataLabel(const char *newlabel)
Definition: HistoND.h:203
def binNumber(station, sl)
void setOverflowsToConst(const Num2 &value)
Definition: HistoND.h:711
ArrayShape makeHistoShape(const Axis &xAxis, const Axis &yAxis, const Axis &zAxis, const Axis &tAxis, const Axis &vAxis)
Definition: HistoND.h:981
void addToBinContents(const Num2 &weight)
Definition: HistoND.h:3423
gs::ClassId classId() const
Definition: ArrayND.h:1039
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
void setBin(const unsigned *index, unsigned indexLen, const Num2 &v)
Definition: HistoND.h:2991
static const char * classname()
Definition: HistoND.h:3567
Numeric & valueAt(const unsigned *index, unsigned indexLen)
Definition: ArrayND.h:3431
void accumulateBinsInBox(const BoxND< double > &box, Acc *acc, bool calculateAverage=false) const
Definition: HistoND.h:1174
void addToOverflows(const Num2 &weight)
Definition: HistoND.h:3435
void setNFillsTotal(const unsigned long i)
Definition: HistoND.h:727
ArrayND< Numeric > data_
Definition: HistoND.h:861
math::XYZPoint Point
void fillC(const double *coords, unsigned coordLength, const Num2 &weight)
Definition: HistoND.h:1782
const Numeric * data() const
Definition: ArrayND.h:234
PreciseTypeHelper< T, gs::IOIsNumber< T >::value >::type type
Definition: PreciseType.h:39
double f[11][100]
ArrayND & uninitialize()
Definition: ArrayND.h:4783
bool isUniformlyBinned() const
Definition: HistoND.h:1480
Definition: value.py:1
T min(T a, T b)
Definition: MathUtil.h:58
unsigned long nFillsOver() const
Definition: HistoND.h:190
double integral() const
Definition: HistoND.h:1489
std::vector< double > weightBuf_
Definition: HistoND.h:864
const std::vector< Axis > & axes() const
Definition: HistoND.h:173
unsigned long overCount_
Definition: HistoND.h:867
void allBinCenters(std::vector< Point > *centers) const
Definition: HistoND.h:1545
static void restore(const gs::ClassId &id, std::istream &in, ArrayND *array)
Definition: ArrayND.h:6052
std::vector< unsigned > indexBuf_
Definition: HistoND.h:865
std::vector< Axis > rebinAxes(const std::vector< Axis > &axes, const unsigned *newBins, const unsigned lenNewBins)
Definition: HistoND.h:996
void clearOverflows()
Definition: HistoND.h:1204
unsigned long nBins() const
Definition: HistoND.h:180
std::vector< Axis > addAxis(const std::vector< Axis > &axes, const Axis &newAxis, const unsigned newAxisNumber)
Definition: HistoND.h:1088
const Numeric & closestBin() const
Definition: HistoND.h:1849
BoxND< double > boundingBox() const
Definition: HistoND.h:1512
HistoND & operator-=(const HistoND< Num2, Axis > &r)
void setTitle(const char *newtitle)
Definition: HistoND.h:199
void incrModCount()
Definition: HistoND.h:833
HistoND & operator/=(const Num2 &r)
void setOverflows(const Num2 *data, unsigned long dataLength)
Definition: HistoND.h:3519
void binBox(unsigned long binNumber, BoxND< double > *box) const
Definition: HistoND.h:1570
void fillPreservingCentroid(const Num2 &weight)
Definition: HistoND.h:1753
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
unsigned long nFillsInRange() const
Definition: HistoND.h:186
std::vector< Axis > axesOfASlice(const std::vector< Axis > &axes, const unsigned *fixedIndices, const unsigned nFixedIndices)
Definition: HistoND.h:1013
void setBinContents(const Num2 *data, unsigned long dataLength, bool clearOverflows=true)
Definition: HistoND.h:3507
void setAxisLabel(const unsigned axisNum, const char *newlabel)
Definition: HistoND.h:207
void setBinsToConst(const Num2 &value)
Definition: HistoND.h:703
const unsigned long * strides() const
Definition: ArrayND.h:261
static HistoND * read(const gs::ClassId &id, std::istream &in)
Definition: HistoND.h:3590
bool operator!=(const HistoND &) const
Definition: HistoND.h:1607
void setLinearBinAt(const unsigned long index, const Num2 &v)
Definition: HistoND.h:685
std::vector< Axis > axes_
Definition: HistoND.h:863
ArrayShape shapeOfASlice(const std::vector< Axis > &axes, const unsigned *fixedIndices, const unsigned nFixedIndices)
Definition: HistoND.h:1048
ArrayND< Numeric > overflow_
Definition: HistoND.h:862
void clearBinContents()
Definition: HistoND.h:1196
const ArrayND< Numeric > & overflows() const
Definition: HistoND.h:170
std::vector< LinearMapper1d > densityScanHistoMap(const Histo &histo)
Definition: HistoND.h:3637
HistoND transpose(unsigned axisNum1, unsigned axisNum2) const
Definition: HistoND.h:3408
Histogram axis with equidistant bins.
void scaleOverflows(const Num2 *data, unsigned long dataLength)
Definition: HistoND.h:3493
unsigned dim() const
Definition: HistoND.h:157
Arbitrary-dimensional array template.
ArrayShape shapeWithExtraAxis(const std::vector< Axis > &axes, const Axis &newAxis, const unsigned newAxisNumber)
Definition: HistoND.h:1111