1 // Copyright 2009-2014 Neil Groves.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 //
6 // Copyright 2006 Thorsten Ottosen.
7 // Distributed under the Boost Software License, Version 1.0. (See
8 // accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Copyright 2004 Eric Niebler.
12 // Distributed under the Boost Software License, Version 1.0. (See
13 // accompanying file LICENSE_1_0.txt or copy at
14 // http://www.boost.org/LICENSE_1_0.txt)
15 //
16 //   Contains range-based versions of the numeric std algorithms
17 //
18 #if defined(_MSC_VER)
19     #pragma once
20 #endif
21 
22 #ifndef BOOST_RANGE_NUMERIC_HPP
23 #define BOOST_RANGE_NUMERIC_HPP
24 
25 #include <boost/config.hpp>
26 #include <boost/assert.hpp>
27 #include <boost/range/begin.hpp>
28 #include <boost/range/end.hpp>
29 #include <boost/range/category.hpp>
30 #include <boost/range/concepts.hpp>
31 #include <boost/range/distance.hpp>
32 #include <boost/range/size.hpp>
33 #include <numeric>
34 
35 
36 namespace boost
37 {
38     template<class SinglePassRange, class Value>
accumulate(const SinglePassRange & rng,Value init)39     inline Value accumulate(const SinglePassRange& rng, Value init)
40     {
41         BOOST_RANGE_CONCEPT_ASSERT((
42             SinglePassRangeConcept<const SinglePassRange>));
43 
44         return std::accumulate(boost::begin(rng), boost::end(rng), init);
45     }
46 
47     template<class SinglePassRange, class Value, class BinaryOperation>
accumulate(const SinglePassRange & rng,Value init,BinaryOperation op)48     inline Value accumulate(const SinglePassRange& rng, Value init,
49                             BinaryOperation op)
50     {
51         BOOST_RANGE_CONCEPT_ASSERT((
52                 SinglePassRangeConcept<const SinglePassRange> ));
53 
54         return std::accumulate(boost::begin(rng), boost::end(rng), init, op);
55     }
56 
57     namespace range_detail
58     {
59         template<class SinglePassRange1, class SinglePassRange2>
inner_product_precondition(const SinglePassRange1 &,const SinglePassRange2 &,std::input_iterator_tag,std::input_iterator_tag)60         inline bool inner_product_precondition(
61             const SinglePassRange1&,
62             const SinglePassRange2&,
63             std::input_iterator_tag,
64             std::input_iterator_tag)
65         {
66             return true;
67         }
68 
69         template<class SinglePassRange1, class SinglePassRange2>
inner_product_precondition(const SinglePassRange1 & rng1,const SinglePassRange2 & rng2,std::forward_iterator_tag,std::forward_iterator_tag)70         inline bool inner_product_precondition(
71             const SinglePassRange1& rng1,
72             const SinglePassRange2& rng2,
73             std::forward_iterator_tag,
74             std::forward_iterator_tag)
75         {
76             return boost::size(rng2) >= boost::size(rng1);
77         }
78 
79     } // namespace range_detail
80 
81     template<
82         class SinglePassRange1,
83         class SinglePassRange2,
84         class Value
85     >
inner_product(const SinglePassRange1 & rng1,const SinglePassRange2 & rng2,Value init)86     inline Value inner_product(
87         const SinglePassRange1& rng1,
88         const SinglePassRange2& rng2,
89         Value                   init)
90     {
91         BOOST_RANGE_CONCEPT_ASSERT((
92             SinglePassRangeConcept<const SinglePassRange1>));
93 
94         BOOST_RANGE_CONCEPT_ASSERT((
95             SinglePassRangeConcept<const SinglePassRange2>));
96 
97         BOOST_ASSERT(
98             range_detail::inner_product_precondition(
99                     rng1, rng2,
100                     typename range_category<const SinglePassRange1>::type(),
101                     typename range_category<const SinglePassRange2>::type()));
102 
103         return std::inner_product(
104             boost::begin(rng1), boost::end(rng1),
105             boost::begin(rng2), init);
106     }
107 
108     template<
109         class SinglePassRange1,
110         class SinglePassRange2,
111         class Value,
112         class BinaryOperation1,
113         class BinaryOperation2
114     >
inner_product(const SinglePassRange1 & rng1,const SinglePassRange2 & rng2,Value init,BinaryOperation1 op1,BinaryOperation2 op2)115     inline Value inner_product(
116         const SinglePassRange1& rng1,
117         const SinglePassRange2& rng2,
118         Value                   init,
119         BinaryOperation1        op1,
120         BinaryOperation2        op2)
121     {
122         BOOST_RANGE_CONCEPT_ASSERT((
123                 SinglePassRangeConcept<const SinglePassRange1>));
124 
125         BOOST_RANGE_CONCEPT_ASSERT((
126                 SinglePassRangeConcept<const SinglePassRange2>));
127 
128         BOOST_ASSERT(
129             range_detail::inner_product_precondition(
130                 rng1, rng2,
131                 typename range_category<const SinglePassRange1>::type(),
132                 typename range_category<const SinglePassRange2>::type()));
133 
134         return std::inner_product(
135             boost::begin(rng1), boost::end(rng1),
136             boost::begin(rng2), init, op1, op2);
137     }
138 
139     template<class SinglePassRange, class OutputIterator>
partial_sum(const SinglePassRange & rng,OutputIterator result)140     inline OutputIterator partial_sum(const SinglePassRange& rng,
141                                       OutputIterator result)
142     {
143         BOOST_RANGE_CONCEPT_ASSERT((
144                 SinglePassRangeConcept<const SinglePassRange>));
145 
146         return std::partial_sum(boost::begin(rng), boost::end(rng), result);
147     }
148 
149     template<class SinglePassRange, class OutputIterator, class BinaryOperation>
partial_sum(const SinglePassRange & rng,OutputIterator result,BinaryOperation op)150     inline OutputIterator partial_sum(
151         const SinglePassRange&  rng,
152         OutputIterator          result,
153         BinaryOperation         op)
154     {
155         BOOST_RANGE_CONCEPT_ASSERT((
156                 SinglePassRangeConcept<const SinglePassRange>));
157 
158         return std::partial_sum(boost::begin(rng), boost::end(rng), result, op);
159     }
160 
161     template<class SinglePassRange, class OutputIterator>
adjacent_difference(const SinglePassRange & rng,OutputIterator result)162     inline OutputIterator adjacent_difference(
163         const SinglePassRange&  rng,
164         OutputIterator          result)
165     {
166         BOOST_RANGE_CONCEPT_ASSERT((
167                 SinglePassRangeConcept<const SinglePassRange>));
168 
169         return std::adjacent_difference(boost::begin(rng), boost::end(rng),
170                                         result);
171     }
172 
173     template<class SinglePassRange, class OutputIterator, class BinaryOperation>
adjacent_difference(const SinglePassRange & rng,OutputIterator result,BinaryOperation op)174     inline OutputIterator adjacent_difference(
175         const SinglePassRange&  rng,
176         OutputIterator          result,
177         BinaryOperation         op)
178     {
179         BOOST_RANGE_CONCEPT_ASSERT((
180                 SinglePassRangeConcept<const SinglePassRange>));
181 
182         return std::adjacent_difference(boost::begin(rng), boost::end(rng),
183                                         result, op);
184     }
185 
186 } // namespace boost
187 
188 #endif
189