
Hello, There are a few posts these days about generic libraries for math derivation of math functions, analytically or numerically. My objective is to start simple with analytical functions, and to expand the result gradually. I have used proto to define terminals : 1. 1D constants 2. 1D variables 3. 1D basic functions <double (double)> ( c++03 cmath + boost::math ) 4. user-defined functions ( 0 or more dimensions ) HEADER struct constant_tag {}; typedef proto::terminal< constant_tag >::type constant; struct variable_tag {}; typedef proto::terminal< variable_tag >::type variable; template < double (*basic_function_ptr)(double) > struct basic_function_tag { typedef double result_type; result_type operator()(double d) const { return basic_function_ptr(d); } }; proto::terminal< basic_function_tag<std::log> >::type const log = {{}}; // 1 example, I have one of these for each function template <size_t dim =1> struct function_tag {}; template <size_t dim> struct function : proto::terminal< function_tag<1> >::type {}; USER CODE ------------------ constant c; variable x,y,z,t,u,v; function<0> h; function<1> f; function<5> g; My grammar will be very simple for a start. All I want to allow are statements like: 1.variable = constant(proto terminal) or literal (actual number, does it have to be proto terminal), for e.g. x = 5; 2. function definition with the = operator. The LHS of the operator can one of: h = h() = f(x) = g(x,y,z,t,u) = // All arguments of f should be "variable"s only and they can't be repeated, and they have to match the dimension my LHS grammar looks like: template <size_t dim> struct function_def_lhs_grammar : proto::function< function_tag<dim>, proto::vararg< proto::terminal< variable_tag > > > {}; template <> struct function_def_lhs_grammar<0> : proto::or_< proto::terminal< function_tag<0> >, proto::function< function_tag<0>, proto::vararg< proto::terminal< variable_tag > > > {}; But vararg is not what I want at all: I want to have 0 variables (nothing) for the 0-dim function in the proto::function case, And I want to have exactly dim variables in the dim>0 proto::function case. Is it possible to "math-define" the function at the same time of the function<> object definition (in c++ terms) and have the dimension deducted, like: function f(x,y,z) = x+y+z ; The next step will be to worry about the RHS which is the much more complicated bit, regards,

