[ create a new paste ] login | about

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

joel_f - C++, pasted on Feb 23:
#include <boost/proto/proto.hpp>

////////////////////////////////////////////////////////////////////////////////
// Strip potential parens around macro parameters.
// Details are in http://article.gmane.org/gmane.comp.lib.boost.user/61011
////////////////////////////////////////////////////////////////////////////////
#define NT2_PP_DETAILS_APPLY(macro, args)   NT2_PP_DETAILS_APPLY_I(macro, args)
#define NT2_PP_DETAILS_APPLY_I(macro, args) macro args
#define NT2_PP_DETAILS_STRIP_PARENS_I(...) 1,1
#define NT2_PP_DETAILS_EVAL(test, x) NT2_PP_DETAILS_EVAL_I(test, x)
#define NT2_PP_DETAILS_EVAL_I(test, x) NT2_PP_DETAILS_MAYBE_STRIP_PARENS(NT2_PP_DETAILS_TEST_ARITY test, x)
#define NT2_PP_DETAILS_TEST_ARITY(...) NT2_PP_DETAILS_APPLY(NT2_PP_DETAILS_TEST_ARITY_I, (__VA_ARGS__, 2, 1))
#define NT2_PP_DETAILS_TEST_ARITY_I(a,b,c,...) c
#define NT2_PP_DETAILS_MAYBE_STRIP_PARENS(cond, x) NT2_PP_DETAILS_MAYBE_STRIP_PARENS_I(cond, x)
#define NT2_PP_DETAILS_MAYBE_STRIP_PARENS_I(cond, x) BOOST_PP_CAT(NT2_PP_DETAILS_MAYBE_STRIP_PARENS_, cond)(x)
#define NT2_PP_DETAILS_MAYBE_STRIP_PARENS_1(x) x
#define NT2_PP_DETAILS_MAYBE_STRIP_PARENS_2(x) NT2_PP_DETAILS_APPLY(NT2_PP_DETAILS_MAYBE_STRIP_PARENS_2_I, x)
#define NT2_PP_DETAILS_MAYBE_STRIP_PARENS_2_I(...) __VA_ARGS__

#define NT2_PP_STRIP(x) NT2_PP_DETAILS_EVAL((NT2_PP_DETAILS_STRIP_PARENS_I x), x)

////////////////////////////////////////////////////////////////////////////////
// Proto basic extends for template domain
////////////////////////////////////////////////////////////////////////////////
#define BOOST_PROTO_BASIC_EXTENDS_TPL(Expr, Derived, Domain)                  \
BOOST_PROTO_BASIC_EXTENDS_( NT2_PP_STRIP(Expr)                                \
                          , NT2_PP_STRIP(Derived)                             \
                          , NT2_PP_STRIP(Domain)                              \
                          )                                                   \
typedef void                                            proto_is_aggregate_;  \
typedef typename NT2_PP_STRIP(Domain)::proto_generator  proto_generator;      \

namespace nt2 { namespace simd
{
  ////////////////////////////////////////////////////////////////////////////////
  // Some forward
  ////////////////////////////////////////////////////////////////////////////////
  template< class Type, class Cardinal> struct domain;

  template< class Expression
          , class Type
          , class Cardinal
          , class Dummy = boost::proto::is_proto_expr
          >
  struct expression;

  ////////////////////////////////////////////////////////////////////////////////
  // Fake data to be stored in terminals
  ////////////////////////////////////////////////////////////////////////////////
  template<class T, class C>
  struct data {};

  ////////////////////////////////////////////////////////////////////////////////
  // the template grammar
  ////////////////////////////////////////////////////////////////////////////////
  template<class T, class C>
  struct grammar
    : boost::proto
        ::or_ < boost::proto::terminal< data<T,C> >
              , boost::proto::
                and_< boost::proto::
                      nary_expr < boost::proto::_
                                , boost::proto::vararg< grammar<T,C> >
                                >
                    , boost::proto::
                      not_< boost::proto::or_ < boost::proto::
                                                address_of< grammar<T,C> >
                                              , boost::proto::
                                                dereference< grammar<T,C> >
                                              , boost::proto::
                                                comma < grammar<T,C>
                                                      , grammar<T,C>
                                                      >
                                              >
                          >
                    >
              >
    {};

  ////////////////////////////////////////////////////////////////////////////////
  // The template generator
  ////////////////////////////////////////////////////////////////////////////////
  template<class Type,class Cardinal> struct generator
  {
    template<class Sig> struct result;
    template<class This, class Expr>
    struct result<This(Expr)> { typedef expression<Expr,Type,Cardinal> type; };

    template<class Expr>
    expression<Expr,Type,Cardinal> const operator()(Expr const &xpr) const
    {
      expression<Expr,Type,Cardinal> const that = {xpr};
      return that;
    }
  };

  ////////////////////////////////////////////////////////////////////////////////
  // simd expression
  ////////////////////////////////////////////////////////////////////////////////
  template<class Expr,class Type,class Cardinal, class Dummy>
  struct expression
  {
    ////////////////////////////////////////////////////////////////////////////
    // Make this a proto expression
    ////////////////////////////////////////////////////////////////////////////
    typedef domain<Type,Cardinal>                 domain_type;
    typedef expression<Expr,Type,Cardinal,Dummy>  self_type;

    BOOST_PROTO_BASIC_EXTENDS_TPL(Expr, self_type, domain_type)

  };

  ////////////////////////////////////////////////////////////////////////////////
  // simd expression domain
  ////////////////////////////////////////////////////////////////////////////////
  template<class Type,class Cardinal>
  struct domain : boost::proto::domain< generator<Type,Cardinal>
                                      , grammar<Type,Cardinal>
                                      >
  {
  };

  template<class Type,std::size_t Cardinal,class BP = boost::proto::is_proto_expr>
  struct  pack
  {
    ////////////////////////////////////////////////////////////////////////////
    // Data holder of pack terminals
    ////////////////////////////////////////////////////////////////////////////
    typedef data<Type,boost::mpl::size_t<Cardinal> >            data_type;

    ////////////////////////////////////////////////////////////////////////////
    // Make pack a POD proto expression
    ////////////////////////////////////////////////////////////////////////////
    BOOST_PROTO_BASIC_EXTENDS_TPL
    ( typename boost::proto::terminal<data_type>::type
    , (pack<Type,Cardinal>)
    , (simd::domain<Type, boost::mpl::size_t<Cardinal> >)
    )
  };

  // The exponent bits function turn pack<float,4> into pack<int,4>
  struct exponentbits_ {};

  boost::proto::
  result_of::make_expr< exponentbits_, domain<int,boost::mpl::size_t<4> >,pack<float,4> const& >::type
  exponentbits( pack<float,4> const& x)
  {
    return  boost::proto::
            make_expr< exponentbits_, domain<int,boost::mpl::size_t<4> > >( boost::cref(x) );
  }
} }

int main()
{
  nt2::simd::pack<float,4> x;
  nt2::simd::pack<int,4>   y;

  boost::proto::display_expr(x+x); // ok
  //boost::proto::display_expr(y+x); // not ok -- expected
  boost::proto::display_expr(exponentbits(x));
  boost::proto::display_expr(exponentbits(x)+y); // not ok - unexpected.

  // fails with:
  /*
   * /Users/joelfalcou/nt2/sandbox/proto.cpp:161:46:
   * error: no match for 'operator+' in
   * 'nt2::simd::exponentbits(((const nt2::simd::pack<float, 4ul>&)((const nt2::simd::pack<float, 4ul>*)(& x)))) + y'
   */
}


Create a new paste based on this one


Comments: