Boost logo

Boost Users :

Subject: Re: [Boost-users] [phoenix][lambda] lambda to phoenix translation: get sig (signature) from actor
From: alfC (alfredo.correa_at_[hidden])
Date: 2010-06-05 06:21:20


> > On May 31, 3:07 am, Joel de Guzman<j..._at_[hidden]>  wrote:
> First, I'll start with a phoenix function taking in a higher order
> phoenix function: _1+1.
>
>      boost::function<double(double)> f
>          = divdoub(_1, lambda[_1+1.0]);
>

Hi Joel DG., Eric N. and Steven W.,
thank you so much for your help after all these posts I can call my
little experiment a success,
a nice mashup between, numeric libraries (not from Boost),
Boost.Units, Boost.Interval and Boost.Phoenix (Boost.Lambda didn't
make it to the end).
It can be resumed in this actual line of code

cout << qawc( _1 / (_1 - 3.*si::hertz), interval(2.*si::hertz,
4.*si::hertz)) << endl; //outputs 2 hertz

let me explain what it does (in can be a nice case study for
Boost.Phoenix3),
1) it takes a phoenix expression [e.g. _1/(_1-3.*si::hertz)], and
singles out the denominator which has a singularity at 3.*si::hertz
this qawc function stores the numerator and the singular point, it
does that by a sort of pattern matching in the function argument:

        actor<composite<
                divides_eval, vector<
                        LambdaExp, composite<
                        minus_eval, vector<
                                argument<0>,
                                boost::phoenix::value<
                                        quantity<UnitIntegrandDomain>
>
>
>
> > >

qawc can accept any expression as long as it has a denominator with
the form (_1 - c) [singular at c]

2) then it generates an adimensional version of the lambda expression
(numerator) that doesn't involves units in its input or output, this
is obtained by a generic adimensionalizer of lambda... sorry phoenix
expressions:

namespace boost{namespace units{
template<class UnitDomain>
struct adimensionalized_{
        template <typename T, typename F> struct result{ typedef T type; };
        template <typename T,typename F> T operator()(T x, F f) const{
                quantity<UnitDomain,T> no_temporary =
quantity<UnitDomain,T>::from_value(x);
                return f(no_temporary).value();
        }
//use as:
// boost::phoenix::function<adimensionalized_<si::length> > const
adimensionalized = adimensionalized_<si::length>();
// boost::function<double(double)> fadd = adimensionalized(arg1,
lambda[arg1*arg1]);
};
}}

3) once a function object that is not dimensional is generated it is
plugged in into an small interface to the GNU GSL which does a so
called "principal value" integration around the sigular point.

        double ret = gsl::integration::qawc(
                fad, //adimensionalized function
                boost::numeric::interval<double>( lower(iv).value() ,
upper(iv).value() ), //adim interval
                c //singular point
        );

4) the result is returned with the correct dimensionality (units)
converted from the adimensional result of the integral

conclusion: a modest symbolic capability is achievable with
Boost.Phoenix, depending on the expression pattern, one or other
numerical integration routine can be called. dimensional quantities
and expression can be used.

BTW, Joel, since you are taking notes, it would be interesting if
dummy named variables can be introduced in this "functional" type
programming:
so something like,

integration( _1*_1/(_1 - 2.), 1., 3.)

can be expressed as

dummy x; //or dummy<double> x; for extra control of usage.
...
integration(x*x/(x-2.), x, 1.,3.); // hey! this is GNU Maxima syntax!

Thank you,
Alfredo


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