[ create a new paste ] login | about

Link: http://codepad.org/Wf6ByFwY    [ raw code | output | fork ]

C++, pasted on Sep 11:
#include <iostream>
#include <boost/proto/proto.hpp>
#include <boost/lexical_cast.hpp>

using namespace std;
namespace bp = boost::proto;
namespace bm = boost::mpl;

template<class SimdDesc> struct simd_context;
////////////////////////////////////////////////////////////////////////////////
// SIMD value holder (empty for test purpose) and value descriptor
////////////////////////////////////////////////////////////////////////////////
template<class Type, int Cardinal>  struct simd_info
{
   typedef Type               type;
   typedef bm::int_<Cardinal> card;
};

template<class SimdDesc>            struct simd_value
{
  typedef typename SimdDesc::type type;

  type value;
  template<class X>type eval(X const& xpr)
  {
    return bp::eval(xpr,simd_context<SimdDesc>());
  }
};

////////////////////////////////////////////////////////////////////////////////
// Grammar helpers
////////////////////////////////////////////////////////////////////////////////
template<class Lambda>
struct lambda_grammar : bp::and_< bp::terminal<bp::_>
                                , bp::if_< bm::apply1<Lambda,bp::_value>()>
                                > {};

template<class Grammar> struct low_level
  : bp::or_< bp::address_of<Grammar>
           , bp::dereference<Grammar>
           , bp::comma<Grammar,Grammar>
           > {};

////////////////////////////////////////////////////////////////////////////////
// SIMD Grammar
////////////////////////////////////////////////////////////////////////////////
struct simd_grammar
    : bp::or_< bp::terminal< simd_value<bp::_> >
             , lambda_grammar< boost::is_arithmetic<bm::_> >
             , bp::and_< bp::nary_expr< bp::_
                                      , bp::vararg< simd_grammar >
                                      >
                       , bp::not_<low_level<bp::_> >
                       >
             > {};

//////////////////////////////////////////////////////////////////////////////
// simd_expr forward declaration
//////////////////////////////////////////////////////////////////////////////
template<class X,class SwarType,class BP = bp::is_proto_expr> struct simd_expr;

//////////////////////////////////////////////////////////////////////////////
// SIMD Expression Generator - SIMD Expression use a template parameters
// so proto expression generator should be extended
//////////////////////////////////////////////////////////////////////////////
template<class SimdDesc> struct simd_generator
{
  template<class Sig> struct result;

  template<class This, class Expr> struct result<This(Expr)>
  {
    typedef simd_expr<Expr,SimdDesc> type;
  };

  template<class Expr> simd_expr<Expr,SimdDesc> const
  operator()(Expr const &expr) const
  {
    simd_expr<Expr,SimdDesc> that = {expr};
    return that;
  }
};

//////////////////////////////////////////////////////////////////////////////
// SIMD Expression Intrinsic
// In this exampel they're stupidly useless but in SIMD mode
// they contains SIMD specific intrinsic or asm code
//////////////////////////////////////////////////////////////////////////////
template<class Tag,class Target> struct intrinsic;

//////////////////////////////////////////////////////////////////////////////
// SIMD Expression Evaluation  Context
//////////////////////////////////////////////////////////////////////////////
template<class SimdDesc>
struct simd_context
     : bp::callable_context< simd_context<SimdDesc> const
                           , bp::null_context const
                           >
{
  //////////////////////////////////////////////////////////////////////////
  // reuslt_of of context use the intrinsic result_of support
  //////////////////////////////////////////////////////////////////////////
  template<class Sig> struct result;

  template<class This,class Tag,class X>
  struct result<This(Tag,X)>
  {
    typedef typename boost::result_of<intrinsic<Tag,typename SimdDesc::type>(X)>::type type;
  };

  template<class This,class Tag,class L,class R>
  struct result<This(Tag,L,R)>
  {
    typedef typename boost::result_of<intrinsic<Tag,typename SimdDesc::type>(L,R)>::type type;
  };

  template<class This,class X>
  struct result<This(bp::tag::terminal,X)>
  {
    typedef typename SimdDesc::type type;
  };

  template<class This,class X>
  struct result<This(bp::tag::terminal,simd_value<X>)>
  {
    typedef typename X::type type;
  };

  template<class V> inline
  typename boost::enable_if<boost::is_arithmetic<V>
                           ,typename boost::result_of<simd_context(bp::tag::terminal,V)>::type
                           >::type
  operator()(bp::tag::terminal,V const& v) const
  {
    return v;
  }

  template<class V> inline
  typename boost::disable_if<boost::is_arithmetic<V>
                            ,typename boost::result_of<simd_context(bp::tag::terminal,V)>::type
                            >::type
  operator()(bp::tag::terminal,V const& v) const
  {
    return v.value;
  }

  template<class Tag,class X> inline
  typename boost::result_of<simd_context(Tag,X)>::type
  operator()(Tag, X const& x ) const
  {
    intrinsic<Tag,typename SimdDesc::type> callee;
    return callee(x);
  }

  template<class Tag,class L,class R> inline
  typename boost::result_of<simd_context(Tag,L,R)>::type
  operator()(Tag , L const& l, R const& r ) const
  {
    intrinsic<Tag,typename SimdDesc::type> callee;
    return callee(l,r);
  }
};

