summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/proto/example/tarray.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/proto/example/tarray.cpp')
-rw-r--r--src/boost/libs/proto/example/tarray.cpp222
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;
+}
+//]