diff options
Diffstat (limited to 'src/boost/libs/proto/example/mixed.cpp')
-rw-r--r-- | src/boost/libs/proto/example/mixed.cpp | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/src/boost/libs/proto/example/mixed.cpp b/src/boost/libs/proto/example/mixed.cpp new file mode 100644 index 00000000..d48e21dc --- /dev/null +++ b/src/boost/libs/proto/example/mixed.cpp @@ -0,0 +1,375 @@ +//[ Mixed +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2008 Eric Niebler. 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) +// +// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to Protofy +// expressions using std::vector<> and std::list, non-proto types. It is a port +// of the Mixed example from PETE. +// (http://www.codesourcery.com/pooma/download.html). + +#include <list> +#include <cmath> +#include <vector> +#include <complex> +#include <iostream> +#include <stdexcept> +#include <boost/proto/core.hpp> +#include <boost/proto/debug.hpp> +#include <boost/proto/context.hpp> +#include <boost/proto/transform.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/typeof/std/list.hpp> +#include <boost/typeof/std/vector.hpp> +#include <boost/typeof/std/complex.hpp> +#include <boost/type_traits/remove_reference.hpp> +namespace proto = boost::proto; +namespace mpl = boost::mpl; +using proto::_; + +template<typename Expr> +struct MixedExpr; + +template<typename Iter> +struct iterator_wrapper +{ + typedef Iter iterator; + + explicit iterator_wrapper(Iter iter) + : it(iter) + {} + + mutable Iter it; +}; + +struct begin : proto::callable +{ + template<class Sig> + struct result; + + template<class This, class Cont> + struct result<This(Cont)> + : proto::result_of::as_expr< + iterator_wrapper<typename boost::remove_reference<Cont>::type::const_iterator> + > + {}; + + template<typename Cont> + typename result<begin(Cont const &)>::type + operator ()(Cont const &cont) const + { + iterator_wrapper<typename Cont::const_iterator> it(cont.begin()); + return proto::as_expr(it); + } +}; + +// Here is a grammar that replaces vector and list terminals with their +// begin iterators +struct Begin + : proto::or_< + proto::when< proto::terminal< std::vector<_, _> >, begin(proto::_value) > + , proto::when< proto::terminal< std::list<_, _> >, begin(proto::_value) > + , proto::when< proto::terminal<_> > + , proto::when< proto::nary_expr<_, proto::vararg<Begin> > > + > +{}; + +// Here is an evaluation context that dereferences iterator +// terminals. +struct DereferenceCtx +{ + // Unless this is an iterator terminal, use the + // default evaluation context + template<typename Expr, typename EnableIf = void> + struct eval + : proto::default_eval<Expr, DereferenceCtx const> + {}; + + // Dereference iterator terminals. + template<typename Expr> + struct eval< + Expr + , typename boost::enable_if< + proto::matches<Expr, proto::terminal<iterator_wrapper<_> > > + >::type + > + { + typedef typename proto::result_of::value<Expr>::type IteratorWrapper; + typedef typename IteratorWrapper::iterator iterator; + typedef typename std::iterator_traits<iterator>::reference result_type; + + result_type operator ()(Expr &expr, DereferenceCtx const &) const + { + return *proto::value(expr).it; + } + }; +}; + +// Here is an evaluation context that increments iterator +// terminals. +struct IncrementCtx +{ + // Unless this is an iterator terminal, use the + // default evaluation context + template<typename Expr, typename EnableIf = void> + struct eval + : proto::null_eval<Expr, IncrementCtx const> + {}; + + // advance iterator terminals. + template<typename Expr> + struct eval< + Expr + , typename boost::enable_if< + proto::matches<Expr, proto::terminal<iterator_wrapper<_> > > + >::type + > + { + typedef void result_type; + + result_type operator ()(Expr &expr, IncrementCtx const &) const + { + ++proto::value(expr).it; + } + }; +}; + +// A grammar which matches all the assignment operators, +// so we can easily disable them. +struct AssignOps + : proto::switch_<struct AssignOpsCases> +{}; + +// Here are the cases used by the switch_ above. +struct AssignOpsCases +{ + template<typename Tag, int D = 0> struct case_ : proto::not_<_> {}; + + template<int D> struct case_< proto::tag::plus_assign, D > : _ {}; + template<int D> struct case_< proto::tag::minus_assign, D > : _ {}; + template<int D> struct case_< proto::tag::multiplies_assign, D > : _ {}; + template<int D> struct case_< proto::tag::divides_assign, D > : _ {}; + template<int D> struct case_< proto::tag::modulus_assign, D > : _ {}; + template<int D> struct case_< proto::tag::shift_left_assign, D > : _ {}; + template<int D> struct case_< proto::tag::shift_right_assign, D > : _ {}; + template<int D> struct case_< proto::tag::bitwise_and_assign, D > : _ {}; + template<int D> struct case_< proto::tag::bitwise_or_assign, D > : _ {}; + template<int D> struct case_< proto::tag::bitwise_xor_assign, D > : _ {}; +}; + +// An expression conforms to the MixedGrammar if it is a terminal or some +// op that is not an assignment op. (Assignment will be handled specially.) +struct MixedGrammar + : proto::or_< + proto::terminal<_> + , proto::and_< + proto::nary_expr<_, proto::vararg<MixedGrammar> > + , proto::not_<AssignOps> + > + > +{}; + +// Expressions in the MixedDomain will be wrapped in MixedExpr<> +// and must conform to the MixedGrammar +struct MixedDomain + : proto::domain<proto::generator<MixedExpr>, MixedGrammar> +{}; + +// Here is MixedExpr, a wrapper for expression types in the MixedDomain. +template<typename Expr> +struct MixedExpr + : proto::extends<Expr, MixedExpr<Expr>, MixedDomain> +{ + explicit MixedExpr(Expr const &expr) + : MixedExpr::proto_extends(expr) + {} +private: + // hide this: + using proto::extends<Expr, MixedExpr<Expr>, MixedDomain>::operator []; +}; + +// Define a trait type for detecting vector and list terminals, to +// be used by the BOOST_PROTO_DEFINE_OPERATORS macro below. +template<typename T> +struct IsMixed + : mpl::false_ +{}; + +template<typename T, typename A> +struct IsMixed<std::list<T, A> > + : mpl::true_ +{}; + +template<typename T, typename A> +struct IsMixed<std::vector<T, A> > + : mpl::true_ +{}; + +namespace MixedOps +{ + // This defines all the overloads to make expressions involving + // std::vector to build expression templates. + BOOST_PROTO_DEFINE_OPERATORS(IsMixed, MixedDomain) + + struct assign_op + { + template<typename T, typename U> + void operator ()(T &t, U const &u) const + { + t = u; + } + }; + + struct plus_assign_op + { + template<typename T, typename U> + void operator ()(T &t, U const &u) const + { + t += u; + } + }; + + struct minus_assign_op + { + template<typename T, typename U> + void operator ()(T &t, U const &u) const + { + t -= u; + } + }; + + struct sin_ + { + template<typename Sig> + struct result; + + template<typename This, typename Arg> + struct result<This(Arg)> + : boost::remove_const<typename boost::remove_reference<Arg>::type> + {}; + + template<typename Arg> + Arg operator ()(Arg const &a) const + { + return std::sin(a); + } + }; + + template<typename A> + typename proto::result_of::make_expr< + proto::tag::function + , MixedDomain + , sin_ const + , A const & + >::type sin(A const &a) + { + return proto::make_expr<proto::tag::function, MixedDomain>(sin_(), boost::ref(a)); + } + + template<typename FwdIter, typename Expr, typename Op> + void evaluate(FwdIter begin, FwdIter end, Expr const &expr, Op op) + { + IncrementCtx const inc = {}; + DereferenceCtx const deref = {}; + typename boost::result_of<Begin(Expr const &)>::type expr2 = Begin()(expr); + for(; begin != end; ++begin) + { + op(*begin, proto::eval(expr2, deref)); + proto::eval(expr2, inc); + } + } + + // Add-assign to a vector from some expression. + template<typename T, typename A, typename Expr> + std::vector<T, A> &assign(std::vector<T, A> &arr, Expr const &expr) + { + evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), assign_op()); + return arr; + } + + // Add-assign to a list from some expression. + template<typename T, typename A, typename Expr> + std::list<T, A> &assign(std::list<T, A> &arr, Expr const &expr) + { + evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), assign_op()); + return arr; + } + + // Add-assign to a vector from some expression. + template<typename T, typename A, typename Expr> + std::vector<T, A> &operator +=(std::vector<T, A> &arr, Expr const &expr) + { + evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), plus_assign_op()); + return arr; + } + + // Add-assign to a list from some expression. + template<typename T, typename A, typename Expr> + std::list<T, A> &operator +=(std::list<T, A> &arr, Expr const &expr) + { + evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), plus_assign_op()); + return arr; + } + + // Minus-assign to a vector from some expression. + template<typename T, typename A, typename Expr> + std::vector<T, A> &operator -=(std::vector<T, A> &arr, Expr const &expr) + { + evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), minus_assign_op()); + return arr; + } + + // Minus-assign to a list from some expression. + template<typename T, typename A, typename Expr> + std::list<T, A> &operator -=(std::list<T, A> &arr, Expr const &expr) + { + evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), minus_assign_op()); + return arr; + } +} + +int main() +{ + using namespace MixedOps; + + 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)); + } + + MixedOps::assign(b, 2); + MixedOps::assign(d, a + b * c); + a += if_else(d < 30, b, c); + + MixedOps::assign(e, c); + e += e - 4 / (c + 1); + + 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; + } +} +//] |