diff options
Diffstat (limited to 'src/boost/libs/yap/example/mixed.cpp')
-rw-r--r-- | src/boost/libs/yap/example/mixed.cpp | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/src/boost/libs/yap/example/mixed.cpp b/src/boost/libs/yap/example/mixed.cpp new file mode 100644 index 00000000..e7dee54c --- /dev/null +++ b/src/boost/libs/yap/example/mixed.cpp @@ -0,0 +1,213 @@ +// Copyright (C) 2016-2018 T. Zachary Laine +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//[ mixed +#include <boost/yap/yap.hpp> + +#include <complex> +#include <list> +#include <vector> +#include <iostream> + + +// This wrapper makes the pattern matching in transforms below (like deref and +// incr) a lot easier to write. +template <typename Iter> +struct iter_wrapper +{ + Iter it; +}; + +template <typename Iter> +auto make_iter_wrapper (Iter it) +{ return iter_wrapper<Iter>{it}; } + + +// A container -> wrapped-begin transform. +struct begin +{ + template <typename Cont> + auto operator() (boost::yap::expr_tag<boost::yap::expr_kind::terminal>, + Cont const & cont) + -> decltype(boost::yap::make_terminal(make_iter_wrapper(cont.begin()))) + { return boost::yap::make_terminal(make_iter_wrapper(cont.begin())); } +}; + +// A wrapped-iterator -> dereferenced value transform. +struct deref +{ + template <typename Iter> + auto operator() (boost::yap::expr_tag<boost::yap::expr_kind::terminal>, + iter_wrapper<Iter> wrapper) + -> decltype(boost::yap::make_terminal(*wrapper.it)) + { return boost::yap::make_terminal(*wrapper.it); } +}; + +// A wrapped-iterator increment transform, using side effects. +struct incr +{ + template <typename Iter> + auto operator() (boost::yap::expr_tag<boost::yap::expr_kind::terminal>, + iter_wrapper<Iter> & wrapper) + -> decltype(boost::yap::make_terminal(wrapper.it)) + { + ++wrapper.it; + // Since this transform is valuable for its side effects, and thus the + // result of the transform is ignored, we could return anything here. + return boost::yap::make_terminal(wrapper.it); + } +}; + + +// The implementation of elementwise evaluation of expressions of sequences; +// all the later operations use this one. +template < + template <class, class> class Cont, + typename T, + typename A, + typename Expr, + typename Op +> +Cont<T, A> & op_assign (Cont<T, A> & cont, Expr const & e, Op && op) +{ + decltype(auto) expr = boost::yap::as_expr(e); + // Transform the expression of sequences into an expression of + // begin-iterators. + auto expr2 = boost::yap::transform(boost::yap::as_expr(expr), begin{}); + for (auto && x : cont) { + // Transform the expression of iterators into an expression of + // pointed-to-values, evaluate the resulting expression, and call op() + // with the result of the evaluation. + op(x, boost::yap::evaluate(boost::yap::transform(expr2, deref{}))); + // Transform the expression of iterators into an ignored value; as a + // side effect, increment the iterators in the expression. + boost::yap::transform(expr2, incr{}); + } + return cont; +} + +template < + template <class, class> class Cont, + typename T, + typename A, + typename Expr +> +Cont<T, A> & assign (Cont<T, A> & cont, Expr const & expr) +{ + return op_assign(cont, expr, [](auto & cont_value, auto && expr_value) { + cont_value = std::forward<decltype(expr_value)>(expr_value); + }); +} + +template < + template <class, class> class Cont, + typename T, + typename A, + typename Expr +> +Cont<T, A> & operator+= (Cont<T, A> & cont, Expr const & expr) +{ + return op_assign(cont, expr, [](auto & cont_value, auto && expr_value) { + cont_value += std::forward<decltype(expr_value)>(expr_value); + }); +} + +template < + template <class, class> class Cont, + typename T, + typename A, + typename Expr +> +Cont<T, A> & operator-= (Cont<T, A> & cont, Expr const & expr) +{ + return op_assign(cont, expr, [](auto & cont_value, auto && expr_value) { + cont_value -= std::forward<decltype(expr_value)>(expr_value); + }); +} + +// A type trait that identifies std::vectors and std::lists. +template <typename T> +struct is_mixed : std::false_type {}; + +template <typename T, typename A> +struct is_mixed<std::vector<T, A>> : std::true_type {}; + +template <typename T, typename A> +struct is_mixed<std::list<T, A>> : std::true_type {}; + +// Define expression-producing operators over std::vectors and std::lists. +BOOST_YAP_USER_UDT_UNARY_OPERATOR(negate, boost::yap::expression, is_mixed); // - +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(multiplies, boost::yap::expression, is_mixed); // * +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(divides, boost::yap::expression, is_mixed); // / +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(modulus, boost::yap::expression, is_mixed); // % +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(plus, boost::yap::expression, is_mixed); // + +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(minus, boost::yap::expression, is_mixed); // - +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(less, boost::yap::expression, is_mixed); // < +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(greater, boost::yap::expression, is_mixed); // > +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(less_equal, boost::yap::expression, is_mixed); // <= +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(greater_equal, boost::yap::expression, is_mixed); // >= +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(equal_to, boost::yap::expression, is_mixed); // == +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(not_equal_to, boost::yap::expression, is_mixed); // != +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(logical_or, boost::yap::expression, is_mixed); // || +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(logical_and, boost::yap::expression, is_mixed); // && +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(bitwise_and, boost::yap::expression, is_mixed); // & +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(bitwise_or, boost::yap::expression, is_mixed); // | +BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(bitwise_xor, boost::yap::expression, is_mixed); // ^ + +// Define a type that can resolve to any overload of std::sin(). +struct sin_t +{ + template<typename T> + T operator()(T x) + { + return std::sin(x); + } +}; + +int main() +{ + int n = 10; + std::vector<int> a,b,c,d; + std::list<double> e; + std::list<std::complex<double>> f; + + int i; + for(i = 0;i < n; ++i) + { + a.push_back(i); + b.push_back(2*i); + c.push_back(3*i); + d.push_back(i); + e.push_back(0.0); + f.push_back(std::complex<double>(1.0, 1.0)); + } + + assign(b, 2); + assign(d, a + b * c); + a += if_else(d < 30, b, c); + + assign(e, c); + e += e - 4 / (c + 1); + + auto sin = boost::yap::make_terminal(sin_t{}); + f -= sin(0.1 * e * std::complex<double>(0.2, 1.2)); + + std::list<double>::const_iterator ei = e.begin(); + std::list<std::complex<double>>::const_iterator fi = f.begin(); + for (i = 0; i < n; ++i) + { + std::cout + << "a(" << i << ") = " << a[i] + << " b(" << i << ") = " << b[i] + << " c(" << i << ") = " << c[i] + << " d(" << i << ") = " << d[i] + << " e(" << i << ") = " << *ei++ + << " f(" << i << ") = " << *fi++ + << std::endl; + } + + return 0; +} +//] |