Hi Hicham, Hicham Mouline wrote:
Hello,
There are a few posts these days about generic libraries for math derivation of math functions, analytically or numerically.
<snip>
template <size_t dim =1> struct function_tag {};
Use MPL Integral Constants here instead: template<typename dim = mpl::size_t<1> > struct function_tag { typedef dim dimension; }; And define a dimension_of metafunction like this: template<typename FunTag> struct dimension_of { typedef typename FunTag::dimension type; };
I want to have 0 variables (nothing) for the 0-dim function in the proto::function case, and I want to have exactly dim variables in the dim>0 proto::function case.
Is it possible to “math-define” the function at the same time of the function<> object definition (in c++ terms) and have the dimension deducted, like:
function f(x,y,z) = x+y+z ;
Yes. Your LHS grammar should look something like this (untested): struct lhs_grammar : proto::or_< // lone functions are ok proto::terminal< function_tag< mpl::size_t<0> > > , proto::and_< // f(x,y,z,...) is ok ... proto::function< proto::terminal< function_tag< proto::_ > > , proto::vararg< proto::terminal< variable_tag > > > // ... 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::_> > >() > > > {}; HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Hi Eric, Thank you for the LHS grammar. I have made the changes you suggested in the attached files. The main header <math.h> (I'll change this name later) includes constants (c0 ... c100), variables(x0... x100 and x y z S r q v t), basic functions from <cmath> and general functions defined by the user, with dimensions 0 to 100. Question1: With PP, I define constants c0 to c100, as non-const because I let the user initialize them to a integer variables or literals or floating point variables or literals. Does the non-constness matter? They are defined in a header file included by users of the library. Question2: With PP, I also define variables. I had variable_tag as a template taking <unsigned int subscript>. Not subscript has nothing to do with the dimensionality here. These are just different 1d variables. But then to match the proto:_ in the grammar, I high jacked your idea of a numerical MPL metafunction mpl::size_t<> for variables as well. Also, note the non-constness?? What do you think of the stand alone x y z S .... non subscripted variables? Queestion3: I made dimension_of a numerical metafunction with an embedded value member. What is the convenience of making metafunctions numerical? Should dimension_of be specialized for function_tag<> templates rather than on any type, as: template <size_t dim> struct dimension_of< function_tag< mpl::size_t<dim> > > { ... }; Any advantage to this? Question4: What is a quick way to test fundef_lhs_grammar does what I intend? Thank you for your help, Regards, -----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Eric Niebler Sent: 03 February 2009 17:46 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Hi Hicham, Hicham Mouline wrote:
Hello,
There are a few posts these days about generic libraries for math derivation of math functions, analytically or numerically.
<snip>
template <size_t dim =1> struct function_tag {};
Use MPL Integral Constants here instead: template<typename dim = mpl::size_t<1> > struct function_tag { typedef dim dimension; }; And define a dimension_of metafunction like this: template<typename FunTag> struct dimension_of { typedef typename FunTag::dimension type; };
I want to have 0 variables (nothing) for the 0-dim function in the proto::function case, and I want to have exactly dim variables in the dim>0 proto::function case.
Is it possible to "math-define" the function at the same time of the function<> object definition (in c++ terms) and have the dimension deducted, like:
function f(x,y,z) = x+y+z ;
Yes. Your LHS grammar should look something like this (untested): struct lhs_grammar : proto::or_< // lone functions are ok proto::terminal< function_tag< mpl::size_t<0> > > , proto::and_< // f(x,y,z,...) is ok ... proto::function< proto::terminal< function_tag< proto::_ > > , proto::vararg< proto::terminal< variable_tag > > > // ... 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::_> > >() > > > {}; HTH, -- Eric Niebler BoostPro Computing

