Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:51

0001 /* @(#)root/core/cont:$Id$ */
0002 // Author: Danilo Piparo November 2015
0003 
0004 /*************************************************************************
0005  * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers.               *
0006  * All rights reserved.                                                  *
0007  *                                                                       *
0008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0010  *************************************************************************/
0011 
0012 #ifndef ROOT_TSeq
0013 #define ROOT_TSeq
0014 
0015 #include "TError.h"
0016 #include <iterator>
0017 #include <type_traits>
0018 
0019 /**
0020 \class ROOT::TSeq
0021 \brief A pseudo container class which is a generator of indices.
0022 
0023 \tparam T Type of the numerical sequence.
0024 \ingroup Containers
0025 A pseudo container class which is a generator of indices. The model is the `xrange`
0026 built-in function of Python.
0027 Possible usages:
0028 Loop on a sequence of integers
0029 ~~~{.cpp}
0030    for (auto i : TSeqI(10)) {
0031       cout << "Element " << i << endl;
0032    }
0033 ~~~
0034 Loop on a sequence of integers in steps
0035 ~~~{.cpp}
0036    for (auto i : TSeqI(-5, 29, 6)) {
0037       cout << "Element " << i << endl;
0038    }
0039 ~~~
0040 Loop backwards on a sequence of integers
0041 ~~~{.cpp}
0042    for (auto i : TSeqI(50, 30, -3)) {
0043       cout << "Element " << i << endl;
0044    }
0045 ~~~
0046 Use an stl algorithm, for_each
0047 ~~~{.cpp}
0048    TSeqUL ulSeq(2,30,3);
0049    std::for_each(std::begin(ulSeq),std::end(ulSeq),[](ULong_t i){cout << "For each: " << i <<endl;});
0050 ~~~
0051 Random access:
0052 ~~~{.cpp}
0053    cout << "Random access: 3rd element is " << ulSeq[2] << endl;
0054 ~~~
0055 A function to create sequences inferring the type:
0056 ~~~{.cpp}
0057    for (auto i : MakeSeq(1000000000000UL, 1000000000003UL)) {
0058       cout << "Element " << i << endl;
0059    }
0060 ~~~
0061 
0062 **/
0063 
0064 namespace ROOT {
0065 
0066    template<class T>
0067    class TSeq {
0068    private:
0069       void checkIntegralType() {
0070          static_assert(std::is_integral<T>::value, "Only integral types are supported.");
0071       }
0072       const T fBegin;
0073       const T fEnd;
0074       const T fStep;
0075    public:
0076       using value_type = T;
0077       using difference_type = typename std::make_signed<T>::type;
0078 
0079       TSeq(T theEnd): fBegin(), fEnd(theEnd), fStep(1) {
0080          checkIntegralType();
0081       }
0082       TSeq(T theBegin, T theEnd, T theStep = 1):
0083         fBegin(theBegin), fEnd(theEnd), fStep(theStep) {
0084          checkIntegralType();
0085          R__ASSERT(fStep != 0 && "TSeq does not support steps of size 0.");
0086       }
0087 
0088       class iterator {
0089       private:
0090          T fCounter;
0091          T fStep;
0092       public:
0093          using iterator_category = std::random_access_iterator_tag;
0094          using value_type = T;
0095          using difference_type = typename std::make_signed<T>::type;
0096          using pointer = T *;
0097          using const_pointer = const T *;
0098          using reference = T &;
0099 
0100          iterator(T start, T step): fCounter(start), fStep(step) {}
0101          T operator*() const {
0102             return fCounter;
0103          }
0104          // equality
0105          bool operator==(const iterator &other) const {
0106             return fCounter == other.fCounter;
0107          }
0108          // inequality
0109          bool operator!=(const iterator &other) const {
0110             return fCounter != other.fCounter;
0111          }
0112          // sum with integer
0113          iterator operator+(difference_type v) const {
0114             return iterator(fCounter + v * fStep, fStep);
0115          }
0116          // difference with integer
0117          iterator operator-(difference_type v) const {
0118             return iterator(fCounter - v * fStep, fStep);
0119          }
0120          // distance
0121          difference_type operator-(const iterator &other) const {
0122             return (fCounter - other.fCounter) / fStep;
0123          }
0124          // increments
0125          iterator &operator++() {
0126             fCounter += fStep;
0127             return *this;
0128          }
0129          iterator operator++(int) {
0130             iterator tmp(*this);
0131             operator++();
0132             return tmp;
0133          }
0134          // decrements
0135          iterator &operator--() {
0136             fCounter -= fStep;
0137             return *this;
0138          }
0139          iterator operator--(int) {
0140             iterator tmp(*this);
0141             operator--();
0142             return tmp;
0143          }
0144          // compound assignments
0145          iterator &operator+=(const difference_type& v) {
0146             *this = *this + v;
0147             return *this;
0148          }
0149          iterator &operator-=(const difference_type& v) {
0150             *this = *this - v;
0151             return *this;
0152          }
0153          // comparison operators
0154          bool operator <(const iterator &other) const {
0155              return (other - *this) > 0;
0156          }
0157          bool operator >(const iterator &other) const {
0158              return other < *this;
0159          }
0160          bool operator <=(const iterator &other) const {
0161              return !(*this > other);
0162          }
0163          bool operator >=(const iterator &other) const {
0164              return !(other > *this);
0165          }
0166          // subscript operator
0167          const T operator[](const difference_type& v) const{
0168              return *(*this + v);
0169          }
0170       };
0171 
0172       iterator begin() const {
0173          return iterator(fBegin, fStep);
0174       }
0175       iterator end() const {
0176          auto isStepMultiple = (fEnd - fBegin) % fStep == 0;
0177          auto theEnd = isStepMultiple ? fEnd : fStep * (((fEnd - fBegin) / fStep) + 1) + fBegin;
0178          return iterator(theEnd, fStep);
0179       }
0180 
0181       T const &front() const {
0182          return fBegin;
0183       }
0184 
0185       T operator[](T s) const {
0186          return s * fStep + fBegin;
0187       }
0188 
0189       std::size_t size() const {
0190          return end() - begin();
0191       }
0192 
0193       T step() const {
0194          return fStep;
0195       }
0196 
0197       bool empty() const {
0198          return fEnd == fBegin;
0199       }
0200 
0201    };
0202 
0203    using TSeqI = TSeq<int>;
0204    using TSeqU = TSeq<unsigned int>;
0205    using TSeqL = TSeq<long>;
0206    using TSeqUL = TSeq<unsigned long>;
0207 
0208    template<class T>
0209    TSeq<T> MakeSeq(T end)
0210    {
0211       return TSeq<T>(end);
0212    }
0213 
0214    template<class T>
0215    TSeq<T> MakeSeq(T begin, T end, T step = 1)
0216    {
0217       return TSeq<T>(begin, end, step);
0218    }
0219 
0220 }
0221 
0222 #include <sstream>
0223 
0224 ////////////////////////////////////////////////////////////////////////////////
0225 /// Print a TSeq at the prompt:
0226 
0227 namespace cling {
0228    template<class T>
0229    std::string printValue(ROOT::TSeq<T> *val)
0230    {
0231       std::ostringstream ret;
0232       auto step = val->step();
0233       ret << "A sequence of values: " << *val->begin() << ((step > 0) ? " <= i < " : " >= i > ") << *val->end();
0234       if (1 != step)
0235           ret << " in steps of " <<  step;
0236       return ret.str();
0237    }
0238 }
0239 
0240 #endif