Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-14 08:53:48

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 *                                                                                   *
0004 * This software is distributed under the terms of the Apache version 2 licence,     *
0005 * copied verbatim in the file "LICENSE".                                            *
0006 *                                                                                   *
0007 * In applying this licence, CERN does not waive the privileges and immunities       *
0008 * granted to it by virtue of its status as an Intergovernmental Organization        *
0009 * or submit itself to any jurisdiction.                                             *
0010 \***********************************************************************************/
0011 #ifndef GAUDI_RANGE_H
0012 #define GAUDI_RANGE_H 1
0013 // ============================================================================
0014 // Include files
0015 // ============================================================================
0016 // STD & STL
0017 // ============================================================================
0018 #include <algorithm>
0019 #include <utility>
0020 // ============================================================================
0021 // GaudiKernel
0022 // ============================================================================
0023 #include <GaudiKernel/Kernel.h>
0024 #include <GaudiKernel/detected.h>
0025 // ============================================================================
0026 /** @file
0027  *
0028  *  This file has been imported from
0029  *  <a href="http://savannah.cern.ch/projects/loki">LoKi project</a>
0030  *  <a href="http://cern.ch/lhcb%2Dcomp/Analysis/Loki">
0031  *  "C++ ToolKit  for Smart and Friendly Physics Analysis"</a>
0032  *
0033  *  The package has been designed with the kind help from
0034  *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
0035  *  contributions and advises from G.Raven, J.van Tilburg,
0036  *  A.Golutvin, P.Koppenburg have been used in the design.
0037  *
0038  *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
0039  *  @date 2001-01-23
0040  */
0041 // ============================================================================
0042 namespace Gaudi {
0043   // ==========================================================================
0044   namespace details {
0045     // ========================================================================
0046     /** Helpful function to throw an "out-of-range exception" for class Range_
0047      *  @see GaudiException
0048      *  @param index invalid index
0049      *  @param size  range size
0050      */
0051     GAUDI_API void rangeException( const long index, const size_t size );
0052     // ========================================================================
0053     /// helper structure to get container type
0054     template <class CONTAINER>
0055     struct container {
0056       template <typename T>
0057       using _has_container_t = typename T::Container;
0058       using Container        = Gaudi::cpp17::detected_or_t<CONTAINER, _has_container_t, CONTAINER>;
0059       using Iterator         = typename CONTAINER::const_iterator;
0060     };
0061     // =========================================================================
0062   } // namespace details
0063   // ==========================================================================
0064   /** @struct RangeBase_ GaudiUtils/Range.h
0065    *  helper class to simplify the dealing with ranges in Python
0066    *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0067    *  @date 2006-09-01
0068    */
0069   struct RangeBase_ {};
0070   // ==========================================================================
0071   /** @class Range_ Range.h GaudiUtils/Range.h
0072    *
0073    *  Useful class for representation of "sequence" of the objects
0074    *  through the range of valid iterators.
0075    *
0076    *  The range could be created over *ALL* container types which
0077    *  supports at least bidirectional iterators.
0078    *
0079    *  The minimum requirements from the container type:
0080    *    - support the concept of "CONTAINER::value_type"
0081    *    - support the concept of "CONTAINER::const_iterator"
0082    *    - support the concept of "CONTAINER::const_reference"
0083    *    - support the concept of "CONTAINER::const_reverse_iterator"
0084    *    - the iterator should be ok for "std::distance" and "std::advance"
0085    *    - support for "const_iterator         CONTAINER::begin  () const"
0086    *    - support for "const_iterator         CONTAINER::end    () const"
0087    *    - support for "const_reverse_iterator CONTAINER::rbegin () const"
0088    *    - support for "const_reverse_iterator CONTAINER::rend   () const"
0089    *
0090    *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
0091    *  @date   2002-07-12
0092    */
0093   template <class CONTAINER, class ITERATOR = typename Gaudi::details::container<CONTAINER>::Iterator>
0094   class Range_ : public RangeBase_ {
0095     // FIXME: prepare for removal of ITERATOR argument: check whether the default is _always_ used
0096     static_assert( std::is_same_v<ITERATOR, typename Gaudi::details::container<CONTAINER>::Iterator> );
0097 
0098   public:
0099     // ========================================================================
0100     typedef std::pair<ITERATOR, ITERATOR> Base;
0101     // ========================================================================
0102   public:
0103     // ========================================================================
0104     /// type for actual contained iterator
0105     typedef typename Gaudi::details::container<CONTAINER>::Container Container;
0106     //
0107     typedef ITERATOR iterator;
0108     typedef ITERATOR const_iterator;
0109     //
0110   private:
0111     //
0112     typedef typename std::iterator_traits<iterator> iter_traits;
0113     //
0114   public:
0115     //
0116     typedef typename iter_traits::value_type value_type;
0117     typedef typename iter_traits::reference  reference;
0118     typedef typename iter_traits::reference  const_reference;
0119     //
0120     typedef std::reverse_iterator<iterator> reverse_iterator;
0121     typedef std::reverse_iterator<iterator> const_reverse_iterator;
0122     /// internal types
0123     // ========================================================================
0124   public:
0125     // ========================================================================
0126     /// default constructor
0127     Range_() = default;
0128     /** Constructor
0129      *  @param ibegin  iterator to begin of the sequence
0130      *  @param iend    iterator to end   of the sequence
0131      */
0132     template <typename InputIterator>
0133     Range_( InputIterator first, InputIterator last ) : m_base( first, last ) {}
0134     /** constructor from the pair of iterators
0135      *  @param base pair of the iterators
0136      */
0137     Range_( const Base& base ) : m_base( base ) {}
0138     /** constructor from the container
0139      *  @param cont  reference to the container
0140      */
0141     Range_( const Container& cont ) : m_base( cont.begin(), cont.end() ) {}
0142     /* constructor of empty range/sequence
0143      * @param ibegin  iterator to begin of empty sequence
0144      */
0145     Range_( iterator ibegin ) : m_base( ibegin, ibegin ) {}
0146     /// destructor
0147     ~Range_() = default;
0148     // ========================================================================
0149     /// empty sequence ?
0150     bool empty() const { return m_base.second == m_base.first; }
0151     /// size of the sequence (number of elements)
0152     size_t size() const { return std::distance( m_base.first, m_base.second ); }
0153     /// access to begin of the sequence (const version )
0154     iterator begin() const { return m_base.first; }
0155     /// access to end   of the sequence (const version)
0156     iterator end() const { return m_base.second; }
0157     /// access to begin of the sequence (const version )
0158     iterator cbegin() const { return m_base.first; }
0159     /// access to end   of the sequence (const version)
0160     iterator cend() const { return m_base.second; }
0161     /// access to begin of the reversed sequence (const)
0162     reverse_iterator rbegin() const { return reverse_iterator( end() ); }
0163     /// access to begin of the reversed sequence (const)
0164     reverse_iterator rend() const { return reverse_iterator( begin() ); }
0165     /// access for the first element (only for non-empty ranges!)
0166     const_reference front() const { return *begin(); }
0167     /// access for the back  element (only for non-empty ranges!)
0168     const_reference back() const { return *std::prev( end() ); }
0169     // ========================================================================
0170     /// get a "slice" of a range, in Python style
0171     Range_ slice( long index1, long index2 ) const {
0172       // trivial cases
0173       if ( empty() || index1 == index2 ) { return Range_(); } // RETURN
0174       // adjust indices
0175       if ( index1 < 0 ) { index1 += size(); }
0176       if ( index2 < 0 ) { index2 += size(); }
0177       // check
0178       if ( index1 < 0 ) { return Range_(); }      // RETURN
0179       if ( index2 < index1 ) { return Range_(); } // RETURN
0180 
0181       if ( index1 > (long)size() ) { return Range_(); } // RETURN
0182       if ( index2 > (long)size() ) { index2 = size(); }
0183 
0184       // construct the slice
0185       return Range_( std::next( begin(), index1 ), std::next( begin(), index2 ) ); // RETURN
0186     }
0187     // ========================================================================
0188     /** non-checked access to the elements by index
0189      *  (valid only for non-empty sequences)
0190      *  @param index the index of the lement to be accessed
0191      */
0192     inline const_reference operator()( const size_t index ) const { return *std::next( begin(), index ); }
0193     /** non-checked access to the elements by index
0194      *  (valid only for non-empty sequences)
0195      *  @param index the index of the lement to be accessed
0196      */
0197     inline const_reference operator[]( const long index ) const { return ( *this )( index ); }
0198     /** Checked access to the elements by index
0199      *  (valid for all sequences)
0200      *  @exception GaudiException for out-of-range access
0201      *  @param index the index of the element to be accessed
0202      */
0203     inline const_reference at( const long index ) const {
0204       if ( index < 0 || index >= (long)size() ) { Gaudi::details::rangeException( index, size() ); }
0205       return ( *this )( index );
0206     }
0207     // ========================================================================
0208   public:
0209     // ========================================================================
0210     /// compare with another range
0211     template <class C, class I>
0212     bool operator<( const Range_<C, I>& right ) const {
0213       return std::lexicographical_compare( begin(), end(), right.begin(), right.end() );
0214     }
0215     /// compare with another container
0216     template <class ANOTHERCONTAINER>
0217     bool operator<( const ANOTHERCONTAINER& right ) const {
0218       return std::lexicographical_compare( begin(), end(), right.begin(), right.end() );
0219     }
0220     // ========================================================================
0221   public:
0222     // ========================================================================
0223     /// equality with another range
0224     bool operator==( const Range_& right ) const {
0225       if ( &right == this ) { return true; } // RETURN
0226       return right.size() == size() && std::equal( begin(), end(), right.begin() );
0227     }
0228     /// compare with another container
0229     template <class ANOTHERCONTAINER>
0230     bool operator==( const ANOTHERCONTAINER& right ) const {
0231       return right.size() == size() && std::equal( begin(), end(), right.begin() );
0232     }
0233     // ========================================================================
0234   public:
0235     // ========================================================================
0236     /// empty sequence?
0237     bool operator!() const { return empty(); }
0238     /// non-empty sequence?
0239     explicit operator bool() const { return !empty(); }
0240     // ========================================================================
0241   public:
0242     // ========================================================================
0243     /// conversion operator to the std::pair
0244     operator const Base&() const { return base(); }
0245     /// conversion operator to the std::pair
0246     inline const Base& base() const { return m_base; }
0247     // ========================================================================
0248   private:
0249     // ========================================================================
0250     // the base itself
0251     Base m_base; ///< the base itself
0252     // ========================================================================
0253   }; // end of class Range_
0254   // ==========================================================================
0255   /** simple function to create the range from the arbitrary container
0256    *
0257    *  @code
0258    *
0259    *    const CONTAINER& cnt = ... ;
0260    *
0261    *    Range_<CONTAINER> r = range ( cnt ) ;
0262    *
0263    *  @endcode
0264    *
0265    *  The range could be created over *ALL* container types which
0266    *  supports at least the bidirectional iterators.
0267    *
0268    *  The minimum requirements from the container type:
0269    *    - support the concept of "CONTAINER::value_type"
0270    *    - support the concept of "CONTAINER::const_iterator"
0271    *    - support the concept of "CONTAINER::const_reference"
0272    *    - support the concept of "CONTAINER::const_reverse_iterator"
0273    *    - the iterator should be ok for "std::distance" and "std::advance"
0274    *    - support for "const_iterator         CONTAINER::begin  () const"
0275    *    - support for "const_iterator         CONTAINER::end    () const"
0276    *    - support for "const_reverse_iterator CONTAINER::rbegin () const"
0277    *    - support for "const_reverse_iterator CONTAINER::rend   () const"
0278    *
0279    *  @author Vanya BELYAEV ibelyaev@physics.syre.edu
0280    *  @date 2007-11-29
0281    */
0282   template <class CONTAINER>
0283   inline Range_<CONTAINER> range( const CONTAINER& cnt ) {
0284     return Range_<CONTAINER>( cnt.begin(), cnt.end() );
0285   }
0286   // ==========================================================================
0287 } // end of namespace Gaudi
0288 // ============================================================================
0289 // The END
0290 // ============================================================================
0291 #endif // GAUDI_RANGE_H