Hicham Mouline wrote:
Hi Eric,
Thank you for the LHS grammar. I have made the changes you suggested in the attached files.
The main header <math.h> (I'll change this name later) includes constants (c0 ... c100), variables(x0... x100 and x y z S r q v t), basic functions from <cmath> and general functions defined by the user, with dimensions 0 to 100.
Question1: With PP, I define constants c0 to c100, as non-const because I let the user initialize them to a integer variables or literals or floating point variables or literals.
I don't understand, but it probably doesn't matter.
Does the non-constness matter? They are defined in a header file included by users of the library.
You'll have linker trouble if two translation units include that header. You should define them in a .cpp file and mark them as extern in the header.
Question2: With PP, I also define variables. I had variable_tag as a template taking <unsigned int subscript>. Not subscript has nothing to do with the dimensionality here. These are just different 1d variables. But then to match the proto:_ in the grammar, I high jacked your idea of a numerical MPL metafunction mpl::size_t<> for variables as well. Also, note the non-constness?? What do you think of the stand alone x y z S .... non subscripted variables?
I'm not sure what you're asking here.
Queestion3: I made dimension_of a numerical metafunction with an embedded value member.
OK, that's reasonable.
What is the convenience of making metafunctions numerical?
I don't know what you're asking.
Should dimension_of be specialized for function_tag<> templates rather than on any type, as: template <size_t dim> struct dimension_of< function_tag< mpl::size_t<dim> > > { ... };
Any advantage to this?
No real advantage, but a couple of disadvantages. You'll find that with this formulation, dimension_of< const function_tag<mpl::size_t<1> > > is undefined (note the const).
Question4: What is a quick way to test fundef_lhs_grammar does what I intend?
When I want to test a grammar, I define two functions like this: template<typename E> void assert_matches( E const & ) { BOOST_MPL_ASSERT((proto::matches<E, fundef_lhs_grammar>)); } template<typename E> void assert_not_matches( E const & ) { BOOST_MPL_ASSERT_NOT((proto::matches<E, fundef_lhs_grammar>)); } Then in main(), I can create expressions and pass them to one of these functions. Either it matches or it doesn't, and I can find out at compile time. HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Eric Niebler Sent: 05 February 2009 16:40 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions
Question4: What is a quick way to test fundef_lhs_grammar does what I intend?
When I want to test a grammar, I define two functions like this:
template<typename E> void assert_matches( E const & ) { BOOST_MPL_ASSERT((proto::matches<E, fundef_lhs_grammar>)); }
template<typename E> void assert_not_matches( E const & ) { BOOST_MPL_ASSERT_NOT((proto::matches<E, fundef_lhs_grammar>)); }
Then in main(), I can create expressions and pass them to one of these functions. Either it matches or it doesn't, and I can find out at compile time. HTH,
The grammar of the LHS function definition seems correct. The compilation takes too long however (using here intel/msvc libs). See the main.cpp and includes below. Any ideas how to speed compile time up? Regards, --------------------------------------- main.cpp #include <boost/mpl/assert.hpp> #include "math.h" using namespace boost; using namespace mathtest; template<typename E> void assert_matches( E const & ) { BOOST_MPL_ASSERT((proto::matches<E, mathtest::fundef_lhs_grammar>)); } template<typename E> void assert_not_matches( E const & ) { BOOST_MPL_ASSERT_NOT((proto::matches<E, mathtest::fundef_lhs_grammar>)); } int main() { function2 f; assert_matches( f(x0,x1) ); assert_not_matches( f(x0,x1) ); return 0; } --------------------------------------- math.h #ifndef TEST_MATH_HPP #define TEST_MATH_HPP #include <boost/mpl/size_t.hpp> #include <boost/mpl/prior.hpp> #include <boost/proto/proto.hpp> #ifndef TEST_MATH_MAX_DIMENSION #define TEST_MATH_MAX_DIMENSION 100 #endif #include "constants.hpp" #include "variables.hpp" #include "basic_functions.hpp" #include "functions.hpp" namespace mathtest { using namespace boost; //// Valid expressions on the LHS of the = operator struct fundef_lhs_grammar : proto::or_< // lone functions are ok function_constant_proto_terminal , proto::and_< // f(x,y,z,...) is ok ... proto::function< proto::terminal< function_tag< proto::_ > > , proto::vararg< proto::terminal< variable_tag< proto::_ > >
> // ... 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::_> > >() > > > {}; } #endif //TEST_MATH_HPP --------------------------------------- functions.hpp #ifndef TEST_MATH_FUNCTIONS_HPP #define TEST_MATH_FUNCTIONS_HPP #include <boost/proto/proto.hpp> #include <boost/mpl/size_t.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/iteration/local.hpp> namespace mathtest { using namespace boost; // to represent general functions of dimensions up to TEST_MATH_MAX_DIMENSION template <typename dim> struct function_tag { typedef dim dimension; }; typedef proto::terminal< function_tag< mpl::size_t<0> > > function_constant_proto_terminal; typedef function_constant_proto_terminal::type function_constant; // constant functions typedef proto::terminal< function_tag< mpl::size_t<1> > >::type function; // 1-variable functions #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(\ typedef proto::terminal< function_tag< mpl::size_t<\ BOOST_PP_CAT(n,> > >::type function)\ ), n ), ;) ??=include BOOST_PP_LOCAL_ITERATE() // Numerical metafunction that returns the dimensionality of a mathtest::function_tag<dim> template<typename FunTag> struct dimension_of { typedef typename FunTag::dimension type; const static size_t value = type::value; }; } #endif // TEST_MATH_FUNCTIONS_HPP

Hicham Mouline wrote:
The grammar of the LHS function definition seems correct. The compilation takes too long however (using here intel/msvc libs). See the main.cpp and includes below.
Any ideas how to speed compile time up?
<snip> There are ways to speed up Proto grammars, but the result is less terse and fungible. I wouldn't worry too much about compile times right now. From what I can tell, you're still in the early phases of your DSEL design. An expressive, agile DSEL definition will give you freedom to experiment. Once things are working to your satisfaction, you can think about replacing some of the complicated composite transforms with custom primitive transforms, as described here: http://boost-sandbox.sf.net/libs/proto/doc/html/boost_proto/users_guide/back... HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Eric Niebler Sent: 07 February 2009 17:47 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Hicham Mouline wrote:
The grammar of the LHS function definition seems correct. The compilation takes too long however (using here intel/msvc libs). See the main.cpp and includes below.
Any ideas how to speed compile time up?
<snip> There are ways to speed up Proto grammars, but the result is less terse and fungible. I wouldn't worry too much about compile times right now. From what I can tell, you're still in the early phases of your DSEL design. An expressive, agile DSEL definition will give you freedom to experiment. Once things are working to your satisfaction, you can think about replacing some of the complicated composite transforms with custom primitive transforms, as described here: http://boost-sandbox.sf.net/libs/proto/doc/html/boost_proto/users_guide/back _end/expression_transformation/primitives.html HTH, -------------------------------------------- Thank you, 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? 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?

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 ... */ } }; HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