//////////////////////////////////////////////////////////////////////////////
// SIMD Domain forward
//////////////////////////////////////////////////////////////////////////////
template<class SimdDesc> struct simd_domain;

//////////////////////////////////////////////////////////////////////////////
// SIMD Expression
//////////////////////////////////////////////////////////////////////////////
template<class X,class SimdDesc,class BP> struct simd_expr
{
  typedef SimdDesc                  info_type;
  typedef X                         content_type;
  typedef typename SimdDesc::type   value_type; // This expression contains value_type elements
  typedef simd_domain<info_type>    domain_type;

  BOOST_PROTO_BASIC_EXTENDS(X, simd_expr, domain_type)

  //////////////////////////////////////////////////////////////////////////
  // simd_expr<X,S> can be casted to its underlying SIMD native type for ease
  // of writing of intrinsic
  //////////////////////////////////////////////////////////////////////////
  operator value_type() const
  {
    // Extracts the SIMD type from simd_data, here just returns its value
    return eval();
  }

  value_type eval() const
  {
    // Extracts the SIMD type from simd_data, here just returns its value
    simd_value<info_type> data;
    return data.eval(*this);
  }

};

////////////////////////////////////////////////////////////////////////////
// Tell proto that in the simd_domain, all expressions should be
// wrapped in simd_expr<>
////////////////////////////////////////////////////////////////////////////
template<class SimdDesc>
struct simd_domain : bp::domain< simd_generator<SimdDesc>
                               , simd_grammar
                               > {};

////////////////////////////////////////////////////////////////////////////
// Build a simd_expr from normalized type
////////////////////////////////////////////////////////////////////////////
template<class Type,int Cardinal> struct make_simd_expr
{
  typedef simd_info<Type,Cardinal>              info_type;
  typedef simd_value<info_type>                 vec_type;
  typedef typename bp::terminal<vec_type>::type term_;
  typedef simd_expr<term_,info_type>            type;
};

template<class Type,int Cardinal,class BP = bp::is_proto_expr>
struct vec : public make_simd_expr<Type,Cardinal>::type
{
  typedef typename make_simd_expr<Type,Cardinal>::type  parent;
  typedef typename parent::value_type                   value_type;
  vec() {}

  template<class A0>
  vec( A0 const& v ) { bp::value(*this).value = v; }

  template<class X>
  vec( simd_expr<X, simd_info<Type,Cardinal> > const& xpr )
  {
    bp::value(*this).value = bp::eval(xpr, simd_context<simd_info<Type,Cardinal> >());
  }

  template<class X>
  vec& operator=( simd_expr<X, simd_info<Type,Cardinal> > const& xpr )
  {
    bp::value(*this).value = bp::eval(xpr, simd_context<simd_info<Type,Cardinal> >());
    return *this;
  }

  //////////////////////////////////////////////////////////////////////////
  // vec<T,C> can be casted to its underlying SIMD native type for ease of
  // writing of intrinsic
  //////////////////////////////////////////////////////////////////////////
  operator value_type() const
  {
    // Extracts the SIMD type from simd_data, here just returns its value
    return parent::eval();
  }

  //////////////////////////////////////////////////////////////////////////
  // access ot the scalar components of the vector type /useless here
  //////////////////////////////////////////////////////////////////////////
  Type& operator[](int i)        { return bp::value(*this).value; }
  Type  operator[](int i) const  { return bp::value(*this).value; }
};

/////////////////////////////////////////////////////////////////////////////
// Some intrinsics
/////////////////////////////////////////////////////////////////////////////
template<class Target>
struct intrinsic<bp::tag::plus,Target>
{
  typedef Target result_type;

  template<class A0, class A1> inline
  result_type operator()( A0 const& a0, A1 const& a1) const
  {
    return result_type(a0) + result_type(a1);
  }
};

struct to_float_ {};

template<class Target> struct intrinsic<to_float_,Target>
{
  typedef Target result_type;

  template<class A0> inline
  result_type operator()( A0 const& a0 ) const
  {
    return "(" + boost::lexical_cast<result_type>( a0.eval() ) + ")";
  }
};

template<class A0>
typename bp::result_of::make_expr< to_float_
                                 , simd_domain< simd_info<std::string
                                                         ,4
                                                         >
                                              >
                                 , A0 const&
                                 >::type
to_float( A0 const& a0 )
{
  return bp::make_expr< to_float_
                       , simd_domain< simd_info<std::string
                                               ,4
                                               >
                                    >
                                    >( boost::cref(a0) );
}

int main()
{
  vec<int,4> v(3);
  vec<int,4> u(5);
  vec<int,4> z;
  vec<std::string,4> f;

  z = u+v;
  z = (u+v)+(z+z);
  cout << z[0] << endl;

  //f = to_float(z); // don't work
  cout << to_float(z).eval() << endl; //don't work either

}


Output:
1
2
3
Line 32: error: boost/proto/proto.hpp: No such file or directory
Line 6: error: 'proto' is not a namespace-name
compilation terminated due to -Wfatal-errors.


Create a new paste based on this one


Comments: