Re: [Boost-users] proto: analytical-only math functions
----- Original Message ----- From: peter_foelsche@agilent.com To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Date: Fri, 6 Mar 2009 12:40:22 -0700
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
Step1 is to have a derivative metafunction which computers the nth derivative of a function at compile time. In order to do that, I need a mathematical language to write my functions. so I have constants, variables, basic_functions and user-defined functions that are terminals of my language f(x) = log(x); g(x) = derivative(1, f, x); g(x) will be 1/x; I should manage to run derivative purely in compile time. Later, I will look at stochastic and partial differential equations and write functions to solve them analytically whenever possible... proto will help me define terminals, the grammars for what are acceptable expressions. regards,
Hicham Mouline wrote:
Step1 is to have a derivative metafunction which computers the nth derivative of a function at compile time.
In order to do that, I need a mathematical language to write my functions.
so I have constants, variables, basic_functions and user-defined functions that are terminals of my language
f(x) = log(x);
g(x) = derivative(1, f, x);
g(x) will be 1/x;
I should manage to run derivative purely in compile time.
You won't be able to do it this way with exactly this syntax. The object "f" will not carry the compile-time information that derivative() would need to do its job. You might need something like this: BOOST_PROTO_AUTO( _f, f(x) = log(x) ); BOOST_PROTO_AUTO( _g, g(x) = derivative(1, _f, x) ); Or, you could do it all in one big expression, like: let( f(x) = log(x) )[ g(x) = derivative(1, f, x) ]; or something. And if I'm right in assuming that the first parameter of derivative is which derivative to take, you'll need to make that information available at compile-time as well, so: let( f(x) = log(x) )[ g(x) = derivative<1>(f, x) ];
Later, I will look at stochastic and partial differential equations and write functions to solve them analytically whenever possible...
proto will help me define terminals, the grammars for what are acceptable expressions.
Right. -- 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 March 2009 02:32 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Hicham Mouline wrote:
Step1 is to have a derivative metafunction which computers the nth derivative of a function at compile time.
In order to do that, I need a mathematical language to write my functions.
so I have constants, variables, basic_functions and user-defined functions that are terminals of my language
f(x) = log(x);
g(x) = derivative(1, f, x);
g(x) will be 1/x;
I should manage to run derivative purely in compile time.
You won't be able to do it this way with exactly this syntax. The object "f" will not carry the compile-time information that derivative() would need to do its job. You might need something like this: BOOST_PROTO_AUTO( _f, f(x) = log(x) ); BOOST_PROTO_AUTO( _g, g(x) = derivative(1, _f, x) ); Hmm. That is a bit unfortunate. I don't like very much how this syntax looks like. I thought I could store the expression tree inside the f objects themselves. that is I thought the operator= or the ctor of the function_tag could be run entirely at compile-time? But I realize it might not be possible: The ideal syntax would be: function<2> f(x,y) = x*y + x - y; // f object defined in c++ terms and at the same assigned to the expression tree // all at compile time // The above can't be correct c++ right? Both construction and call to operator= // how about the following? const function<2> f(x, y, x*y + x - y); // this might be ok, only constructor called //can this be ran entirely at compile time? Or, you could do it all in one big expression, like: let( f(x) = log(x) )[ g(x) = derivative(1, f, x) ]; or something. And if I'm right in assuming that the first parameter of derivative is which derivative to take, you'll need to make that information available at compile-time as well, so: let( f(x) = log(x) )[ g(x) = derivative<1>(f, x) ]; Yes, I didn't think the derivative function/metafunction through. These are the valid expressions: derivative<1>(f, x) // first order derivative of f wrt to x derivative<1>(f, y) // first order derivative of f wrt to y derivative<2>(f, x) // second order derivative of f wrt to x derivative<2>(f, y) // second order derivative of f wrt to y derivative<2>(f, x, y) // second order cross derivative of f wrt to x and y in general, a n-dim function of n variables x1.xn, you can define all these valid expression derivative<1>(f, x1).. derivative<1>(f, xn) derivative<2>(f, x1).. derivative<2>(f, xn) derivative<2>(f, x1, x2). all combinations of 2 vars derivative<3>(f, x1).. ).. derivative<3>(f, xn) derivative<3>(f, x1, x2) derivative<3>(f, x1, x3). derivative<3>(f, x1, x2, x3). all comb. of 3 vars . derivative<n>(f, x1).. You get the idea For now, I am still focusing on constants. Thanks very much,
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Eric Niebler Sent: 07 March 2009 02:32 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Hicham Mouline wrote:
Step1 is to have a derivative metafunction which computers the nth derivative of a function at compile time.
In order to do that, I need a mathematical language to write my functions.
so I have constants, variables, basic_functions and user-defined functions that are terminals of my language
f(x) = log(x);
g(x) = derivative(1, f, x);
g(x) will be 1/x;
I should manage to run derivative purely in compile time.
You won't be able to do it this way with exactly this syntax. The object "f" will not carry the compile-time information that derivative() would need to do its job. You might need something like this:
BOOST_PROTO_AUTO( _f, f(x) = log(x) ); BOOST_PROTO_AUTO( _g, g(x) = derivative(1, _f, x) );
Or, you could do it all in one big expression, like:
let( f(x) = log(x) )[ g(x) = derivative(1, f, x) ];
or something. And if I'm right in assuming that the first parameter of derivative is which derivative to take, you'll need to make that information available at compile-time as well, so: let( f(x) = log(x) )[ g(x) = derivative<1>(f, x) ];
I am thinking about user friendliness. I think I will have the user define this: typedef proto::terminal< function_tag< mpl::size_t<3> > >::type function3; function3 f( x1, x2, x3, x1+ x2+ x3+ c6 ); // after all, store the expression tree at runtime 1. Can I define a constructor for the terminal like this? 2. Can I store the expression tree somewhere? Inside the function_tag template? Regards,
Hicham Mouline wrote:
Eric Niebler wrote:
And if I'm right in assuming that the first parameter of derivative is which derivative to take, you'll need to make that information available at compile-time as well, so: let( f(x) = log(x) )[ g(x) = derivative<1>(f, x) ];
I am thinking about user friendliness. I think I will have the user define this:
typedef proto::terminal< function_tag< mpl::size_t<3> > >::type function3; function3 f( x1, x2, x3, x1+ x2+ x3+ c6 ); // after all, store the expression tree at runtime
1. Can I define a constructor for the terminal like this?
You could, but ...
2. Can I store the expression tree somewhere? Inside the function_tag template?
You could store the expression tree within such a function3 object, but only by erasing its type. (See http://www.artima.com/cppsource/type_erasure.html for more on type erasure.) Look at the type "function3" you've defined above. It has absolutely no compile-time information whatsoever about what expression might be stored inside it. If you want to use this variable in more complicated expressions and do expression template magic to compute derivatives and stuff at compile time, you can't. The options I offered above make all the compile-time information *about the full expression* available to Proto so you can compute interesting things at compile time. -- 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: 14 March 2009 17:37 To: boost-users@lists.boost.org Subject: Re: [Boost-users] proto: analytical-only math functions Hicham Mouline wrote:
Eric Niebler wrote:
And if I'm right in assuming that the first parameter of derivative is which derivative to take, you'll need to make that information available at compile-time as well, so: let( f(x) = log(x) )[ g(x) = derivative<1>(f, x) ];
I am thinking about user friendliness. I think I will have the user define this:
typedef proto::terminal< function_tag< mpl::size_t<3> > >::type function3; function3 f( x1, x2, x3, x1+ x2+ x3+ c6 ); // after all, store the expression tree at runtime
1. Can I define a constructor for the terminal like this?
You could, but ...
2. Can I store the expression tree somewhere? Inside the function_tag template?
You could store the expression tree within such a function3 object, but only by erasing its type. (See http://www.artima.com/cppsource/type_erasure.html for more on type erasure.)
Look at the type "function3" you've defined above. It has absolutely no compile-time information whatsoever about what expression might be stored inside it. If you want to use this variable in more complicated expressions and do expression template magic to compute derivatives and stuff at compile time, you can't.
The options I offered above make all the compile-time information *about the full expression* available to Proto so you can compute interesting things at compile time.
And I would definitely prefer compile-time as well, but as a user I would call the the derivative function in a scope that is very far from where f is defined. Does that matter? In the syntax you proposed above, what is the "let"? What are the curly and square brackets for? If the derivative function is called outside those square bracket, it will not work? The declaration of f would be earlier than its definition? Will I be able to put regular c++ code that is not related to f/g inside the brackets? Will I be able to use g outside of the brackets? Regards,
Hicham, your mail client is messing up the quoting. Is there anything you can do about that? I'll just snip everything that's been misquoted, but it is making the discussion very hard to follow. Hicham Mouline wrote:
And I would definitely prefer compile-time as well, but as a user I would call the the derivative function in a scope that is very far from where f is defined. Does that matter?
It certainly does matter. The variable 'f' would need to encode the entire expression in its type. For that, BOOST_PROTO_AUTO is your only option (until c++0x and 'auto' declarations).
In the syntax you proposed above, what is the "let"?
Just another part of the DSEL. It makes it possible to have 'f' and 'g' defined in the same expression so that 'g' can take the derivative of 'f'.
What are the curly and square brackets for?
What curly braces? The let defines the formula 'f'. The brackets denote a scope in which the definition of 'g' can have access to the definition of 'f'.
If the derivative function is called outside those square bracket, it will not work?
Correct. It has no static type information to work with.
The declaration of f would be earlier than its definition?
I don't understand.
Will I be able to put regular c++ code that is not related to f/g inside the brackets?
No, everything in the square brackets is part of the DSEL you're defining.
Will I be able to use g outside of the brackets?
You could assign the whole expression to some variable, which could then be used outside the brackets. But then you get into the same trouble with type erasure. I suggest you take the time to read about type erasure. See the link I sent in the earlier message. Once you understand the runtime/compile-time issues, you'll understand why what you want to do is impossible. -- Eric Niebler BoostPro Computing http://www.boostpro.com
participants (2)
-
Eric Niebler
-
Hicham Mouline