-----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,

-----Original Message-----
From: boost-users-bounces@lists.boost.org Sent: 09 February 2009 17:25 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Hicham Mouline wrote:
Hello, I pasted the code I have so far in http://codepad.org/gk9KoR31 a really cool tool indeed. First, let me recap my objective 1. I have a mathematical functions DSEL which accepts "constants", "variables", "basic functions" and "functions". "constants" are so in the mathematical sense in that not in the computational sense. f(x) = x +c24; // meaning f depends on 1 variable only x, and deriving f wrt to x will give 1 "constants" are predeclared by the library. The grammar allows only c24= const-expression; // Assignment operator, takes a const expression tree RHS "variables" are predeclared by the library. They cannot be assigned values. They serve for derivation, integration and in other equation systems. "basic functions" are c++03 cmath defined functions ( I shall make them lazy functions like in the user guide ), of which derivatives and integrals are known. "functions" are user defined functions, the EBNF of which is to be defined later. Not predeclared by the library. My questions (please refer to the code): 1. Templating constant_tag with unsigned int, will it be recognized in the grammar by terminal< constant_tag< _ > > ? 2. I declared a constants_domain tag, which I don't know how to define. The grammar is an inner type of the expression wrapper constant_wrapper to make it easy in the grammar to exclude the constant being assigned to. What should constants_domain inherit from proto::domain< constants_domain, ????? > 3. I'm taking the idea for constant_wrapper from the user guide. The 2nd arg of proto::extends is constant_tag<subscript>, the expression being wrapped, while the templ arg of constant_wrapper in "unsigned int" ? 4. Does convertible<double> describe all integer and floating literals as well as integer and floating runtime variables? 5. I make operator= returns just c24 itself, so that if an expression tree meets ( c24=.... ), the whole thing is replaced by c24, right? Based on your experiences with defining DSEL, would this make sense? 6. constdef_rhs_grammar is an inner type grammar for the RHS of =. The LHS of = is simply constdef_lhs_grammar Should constdef_grammar just be the commented code? 7. The biggest question ( I feel I will have to let this go for now ) 7.1. If e, the argument in = operator, 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? 7.2. If e contains only literals and convertible to double runtime variables, I want = to evaluate e to the number and store it... 7.3. If e contains other math constants (constant_tag<>), evaluation is not possible and the canonical expression should be stored ( for e.g. 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.... Thank you very much, regards,

