[lambda] make lambda play well with std::complex, imag, real, abs, etc.

Hi, I need some complex arithmetic in lambda expressions, for that I
implemented this to make some std::complex functions work with
Boost.Lambda.
namespace boost{
namespace lambda{
#define BOOST_LAMBDA_COMPLEX_IMPL(function_name) \
template<typename Arg> \
lambda_functor
function_name(const lambda_functor<Arg>& f){ \ return boost::lambda::bind(static_cast
(&std::function_name<double>), f); \ } BOOST_LAMBDA_COMPLEX_IMPL(real) BOOST_LAMBDA_COMPLEX_IMPL(imag) BOOST_LAMBDA_COMPLEX_IMPL(abs) BOOST_LAMBDA_COMPLEX_IMPL(norm) } }
use as
boost::function

On Jun 2, 2:01 pm, alfC
Hi, I need some complex arithmetic in lambda expressions, for that I implemented this to make some std::complex functions work with Boost.Lambda. ... 2) it seem imposible to generalized to other template overloads of imag<T>, real<T> (i.e. something that can be used for std::complex<T>) because the template parameter Arg doesn't have information about the actual type. is it so?
I think I now appreciate what Joel DG. refers to when he says that
bind functions are monomorphic, and why they cannot do what I pointed
in 2).
The following is the Phoenix equivalent, i.e. the code that makes
std::complex play well with Phoenix, moreover it is truly polymorphic,
they work for all std::complex<T> types, (in fact it should work for
any type that has the nested type ::value_type)
#ifndef BOOST_PHOENIX_COMPLEX_HPP
#define BOOST_PHOENIX_COMPLEX_HPP
#include

On 6/6/10 10:10 AM, alfC wrote:
On Jun 2, 2:01 pm, alfC
wrote: Hi, I need some complex arithmetic in lambda expressions, for that I implemented this to make some std::complex functions work with Boost.Lambda. ... 2) it seem imposible to generalized to other template overloads of imag<T>, real<T> (i.e. something that can be used for std::complex<T>) because the template parameter Arg doesn't have information about the actual type. is it so?
I think I now appreciate what Joel DG. refers to when he says that bind functions are monomorphic, and why they cannot do what I pointed in 2). The following is the Phoenix equivalent, i.e. the code that makes std::complex play well with Phoenix, moreover it is truly polymorphic, they work for all std::complex<T> types, (in fact it should work for any type that has the nested type ::value_type)
#ifndef BOOST_PHOENIX_COMPLEX_HPP #define BOOST_PHOENIX_COMPLEX_HPP #include
#include<complex> namespace boost{ namespace phoenix{ #define BOOST_PHOENIX_UNARY_COMPLEX_TO_REAL( FunctionnamE ) \ struct FunctionnamE##_eval{ \ template struct result{typedef typename boost::mpl::at_c ::type::value_type type;}; \ template static RT eval(Env const& env, Arg_ const& arg_){ \ return FunctionnamE(arg_.eval(env)); \ } \ }; \ template<typename Arg_> actor ::type> \ FunctionnamE(Arg_ const& arg_){ \ return compose (arg_); \ } //as listed in http://www.cplusplus.com/reference/std/complex/ BOOST_PHOENIX_UNARY_COMPLEX_TO_REAL( real ) BOOST_PHOENIX_UNARY_COMPLEX_TO_REAL( imag ) BOOST_PHOENIX_UNARY_COMPLEX_TO_REAL( abs ) BOOST_PHOENIX_UNARY_COMPLEX_TO_REAL( norm ) BOOST_PHOENIX_UNARY_COMPLEX_TO_REAL( arg ) //argument complex function, do not confuse with arg_ #undef BOOST_PHOENIX_UNARY_COMPLEX_TO_REAL #define BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( FunctionnamE ) \ struct FunctionnamE##_eval{ \ template
struct result{typedef typename boost::mpl::at_c ::type type;}; \ template static RT eval(Env const& env, Arg_ const& arg_){ \ return FunctionnamE(arg_.eval(env)); \ } \ }; \ template<typename Arg_> actor ::type> \ FunctionnamE(Arg_ const& arg_){ \ return compose (arg_); \ } BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( conj ) //todo: polar BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( cos ) BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( cosh ) BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( exp ) BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( log ) BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( log10 ) BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( pow ) BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( sin ) BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( sinh ) BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( sqrt ) BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( tan ) BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX( tanh ) #undef BOOST_PHOENIX_UNARY_COMPLEX_TO_COMPLEX }} #endif
Is there a reason why you are not using plain phoenix::function(s) for this? Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

