
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Eric Niebler Sent: 09 February 2009 17:25 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Hicham Mouline wrote:
Re my constants definitions (my constant terminals are defined as proto::terminal< constant_tag<24> >::type c24; ), the allowed syntax is : c24 = const_expression; // const_expression cannot include c24
a loose EBNF for my const_expression is:
const_expression :: integer-literal e.g. 7 | floating-literal e.g. 5.4 | integer-type runtime variable e.g. int x, long y
(known
only at runtime) | fp runtime variable e.g. float r, double q (known only at runtime) | my DSEL constants | - const_expression | const_expression + const_expression | const_expression - const_expression | const_expression * const_expression | const_expression / const_expression | const_expression % const_expression | basic_function( const_expression ) | function( const_expression, ..., const_expression ) // respect the dimensionality
I don't see I am missing anything obvious?
I don't know, that's really for you to say as the DSEL designer.
The concept of const_expression here is not meant that the value of the expression is known at compile-time. It only means that on taking the derivatives of my functions wrt to my DSEL variables, the const_expression disappears.
In order to exclude the constant being defined from the = RHS, I need to define the grammar wholly for LHS and RHS of = at the same time, I couldn't define RHS grammar alone because I need to exclude c24, right?
Not necessarily. I would just define the RHS grammar without worrying about excluding any particular constants. Then give your constants an overloaded operator= that uses a compile-time assertion to make sure the RHS doesn't contain the constant currently being assigned. Something like (untested) ... template<class ID> struct constant : proto::extends< typename proto::terminal<constant_impl<ID> >::type , constant<ID> > { // For this constant, this grammar defines the valid // right-hand side expressions. struct RHS : proto::or_< proto::and_< proto::terminal<_> , proto::not_<proto::terminal<constant_impl<ID> > > > , proto::nary_expr<_, proto::vararg<RHS> > > {}; template<typename E> /* ... whatever you want this to return ... */ operator=(E const &e) const { // Make sure E doesn't contain the constant // currently being assigned. BOOST_MPL_ASSERT((proto::matches<E, RHS>)); /* ... whatever else you want here ... */ } }; -----Original Message----- I'm back to this after 2 weeks. I modified the above code like this, within lie questions: template <unsigned int subscript> <= 1. Will proto:_ match this non-type tmpl arg? struct constant_tag {}; #define BOOST_PP_LOCAL_LIMITS (0, TEST_MATH_MAX_DIMENSION) #define BOOST_PP_LOCAL_MACRO(n)\ BOOST_PP_CAT(\ BOOST_PP_CAT(\ BOOST_PP_CAT(\ proto::terminal< constant_tag<\ BOOST_PP_CAT(n,> >::type c)\ ), n ), ={{}};) ??=include BOOST_PP_LOCAL_ITERATE() struct constdef_lhs_grammar : proto::terminal< constant_tag< proto::_ > > <= see question 1. {}; struct contants_domain; template<typename FunTag> struct dimension_of { typedef typename FunTag::dimension type; const static size_t value = type::value; }; 2. I'm taking from the user guide the definition of the expression wrapper for constants. template<unsigned int subscript> struct constant_wrapper : proto::extends< constant_tag<subscript>, <= 2. The expression being wrapped, ok? constant_wrapper< constant_tag<subscript> >, contants_domain > { // For this constant, this grammar defines the valid // right-hand side expressions. struct constdef_rhs_grammar : proto::or_< proto::convertible_to<double>, <= 3. does this match both literals and runtime vars? proto::and_< proto::terminal< constant_tag< proto::_ > >, proto::not_<proto::terminal< constant_tag<subscript> > > >, proto::negate< constdef_rhs_grammar >, proto::multiplies< constdef_rhs_grammar, constdef_rhs_grammar
, proto::divides< constdef_rhs_grammar, constdef_rhs_grammar >, proto::plus< constdef_rhs_grammar, constdef_rhs_grammar >, proto::minus< constdef_rhs_grammar, constdef_rhs_grammar >, proto::modulus< constdef_rhs_grammar, constdef_rhs_grammar >, proto::function< proto::terminal< basic_function_tag< proto::_ > >, <= 4. I see I need to make basic_function_tag constdef_rhs_grammar <= lazy like in the user guide >, proto::and_< // f(..., ..., ..., ...) is ok ... proto::function< proto::terminal< function_tag< proto::_ > >, proto::vararg< constdef_rhs_grammar > >, // ... as long as the dimension of the function // matches the number of arguments. proto::if_< mpl::equal_to< dimension_of< proto::_value(proto::_child0) >, mpl::prior<proto::arity_of<proto::_> >
>() > > > {}; <= 5. I make operator= returns just c24 itself, so that if an expression tree = meets ( c24=.... ), the whole thing is replaced by c24 , right? template<typename E> typename proto::terminal< constant_tag< subscript > >::type operator=(E const &e) const { // Make sure E doesn't contain the constant // currently being assigned. BOOST_MPL_ASSERT((proto::matches<E, constdef_rhs_grammar>)); // evaluate the expression e as much as possible <= 6. Very big question here, see below } }; //struct constdef_grammar // : proto::assign< constdef_lhs_grammar, constdef_rhs_grammar > //{}; <=7. How to define the main grammar that is: C24 = const-expression (excluding c24) <=6. The biggest question: 1. If e contains only literals, I want e to be evaluated at compile time, and be assigned to c24. Should I make constant_tag<24> hold a member double ( that can be NaN meaning undefined, or the result ) and another member, what type, to store the const-expression being assigned to it? 2. If e contains only literals and convertible to double runtime variables, I want to e to evaluate to a number 3. If e contains other math constants (constant_tag<>), evaluation is not possible and the canonical expression should be stored ( c24 = c25+c0 - c0 -5 should be stored as c24 = c25 -5 if c25 is undefined, otherwise store the result )... I suspect this is not possible as I saw a similar question by Joel Falcou about this.... I'm aware these are too many questions, but any pointers will be helpful, Thank you very much, Best regards,