Hicham Mouline wrote:
Hello, I pasted the code I have so far in http://codepad.org/gk9KoR31 a really cool tool indeed.
<snip>
My questions (please refer to the code):
<snip> Hi Hicham, First let me apologize for not answering your questions the first time you posted them. I thought, "That's a lot of questions. I'll get to it when I have time." And I just haven't. Some of your questions are easy, though, so I'll give you some tips and get to the rest as time allows. proto::_ can only match types, not non-type template parameters, so you need to change constant_tag to take an MPL Integral Constant. The first parameter to proto::extends must be an expression type, so on line 47, you should probably have "typename proto::terminal<constant_tag<subscript> >::type", or something. On line 56, make it: proto::terminal< proto::convertible_to<double> > to match any terminal expression that is convertible to a double. (It says so much in the users' guide in the section "fuzzy and exact matches of terminals".) You really need to reread the section on domains again. The parameter to proto::generator must be an expression extension class template. That's all I have for now. Good luck. And be sure to check the docs, because you could have found many of these answers there. -- Eric Niebler BoostPro Computing http://www.boostpro.com

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Eric Niebler Sent: 01 March 2009 02:33 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Hicham Mouline wrote:
Hello, I pasted the code I have so far in http://codepad.org/gk9KoR31 a really cool tool indeed.
<snip>
My questions (please refer to the code):
<snip>
Hi Hicham,
First let me apologize for not answering your questions the first time you posted them. I thought, "That's a lot of questions. I'll get to it when I have time." And I just haven't. Some of your questions are easy, though, so I'll give you some tips and get to the rest as time allows. Please. I and I'm sure others are grateful for proto.
proto::_ can only match types, not non-type template parameters, so you need to change constant_tag to take an MPL Integral Constant.
The first parameter to proto::extends must be an expression type, so on line 47, you should probably have "typename proto::terminal<constant_tag<subscript> >::type", or something.
On line 56, make it: proto::terminal< proto::convertible_to<double> > to match any terminal expression that is convertible to a double. (It says so much in the users' guide in the section "fuzzy and exact matches of terminals".)
You really need to reread the section on domains again. The parameter to proto::generator must be an expression extension class template. That's all I have for now. Good luck. And be sure to check the docs, because you could have found many of these answers there. The complication comes in my case from the fact that the grammar is not stand alone type but an inner-type.
I have a new question. I am trying to make my basic functions (the cmath ones) lazy functions as in the user guide. // to represent the c++03 math functions // c++0x math functions are commented out. template < double (*basic_function_ptr)(double) > struct basic_function_tag { typedef double result_type; result_type operator()(double d) const { return basic_function_ptr(d); } }; proto::terminal< basic_function_tag<std::sin> >::type const sinfct = {{}}; // Define a lazy sin // template<typename Arg> typename proto::result_of::make_expr< proto::tag::function, // Tag type basic_function_tag<std::sin>, // First child (by value) Arg const & // Second child (by reference)
::type sin(Arg const &arg) { return proto::make_expr<proto::tag::function>( basic_function_tag< std::sin >(), // First child (by value) boost::ref(arg) // Second child (by reference) ); }
This should work for sin( literals and c++ vars ) and for sin( proto expressions ). As in my grammar I used to accept basic functions as proto terminals , How can I change the grammar to take this new sin() instead? Regards,

Hicham Mouline wrote:
Eric Niebler wrote:
You really need to reread the section on domains again. The parameter to proto::generator must be an expression extension class template. That's all I have for now. Good luck. And be sure to check the docs, because you could have found many of these answers there.
The complication comes in my case from the fact that the grammar is not stand alone type but an inner-type.
Why does that make a difference?
I have a new question. I am trying to make my basic functions (the cmath ones) lazy functions as in the user guide.
// to represent the c++03 math functions // c++0x math functions are commented out. template < double (*basic_function_ptr)(double) > struct basic_function_tag { typedef double result_type; result_type operator()(double d) const { return basic_function_ptr(d); } };
proto::terminal< basic_function_tag<std::sin> >::type const sinfct = {{}};
// Define a lazy sin // template<typename Arg> typename proto::result_of::make_expr< proto::tag::function, // Tag type basic_function_tag<std::sin>, // First child (by value) Arg const & // Second child (by reference)
::type sin(Arg const &arg) { return proto::make_expr<proto::tag::function>( basic_function_tag< std::sin >(), // First child (by value) boost::ref(arg) // Second child (by reference) ); }
This should work for sin( literals and c++ vars ) and for sin( proto expressions ).
As in my grammar I used to accept basic functions as proto terminals , How can I change the grammar to take this new sin() instead?
Well, what you really want is to say is something like this: proto::function< proto::terminal<basic_function_tag<_> > // Whoops! :-( , proto::_
But proto::_ only matches types, not non-type template parameters. What you can do instead is something like this: template<typename T> struct is_basic_function_tag : mpl::false_ {}; template<double (*F)(double)> struct is_basic_function_tag<basic_function_tag<F> > : mpl::true_ {}; proto::function< proto::and_< proto::terminal<_> , proto::if_< is_basic_function_tag<proto::_value>() > > , proto::_
HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Eric Niebler Sent: 05 March 2009 17:54 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Hicham Mouline wrote:
Eric Niebler wrote:
You really need to reread the section on domains again. The parameter to proto::generator must be an expression extension class template. That's all I have for now. Good luck. And be sure to check the docs, because you could have found many of these answers there.
The complication comes in my case from the fact that the grammar is not stand alone type but an inner-type.
Why does that make a difference? Rather I meant to say that the grammar "constdef_rhs_grammar" is an inner type of
template<typename Expr> struct constant_wrapper { ... }; And so in struct contants_domain : proto::domain< proto::pod_generator<constant_wrapper>, constant_wrapper<Expr>::constdef_rhs_grammar > {}; obviously wouldn't work. I could then make contants_domain templated on the Expr template <typename Expr> struct contants_domain : proto::domain< proto::pod_generator<constant_wrapper>, constant_wrapper<Expr>::constdef_rhs_grammar > {}; And then template<typename Expr> struct constant_wrapper { BOOST_PROTO_BASIC_EXTENDS(Expr, constant_wrapper< Expr >, contants_domain<Expr> ) } This would create DIFFERENT domains, one for each constant. Does this seem a sensible way to go... I saw Joel's problems with different domains, was that related to this at all?
I have a new question. I am trying to make my basic functions (the cmath ones) lazy functions as in the user guide.
// to represent the c++03 math functions // c++0x math functions are commented out. template < double (*basic_function_ptr)(double) > struct basic_function_tag { typedef double result_type; result_type operator()(double d) const { return basic_function_ptr(d); }
};
proto::terminal< basic_function_tag<std::sin> >::type const sinfct = {{}};
// Define a lazy sin // template<typename Arg> typename proto::result_of::make_expr< proto::tag::function, // Tag type basic_function_tag<std::sin>, // First child (by value) Arg const & // Second child (by reference)
::type sin(Arg const &arg) { return proto::make_expr<proto::tag::function>( basic_function_tag< std::sin >(), // First child (by value) boost::ref(arg) // Second child (by reference) ); }
This should work for sin( literals and c++ vars ) and for sin( proto expressions ).
As in my grammar I used to accept basic functions as proto terminals , How can I change the grammar to take this new sin() instead?
Well, what you really want is to say is something like this:
proto::function< proto::terminal<basic_function_tag<_> > // Whoops! :-( , proto::_
But proto::_ only matches types, not non-type template parameters. What you can do instead is something like this:
template<typename T> struct is_basic_function_tag : mpl::false_ {};
template<double (*F)(double)> struct is_basic_function_tag<basic_function_tag<F> > : mpl::true_ {};
proto::function< proto::and_< proto::terminal<_> , proto::if_< is_basic_function_tag<proto::_value>() > > , proto::_
I'll play with this. Thank you very much, Hicham

Hicham Mouline a écrit :
Does this seem a sensible way to go... I saw Joel's problems with different domains, was that related to this at all I had a different use-case but you may end up with a similar difficulty. I's not that hard to circumvent, playing with domain_of and a set of smart meta-function to computes the correct domain of a function application.

Could the originator of this thread try to explain to me what he wants to accomplish? I still cannot figure any use case for proto. Peter

Hicham Mouline wrote:
Eric Niebler wrote:
Hicham Mouline wrote:
The complication comes in my case from the fact that the grammar is not stand alone type but an inner-type.
Why does that make a difference?
Rather I meant to say that the grammar "constdef_rhs_grammar" is an inner type of
template<typename Expr> struct constant_wrapper { ... };
And so in struct contants_domain : proto::domain< proto::pod_generator<constant_wrapper>, constant_wrapper<Expr>::constdef_rhs_grammar > {}; obviously wouldn't work.
It wasn't the grammar parameter I was objecting to. In the code you posted, you had a bogus generator: struct contants_domain : proto::domain< proto::generator<contants_domain> // THIS IS WRONG , calculator_grammar > {}; Now you've changed the generator to proto::pod_generator<constant_wrapper> which looks better. As for the grammar parameter, just leave it unspecified. In your constant_wrapper::operator= overload, you have a compile-time assertion to catch invalid assignment expressions. That's sufficient. For any particular Proto-based DSEL, there needs to be a 1-to-1-to-1 correspondence between: 1) The domain type, 2) The generator for the domain, which adds extra domain-specific functionality to expressions within the domain, and 3) The grammar for the domain, which is used to disable Proto's operator overloads that would create invalid expressions. You seem to be creating a domain for constant expressions. Will these constants be appearing within expressions of another domain? If so, I suspect you'll run into trouble. I suggest you create 1 domain for your DSEL, with 1 generator and 1 grammar. You can actually have multiple expression wrappers within the same domain with a cleverly defined generator. The only requirement on the generator is that it is a polymorphic function object that accepts expressions and returns (possibly wrapped) expressions. A grammar with transforms fits this definition. Check out the following: #include <boost/proto/proto.hpp> namespace proto = boost::proto; using proto::_; template<class E> struct wrap1; template<class E> struct wrap2; // You can use a grammar with transforms as a generator struct Generator : proto::or_< proto::when< proto::assign<_,_> , proto::pod_generator<wrap1>(_) > , proto::otherwise< proto::pod_generator<wrap2>(_) > > {}; struct Domain : proto::domain<Generator> {}; // Note, wrap1 and wrap2 are both in the same domain template<class E> struct wrap1 { BOOST_PROTO_EXTENDS(E, wrap1, Domain) }; template<class E> struct wrap2 { BOOST_PROTO_EXTENDS(E, wrap2, Domain) }; typedef wrap1<proto::terminal<int>::type> I; typedef wrap2<proto::terminal<int>::type> J; I const i = {{1}}; J const j = {{2}}; int main() { wrap1< proto::assign<I const &, J const &>::type > x = (i = j); // OK, i and j are in the same domain wrap2< proto::plus<I const &, J const &>::type > y = (i + j); // OK, i and j are in the same domain } In main(), notice that an assignment creates a wrap1 object, whereas an addition creates a wrap2 object. Both are in the same domain. In short, you should be able to get along with just 1 domain for your DSEL, and it'll make things *much* simpler. HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

-----Original Message----- From: Hicham Mouline [mailto:hicham@mouline.org] Sent: 08 February 2009 01:02 To: 'boost-users@lists.boost.org' Subject: RE: [Boost-users] proto: analytical-only math functions -----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Eric Niebler Sent: 07 February 2009 17:47 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Hicham Mouline wrote:
The grammar of the LHS function definition seems correct. The compilation takes too long however (using here intel/msvc libs). See the main.cpp and includes below.
Any ideas how to speed compile time up?
<snip> There are ways to speed up Proto grammars, but the result is less terse and fungible. I wouldn't worry too much about compile times right now. From what I can tell, you're still in the early phases of your DSEL design. An expressive, agile DSEL definition will give you freedom to experiment. Once things are working to your satisfaction, you can think about replacing some of the complicated composite transforms with custom primitive transforms, as described here: http://boost-sandbox.sf.net/libs/proto/doc/html/boost_proto/users_guide/back _end/expression_transformation/primitives.html HTH, --------------------------------------------
Thank you,
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?
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?
----------------------------------- By the way, I can't find unary_minus<> in proto, how come? rds,

Hicham Mouline wrote:
By the way, I can't find unary_minus<> in proto, how come?
It's called "negate". -- Eric Niebler BoostPro Computing http://www.boostpro.com
participants (4)
-
Eric Niebler
-
Hicham Mouline
-
Joel Falcou
-
peter_foelsche@agilent.com