On Sun, Jun 6, 2010 at 4:41 PM, Joel de Guzman
Is there a reason why you are not using plain phoenix::function(s) for this?
good point, I am still phoenix-challenged I guess. I got driven by the
"Composite" example in the manual.
This is the alternative implementation using phoenix::function:
namespace boost{namespace phoenix{
struct real_impl{
template <typename Arg> struct result{
typedef double type; //can be generalized
};
template <typename Arg>
typename result<Arg>::type
operator()(Arg z) const{
return real(z);
}
};
function

On 6/7/10 3:42 PM, Alfredo Correa wrote:
On Sun, Jun 6, 2010 at 4:41 PM, Joel de Guzman
wrote: Is there a reason why you are not using plain phoenix::function(s) for this?
good point, I am still phoenix-challenged I guess. I got driven by the "Composite" example in the manual. This is the alternative implementation using phoenix::function:
namespace boost{namespace phoenix{ struct real_impl{ template<typename Arg> struct result{ typedef double type; //can be generalized }; template<typename Arg> typename result<Arg>::type operator()(Arg z) const{ return real(z); } }; function
real_; // "real" as name doesn't work }} int main(){ std::complex<double> z(1.,2.); cout<< real_(arg1)(z)< which works. ...But there is a problem it seem that I can not call "real_" as "real", so the resulting syntax is degraded. (Either I have to call the phoenix::function real_ or put std::real in the operator()) It seems that the overload get confused. Is there a way to go around this? (my poorly written first version --with no phoenix::function-- at least didn't have this limitation)
Good point. Well, you can make real_ and friends use the extension mechanism as before, then use functions for all else. Duly noted. In phoenix3, we'll have an easy way to have nullary functions which do not require (). Thanks for working on this! Very good timing! :-) Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

On Jun 7, 12:52 am, Joel de Guzman
On 6/7/10 3:42 PM, Alfredo Correa wrote:
On Sun, Jun 6, 2010 at 4:41 PM, Joel de Guzman
wrote: Is there a reason why you are not using plain phoenix::function(s) for this?
good point, I am still phoenix-challenged I guess. I got driven by the "Composite" example in the manual. This is the alternative implementation using phoenix::function:
namespace boost{namespace phoenix{ struct real_impl{ template<typename Arg> struct result{ typedef double type; //can be generalized }; template<typename Arg> typename result<Arg>::type operator()(Arg z) const{ return real(z); } }; function
real_; // "real" as name doesn't work }} int main(){ std::complex<double> z(1.,2.); cout<< real_(arg1)(z)< which works. ...But there is a problem it seem that I can not call "real_" as "real", so the resulting syntax is degraded. (Either I have to call the phoenix::function real_ or put std::real in the operator()) It seems that the overload get confused. Is there a way to go around this? (my poorly written first version --with no phoenix::function-- at least didn't have this limitation)
Good point. Well, you can make real_ and friends use the extension mechanism as before, then use functions for all else.
nice to see that I found the workaround before knowing about the limitation. Now, that seems also to be the case for all functions (for example in std::) for which we need a phoenix counterpart with the *same name* (with no underscore).
Duly noted. In phoenix3, we'll have an easy way to have nullary functions which do not require ().
interesting. but I don't see how this can be applied to these examples. Thanks, Alfredo

On Mon, Jun 7, 2010 at 12:52 AM, Joel de Guzman
On 6/7/10 3:42 PM, Alfredo Correa wrote:
On Sun, Jun 6, 2010 at 4:41 PM, Joel de Guzman
wrote: Is there a reason why you are not using plain phoenix::function(s) for this?
good point, I am still phoenix-challenged I guess. I got driven by the "Composite" example in the manual. This is the alternative implementation using phoenix::function:
namespace boost{namespace phoenix{ struct real_impl{ template<typename Arg> struct result{ typedef double type; //can be generalized }; template<typename Arg> typename result<Arg>::type operator()(Arg z) const{ return real(z); } }; function
real_; // "real" as name doesn't work }} int main(){ std::complex<double> z(1.,2.); cout<< real_(arg1)(z)< which works. ...But there is a problem it seem that I can not call "real_" as "real", so the resulting syntax is degraded. (Either I have to call the phoenix::function real_ or put std::real in the operator()) It seems that the overload get confused. Is there a way to go around this? (my poorly written first version --with no phoenix::function-- at least didn't have this limitation)
Good point. Well, you can make real_ and friends use the extension mechanism as before, then use functions for all else.
I understand the underscore is necessary for reserved keywords, but
using it for everything is a pity.
So I stick with the solution that allows the same phoenix and (rest
of) C++ the same name.
In fact I realized that if I need any function (from example in std
cmath) it is good to define the following macro to "register" existing
functions, to be used in phoenix expressions.
#include
participants (4)
-
alfC
-
Alfredo Correa
-
Alfredo Correa
-
Joel de Guzman