Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:19:19

0001 #ifndef NPSTAT_ARRAYNDSCANNER_HH_
0002 #define NPSTAT_ARRAYNDSCANNER_HH_
0003 
0004 /*!
0005 // \file ArrayNDScanner.h
0006 //
0007 // \brief Iteration over indices of a multidimensional array
0008 //
0009 // Author: I. Volobouev
0010 //
0011 // July 2012
0012 */
0013 
0014 #include <vector>
0015 #include <climits>
0016 
0017 namespace npstat {
0018   /**
0019     * This class can be used to iterate over array indices without actually
0020     * building the array or requesting any memory from the heap. Typical use:
0021     *
0022     * @code
0023     *   for (ArrayNDScanner scanner(shape); scanner.isValid(); ++scanner)
0024     *   {
0025     *       scanner.getIndex(indexArray, indexArrayLen);
0026     *       .... Do what is necessary with multidimensional index ....
0027     *       .... Extract linear index: ...............................
0028     *       scanner.state();
0029     *   }
0030     * @endcode
0031     *
0032     * This can be useful, for example, in case one needs to iterate over
0033     * slices of some array (so that the array itself can not be used
0034     * to obtain similar information easily).
0035     */
0036   class ArrayNDScanner {
0037   public:
0038     //@{
0039     /** Constructor from a multidimensional array shape */
0040     inline ArrayNDScanner(const unsigned* shape, const unsigned lenShape) { initialize(shape, lenShape); }
0041 
0042     inline explicit ArrayNDScanner(const std::vector<unsigned>& shape) {
0043       initialize(shape.empty() ? static_cast<unsigned*>(nullptr) : &shape[0], shape.size());
0044     }
0045 
0046     ArrayNDScanner() = delete;
0047     //@}
0048 
0049     /** Dimensionality of the scan */
0050     inline unsigned dim() const { return dim_; }
0051 
0052     /** Retrieve current state (i.e., linear index of the scan) */
0053     inline unsigned long state() const { return state_; }
0054 
0055     /** Maximum possible state (i.e., linear index of the scan) */
0056     inline unsigned long maxState() const { return maxState_; }
0057 
0058     /** Returns false when iteration is complete */
0059     inline bool isValid() const { return state_ < maxState_; }
0060 
0061     /** Retrieve current multidimensional index */
0062     void getIndex(unsigned* index, unsigned indexBufferLen) const;
0063 
0064     /** Reset the state (as if the object has just been constructed) */
0065     inline void reset() { state_ = 0UL; }
0066 
0067     /** Prefix increment */
0068     inline ArrayNDScanner& operator++() {
0069       if (state_ < maxState_)
0070         ++state_;
0071       return *this;
0072     }
0073 
0074     /** Postfix increment (distinguished by the dummy "int" parameter) */
0075     inline void operator++(int) {
0076       if (state_ < maxState_)
0077         ++state_;
0078     }
0079 
0080     /** Set the state directly */
0081     inline void setState(const unsigned long state) { state_ = state <= maxState_ ? state : maxState_; }
0082 
0083   private:
0084     void initialize(const unsigned* shape, unsigned lenShape);
0085 
0086     unsigned long strides_[CHAR_BIT * sizeof(unsigned long)];
0087     unsigned long state_;
0088     unsigned long maxState_;
0089     unsigned dim_;
0090   };
0091 }  // namespace npstat
0092 
0093 #endif  // NPSTAT_ARRAYSCANNER_HH_