Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:07:18

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