On May 31, 3:07 am, Joel de Guzman wrote:
First, I'll start with a phoenix function taking in a higher order
phoenix function: _1+1.
boost::function 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,
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 struct result{ typedef T type; };
template T operator()(T x, F f) const{
quantity no_temporary =
quantity::from_value(x);
return f(no_temporary).value();
}
//use as:
// boost::phoenix::functionsi::length > const
adimensionalized = adimensionalized_si::length();
// boost::function 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