Boost logo

Boost Users :

Subject: Re: [Boost-users] proto: analytical-only math functions
From: Hicham Mouline (hicham_at_[hidden])
Date: 2009-02-20 22:43:36


-----Original Message-----
From: boost-users-bounces_at_[hidden]
[mailto:boost-users-bounces_at_[hidden]] On Behalf Of Eric Niebler
Sent: 09 February 2009 17:25
To: boost-users_at_[hidden]
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,


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net