]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/yap/example/mixed.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / yap / example / mixed.cpp
1 // Copyright (C) 2016-2018 T. Zachary Laine
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //[ mixed
7 #include <boost/yap/yap.hpp>
8
9 #include <complex>
10 #include <list>
11 #include <vector>
12 #include <iostream>
13
14
15 // This wrapper makes the pattern matching in transforms below (like deref and
16 // incr) a lot easier to write.
17 template <typename Iter>
18 struct iter_wrapper
19 {
20 Iter it;
21 };
22
23 template <typename Iter>
24 auto make_iter_wrapper (Iter it)
25 { return iter_wrapper<Iter>{it}; }
26
27
28 // A container -> wrapped-begin transform.
29 struct begin
30 {
31 template <typename Cont>
32 auto operator() (boost::yap::expr_tag<boost::yap::expr_kind::terminal>,
33 Cont const & cont)
34 -> decltype(boost::yap::make_terminal(make_iter_wrapper(cont.begin())))
35 { return boost::yap::make_terminal(make_iter_wrapper(cont.begin())); }
36 };
37
38 // A wrapped-iterator -> dereferenced value transform.
39 struct deref
40 {
41 template <typename Iter>
42 auto operator() (boost::yap::expr_tag<boost::yap::expr_kind::terminal>,
43 iter_wrapper<Iter> wrapper)
44 -> decltype(boost::yap::make_terminal(*wrapper.it))
45 { return boost::yap::make_terminal(*wrapper.it); }
46 };
47
48 // A wrapped-iterator increment transform, using side effects.
49 struct incr
50 {
51 template <typename Iter>
52 auto operator() (boost::yap::expr_tag<boost::yap::expr_kind::terminal>,
53 iter_wrapper<Iter> & wrapper)
54 -> decltype(boost::yap::make_terminal(wrapper.it))
55 {
56 ++wrapper.it;
57 // Since this transform is valuable for its side effects, and thus the
58 // result of the transform is ignored, we could return anything here.
59 return boost::yap::make_terminal(wrapper.it);
60 }
61 };
62
63
64 // The implementation of elementwise evaluation of expressions of sequences;
65 // all the later operations use this one.
66 template <
67 template <class, class> class Cont,
68 typename T,
69 typename A,
70 typename Expr,
71 typename Op
72 >
73 Cont<T, A> & op_assign (Cont<T, A> & cont, Expr const & e, Op && op)
74 {
75 decltype(auto) expr = boost::yap::as_expr(e);
76 // Transform the expression of sequences into an expression of
77 // begin-iterators.
78 auto expr2 = boost::yap::transform(boost::yap::as_expr(expr), begin{});
79 for (auto && x : cont) {
80 // Transform the expression of iterators into an expression of
81 // pointed-to-values, evaluate the resulting expression, and call op()
82 // with the result of the evaluation.
83 op(x, boost::yap::evaluate(boost::yap::transform(expr2, deref{})));
84 // Transform the expression of iterators into an ignored value; as a
85 // side effect, increment the iterators in the expression.
86 boost::yap::transform(expr2, incr{});
87 }
88 return cont;
89 }
90
91 template <
92 template <class, class> class Cont,
93 typename T,
94 typename A,
95 typename Expr
96 >
97 Cont<T, A> & assign (Cont<T, A> & cont, Expr const & expr)
98 {
99 return op_assign(cont, expr, [](auto & cont_value, auto && expr_value) {
100 cont_value = std::forward<decltype(expr_value)>(expr_value);
101 });
102 }
103
104 template <
105 template <class, class> class Cont,
106 typename T,
107 typename A,
108 typename Expr
109 >
110 Cont<T, A> & operator+= (Cont<T, A> & cont, Expr const & expr)
111 {
112 return op_assign(cont, expr, [](auto & cont_value, auto && expr_value) {
113 cont_value += std::forward<decltype(expr_value)>(expr_value);
114 });
115 }
116
117 template <
118 template <class, class> class Cont,
119 typename T,
120 typename A,
121 typename Expr
122 >
123 Cont<T, A> & operator-= (Cont<T, A> & cont, Expr const & expr)
124 {
125 return op_assign(cont, expr, [](auto & cont_value, auto && expr_value) {
126 cont_value -= std::forward<decltype(expr_value)>(expr_value);
127 });
128 }
129
130 // A type trait that identifies std::vectors and std::lists.
131 template <typename T>
132 struct is_mixed : std::false_type {};
133
134 template <typename T, typename A>
135 struct is_mixed<std::vector<T, A>> : std::true_type {};
136
137 template <typename T, typename A>
138 struct is_mixed<std::list<T, A>> : std::true_type {};
139
140 // Define expression-producing operators over std::vectors and std::lists.
141 BOOST_YAP_USER_UDT_UNARY_OPERATOR(negate, boost::yap::expression, is_mixed); // -
142 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(multiplies, boost::yap::expression, is_mixed); // *
143 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(divides, boost::yap::expression, is_mixed); // /
144 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(modulus, boost::yap::expression, is_mixed); // %
145 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(plus, boost::yap::expression, is_mixed); // +
146 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(minus, boost::yap::expression, is_mixed); // -
147 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(less, boost::yap::expression, is_mixed); // <
148 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(greater, boost::yap::expression, is_mixed); // >
149 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(less_equal, boost::yap::expression, is_mixed); // <=
150 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(greater_equal, boost::yap::expression, is_mixed); // >=
151 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(equal_to, boost::yap::expression, is_mixed); // ==
152 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(not_equal_to, boost::yap::expression, is_mixed); // !=
153 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(logical_or, boost::yap::expression, is_mixed); // ||
154 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(logical_and, boost::yap::expression, is_mixed); // &&
155 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(bitwise_and, boost::yap::expression, is_mixed); // &
156 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(bitwise_or, boost::yap::expression, is_mixed); // |
157 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(bitwise_xor, boost::yap::expression, is_mixed); // ^
158
159 // Define a type that can resolve to any overload of std::sin().
160 struct sin_t
161 {
162 template<typename T>
163 T operator()(T x)
164 {
165 return std::sin(x);
166 }
167 };
168
169 int main()
170 {
171 int n = 10;
172 std::vector<int> a,b,c,d;
173 std::list<double> e;
174 std::list<std::complex<double>> f;
175
176 int i;
177 for(i = 0;i < n; ++i)
178 {
179 a.push_back(i);
180 b.push_back(2*i);
181 c.push_back(3*i);
182 d.push_back(i);
183 e.push_back(0.0);
184 f.push_back(std::complex<double>(1.0, 1.0));
185 }
186
187 assign(b, 2);
188 assign(d, a + b * c);
189 a += if_else(d < 30, b, c);
190
191 assign(e, c);
192 e += e - 4 / (c + 1);
193
194 auto sin = boost::yap::make_terminal(sin_t{});
195 f -= sin(0.1 * e * std::complex<double>(0.2, 1.2));
196
197 std::list<double>::const_iterator ei = e.begin();
198 std::list<std::complex<double>>::const_iterator fi = f.begin();
199 for (i = 0; i < n; ++i)
200 {
201 std::cout
202 << "a(" << i << ") = " << a[i]
203 << " b(" << i << ") = " << b[i]
204 << " c(" << i << ") = " << c[i]
205 << " d(" << i << ") = " << d[i]
206 << " e(" << i << ") = " << *ei++
207 << " f(" << i << ") = " << *fi++
208 << std::endl;
209 }
210
211 return 0;
212 }
213 //]