• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2010 Christopher Schmidt
3 
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 
8 #include <boost/config.hpp>
9 #include <boost/detail/lightweight_test.hpp>
10 #include <boost/fusion/sequence.hpp>
11 #include <boost/fusion/iterator.hpp>
12 #include <boost/fusion/algorithm/transformation/reverse.hpp>
13 #include <boost/fusion/algorithm/iteration/fold.hpp>
14 #include <boost/fusion/algorithm/iteration/reverse_fold.hpp>
15 #include <boost/fusion/algorithm/iteration/iter_fold.hpp>
16 #include <boost/fusion/algorithm/iteration/reverse_iter_fold.hpp>
17 #include <boost/fusion/container/vector/convert.hpp>
18 #include <boost/fusion/container/vector/vector.hpp>
19 #include <boost/fusion/adapted/mpl.hpp>
20 #include <boost/fusion/support/pair.hpp>
21 #include <boost/fusion/mpl.hpp>
22 #include <boost/mpl/transform.hpp>
23 #include <boost/mpl/front.hpp>
24 #include <boost/mpl/back.hpp>
25 #include <boost/mpl/int.hpp>
26 #include <boost/mpl/assert.hpp>
27 #include <boost/mpl/for_each.hpp>
28 #include <boost/mpl/range_c.hpp>
29 #include <boost/mpl/vector.hpp>
30 #include <boost/mpl/if.hpp>
31 #include <boost/mpl/back_inserter.hpp>
32 #include <boost/mpl/always.hpp>
33 #include <boost/mpl/copy.hpp>
34 #include <boost/type_traits/is_same.hpp>
35 #include <boost/type_traits/remove_reference.hpp>
36 #include <iostream>
37 
38 namespace mpl=boost::mpl;
39 namespace fusion=boost::fusion;
40 
41 #ifdef BOOST_FUSION_TEST_REVERSE_FOLD
42 #   ifdef BOOST_FUSION_TEST_ITER_FOLD
43 #       define BOOST_FUSION_TEST_FOLD_NAME reverse_iter_fold
44 #   else
45 #       define BOOST_FUSION_TEST_FOLD_NAME reverse_fold
46 #   endif
47 #else
48 #   ifdef BOOST_FUSION_TEST_ITER_FOLD
49 #       define BOOST_FUSION_TEST_FOLD_NAME iter_fold
50 #   else
51 #       define BOOST_FUSION_TEST_FOLD_NAME fold
52 #   endif
53 #endif
54 
55 struct sum
56 {
57     template<typename Sig>
58     struct result;
59 
60     template<typename Self, typename State, typename T>
61     struct result<Self(State,T)>
62       : boost::fusion::result_of::make_pair<
63             mpl::int_<
64                 boost::remove_reference<
65                     State
66                 >::type::first_type::value+1
67             >
68           , int
69         >
70     {
71         BOOST_MPL_ASSERT((typename boost::is_reference<State>::type));
72         BOOST_MPL_ASSERT((typename boost::is_reference<T>::type));
73     };
74 
75 #ifdef BOOST_FUSION_TEST_ITER_FOLD
76     template<typename State, typename It>
77     typename result<sum const&(State const&,It const&)>::type
operator ()sum78     operator()(State const& state, It const& it)const
79     {
80         static const int n=State::first_type::value;
81         return fusion::make_pair<mpl::int_<n+1> >(
82             state.second+fusion::deref(it)*n);
83     }
84 #else
85     template<typename State>
86     typename result<sum const&(State const&, int const&)>::type
operator ()sum87     operator()(State const& state, int const& e)const
88     {
89         static const int n=State::first_type::value;
90         return fusion::make_pair<mpl::int_<n+1> >(state.second+e*n);
91     }
92 #endif
93 };
94 
95 struct meta_sum
96 {
97     template<typename Sig>
98     struct result;
99 
100     template<typename Self, typename State, typename T>
101     struct result<Self(State,T)>
102     {
103         BOOST_MPL_ASSERT((typename boost::is_reference<State>::type));
104         BOOST_MPL_ASSERT((typename boost::is_reference<T>::type));
105 
106         typedef typename boost::remove_reference<State>::type state;
107         static const int n=mpl::front<state>::type::value;
108 
109 #ifdef BOOST_FUSION_TEST_ITER_FOLD
110         typedef typename
111             boost::fusion::result_of::value_of<
112                 typename boost::remove_reference<T>::type
113             >::type
114         t;
115 #else
116         typedef typename boost::remove_reference<T>::type t;
117 #endif
118 
119         typedef
120             mpl::vector<
121                 mpl::int_<n+1>
122               , mpl::int_<
123                     mpl::back<state>::type::value+t::value*n
124                 >
125             >
126         type;
127     };
128 
129     template<typename State, typename T>
130     typename result<meta_sum const&(State const&,T const&)>::type
131     operator()(State const&, T const&)const;
132 };
133 
134 struct fold_test_n
135 {
136     template<typename I>
137     void
operator ()fold_test_n138     operator()(I)const
139     {
140         static const int n=I::value;
141         typedef mpl::range_c<int, 0, n> range;
142 
143         static const int squares_sum=n*(n+1)*(2*n+1)/6;
144 
145         {
146             mpl::range_c<int, 1, n+1> init_range;
147             typename boost::fusion::result_of::as_vector<
148                 typename mpl::transform<
149                     range
150                   , mpl::always<int>
151                   , mpl::back_inserter<mpl::vector<> >
152                 >::type
153             >::type vec(
154 #ifdef BOOST_FUSION_TEST_REVERSE_FOLD
155                 fusion::reverse(init_range)
156 #else
157                 init_range
158 #endif
159             );
160 
161             int result=BOOST_FUSION_TEST_FOLD_NAME(
162                 vec,
163                 fusion::make_pair<mpl::int_<1> >(0),
164                 sum()).second;
165             std::cout << n << ": " << result << std::endl;
166             BOOST_TEST(result==squares_sum);
167         }
168 
169         {
170             typedef typename
171 #ifdef BOOST_FUSION_TEST_REVERSE_FOLD
172                 boost::fusion::result_of::as_vector<
173                     typename mpl::copy<
174                         mpl::range_c<int, 1, n+1>
175                       , mpl::front_inserter<fusion::vector<> >
176                     >::type
177                 >::type
178 #else
179                 boost::fusion::result_of::as_vector<mpl::range_c<int, 1, n+1> >::type
180 #endif
181             vec;
182 
183             typedef
184                 boost::is_same<
185                     typename boost::fusion::result_of::BOOST_FUSION_TEST_FOLD_NAME<
186                         vec
187                       , mpl::vector<mpl::int_<1>, mpl::int_<0> >
188                       , meta_sum
189                     >::type
190                   , typename mpl::if_c<
191                         !n
192                       , mpl::vector<mpl::int_<1>, mpl::int_<0> >&
193                       , mpl::vector<mpl::int_<n+1>, mpl::int_<squares_sum> >
194                     >::type
195                 >
196             result_test;
197 
198             BOOST_MPL_ASSERT((result_test));
199         }
200     }
201 };
202 
203 int
main()204 main()
205 {
206     mpl::for_each<mpl::range_c<int, 0, 10> >(fold_test_n());
207 
208     return boost::report_errors();
209 }
210 
211 #undef BOOST_FUSION_TEST_FOLD_NAME
212 
213