1 /*
2  [auto_generated]
3  boost/numeric/odeint/util/split_adaptor.hpp
4 
5  [begin_description]
6  A range adaptor which returns even-sized slices.
7  [end_description]
8 
9  Copyright 2013 Karsten Ahnert
10  Copyright 2013 Mario Mulansky
11  Copyright 2013 Pascal Germroth
12 
13  Distributed under the Boost Software License, Version 1.0.
14  (See accompanying file LICENSE_1_0.txt or
15  copy at http://www.boost.org/LICENSE_1_0.txt)
16  */
17 
18 
19 #ifndef BOOST_NUMERIC_ODEINT_UTIL_SPLIT_ADAPTOR_INCLUDED
20 #define BOOST_NUMERIC_ODEINT_UTIL_SPLIT_ADAPTOR_INCLUDED
21 
22 #include <boost/range/adaptor/argument_fwd.hpp>
23 #include <boost/range/size_type.hpp>
24 #include <boost/range/iterator_range.hpp>
25 #include <algorithm>
26 
27 namespace boost {
28 namespace numeric {
29 namespace odeint {
30 namespace detail {
31 
32 /** \brief Returns the begin and end offset for a sub-range */
33 inline std::pair<std::size_t, std::size_t>
split_offsets(std::size_t total_length,std::size_t index,std::size_t parts)34 split_offsets( std::size_t total_length, std::size_t index, std::size_t parts )
35 {
36     BOOST_ASSERT( parts > 0 );
37     BOOST_ASSERT( index < parts );
38     const std::size_t
39         slice = total_length / parts,
40         partial = total_length % parts,
41         lo = (std::min)(index, partial),
42         hi = (std::max<std::ptrdiff_t>)(0, index - partial),
43         begin_offset = lo * (slice + 1) + hi * slice,
44         length = slice + (index < partial ? 1 : 0),
45         end_offset = begin_offset + length;
46     return std::make_pair( begin_offset, end_offset );
47 }
48 
49 /** \brief Return the sub-range `index` from a range which is split into `parts`.
50  *
51  * For example, splitting a range into three about equal-sized sub-ranges:
52  * \code
53  * sub0 = make_split_range(rng, 0, 3);
54  * sub1 = rng | split(1, 3);
55  * sub2 = rng | split(2, 3);
56  * \endcode
57  */
58 template< class RandomAccessRange >
59 inline iterator_range< typename range_iterator<RandomAccessRange>::type >
make_split_range(RandomAccessRange & rng,std::size_t index,std::size_t parts)60 make_split_range( RandomAccessRange& rng, std::size_t index, std::size_t parts )
61 {
62     const std::pair<std::size_t, std::size_t> off = split_offsets(boost::size(rng), index, parts);
63     return make_iterator_range( boost::begin(rng) + off.first, boost::begin(rng) + off.second );
64 }
65 
66 template< class RandomAccessRange >
67 inline iterator_range< typename range_iterator<const RandomAccessRange>::type >
make_split_range(const RandomAccessRange & rng,std::size_t index,std::size_t parts)68 make_split_range( const RandomAccessRange& rng, std::size_t index, std::size_t parts )
69 {
70     const std::pair<std::size_t, std::size_t> off = split_offsets(boost::size(rng), index, parts);
71     return make_iterator_range( boost::begin(rng) + off.first, boost::begin(rng) + off.second );
72 }
73 
74 
75 struct split
76 {
splitboost::numeric::odeint::detail::split77     split(std::size_t index, std::size_t parts)
78         : index(index), parts(parts) {}
79     std::size_t index, parts;
80 };
81 
82 template< class RandomAccessRange >
83 inline iterator_range< typename range_iterator<RandomAccessRange>::type >
operator |(RandomAccessRange & rng,const split & f)84 operator|( RandomAccessRange& rng, const split& f )
85 {
86     return make_split_range( rng, f.index, f.parts );
87 }
88 
89 template< class RandomAccessRange >
90 inline iterator_range< typename range_iterator<const RandomAccessRange>::type >
operator |(const RandomAccessRange & rng,const split & f)91 operator|( const RandomAccessRange& rng, const split& f )
92 {
93     return make_split_range( rng, f.index, f.parts );
94 }
95 
96 
97 }
98 }
99 }
100 }
101 
102 #endif
103