diff options
Diffstat (limited to 'src/boost/libs/proto/example/tarray.cpp')
-rw-r--r-- | src/boost/libs/proto/example/tarray.cpp | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/src/boost/libs/proto/example/tarray.cpp b/src/boost/libs/proto/example/tarray.cpp new file mode 100644 index 00000000..338f69b1 --- /dev/null +++ b/src/boost/libs/proto/example/tarray.cpp @@ -0,0 +1,222 @@ +//[ TArray +/////////////////////////////////////////////////////////////////////////////// +// 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 example constructs a mini-library for linear algebra, using +// expression templates to eliminate the need for temporaries when +// adding arrays of numbers. It duplicates the TArray example from +// PETE (http://www.codesourcery.com/pooma/download.html) + +#include <iostream> +#include <boost/mpl/int.hpp> +#include <boost/proto/core.hpp> +#include <boost/proto/context.hpp> +namespace mpl = boost::mpl; +namespace proto = boost::proto; +using proto::_; + +// This grammar describes which TArray expressions +// are allowed; namely, int and array terminals +// plus, minus, multiplies and divides of TArray expressions. +struct TArrayGrammar + : proto::or_< + proto::terminal< int > + , proto::terminal< int[3] > + , proto::plus< TArrayGrammar, TArrayGrammar > + , proto::minus< TArrayGrammar, TArrayGrammar > + , proto::multiplies< TArrayGrammar, TArrayGrammar > + , proto::divides< TArrayGrammar, TArrayGrammar > + > +{}; + +template<typename Expr> +struct TArrayExpr; + +// Tell proto that in the TArrayDomain, all +// expressions should be wrapped in TArrayExpr<> and +// must conform to the TArrayGrammar +struct TArrayDomain + : proto::domain<proto::generator<TArrayExpr>, TArrayGrammar> +{}; + +// Here is an evaluation context that indexes into a TArray +// expression, and combines the result. +struct TArraySubscriptCtx + : proto::callable_context< TArraySubscriptCtx const > +{ + typedef int result_type; + + TArraySubscriptCtx(std::ptrdiff_t i) + : i_(i) + {} + + // Index array terminals with our subscript. Everything + // else will be handled by the default evaluation context. + int operator ()(proto::tag::terminal, int const (&data)[3]) const + { + return data[this->i_]; + } + + std::ptrdiff_t i_; +}; + +// Here is an evaluation context that prints a TArray expression. +struct TArrayPrintCtx + : proto::callable_context< TArrayPrintCtx const > +{ + typedef std::ostream &result_type; + + TArrayPrintCtx() {} + + std::ostream &operator ()(proto::tag::terminal, int i) const + { + return std::cout << i; + } + + std::ostream &operator ()(proto::tag::terminal, int const (&arr)[3]) const + { + return std::cout << '{' << arr[0] << ", " << arr[1] << ", " << arr[2] << '}'; + } + + template<typename L, typename R> + std::ostream &operator ()(proto::tag::plus, L const &l, R const &r) const + { + return std::cout << '(' << l << " + " << r << ')'; + } + + template<typename L, typename R> + std::ostream &operator ()(proto::tag::minus, L const &l, R const &r) const + { + return std::cout << '(' << l << " - " << r << ')'; + } + + template<typename L, typename R> + std::ostream &operator ()(proto::tag::multiplies, L const &l, R const &r) const + { + return std::cout << l << " * " << r; + } + + template<typename L, typename R> + std::ostream &operator ()(proto::tag::divides, L const &l, R const &r) const + { + return std::cout << l << " / " << r; + } +}; + +// Here is the domain-specific expression wrapper, which overrides +// operator [] to evaluate the expression using the TArraySubscriptCtx. +template<typename Expr> +struct TArrayExpr + : proto::extends<Expr, TArrayExpr<Expr>, TArrayDomain> +{ + typedef proto::extends<Expr, TArrayExpr<Expr>, TArrayDomain> base_type; + + TArrayExpr( Expr const & expr = Expr() ) + : base_type( expr ) + {} + + // Use the TArraySubscriptCtx to implement subscripting + // of a TArray expression tree. + int operator []( std::ptrdiff_t i ) const + { + TArraySubscriptCtx const ctx(i); + return proto::eval(*this, ctx); + } + + // Use the TArrayPrintCtx to display a TArray expression tree. + friend std::ostream &operator <<(std::ostream &sout, TArrayExpr<Expr> const &expr) + { + TArrayPrintCtx const ctx; + return proto::eval(expr, ctx); + } +}; + +// Here is our TArray terminal, implemented in terms of TArrayExpr +// It is basically just an array of 3 integers. +struct TArray + : TArrayExpr< proto::terminal< int[3] >::type > +{ + explicit TArray( int i = 0, int j = 0, int k = 0 ) + { + (*this)[0] = i; + (*this)[1] = j; + (*this)[2] = k; + } + + // Here we override operator [] to give read/write access to + // the elements of the array. (We could use the TArrayExpr + // operator [] if we made the subscript context smarter about + // returning non-const reference when appropriate.) + int &operator [](std::ptrdiff_t i) + { + return proto::value(*this)[i]; + } + + int const &operator [](std::ptrdiff_t i) const + { + return proto::value(*this)[i]; + } + + // Here we define a operator = for TArray terminals that + // takes a TArray expression. + template< typename Expr > + TArray &operator =(Expr const & expr) + { + // proto::as_expr<TArrayDomain>(expr) is the same as + // expr unless expr is an integer, in which case it + // is made into a TArrayExpr terminal first. + return this->assign(proto::as_expr<TArrayDomain>(expr)); + } + + template< typename Expr > + TArray &printAssign(Expr const & expr) + { + *this = expr; + std::cout << *this << " = " << expr << std::endl; + return *this; + } + +private: + template< typename Expr > + TArray &assign(Expr const & expr) + { + // expr[i] here uses TArraySubscriptCtx under the covers. + (*this)[0] = expr[0]; + (*this)[1] = expr[1]; + (*this)[2] = expr[2]; + return *this; + } +}; + +int main() +{ + TArray a(3,1,2); + + TArray b; + + std::cout << a << std::endl; + std::cout << b << std::endl; + + b[0] = 7; b[1] = 33; b[2] = -99; + + TArray c(a); + + std::cout << c << std::endl; + + a = 0; + + std::cout << a << std::endl; + std::cout << b << std::endl; + std::cout << c << std::endl; + + a = b + c; + + std::cout << a << std::endl; + + a.printAssign(b+c*(b + 3*c)); + + return 0; +} +//] |