MADNESS  0.10.1
range.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30 */
31 
32 #ifndef MADNESS_WORLD_RANGE_H__INCLUDED
33 #define MADNESS_WORLD_RANGE_H__INCLUDED
34 
35 #include <type_traits>
36 #include <iterator>
37 #ifdef HAVE_INTEL_TBB
38 # include <tbb/partitioner.h>
39 #endif
40 
41 /**
42  \file range.h
43  \brief Implement the \c Range class for parallel iteration.
44  \ingroup parallel_runtime
45 */
46 
47 namespace madness {
48 
49  /// \addtogroup parallel_runtime
50  /// @{
51 
52  /// Dummy class, a la Intel TBB, used to distinguish splitting constructor.
53 #ifdef HAVE_INTEL_TBB
54  typedef tbb::split Split;
55 #else
56  class Split {};
57 #endif // HAVE_INTEL_TBB
58 
59  /// \brief Range, vaguely a la Intel TBB, to encapsulate a random-access,
60  /// STL-like start and end iterator with chunksize.
61 
62  /// \tparam iteratorT The iterator type.
63  template <typename iteratorT>
64  class Range {
65  long n; ///< Number of items to iterator over. \todo Could this be replaced by size_t?
66  iteratorT start; ///< First item for iteration.
67  iteratorT finish; ///< Last item for iteration (first past the end, conventionally).
68  int chunksize; ///< Number of items to give to each thread/process.
69 
70  public:
71  using iterator = iteratorT; ///< Alias for the iterator type.
72 
73  /// Makes the range [start, finish).
74 
75  /// The motivated reader should look at the Intel TBB range,
76  /// partitioner, split, concepts, etc.
77  /// \param[in] start The first item to iterate over.
78  /// \param[in] finish The last item for iteration (one past the end).
79  /// \param[in] chunk The number of items to give to each thread/process.
80  Range(const iterator& start, const iterator& finish, int chunk=1)
82  , start(start)
83  , finish(finish)
84  , chunksize(chunk)
85  {
86  if (chunksize < 1) chunksize = 1;
87  }
88 
89  /// Copy constructor. Cost is O(1).
90 
91  /// \todo Can we make this `= default`?
92  /// \param[in] r The \c Range to copy.
93  Range(const Range& r)
94  : n(r.n)
95  , start(r.start)
96  , finish(r.finish)
97  , chunksize(r.chunksize)
98  {}
99 
100  /// Splits range between new and old (r) objects. Cost is O(1).
101 
102  /// \param[in] left The range to be split.
103  Range(Range& left, const Split& /*split*/)
104  : n(0)
105  , start(left.finish)
106  , finish(left.finish)
107  , chunksize(left.chunksize)
108  {
109  if (left.n > chunksize) {
110  int nleft = (left.n+1)/2;
111 
112  start = left.start;
113  advance(start,nleft);
114  finish = left.finish;
115  n = left.n - nleft;
116 
117  left.finish = start;
118  left.n = nleft;
119  }
120  }
121 
122  /// Returns the number of items in the range (cost is O(1)).
123 
124  /// \return The number of items in the range.
125  size_t size() const { return n; }
126 
127  /// Returns true if `size == 0`.
128 
129  /// \return True if `size == 0`.
130  bool empty() const { return n==0; }
131 
132  /// Access the beginning.
133 
134  /// \return Iterator to the first element.
135  const iterator& begin() const { return start; }
136 
137  /// Access the end.
138 
139  /// \return Iterator to the last element (one past the end).
140  const iterator& end() const { return finish; }
141 
142  /// \brief Return true if this iteration range can be divided; that is,
143  /// there are more items than the chunk size.
144 
145  /// \return True if this range can be divided.
146  bool is_divisible() const { return n > chunksize; }
147 
148  /// Access the chunk size.
149 
150  /// \todo Should this return `long`, or `size_t`?
151  /// \return The chunk size.
152  unsigned int get_chunksize() const { return chunksize; }
153 
154  private:
155  /// Advance by \c n elements in the range.
156 
157  /// This version is for cases where the "iterator type" is integral.
158  /// \tparam integralT The integral iterator type.
159  /// \tparam distanceT The distance type.
160  /// \param[in,out] i The integral iterator.
161  /// \param[in] n The number of elements to advance.
162  template<typename integralT, typename distanceT>
163  inline static typename std::enable_if<std::is_integral<integralT>::value, void>::type
164  advance(integralT& i, distanceT n) { i += n; }
165 
166  /// Advance by \c n elements in the range.
167 
168  /// This version is for cases where the "iterator type" is not integral.
169  /// \tparam iterT The non-integral iterator type.
170  /// \tparam distanceT The distance type.
171  /// \param[in,out] it The iterator.
172  /// \param[in] n The number of elements to advance.
173  template<typename iterT, typename distanceT>
174  inline static typename std::enable_if<!std::is_integral<iterT>::value, void>::type
175  advance(iterT& it, distanceT n) { std::advance(it, n); }
176 
177  /// Calculate the distance between two iterators.
178 
179  /// This version is for cases where the "iterator type" is integral.
180  /// \tparam integralT The integral iterator type.
181  /// \param[in] first One iterator.
182  /// \param[in] last The other iterator.
183  /// \return The distance between the first and last iterators.
184  template<class integralT>
185  inline static typename std::enable_if<std::is_integral<integralT>::value, integralT>::type
186  distance(integralT first, integralT last) { return last - first; }
187 
188  /// Calculate the distance between two iterators.
189 
190  /// This version is for cases where the "iterator type" is not integral.
191  /// \tparam iterT The non-integral iterator type.
192  /// \param[in] first One iterator.
193  /// \param[in] last The other iterator.
194  /// \return The distance between the first and last iterators.
195  template<class iterT>
196  inline static auto
197  distance(iterT first, iterT last,
198  typename std::enable_if<!std::is_integral<iterT>::value>::type* = nullptr)
199  -> decltype(std::distance(first, last))
200  { return std::distance(first, last); }
201  };
202 
203  /// @}
204 
205 } // namespace madness
206 
207 #endif // MADNESS_WORLD_RANGE_H__INCLUDED
Range, vaguely a la Intel TBB, to encapsulate a random-access, STL-like start and end iterator with c...
Definition: range.h:64
Range(Range &left, const Split &)
Splits range between new and old (r) objects. Cost is O(1).
Definition: range.h:103
unsigned int get_chunksize() const
Access the chunk size.
Definition: range.h:152
static std::enable_if< std::is_integral< integralT >::value, integralT >::type distance(integralT first, integralT last)
Calculate the distance between two iterators.
Definition: range.h:186
bool is_divisible() const
Return true if this iteration range can be divided; that is, there are more items than the chunk size...
Definition: range.h:146
static auto distance(iterT first, iterT last, typename std::enable_if<!std::is_integral< iterT >::value >::type *=nullptr) -> decltype(std::distance(first, last))
Calculate the distance between two iterators.
Definition: range.h:197
long n
Number of items to iterator over.
Definition: range.h:65
iteratorT iterator
Alias for the iterator type.
Definition: range.h:71
bool empty() const
Returns true if size == 0.
Definition: range.h:130
int chunksize
Number of items to give to each thread/process.
Definition: range.h:68
Range(const iterator &start, const iterator &finish, int chunk=1)
Makes the range [start, finish).
Definition: range.h:80
iteratorT finish
Last item for iteration (first past the end, conventionally).
Definition: range.h:67
iteratorT start
First item for iteration.
Definition: range.h:66
static std::enable_if< std::is_integral< integralT >::value, void >::type advance(integralT &i, distanceT n)
Advance by n elements in the range.
Definition: range.h:164
const iterator & end() const
Access the end.
Definition: range.h:140
static std::enable_if<!std::is_integral< iterT >::value, void >::type advance(iterT &it, distanceT n)
Advance by n elements in the range.
Definition: range.h:175
size_t size() const
Returns the number of items in the range (cost is O(1)).
Definition: range.h:125
const iterator & begin() const
Access the beginning.
Definition: range.h:135
Range(const Range &r)
Copy constructor. Cost is O(1).
Definition: range.h:93
tbb::split Split
Dummy class, a la Intel TBB, used to distinguish splitting constructor.
Definition: range.h:54
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
std::string type(const PairType &n)
Definition: PNOParameters.h:18
void advance(madness::Hash_private::HashIterator< hashT > &it, const distT &dist)
Definition: worldhashmap.h:610
int distance(const madness::Hash_private::HashIterator< hashT > &it, const madness::Hash_private::HashIterator< hashT > &jt)
Definition: worldhashmap.h:616
void split(const Range< ConcurrentHashMap< int, int >::iterator > &range)
Definition: test_hashthreaded.cc:63